What does Core.PartialStruct means for type stability?

Hi, I was toying around with NamedTuple and I’m wondering if my code is type-stable.

struct A end
name(::A) = :a
value(::A) = "test"

struct B end
name(::B) = :b
value(::B) = ones(3, 3)

function get_values(inputs)
    names = name.(inputs)
    values = value.(inputs)
    NamedTuple{names}(values)
end

@inferred get_values((A(), B())) # works properly
@code_warntype get_values((A(), B()))

Here is the output of @code_warntype:

MethodInstance for get_values(::Tuple{A, B})
  from get_values(inputs) @ Main [redacted]
Arguments
  #self#::Core.Const(Main.get_values)
  inputs::Core.Const((A(), B()))
Locals
  values::Tuple{String, Matrix{Float64}}
  names::Tuple{Symbol, Symbol}
Body::@NamedTuple{a::String, b::Matrix{Float64}}
1 ─ %1 = Base.broadcasted(Main.name, inputs)::Core.Const(Base.Broadcast.Broadcasted(name, ((A(), B()),)))
│        (names = Base.materialize(%1))
│   %3 = Base.broadcasted(Main.value, inputs)::Core.Const(Base.Broadcast.Broadcasted(value, ((A(), B()),)))
│        (values = Base.materialize(%3))
│   %5 = names::Core.Const((:a, :b))
│   %6 = Core.apply_type(Main.NamedTuple, %5)::Core.Const(NamedTuple{(:a, :b)})
│   %7 = values::Core.PartialStruct(Tuple{String, Matrix{Float64}}, Any[Core.Const("test"), Matrix{Float64}])
│   %8 = (%6)(%7)::Core.PartialStruct(@NamedTuple{a::String, b::Matrix{Float64}}, Any[Core.Const("test"), Matrix{Float64}])
└──      return %8

I was wondering what Core.PartialStruct(@NamedTuple{a::String, b::Matrix{Float64}}, Any[Core.Const("test"), Matrix{Float64}])
means, and if having Any inside it is a sign of type instability.

2 Likes

As I understand it, Core.Const and Core.PartialStruct are the bits in Julia IR that allow Julia to do constant propagation. When some constant is known — like the tuple (:a, :b) above — Julia annotates its IR with a ::Core.Const instead of just a ::Tuple{Symbol, Symbol}.

PartialStruct is for when some struct has some constants. So instead of just ::Tuple{String, Matrix{Float64}}, Julia additionally knows that the first field is a constant "test", while the second is a dynamically created matrix.

The fact that the IR uses an Any array to encode this is an implementation detail of the compiler itself, and not a problem with your code at all.

7 Likes