diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 24f1be5db8191..ac86ef6aa7bbc 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -585,7 +585,7 @@ function fieldcount_noerror(@nospecialize t) if !(t isa DataType) return nothing end - if t.name === NamedTuple.body.body.name + if t.name === _NAMEDTUPLE_NAME names, types = t.parameters if names isa Tuple return length(names) @@ -1077,11 +1077,14 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) if !istuple && !isa(headtype, UnionAll) return Union{} end + uw = unwrap_unionall(headtype) + isnamedtuple = isa(uw, DataType) && uw.name === _NAMEDTUPLE_NAME uncertain = false canconst = true tparams = Any[] outervars = Any[] varnamectr = 1 + ua = headtype for i = 1:largs ai = widenconditional(args[i]) if isType(ai) @@ -1103,8 +1106,12 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) # ai = rename_unionall(ai) # unw = unwrap_unionall(ai) #end + ai_w = widenconst(ai) + ub = ai_w isa Type && ai_w <: Type ? instanceof_tfunc(ai)[1] : Any if istuple - if i == largs + # in the last parameter of a Tuple type, if the upper bound is Any + # then this could be a Vararg type. + if i == largs && ub === Any push!(tparams, Vararg) # XXX #elseif isT @@ -1120,13 +1127,29 @@ function apply_type_tfunc(@nospecialize(headtypetype), @nospecialize args...) # ai = ai.body # end else + # Is this the second parameter to a NamedTuple? + if isnamedtuple && isa(ua, UnionAll) && uw.parameters[2] === ua.var + # If the names are known, keep the upper bound, but otherwise widen to Tuple. + # This is a widening heuristic to avoid keeping type information + # that's unlikely to be useful. + if !(uw.parameters[1] isa Tuple || (i == 2 && tparams[1] isa Tuple)) + ub = Any + end + else + ub = Any + end tvname = varnamectr <= length(_tvarnames) ? _tvarnames[varnamectr] : :_Z varnamectr += 1 - v = TypeVar(tvname) + v = TypeVar(tvname, ub) push!(tparams, v) push!(outervars, v) end end + if isa(ua, UnionAll) + ua = ua.body + else + ua = nothing + end end local appl try diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 254ba556671b3..cbc0c757d3f3f 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -2700,3 +2700,10 @@ partial_return_2(x) = Val{partial_return_1(x)[2]} # Precision of abstract_iteration f_splat(x) = (x...,) @test Base.return_types(f_splat, (Pair{Int,Int},)) == Any[Tuple{Int, Int}] + +# issue #32699 +f32699(a) = (id = a[1],).id +@test Base.return_types(f32699, (Vector{Union{Int,Missing}},)) == Any[Union{Int,Missing}] +g32699(a) = Tuple{a} +@test Base.return_types(g32699, (Type{<:Integer},))[1] == Type{<:Tuple{Any}} +@test Base.return_types(g32699, (Type,))[1] == Type{<:Tuple}