diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 572ad43b72e51..66c75c4ae0164 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1028,6 +1028,17 @@ function abstract_eval(interp::AbstractInterpreter, @nospecialize(e), vtypes::Va end elseif e.head === :splatnew t = instanceof_tfunc(abstract_eval(interp, e.args[1], vtypes, sv))[1] + if length(e.args) == 2 && isconcretetype(t) && !t.mutable + at = abstract_eval(interp, e.args[2], vtypes, sv) + n = fieldcount(t) + if isa(at, Const) && isa(at.val, Tuple) && n == length(at.val) && + _all(i->at.val[i] isa fieldtype(t, i), 1:n) + t = Const(ccall(:jl_new_structt, Any, (Any, Any), t, at.val)) + elseif isa(at, PartialStruct) && at ⊑ Tuple && n == length(at.fields) && + _all(i->at.fields[i] ⊑ fieldtype(t, i), 1:n) + t = PartialStruct(t, at.fields) + end + end elseif e.head === :& abstract_eval(interp, e.args[1], vtypes, sv) t = Any diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index fec496f321b5c..525feb5dae2f7 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -2588,3 +2588,16 @@ f() = _foldl_iter(step, (Missing[],), [0.0], 1) end @test Core.Compiler.typesubtract(Tuple{Union{Int,Char}}, Tuple{Char}) == Tuple{Int} @test Base.return_types(Issue35566.f) == [Val{:expected}] + +# constant prop through keyword arguments +_unstable_kw(;x=1,y=2) = x == 1 ? 0 : "" +_use_unstable_kw_1() = _unstable_kw(x = 2) +_use_unstable_kw_2() = _unstable_kw(x = 2, y = rand()) +@test Base.return_types(_use_unstable_kw_1) == Any[String] +@test Base.return_types(_use_unstable_kw_2) == Any[String] +@eval struct StructWithSplatNew + x::Int + StructWithSplatNew(t) = $(Expr(:splatnew, :StructWithSplatNew, :t)) +end +_construct_structwithsplatnew() = StructWithSplatNew(("",)) +@test Base.return_types(_construct_structwithsplatnew) == Any[StructWithSplatNew]