Skip to content

Inferrability of fieldnames #29100

@KristofferC

Description

@KristofferC

While looking into JuliaArrays/StructArrays.jl#3

Would be nice if this could work:

julia> struct Bar
         a::Int
         b::Float64
       end

julia> foo(T, arg1, arg2) = NamedTuple{fieldnames(T)}((arg1, arg2))
foo (generic function with 1 method)

julia> foo(Bar, rand(Int, 2), rand(2))
(a = [4045710338091169239, -2764974619330172803], b = [0.6665, 0.404776])

julia> @code_warntype foo(Bar, rand(Int, 2), rand(2))
Body::Any
...
  11%38 = (Core.apply_type)(Main.NamedTuple, %36)::Type{NamedTuple{_1,T} where T<:Tuple} where _1
  │    %39 = (Core.tuple)(arg1, arg2)::Tuple{Array{Int64,1},Array{Float64,1}}        │
  │    %40 = (%38)(%39)::Any    

Using a @generated function makes it infer

julia> @generated function __fieldnames(t::Type{T}) where {T}
           return :($(Expr(:tuple, [QuoteNode(f) for f in fieldnames(T)]...)))
       end
__fieldnames (generic function with 2 methods)

julia> foo(T, arg1, arg2) = NamedTuple{__fieldnames(T)}((arg1, arg2))
foo (generic function with 1 method)

julia> @code_warntype foo(Bar, rand(Int, 2), rand(2))
Body::NamedTuple{(:a, :b),Tuple{Array{Int64,1},Array{Float64,1}}}
1 1%1 = %new(NamedTuple{(:a, :b),Tuple{Array{Int64,1},Array{Float64,1}}}, arg1, arg2)::NamedTuple{(:a, :b),Tuple{Array{Int64,1},Array{Float64,1}}}
  └──      return %1    

Abusing pure makes it infer...

julia> Base.@pure _fieldnames(T) = fieldnames(T)
_fieldnames (generic function with 1 method)

julia> foo(T, arg1, arg2) = NamedTuple{_fieldnames(T)}((arg1, arg2))
foo (generic function with 1 method)

julia> @code_warntype foo(Bar, rand(Int, 2), rand(2))
Body::NamedTuple{(:a, :b),Tuple{Array{Int64,1},Array{Float64,1}}}
1 1 ─      invoke Main._fieldnames(_2::Type)                                                              │
  │   %2 = %new(NamedTuple{(:a, :b),Tuple{Array{Int64,1},Array{Float64,1}}}, arg1, arg2)::NamedTuple{(:a, :b),Tuple{Array{Int64,1},Array{Float64,1}}}
  └──      return %2  

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions