From b8ee49a94198b9b34cdfd3fa882f080b308fb77b Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 23 Feb 2024 17:54:53 +0000 Subject: [PATCH] allow Tuple{Union{}}, returning Union{} Fixes #52385 --- base/promotion.jl | 1 + src/jltypes.c | 2 +- test/compiler/codegen.jl | 6 ++++++ test/compiler/inference.jl | 2 +- test/subtype.jl | 13 ++++--------- test/tuple.jl | 4 ++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/base/promotion.jl b/base/promotion.jl index 1d4fea8c404eb..d53d4948f30c3 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -496,6 +496,7 @@ else _return_type(@nospecialize(f), @nospecialize(t)) = Any end +# return Tuple{tt...} if the all given elements may have instances, otherwise return Union{} if any cannot have instances function TupleOrBottom(tt...) any(p -> p === Union{}, tt) && return Union{} return Tuple{tt...} diff --git a/src/jltypes.c b/src/jltypes.c index 896e8f7b676c8..545e04c85fec8 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1927,7 +1927,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value } } if (pi == jl_bottom_type) - jl_errorf("Tuple field type cannot be Union{}"); + return jl_bottom_type; if (cacheable && !jl_is_concrete_type(pi)) cacheable = 0; } diff --git a/test/compiler/codegen.jl b/test/compiler/codegen.jl index 805e5c7acc817..78b2b74bc6d2e 100644 --- a/test/compiler/codegen.jl +++ b/test/compiler/codegen.jl @@ -652,6 +652,7 @@ end # issue #41157 f41157(a, b) = a[1] = b[1] @test_throws BoundsError f41157(Tuple{Int}[], (NTuple{N,Union{}} where N)[]) +@test_throws BoundsError f41157(Tuple{Int}[], Tuple{Union{}}[]) # issue #41096 struct Modulate41096{M<:Union{Function, Val{true}, Val{false}}, id} @@ -788,6 +789,11 @@ f_isa_type(@nospecialize(x)) = isa(x, Type) f47247(a::Ref{Int}, b::Nothing) = setfield!(a, :x, b) @test_throws TypeError f47247(Ref(5), nothing) +@testset "regression in generic_bitcast: should support Union{} values" begin + f(x) = Core.bitcast(UInt, Core.compilerbarrier(:type, x)::Int) + @test occursin("unreachable", get_llvm(f, Tuple{UInt})) +end + f48085(@nospecialize x...) = length(x) @test Core.Compiler.get_compileable_sig(which(f48085, (Vararg{Any},)), Tuple{typeof(f48085), Vararg{Int}}, Core.svec()) === nothing @test Core.Compiler.get_compileable_sig(which(f48085, (Vararg{Any},)), Tuple{typeof(f48085), Int, Vararg{Int}}, Core.svec()) === Tuple{typeof(f48085), Any, Vararg{Any}} diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index d6d65faaaf7bb..1a38eb493225f 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -1096,7 +1096,7 @@ end g21771(T) = T f21771(::Val{U}) where {U} = Tuple{g21771(U)} @test @inferred(f21771(Val{Int}())) === Tuple{Int} -@test_throws ErrorException @inferred(f21771(Val{Union{}}())) +@test @inferred(f21771(Val{Union{}}())) === Union{} @test @inferred(f21771(Val{Integer}())) === Tuple{Integer} # PR #28284, check that constants propagate through calls to new diff --git a/test/subtype.jl b/test/subtype.jl index 27e8fa604a5e9..d5512e39133cd 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -596,7 +596,7 @@ function test_old() end const easy_menagerie = - Any[Any, Int, Int8, Integer, Real, + Any[Bottom, Any, Int, Int8, Integer, Real, Array{Int,1}, AbstractArray{Int,1}, Tuple{Int,Vararg{Integer}}, Tuple{Integer,Vararg{Int}}, Tuple{}, Union{Int,Int8}, @@ -635,10 +635,7 @@ end add_variants!(easy_menagerie) add_variants!(hard_menagerie) -push!(easy_menagerie, Bottom) -push!(easy_menagerie, Ref{Bottom}) push!(easy_menagerie, @UnionAll N NTuple{N,Bottom}) -push!(easy_menagerie, @UnionAll S<:Bottom Ref{S}) const menagerie = [easy_menagerie; hard_menagerie] @@ -685,11 +682,9 @@ function test_properties() @test isequal_type(T, S) == isequal_type(Ref{T}, Ref{S}) # covariance - if T !== Bottom && S !== Bottom - @test issubTS == issub(Tuple{T}, Tuple{S}) - @test issubTS == issub(Tuple{Vararg{T}}, Tuple{Vararg{S}}) - @test issubTS == issub(Tuple{T}, Tuple{Vararg{S}}) - end + @test issubTS == issub(Tuple{T}, Tuple{S}) + @test issubTS == issub(Tuple{Vararg{T}}, Tuple{Vararg{S}}) + @test issubTS == issub(Tuple{T}, Tuple{Vararg{S}}) # pseudo-contravariance @test issubTS == issub(¬S, ¬T) diff --git a/test/tuple.jl b/test/tuple.jl index 4b0bfbbb3b055..9cacc91b4212d 100644 --- a/test/tuple.jl +++ b/test/tuple.jl @@ -803,8 +803,8 @@ namedtup = (;a=1, b=2, c=3) # some basic equivalence handling tests for Union{} appearing in Tuple Vararg parameters @test Tuple{} <: Tuple{Vararg{Union{}}} @test Tuple{Int} <: Tuple{Int, Vararg{Union{}}} -@test_throws ErrorException("Tuple field type cannot be Union{}") Tuple{Int, Vararg{Union{},1}} -@test_throws ErrorException("Tuple field type cannot be Union{}") Tuple{Vararg{Union{},1}} +@test Tuple{Int, Vararg{Union{},1}} === Union{} +@test Tuple{Vararg{Union{},1}} === Union{} @test Tuple{} <: Tuple{Vararg{Union{},N}} where N @test !(Tuple{} >: Tuple{Vararg{Union{},N}} where N)