Skip to content

Commit bb79326

Browse files
committed
Subtype: skip slow-path in local_∀_∃_subtype if inputs contain no ∃ typevar.
1 parent ccba6c9 commit bb79326

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

src/jltypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ JL_DLLEXPORT jl_array_t *jl_find_free_typevars(jl_value_t *v)
217217
}
218218

219219
// test whether a type has vars bound by the given environment
220-
static int jl_has_bound_typevars(jl_value_t *v, jl_typeenv_t *env) JL_NOTSAFEPOINT
220+
int jl_has_bound_typevars(jl_value_t *v, jl_typeenv_t *env) JL_NOTSAFEPOINT
221221
{
222222
while (1) {
223223
if (jl_is_typevar(v)) {

src/julia_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry);
750750
jl_typemap_entry_t *jl_method_table_add(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype);
751751
jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED;
752752
int jl_obviously_unequal(jl_value_t *a, jl_value_t *b);
753+
int jl_has_bound_typevars(jl_value_t *v, jl_typeenv_t *env) JL_NOTSAFEPOINT;
753754
JL_DLLEXPORT jl_array_t *jl_find_free_typevars(jl_value_t *v);
754755
int jl_has_fixed_layout(jl_datatype_t *t);
755756
JL_DLLEXPORT int jl_struct_try_layout(jl_datatype_t *dt);

src/subtype.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,23 @@ static int may_contain_union_decision(jl_value_t *x, jl_stenv_t *e, jl_typeenv_t
15121512
may_contain_union_decision(xb ? xb->ub : ((jl_tvar_t *)x)->ub, e, &newlog);
15131513
}
15141514

1515+
static int has_exists_typevar(jl_value_t *x, jl_stenv_t *e) JL_NOTSAFEPOINT
1516+
{
1517+
jl_typeenv_t *env = NULL;
1518+
jl_varbinding_t *v = e->vars;
1519+
while (v != NULL) {
1520+
if (v->right) {
1521+
jl_typeenv_t *newenv = (jl_typeenv_t*)alloca(sizeof(jl_typeenv_t));
1522+
newenv->var = v->var;
1523+
newenv->val = NULL;
1524+
newenv->prev = env;
1525+
env = newenv;
1526+
}
1527+
v = v->prev;
1528+
}
1529+
return env != NULL && jl_has_bound_typevars(x, env);
1530+
}
1531+
15151532
static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int limit_slow)
15161533
{
15171534
int16_t oldRmore = e->Runions.more;
@@ -1531,13 +1548,19 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t
15311548
int count = 0, noRmore = 0;
15321549
sub = _forall_exists_subtype(x, y, e, param, &count, &noRmore);
15331550
pop_unionstate(&e->Runions, &oldRunions);
1534-
// we should not try the slow path if `forall_exists_subtype` has tested all cases;
1535-
// Once limit_slow == 1, also skip it if
1536-
// 1) `forall_exists_subtype` return false
1551+
// We could skip the slow path safely if
1552+
// 1) `_∀_∃_subtype` has tested all cases
1553+
// 2) `_∀_∃_subtype` returns 1 && `x` and `y` contain no ∃ typevar
1554+
// Once `limit_slow == 1`, also skip it if
1555+
// 1) `_∀_∃_subtype` returns 0
15371556
// 2) the left `Union` looks big
1557+
// TODO: `limit_slow` ignores complexity from inner `local_∀_exists_subtype`.
15381558
if (limit_slow == -1)
15391559
limit_slow = kindx || kindy;
1540-
if (noRmore || (limit_slow && (count > 3 || !sub)))
1560+
int skip = noRmore || (limit_slow && (count > 3 || !sub)) ||
1561+
(sub && (kindx || !has_exists_typevar(x, e)) &&
1562+
(kindy || !has_exists_typevar(y, e)));
1563+
if (skip)
15411564
e->Runions.more = oldRmore;
15421565
}
15431566
else {

test/subtype.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,3 +2571,12 @@ let a = Tuple{Union{Nothing, Type{Pair{T1}} where T1}}
25712571
b = Tuple{Type{X2} where X2<:(Pair{T2, Y2} where {Src, Z2<:Src, Y2<:Union{Val{Z2}, Z2}})} where T2
25722572
@test !Base.has_free_typevars(typeintersect(a, b))
25732573
end
2574+
2575+
#issue 53371
2576+
struct T53371{A,B,C,D,E} end
2577+
S53371{A} = Union{Int, <:A}
2578+
R53371{A} = Val{V} where V<:(T53371{B,C,D,E,F} where {B<:Val{A}, C<:S53371{B}, D<:S53371{B}, E<:S53371{B}, F<:S53371{B}})
2579+
let S = Type{T53371{A, B, C, D, E}} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53371{A}, E<:R53371{A}},
2580+
T = Type{T53371{A, B, C, D, E} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53371{A}, E<:R53371{A}}}
2581+
@test !(S <: T)
2582+
end

0 commit comments

Comments
 (0)