Skip to content

Commit e47fedd

Browse files
authored
typeintersect: fix another stack overflow caused by circular constraints (JuliaLang#54363)
The added MWE has been broken since 1.8. The intersect result still looks quite unsoundness, but at least stack overflow get fixed. close JuliaLang#54356
1 parent 0d1d4ba commit e47fedd

File tree

2 files changed

+23
-14
lines changed

2 files changed

+23
-14
lines changed

src/subtype.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,8 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in
13151315
return ans;
13161316
}
13171317

1318+
static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e);
1319+
13181320
// `param` means we are currently looking at a parameter of a type constructor
13191321
// (as opposed to being outside any type constructor, or comparing variable bounds).
13201322
// this is used to record the positions where type variables occur for the
@@ -1365,7 +1367,8 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
13651367
if (yy) record_var_occurrence(yy, e, param);
13661368
if (yr) {
13671369
record_var_occurrence(xx, e, param);
1368-
return subtype(xx->lb, yy->ub, e, 0);
1370+
int trysub = e->intersection ? try_subtype_by_bounds(xx->lb, yy->ub, e) : 0;
1371+
return trysub || subtype(xx->lb, yy->ub, e, 0);
13691372
}
13701373
return var_lt((jl_tvar_t*)x, y, e, param);
13711374
}
@@ -2497,7 +2500,7 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
24972500

24982501
static int subtype_by_bounds(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) JL_NOTSAFEPOINT;
24992502

2500-
// similar to `subtype_by_bounds`, used to avoid stack-overflow caused by circulation constraints.
2503+
// similar to `subtype_by_bounds`, used to avoid stack-overflow caused by circular constraints.
25012504
static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
25022505
{
25032506
if (jl_is_uniontype(a))
@@ -2506,22 +2509,21 @@ static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
25062509
else if (jl_is_uniontype(b))
25072510
return try_subtype_by_bounds(a, ((jl_uniontype_t *)b)->a, e) ||
25082511
try_subtype_by_bounds(a, ((jl_uniontype_t *)b)->b, e);
2509-
else if (jl_egal(a, b))
2512+
else if (a == jl_bottom_type || b == (jl_value_t *)jl_any_type || obviously_egal(a, b))
25102513
return 1;
25112514
else if (!jl_is_typevar(b))
25122515
return 0;
2513-
jl_varbinding_t *vb = e->vars;
2514-
while (vb != NULL) {
2515-
if (subtype_by_bounds(b, (jl_value_t *)vb->var, e) && obviously_in_union(a, vb->ub))
2516-
return 1;
2517-
vb = vb->prev;
2518-
}
2519-
return 0;
2516+
else if (jl_is_typevar(a) && subtype_by_bounds(a, b, e))
2517+
return 1;
2518+
// check if `Union{a, ...} <: b`.
2519+
jl_varbinding_t *vb = lookup(e, (jl_tvar_t *)b);
2520+
jl_value_t *blb = vb ? vb->lb : ((jl_tvar_t *)b)->lb;
2521+
return obviously_in_union(a, blb);
25202522
}
25212523

25222524
static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
25232525
{
2524-
if (a == jl_bottom_type || b == (jl_value_t *)jl_any_type || try_subtype_by_bounds(a, b, e))
2526+
if (try_subtype_by_bounds(a, b, e))
25252527
return 1;
25262528
jl_savedenv_t se;
25272529
save_env(e, &se, 1);

test/subtype.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,9 +2336,10 @@ T46784{B<:Val, M<:AbstractMatrix} = Tuple{<:Union{B, <:Val{<:B}}, M, Union{Abstr
23362336
#issue 36185
23372337
let S = Tuple{Type{T},Array{Union{T,Missing},N}} where {T,N},
23382338
T = Tuple{Type{T},Array{Union{T,Nothing},N}} where {T,N}
2339-
@testintersect(S, T, !Union{})
2340-
@test_broken typeintersect(S, T) != S
2341-
@test_broken typeintersect(T, S) != T
2339+
I = typeintersect(S, T)
2340+
@test I == typeintersect(T, S) != Union{}
2341+
@test_broken I <: S
2342+
@test_broken I <: T
23422343
end
23432344

23442345
#issue 46736
@@ -2606,3 +2607,9 @@ let S = Type{T53371{A, B, C, D, E}} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53
26062607
T = Type{T53371{A, B, C, D, E} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53371{A}, E<:R53371{A}}}
26072608
@test !(S <: T)
26082609
end
2610+
2611+
#issue 54356
2612+
let S = Tuple{Val{Val{Union{Val{A2}, A2}}}, Val{Val{Union{Val{A2}, Val{A4}, A4}}}} where {A2, A4<:Union{Val{A2}, A2}},
2613+
T = Tuple{Vararg{Val{V}}} where {V}
2614+
@testintersect(S, T, !Union{})
2615+
end

0 commit comments

Comments
 (0)