diff --git a/base/compiler/typelimits.jl b/base/compiler/typelimits.jl index 3145517630958..a3a239020ab33 100644 --- a/base/compiler/typelimits.jl +++ b/base/compiler/typelimits.jl @@ -586,39 +586,40 @@ end # compute typeintersect over the extended inference lattice # where v is in the extended lattice, and t is a Type function tmeet(@nospecialize(v), @nospecialize(t)) - if isa(v, Const) - if !has_free_typevars(t) && !isa(v.val, t) - return Bottom - end + if isa(v, Type) + return typeintersect(v, t) + end + has_free_typevars(t) && return v + widev = widenconst(v) + if widev <: t return v - elseif isa(v, PartialStruct) - has_free_typevars(t) && return v - widev = widenconst(v) - if widev <: t - return v - end - ti = typeintersect(widev, t) - if ti === Bottom - return Bottom - end + end + ti = typeintersect(widev, t) + if ti === Bottom + return Bottom + end + if isa(v, PartialStruct) @assert widev <: Tuple - new_fields = Vector{Any}(undef, length(v.fields)) - for i = 1:length(new_fields) - if isa(v.fields[i], Core.TypeofVararg) - new_fields[i] = v.fields[i] - else - new_fields[i] = tmeet(v.fields[i], widenconst(getfield_tfunc(t, Const(i)))) - if new_fields[i] === Bottom - return Bottom - end + if isa(ti, DataType) && ti.name === Tuple.name + num_fields = length(ti.parameters) + isva = isvatuple(ti) + else + nfields_ti = nfields_tfunc(ti) + isva = !isa(nfields_ti, Const) + num_fields = isva ? length(v.fields) : (nfields_ti::Const).val + end + new_fields = Vector{Any}(undef, num_fields) + for i = 1:num_fields + new_fields[i] = tmeet(unwrapva(v.fields[min(i, end)]), widenconst(getfield_tfunc(ti, Const(i)))) + if new_fields[i] === Bottom + return Bottom end end - return tuple_tfunc(new_fields) - elseif isa(v, Conditional) - if !(Bool <: t) - return Bottom + if isva && isvarargtype(v.fields[end]) + new_fields[end] = Vararg{new_fields[end]} end - return v + return tuple_tfunc(new_fields) end - return typeintersect(widenconst(v), t) + # v is a Const or Conditional and its type is compatible with t + return v end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index b84e008c58649..0884886a07daa 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -3146,6 +3146,18 @@ function splat_lotta_unions() end @test Core.Compiler.return_type(splat_lotta_unions, Tuple{}) >: Tuple{Int,Int,Int} +# issue #38971 and related precision issues +f28971() = (1, [2,3]...)::Tuple{Int,Int,Int} +@test @inferred(f28971()) == (1, 2, 3) +g28971(::Type{T}) where {T} = (1, Number[2,3]...)::T +@test Base.return_types(g28971, Tuple{Type{Tuple{Vararg{Int}}}})[1] == Tuple{Int,Vararg{Int}} +@test Base.return_types(g28971, Tuple{Type{Tuple{Int,Vararg{Int}}}})[1] == Tuple{Int,Vararg{Int}} +@test Base.return_types(g28971, Tuple{Type{Tuple{Int,Int,Vararg{Int}}}})[1] == Tuple{Int,Int,Vararg{Int}} +@test Base.return_types(g28971, Tuple{Type{Union{Tuple{Int,Int,Int},Tuple{Vararg{Float64}}}}})[1] == Tuple{Int,Int,Int} +let T = Union{Tuple{Int,Int,Int},Tuple{Int,Vararg{Float64}}} + @test T <: Base.return_types(g28971, Tuple{Type{T}})[1] <: Tuple{Int,Vararg{Union{Int,Float64}}} +end + # Bare Core.Argument in IR @eval f_bare_argument(x) = $(Core.Argument(2)) @test Base.return_types(f_bare_argument, (Int,))[1] == Int