Skip to content

Commit 599593d

Browse files
JeffBezansonsimeonschaub
authored andcommitted
more precise inference of splatnew (JuliaLang#35976)
This allows constant-folding NamedTuple constructors, in turn allowing constant prop through keyword arguments.
1 parent 022c28d commit 599593d

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

base/compiler/abstractinterpretation.jl

+11
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,17 @@ function abstract_eval(interp::AbstractInterpreter, @nospecialize(e), vtypes::Va
10281028
end
10291029
elseif e.head === :splatnew
10301030
t = instanceof_tfunc(abstract_eval(interp, e.args[1], vtypes, sv))[1]
1031+
if length(e.args) == 2 && isconcretetype(t) && !t.mutable
1032+
at = abstract_eval(interp, e.args[2], vtypes, sv)
1033+
n = fieldcount(t)
1034+
if isa(at, Const) && isa(at.val, Tuple) && n == length(at.val) &&
1035+
_all(i->at.val[i] isa fieldtype(t, i), 1:n)
1036+
t = Const(ccall(:jl_new_structt, Any, (Any, Any), t, at.val))
1037+
elseif isa(at, PartialStruct) && at Tuple && n == length(at.fields) &&
1038+
_all(i->at.fields[i] fieldtype(t, i), 1:n)
1039+
t = PartialStruct(t, at.fields)
1040+
end
1041+
end
10311042
elseif e.head === :&
10321043
abstract_eval(interp, e.args[1], vtypes, sv)
10331044
t = Any

test/compiler/inference.jl

+13
Original file line numberDiff line numberDiff line change
@@ -2588,3 +2588,16 @@ f() = _foldl_iter(step, (Missing[],), [0.0], 1)
25882588
end
25892589
@test Core.Compiler.typesubtract(Tuple{Union{Int,Char}}, Tuple{Char}) == Tuple{Int}
25902590
@test Base.return_types(Issue35566.f) == [Val{:expected}]
2591+
2592+
# constant prop through keyword arguments
2593+
_unstable_kw(;x=1,y=2) = x == 1 ? 0 : ""
2594+
_use_unstable_kw_1() = _unstable_kw(x = 2)
2595+
_use_unstable_kw_2() = _unstable_kw(x = 2, y = rand())
2596+
@test Base.return_types(_use_unstable_kw_1) == Any[String]
2597+
@test Base.return_types(_use_unstable_kw_2) == Any[String]
2598+
@eval struct StructWithSplatNew
2599+
x::Int
2600+
StructWithSplatNew(t) = $(Expr(:splatnew, :StructWithSplatNew, :t))
2601+
end
2602+
_construct_structwithsplatnew() = StructWithSplatNew(("",))
2603+
@test Base.return_types(_construct_structwithsplatnew) == Any[StructWithSplatNew]

0 commit comments

Comments
 (0)