Skip to content

Commit ad785dd

Browse files
N5N3KristofferC
authored and
KristofferC
committed
typeintersect: fix another stack overflow caused by circular constraints (#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 #54356 (cherry picked from commit e47fedd)
1 parent d4e097b commit ad785dd

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
@@ -1307,6 +1307,8 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in
13071307
return ans;
13081308
}
13091309

1310+
static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e);
1311+
13101312
// `param` means we are currently looking at a parameter of a type constructor
13111313
// (as opposed to being outside any type constructor, or comparing variable bounds).
13121314
// this is used to record the positions where type variables occur for the
@@ -1357,7 +1359,8 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
13571359
if (yy) record_var_occurrence(yy, e, param);
13581360
if (yr) {
13591361
record_var_occurrence(xx, e, param);
1360-
return subtype(xx->lb, yy->ub, e, 0);
1362+
int trysub = e->intersection ? try_subtype_by_bounds(xx->lb, yy->ub, e) : 0;
1363+
return trysub || subtype(xx->lb, yy->ub, e, 0);
13611364
}
13621365
return var_lt((jl_tvar_t*)x, y, e, param);
13631366
}
@@ -2489,7 +2492,7 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
24892492

24902493
static int subtype_by_bounds(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) JL_NOTSAFEPOINT;
24912494

2492-
// similar to `subtype_by_bounds`, used to avoid stack-overflow caused by circulation constraints.
2495+
// similar to `subtype_by_bounds`, used to avoid stack-overflow caused by circular constraints.
24932496
static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
24942497
{
24952498
if (jl_is_uniontype(a))
@@ -2498,22 +2501,21 @@ static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
24982501
else if (jl_is_uniontype(b))
24992502
return try_subtype_by_bounds(a, ((jl_uniontype_t *)b)->a, e) ||
25002503
try_subtype_by_bounds(a, ((jl_uniontype_t *)b)->b, e);
2501-
else if (jl_egal(a, b))
2504+
else if (a == jl_bottom_type || b == (jl_value_t *)jl_any_type || obviously_egal(a, b))
25022505
return 1;
25032506
else if (!jl_is_typevar(b))
25042507
return 0;
2505-
jl_varbinding_t *vb = e->vars;
2506-
while (vb != NULL) {
2507-
if (subtype_by_bounds(b, (jl_value_t *)vb->var, e) && obviously_in_union(a, vb->ub))
2508-
return 1;
2509-
vb = vb->prev;
2510-
}
2511-
return 0;
2508+
else if (jl_is_typevar(a) && subtype_by_bounds(a, b, e))
2509+
return 1;
2510+
// check if `Union{a, ...} <: b`.
2511+
jl_varbinding_t *vb = lookup(e, (jl_tvar_t *)b);
2512+
jl_value_t *blb = vb ? vb->lb : ((jl_tvar_t *)b)->lb;
2513+
return obviously_in_union(a, blb);
25122514
}
25132515

25142516
static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
25152517
{
2516-
if (a == jl_bottom_type || b == (jl_value_t *)jl_any_type || try_subtype_by_bounds(a, b, e))
2518+
if (try_subtype_by_bounds(a, b, e))
25172519
return 1;
25182520
jl_savedenv_t se;
25192521
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)