diff --git a/src/subtype.c b/src/subtype.c index c2b24a28ccd14..134dab1066417 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2289,7 +2289,6 @@ static jl_value_t *intersect_var(jl_tvar_t *b, jl_value_t *a, jl_stenv_t *e, int if (bb->constraintkind == 0) { JL_GC_PUSH1(&ub); if (!jl_is_typevar(a) && try_subtype_in_env(bb->ub, a, e, 0, d)) { - set_bound(&bb->ub, ub, b, e); JL_GC_POP(); return (jl_value_t*)b; } @@ -2352,7 +2351,7 @@ static int var_occurs_inside(jl_value_t *v, jl_tvar_t *var, int inside, int want } // Caller might not have rooted `res` -static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbinding_t *vb, jl_stenv_t *e) +static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbinding_t *vb, jl_unionall_t *u, jl_stenv_t *e) { jl_value_t *varval = NULL; jl_tvar_t *newvar = vb->var; @@ -2365,7 +2364,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind // given x<:T<:x, substitute x for T varval = vb->ub; } - else if (!vb->occurs_inv && is_leaf_bound(vb->ub)) { + else if (is_leaf_bound(vb->ub) && !var_occurs_invariant(u->body, u->var, 0)) { // replace T<:x with x in covariant position when possible varval = vb->ub; } @@ -2554,7 +2553,7 @@ static jl_value_t *intersect_unionall_(jl_value_t *t, jl_unionall_t *u, jl_stenv } if (res != jl_bottom_type) // res is rooted by callee - res = finish_unionall(res, vb, e); + res = finish_unionall(res, vb, u, e); JL_GC_POP(); return res; } @@ -2977,9 +2976,9 @@ static jl_value_t *intersect(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int pa else lb = simple_join(xlb, ylb); if (yy) { - if (!subtype_by_bounds(lb, y, e)) + if (!reachable_var(lb, y, e)) yy->lb = lb; - if (!subtype_by_bounds(y, ub, e)) + if (!reachable_var(ub, y, e)) yy->ub = ub; assert(yy->ub != y); assert(yy->lb != y); diff --git a/test/subtype.jl b/test/subtype.jl index a39be465b6d1a..569ee6ade708e 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -1032,7 +1032,10 @@ function test_intersection() Bottom) @testintersect(Tuple{Type{Z},Z} where Z, Tuple{Type{Ref{T}} where T, Ref{Float64}}, - Tuple{Type{Ref{Float64}}, Ref{Float64}}) + !Bottom) + @test_broken typeintersect(Tuple{Type{Z},Z} where Z, + Tuple{Type{Ref{T}} where T, Ref{Float64}}) == + Tuple{Type{Ref{Float64}},Ref{Float64}} # issue #32607 @testintersect(Type{<:Tuple{Integer,Integer}}, @@ -1801,7 +1804,7 @@ let X1 = Tuple{AlmostLU, Vector{T}} where T, # TODO: the quality of this intersection is not great; for now just test that it # doesn't stack overflow @test I<:X1 || I<:X2 - actual = Tuple{AlmostLU{S, X} where X<:Matrix{S}, Vector{S}} where S<:Union{Float32, Float64} + actual = Tuple{Union{AlmostLU{S, X} where X<:Matrix{S}, AlmostLU{S, <:Matrix}}, Vector{S}} where S<:Union{Float32, Float64} @test I == actual end @@ -1938,3 +1941,10 @@ let A = Tuple{Dict{I,T}, I, T} where T where I, # TODO: we should probably have I == T here @test typeintersect(A, B) == Tuple{Dict{I,T}, I, T} where {I, T} end + +let A = Tuple{UnionAll, Vector{Any}}, + B = Tuple{Type{T}, T} where T<:AbstractArray, + I = typeintersect(A, B) + @test !isconcretetype(I) + @test_broken I == Tuple{Type{T}, Vector{Any}} where T<:AbstractArray +end