Skip to content

Commit

Permalink
Avoid setting circular var's bounds during intersection.
Browse files Browse the repository at this point in the history
This fixes the MWE reported in #47874 (comment)

And this fixes the remaining internal error in `Healpix.jl`'s test.

gc fix
  • Loading branch information
N5N3 committed Jan 3, 2023
1 parent 2901f0e commit 36cd9c6
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/subtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,8 @@ static int var_outside(jl_stenv_t *e, jl_tvar_t *x, jl_tvar_t *y)

static jl_value_t *intersect_aside(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int R, int d);

static int reachable_var(jl_value_t *x, jl_tvar_t *y, jl_stenv_t *e);

// check that type var `b` is <: `a`, and update b's upper bound.
static int var_lt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
{
Expand All @@ -622,8 +624,10 @@ static int var_lt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
// since otherwise the issub(a, bb.ub) check in var_gt becomes vacuous.
if (e->intersection) {
jl_value_t *ub = intersect_aside(bb->ub, a, e, 0, bb->depth0);
if (ub != (jl_value_t*)b)
JL_GC_PUSH1(&ub);
if (ub != (jl_value_t*)b && (!jl_is_typevar(ub) || !reachable_var(ub, b, e)))
bb->ub = ub;
JL_GC_POP();
}
else {
bb->ub = simple_meet(bb->ub, a);
Expand All @@ -640,8 +644,6 @@ static int var_lt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
return 1;
}

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

// check that type var `b` is >: `a`, and update b's lower bound.
static int var_gt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
{
Expand All @@ -660,8 +662,10 @@ static int var_gt(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int param)
if (!((bb->ub == (jl_value_t*)jl_any_type && !jl_is_type(a) && !jl_is_typevar(a)) || subtype_ccheck(a, bb->ub, e)))
return 0;
jl_value_t *lb = simple_join(bb->lb, a);
if (!e->intersection || !subtype_by_bounds(lb, (jl_value_t*)b, e))
JL_GC_PUSH1(&lb);
if (!e->intersection || !jl_is_typevar(lb) || !reachable_var(lb, b, e))
bb->lb = lb;
JL_GC_POP();
// this bound should not be directly circular
assert(bb->lb != (jl_value_t*)b);
if (jl_is_typevar(a)) {
Expand Down
10 changes: 10 additions & 0 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2304,6 +2304,16 @@ let S = Tuple{Val{T}, T} where {S1,T<:Val{Union{Nothing,S1}}},
@test_broken testintersect(S, T) == Tuple{Val{Val{Union{Nothing, S1}}}, Val{Union{Nothing, S1}}} where S1<:(Union{Nothing, S2} where S2)
end

#issue #47874:case1
let S1 = Tuple{Int, Any, Union{Val{C1}, C1}} where {R1<:Real, C1<:Union{Complex{R1}, R1}},
S2 = Tuple{Int, Any, Union{Val{C1}, C1} where {R1<:Real, C1<:Union{Complex{R1}, R1}}},
T1 = Tuple{Any, Int, Union{Val{C2}, C2}} where {R2<:Real, C2<:Union{Complex{R2}, R2}},
T2 = Tuple{Any, Int, V} where {R2<:Real, C2<:Union{Complex{R2}, R2}, V<:Union{Val{C2}, C2}}
for S in (S1, S2), T in (T1, T2)
@testintersect(S, T, !Union{})
end
end

@testset "known subtype/intersect issue" begin
#issue 45874
# Causes a hang due to jl_critical_error calling back into malloc...
Expand Down

0 comments on commit 36cd9c6

Please sign in to comment.