# Type instability of getfield()

**URL:** <https://discourse.julialang.org/t/type-instability-of-getfield/33205>\
**Category:** Performance\
**Created:** [January 10, 2020, 4:31pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205 "2020-01-10T16:31:04Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)\
**Post date:** [January 10, 2020, 4:31pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205/1 "2020-01-10T16:31:04Z")

</div>

See the following example

```julia
julia> struct Bar{T<:Real}
       x::T
       end

julia> struct Foo{T <: Real}
       bars::Array{Bar{T},1}
       end

julia> foo = Foo(fill(Bar(rand()),2))
Foo{Float64}(Bar{Float64}[Bar{Float64}(0.06299965346289693), Bar{Float64}(0.06299965346289693)])

julia> getfield.(foo.bars, :x)
2-element Array{Float64,1}:
 0.06299965346289693
 0.06299965346289693

julia> f(x::Int) = getfield(foo.bars[1], :x)
f (generic function with 3 methods)

julia> @code_warntype f(1)
Variables
  #self#::Core.Compiler.Const(f, false)
  x::Int64

Body::Any
1 ─ %1 = Base.getproperty(Main.foo, :bars)::Any
│ %2 = Base.getindex(%1, 1)::Any
│ %3 = Main.getfield(%2, :x)::Any
└── return %3

```

Seems to be correctly typed, I don’t see why getfield is not type-stable.

The reason I’m using getfield is because in some cases I want to do `getfield.(foo.bars, :x)` which would return an `Array{Float64,1}`.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [January 10, 2020, 4:39pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205/2 "2020-01-10T16:39:34Z")

</div>

I think you’re seeing that type instability because `foo` is global, and `f` closes over that global variable, so between two calls of `f` the complier doesn’t know that `foo` hasn’t changed into some other type.

you may want to pass `foo` as an argument to `f`, or create `foo` inside a function and return the closure `f`.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [January 10, 2020, 4:40pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205/3 "2020-01-10T16:40:19Z")

</div>

Ignoring the global variable already mentioned,

```julia
f(x::Int) = getfield(foo.bars[1], :x)

```

doesn’t make sense to me. You are not using the input argument `x`?

---

<div class="post-metadata">

**Author:** ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)\
**Post date:** [January 10, 2020, 4:44pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205/4 "2020-01-10T16:44:33Z")

</div>

It was only for the example. In practice I wanted to use the broadcasting `f() = getfield.(foo.bars, :x)`.  
While trying to find the source of instability it boiled down to the non-broadcasted call.

I have to look again because I do see type instability in my code but there it is not global scope.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [January 10, 2020, 5:02pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205/5 "2020-01-10T17:02:19Z")

</div>

If the variable that `f` is closing over has some sufficiently-complicated stuff going on with it, it’s possible that the compiler can’t prove that it’ll never change type so it’s doing the dynamic dispatch you’re seeing.

You could try putting a `let foo=foo` block around your `f` closure definition to see if that helps.

---

<div class="post-metadata">

**Author:** ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)\
**Post date:** [January 10, 2020, 5:10pm UTC](https://discourse.julialang.org/t/type-instability-of-getfield/33205/6 "2020-01-10T17:10:17Z")

</div>

Actually, I simply used `[bar.x for bar in foo.bars]` instead of the broadcast. It’s old code that I’m optimizing so I think didn’t know this notation back then.

But thank you this has been instructive.
