julia
julia copied to clipboard
Constant propagation through NamedTuple destructuring
You can break apart a NamedTuple into pairs and then rebuild it, which is very convenient, especially for programmatically building NamedTuples. However, constant propagation doesn't keep up through the process:
rebuild(named_tuple) = named_tuple |> pairs |> Tuple |> NamedTuple
@code_warntype rebuild((a = 1, b = 1.0, c = "1"))
# inferred result: NamedTuple
# would hope for: NamedTuple{(:a, :b, :c), Tuple{Int64, Float64, String}}
I wonder if it would be feasible for this to work in the first place, and if so, what the steps would be to getting there?
Ref https://github.com/JuliaLang/julia/issues/39910#issuecomment-826845402
I watched the JuliaCon talk where @StefanKarpinski mentioned prioritizing making Julia faster for tabular data and I think solving this would be an important step
There two issues here:
Tuple{::Pairs)looks suboptimal, only givingTuple{Vararg{Pair{Int64, Pair{Symbol}}}}here.x -> (x...,)gives the slightly betterNTuple{3, Pair{Int64, Pair{Symbol}}}, but still looses all const-ness.- Even if
NamedTuplegets a const tuple of pairs, it still only infers asNamedTuple:
julia> foo() = NamedTuple((:a => 1, :b => 1.0, :c => "1"))
foo (generic function with 1 method)
julia> @code_warntype foo()
MethodInstance for foo()
from foo() in Main at REPL[21]:1
Arguments
#self#::Core.Const(foo)
Body::NamedTuple
1 ─ %1 = (:a => 1)::Core.Const(:a => 1)
│ %2 = (:b => 1.0)::Core.Const(:b => 1.0)
│ %3 = (:c => "1")::Core.PartialStruct(Pair{Symbol, String}, Any[Core.Const(:c), String])
│ %4 = Core.tuple(%1, %2, %3)::Core.PartialStruct(Tuple{Pair{Symbol, Int64}, Pair{Symbol, Float64}, Pair{Symbol, String}}, Any[Core.Const(:a => 1), Core.Const(:b => 1.0), Core.PartialStruct(Pair{Symbol, String}, Any[Core.Const(:c), String])])
│ %5 = Main.NamedTuple(%4)::NamedTuple
└── return %5
Thanks for looking into it! It does seem like an uphill battle