diff --git a/src/subtype.c b/src/subtype.c index 1baba395ff3b6..7a5ac6c67a495 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1401,7 +1401,7 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int jl_varbinding_t *bb = lookup(e, b); if (bb == NULL) return R ? intersect_aside(a, b->ub, e, 0) : intersect_aside(b->ub, a, e, 0); - if (bb->lb == bb->ub && jl_is_typevar(bb->lb)) + if (bb->lb == bb->ub && jl_is_typevar(bb->lb) && bb->lb != (jl_value_t*)b) return intersect(a, bb->lb, e, param); if (!jl_is_type(a) && !jl_is_typevar(a)) return set_var_to_const(bb, a, NULL); @@ -1466,8 +1466,11 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int else if (bb->constraintkind == 2) { // TODO: removing this case fixes many test_brokens in test/subtype.jl // but breaks other tests. - if (!subtype_in_env(a, bb->ub, e)) + if (!subtype_in_env(a, bb->ub, e)) { + // mark var as unsatisfiable by making it circular + bb->lb = (jl_value_t*)b; return jl_bottom_type; + } jl_value_t *lb = simple_join(bb->lb, a); set_bound(&bb->lb, lb, b, e); return a; diff --git a/test/subtype.jl b/test/subtype.jl index 5a8f54b85f02c..16b7cf0f1af5a 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1428,3 +1428,8 @@ end @testintersect(Tuple{Pair{B,C},Union{C,Pair{B,C}},Union{B,Real}} where {B,C}, Tuple{Pair{B,C},C,C} where {B,C}, Tuple{Pair{B,C},C,C} where C<:Union{Real, B} where B) + +# issue #31115 +@testintersect(Tuple{Ref{Z} where Z<:(Ref{Y} where Y<:Tuple{<:B}), Int} where B, + Tuple{Ref{Z} where Z<:(Ref{Y} where Y<:Tuple{ B}), Any} where B<:AbstractMatrix, + Tuple{Ref{Z} where Z<:(Ref{Y} where Y<:Tuple{ B}), Int} where B<:AbstractMatrix)