I define a composite type with fields of different types:
struct MyType
i::Int
f::Float64
end
And then:
julia> a = MyType(1,1.0)
MyType(1, 1.0)
julia> @code_warntype a.i
Body::Union{Float64, Int64}
18 1 ─ %1 = (Base.getfield)(x, f)::Union{Float64, Int64} │
└── return %1
Does this mean that any code querying any of the fields of a MyField
instance would be type-unstable?
And if that’s the case, is there a way to avoid it?
c42f
February 8, 2019, 10:35pm
2
No, composite types are perfectly fine with type inference. What you’re seeing here is misleading because of the way @code_warntype
interprets expressions.
The macro is showing you the code for getproperty(::MyType, ::Symbol)
for unknown symbols:
julia> name = :i
julia> @code_warntype getproperty(a, name)
Body::Union{Float64, Int64}
1 ─ %1 = (Base.getfield)(x, f)::Union{Float64, Int64}
└── return %1
Instead, you want the code for a function which uses getproperty
with a particular symbol which may be const propagated into getfield
:
julia> foo(a) = a.i
foo (generic function with 1 method)
julia> @code_warntype foo(a)
Body::Int64
1 ─ %1 = (Base.getfield)(a, :i)::Int64
└── return %1
4 Likes
Sometimes I find it easier to use the regular (non-macro) versions of the code_*
methods:
julia> code_warntype(x -> x.i, (MyType,))
Body::Int64
1 ─ %1 = (Base.getfield)(x, :i)::Int64
└── return %1
4 Likes
You can also put it through an anonymous function, and it’s the same as first creating a function like foo
.
julia> @code_warntype (x->x.i)(a)
Body::Int64
1 ─ %1 = (Base.getfield)(x, :i)::Int64
└── return %1
2 Likes