Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constant propagation through NamedTuple destructuring #40627

Open
bramtayl opened this issue Apr 27, 2021 · 3 comments
Open

Constant propagation through NamedTuple destructuring #40627

bramtayl opened this issue Apr 27, 2021 · 3 comments
Labels
collections Data structures holding multiple items, e.g. sets

Comments

@bramtayl
Copy link
Contributor

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 #39910 (comment)

@bramtayl
Copy link
Contributor Author

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

@martinholters
Copy link
Member

There two issues here:

  1. Tuple{::Pairs) looks suboptimal, only giving Tuple{Vararg{Pair{Int64, Pair{Symbol}}}} here. x -> (x...,) gives the slightly better NTuple{3, Pair{Int64, Pair{Symbol}}}, but still looses all const-ness.
  2. Even if NamedTuple gets a const tuple of pairs, it still only infers as NamedTuple:
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

@bramtayl
Copy link
Contributor Author

Thanks for looking into it! It does seem like an uphill battle

@nsajko nsajko added the collections Data structures holding multiple items, e.g. sets label Aug 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
collections Data structures holding multiple items, e.g. sets
Projects
None yet
Development

No branches or pull requests

3 participants