diff --git a/src/subtype.c b/src/subtype.c index 810d4c33ace8a..f14244cf1cb4f 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1773,6 +1773,14 @@ static jl_value_t *intersect_invariant(jl_value_t *x, jl_value_t *y, jl_stenv_t flip_vars(e); return ii; } + /* + TODO: This is a band-aid for issue #23685. A better solution would be to + first normalize types so that all `where` expressions in covariant position + are pulled out to the top level. + */ + if ((jl_is_typevar(x) && !jl_is_typevar(y) && lookup(e, (jl_tvar_t*)x) == NULL) || + (jl_is_typevar(y) && !jl_is_typevar(x) && lookup(e, (jl_tvar_t*)y) == NULL)) + return ii; jl_value_t *root=NULL; jl_savedenv_t se; JL_GC_PUSH2(&ii, &root); diff --git a/test/inference.jl b/test/inference.jl index a599922235824..0640201d0c51c 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -1201,3 +1201,13 @@ g23024(TT::Tuple{DataType}) = f23024(TT[1], v23024) @test !Core.Inference.isconstType(Type{typeof(Union{})}) # could be Core.TypeofBottom or Type{Union{}} at runtime @test Base.return_types(supertype, (Type{typeof(Union{})},)) == Any[Any] + +# issue #23685 +struct Node23685{T} +end +@inline function update23685!(::Node23685{T}) where T + convert(Node23685{T}, Node23685{Float64}()) +end +h23685 = Node23685{Float64}() +f23685() = update23685!(h23685) +@test f23685() === h23685 diff --git a/test/subtype.jl b/test/subtype.jl index b0907706a4ec1..fd6fb3b9b5147 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -271,6 +271,8 @@ function test_3() @test !issub(Tuple{Type{Vector{T}} where T, Vector{Float64}}, Tuple{Type{T}, T} where T) @test !issub(Tuple{Vector{Float64}, Type{Vector{T}} where T}, Tuple{T, Type{T}} where T) @test !issub(Tuple{Type{Ref{T}} where T, Vector{Float64}}, Tuple{Ref{T}, T} where T) + + @test !issub(Tuple{Type{Ref{T}} where T, Ref{Float64}}, Tuple{Type{T},T} where T) end # level 4: Union @@ -930,6 +932,17 @@ function test_intersection() @testintersect(Tuple{Ref{Ref{T}} where T, Ref}, Tuple{Ref{T}, Ref{T}} where T, Tuple{Ref{Ref{T}}, Ref{Ref{T}}} where T) + + # issue #23685 + @testintersect(Pair{Type{Z},Z} where Z, + Pair{Type{Ref{T}} where T, Ref{Float64}}, + Bottom) + @testintersect(Tuple{Type{Z},Z} where Z, + Tuple{Type{Ref{T}} where T, 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}} end function test_intersection_properties()