Skip to content

Commit 496d822

Browse files
N5N3KristofferC
authored andcommitted
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 2aac3bc commit 496d822

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
@@ -1301,6 +1301,8 @@ static int subtype_tuple(jl_datatype_t *xd, jl_datatype_t *yd, jl_stenv_t *e, in
13011301
return ans;
13021302
}
13031303

1304+
static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e);
1305+
13041306
// `param` means we are currently looking at a parameter of a type constructor
13051307
// (as opposed to being outside any type constructor, or comparing variable bounds).
13061308
// this is used to record the positions where type variables occur for the
@@ -1351,7 +1353,8 @@ static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param)
13511353
if (yy) record_var_occurrence(yy, e, param);
13521354
if (yr) {
13531355
record_var_occurrence(xx, e, param);
1354-
return subtype(xx->lb, yy->ub, e, 0);
1356+
int trysub = e->intersection ? try_subtype_by_bounds(xx->lb, yy->ub, e) : 0;
1357+
return trysub || subtype(xx->lb, yy->ub, e, 0);
13551358
}
13561359
return var_lt((jl_tvar_t*)x, y, e, param);
13571360
}
@@ -2483,7 +2486,7 @@ static jl_value_t *bound_var_below(jl_tvar_t *tv, jl_varbinding_t *bb, jl_stenv_
24832486

24842487
static int subtype_by_bounds(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) JL_NOTSAFEPOINT;
24852488

2486-
// similar to `subtype_by_bounds`, used to avoid stack-overflow caused by circulation constraints.
2489+
// similar to `subtype_by_bounds`, used to avoid stack-overflow caused by circular constraints.
24872490
static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
24882491
{
24892492
if (jl_is_uniontype(a))
@@ -2492,22 +2495,21 @@ static int try_subtype_by_bounds(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
24922495
else if (jl_is_uniontype(b))
24932496
return try_subtype_by_bounds(a, ((jl_uniontype_t *)b)->a, e) ||
24942497
try_subtype_by_bounds(a, ((jl_uniontype_t *)b)->b, e);
2495-
else if (jl_egal(a, b))
2498+
else if (a == jl_bottom_type || b == (jl_value_t *)jl_any_type || obviously_egal(a, b))
24962499
return 1;
24972500
else if (!jl_is_typevar(b))
24982501
return 0;
2499-
jl_varbinding_t *vb = e->vars;
2500-
while (vb != NULL) {
2501-
if (subtype_by_bounds(b, (jl_value_t *)vb->var, e) && obviously_in_union(a, vb->ub))
2502-
return 1;
2503-
vb = vb->prev;
2504-
}
2505-
return 0;
2502+
else if (jl_is_typevar(a) && subtype_by_bounds(a, b, e))
2503+
return 1;
2504+
// check if `Union{a, ...} <: b`.
2505+
jl_varbinding_t *vb = lookup(e, (jl_tvar_t *)b);
2506+
jl_value_t *blb = vb ? vb->lb : ((jl_tvar_t *)b)->lb;
2507+
return obviously_in_union(a, blb);
25062508
}
25072509

25082510
static int try_subtype_in_env(jl_value_t *a, jl_value_t *b, jl_stenv_t *e)
25092511
{
2510-
if (a == jl_bottom_type || b == (jl_value_t *)jl_any_type || try_subtype_by_bounds(a, b, e))
2512+
if (try_subtype_by_bounds(a, b, e))
25112513
return 1;
25122514
jl_savedenv_t se;
25132515
save_env(e, &se, 1);

test/subtype.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2327,9 +2327,10 @@ T46784{B<:Val, M<:AbstractMatrix} = Tuple{<:Union{B, <:Val{<:B}}, M, Union{Abstr
23272327
#issue 36185
23282328
let S = Tuple{Type{T},Array{Union{T,Missing},N}} where {T,N},
23292329
T = Tuple{Type{T},Array{Union{T,Nothing},N}} where {T,N}
2330-
@testintersect(S, T, !Union{})
2331-
@test_broken typeintersect(S, T) != S
2332-
@test_broken typeintersect(T, S) != T
2330+
I = typeintersect(S, T)
2331+
@test I == typeintersect(T, S) != Union{}
2332+
@test_broken I <: S
2333+
@test_broken I <: T
23332334
end
23342335

23352336
#issue 46736
@@ -2597,3 +2598,9 @@ let S = Type{T53371{A, B, C, D, E}} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53
25972598
T = Type{T53371{A, B, C, D, E} where {A, B<:R53371{A}, C<:R53371{A}, D<:R53371{A}, E<:R53371{A}}}
25982599
@test !(S <: T)
25992600
end
2601+
2602+
#issue 54356
2603+
let S = Tuple{Val{Val{Union{Val{A2}, A2}}}, Val{Val{Union{Val{A2}, Val{A4}, A4}}}} where {A2, A4<:Union{Val{A2}, A2}},
2604+
T = Tuple{Vararg{Val{V}}} where {V}
2605+
@testintersect(S, T, !Union{})
2606+
end

0 commit comments

Comments
 (0)