Skip to content

Commit

Permalink
more precise inference of splatnew (#35976)
Browse files Browse the repository at this point in the history
This allows constant-folding NamedTuple constructors, in turn
allowing constant prop through keyword arguments.
  • Loading branch information
JeffBezanson authored May 26, 2020
1 parent 479097c commit 7124472
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
11 changes: 11 additions & 0 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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]

0 comments on commit 7124472

Please sign in to comment.