Skip to content

Commit e0b2828

Browse files
N5N3KristofferC
authored andcommitted
specificity: ensure fast-path in sub/eq_msp handle missing UnionAll wrapper correctly. (#54736)
(cherry picked from commit 34cd610)
1 parent e7ddd62 commit e0b2828

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

src/subtype.c

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4730,6 +4730,56 @@ JL_DLLEXPORT jl_value_t *jl_widen_diagonal(jl_value_t *t, jl_unionall_t *ua)
47304730
}
47314731

47324732
// specificity comparison
4733+
static int count_missing_wrap(jl_value_t *x, jl_typeenv_t *env)
4734+
{
4735+
if (!jl_has_free_typevars(x))
4736+
return 0;
4737+
jl_typeenv_t *wrapped = NULL;
4738+
int count = 0;
4739+
for (jl_typeenv_t *env2 = env; env2 != NULL; env2 = env2->prev) {
4740+
int need_wrap = 0;
4741+
for (jl_typeenv_t *env3 = wrapped; env3 != NULL && need_wrap == 0; env3 = env3->prev) {
4742+
if (env3->var == env2->var)
4743+
need_wrap = -1;
4744+
else if (jl_has_typevar(env3->var->lb, env2->var) || jl_has_typevar(env3->var->ub, env2->var))
4745+
need_wrap = 1;
4746+
}
4747+
need_wrap = need_wrap == 0 ? jl_has_typevar(x, env2->var) :
4748+
need_wrap == -1 ? 0 : 1;
4749+
if (need_wrap) {
4750+
count++;
4751+
jl_typeenv_t *newenv = (jl_typeenv_t*)alloca(sizeof(jl_typeenv_t));
4752+
newenv->var = env2->var;
4753+
newenv->val = NULL;
4754+
newenv->prev = wrapped;
4755+
wrapped = newenv;
4756+
}
4757+
}
4758+
return count;
4759+
}
4760+
4761+
static int obvious_subtype_msp(jl_value_t *x, jl_value_t *y, jl_value_t *y0, int *subtype, int wrapx, int wrapy)
4762+
{
4763+
if (wrapx != 0 || wrapy != 0) {
4764+
int wrap_count = wrapx - wrapy;
4765+
while (wrap_count > 0 && jl_is_unionall(y))
4766+
{
4767+
y = ((jl_unionall_t*)y)->body;
4768+
wrap_count--;
4769+
}
4770+
while (wrap_count < 0 && jl_is_unionall(x))
4771+
{
4772+
x = ((jl_unionall_t*)x)->body;
4773+
wrap_count++;
4774+
}
4775+
if (wrap_count > 0) {
4776+
if (obvious_subtype(jl_unwrap_unionall(x), y, y0, subtype) && !*subtype)
4777+
return 1;
4778+
return 0;
4779+
}
4780+
}
4781+
return obvious_subtype(x, y, y0, subtype);
4782+
}
47334783

47344784
static int eq_msp(jl_value_t *a, jl_value_t *b, jl_value_t *a0, jl_value_t *b0, jl_typeenv_t *env)
47354785
{
@@ -4752,12 +4802,14 @@ static int eq_msp(jl_value_t *a, jl_value_t *b, jl_value_t *a0, jl_value_t *b0,
47524802
a = b;
47534803
b = temp;
47544804
}
4805+
int wrapa = count_missing_wrap(a, env);
4806+
int wrapb = count_missing_wrap(b, env);
47554807
// first check if a <: b has an obvious answer
47564808
int subtype_ab = 2;
47574809
if (b == (jl_value_t*)jl_any_type || a == jl_bottom_type) {
47584810
subtype_ab = 1;
47594811
}
4760-
else if (obvious_subtype(a, b, b0, &subtype_ab)) {
4812+
else if (obvious_subtype_msp(a, b, b0, &subtype_ab, wrapa, wrapb)) {
47614813
#ifdef NDEBUG
47624814
if (subtype_ab == 0)
47634815
return 0;
@@ -4771,7 +4823,7 @@ static int eq_msp(jl_value_t *a, jl_value_t *b, jl_value_t *a0, jl_value_t *b0,
47714823
if (a == (jl_value_t*)jl_any_type || b == jl_bottom_type) {
47724824
subtype_ba = 1;
47734825
}
4774-
else if (obvious_subtype(b, a, a0, &subtype_ba)) {
4826+
else if (obvious_subtype_msp(b, a, a0, &subtype_ba, wrapb, wrapa)) {
47754827
#ifdef NDEBUG
47764828
if (subtype_ba == 0)
47774829
return 0;
@@ -4836,7 +4888,9 @@ static int sub_msp(jl_value_t *x, jl_value_t *y, jl_value_t *y0, jl_typeenv_t *e
48364888
return 1;
48374889
}
48384890
int obvious_sub = 2;
4839-
if (obvious_subtype(x, y, y0, &obvious_sub)) {
4891+
int wrapx = count_missing_wrap(x, env);
4892+
int wrapy = count_missing_wrap(y, env);
4893+
if (obvious_subtype_msp(x, y, y0, &obvious_sub, wrapx, wrapy)) {
48404894
#ifdef NDEBUG
48414895
return obvious_sub;
48424896
#endif

test/specificity.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,14 @@ end
316316
@test args_morespecific(Tuple{typeof(Union{}), Any}, Tuple{Any, Type{Union{}}})
317317
@test args_morespecific(Tuple{Type{Union{}}, Type{Union{}}, Any}, Tuple{Type{Union{}}, Any, Type{Union{}}})
318318
@test args_morespecific(Tuple{Type{Union{}}, Type{Union{}}, Any, Type{Union{}}}, Tuple{Type{Union{}}, Any, Type{Union{}}, Type{Union{}}})
319+
320+
# requires assertions enabled
321+
let root = NTuple
322+
N = root.var
323+
T = root.body.var
324+
x1 = root.body.body
325+
x2 = Dict{T,Tuple{N}}
326+
A = UnionAll(N, UnionAll(T, Tuple{Union{x1, x2}}))
327+
B = Tuple{Union{UnionAll(N, UnionAll(T, x1)), UnionAll(N, UnionAll(T, x2))}}
328+
@ccall jl_type_morespecific_no_subtype(A::Any, B::Any)::Cint
329+
end

0 commit comments

Comments
 (0)