# Help to remove type instability when using getproperty

**URL:** <https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849>\
**Category:** General Usage\
**Created:** [May 5, 2020, 11:56pm UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849 "2020-05-05T23:56:05Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [May 5, 2020, 11:56pm UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/1 "2020-05-05T23:56:05Z")

</div>

Hi!

I have this structure:

```julia
struct Workspace{T}
    x::Vector{T}
    s_i::Vector{T}
    s_b::Vector{T}
end

```

I would like to overload `getproperty` and `getindex` so that `s.JD` is `x[1]` and `s.w` is `view(x,2:4)`. Following the same approach as LabelledArrays, I did the following:

```julia
mutable struct Workspace{T}
    x::Vector{T}
    s_i::Vector{T}
    s_b::Vector{T}
end

# Functions to translate the state-vector into variables.
function Base.getproperty(a::Workspace, f::Symbol)
    if (f ∈ [:JD, :w])
        return getindex(a, Val(f))
    else
        return getfield(a,f)
    end
end

function Base.getindex(a::Workspace, s::Val)
    return __getindex(a,s)
end

function __getindex(a::Workspace, ::Val{:JD})
    return a.x[1]
end

function __getindex(a::Workspace, ::Val{:w})
    return view(a.x, 2:4)
end

```

This works fine and I can access those virtual fields without type-instabilities:

```julia
julia> w = Workspace(zeros(10), zeros(3), zeros(3))
Workspace{Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0])

julia> function test(w)
       w.JD
       end
test (generic function with 1 method)

julia> @code_warntype test(w)
Variables
  #self#::Core.Compiler.Const(test, false)
  w::Workspace{Float64}

Body::Float64
1 ─ %1 = Base.getproperty(w, :JD)::Float64
└── return %1

```

However, if a have another type of variable, like a `Bool`, then the same code has a type instability:

```julia
mutable struct Workspace{T}
    x::Vector{T}
    eclipse::Bool
    s_i::Vector{T}
    s_b::Vector{T}
end

# Functions to translate the state-vector into variables.
function Base.getproperty(a::Workspace, f::Symbol)
    if (f ∈ [:JD, :w])
        return getindex(a, Val(f))
    else
        return getfield(a,f)
    end
end

function Base.getindex(a::Workspace, s::Val)
    return __getindex(a,s)
end

function __getindex(a::Workspace, ::Val{:JD})
    return a.x[1]
end

function __getindex(a::Workspace, ::Val{:w})
    return view(a.x, 2:4)
end

```

```julia
julia> w = Workspace(zeros(10), false, zeros(3), zeros(3))
Workspace{Float64}([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], false, [0.0, 0.0, 0.0], [0.0, 0.0, 0.0])

julia> function test(w)
       w.JD
       end
test (generic function with 1 method)

julia> @code_warntype test(w)
Variables
  #self#::Core.Compiler.Const(test, false)
  w::Workspace{Float64}

Body::Any
1 ─ %1 = Base.getproperty(w, :JD)::Any
└── return %1

```

Is there any way to avoid that?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [May 5, 2020, 11:59pm UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/2 "2020-05-05T23:59:37Z")

</div>

Here’s a blog post on how LabelledArrays was made. If you copy that strategy you should be fine:

> **[Zero-Cost Abstractions in Julia: Indexing Vectors by Name with LabelledArrays...](https://www.stochasticlifestyle.com/zero-cost-abstractions-in-julia-indexing-vectors-by-name-with-labelledarrays/)**
>
> The ability to build robust array type abstractions without overhead is one of the most fantastic features of Julia. It can be surprising how much one can do with the idea of an array to end up with better code. In this blog post I want to show how...

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [May 6, 2020, 12:03am UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/3 "2020-05-06T00:03:46Z")

</div>

Hum, it seems that I really used the same approach (at least I was not able to understand the difference). As you put on the blog, it works fine if all the variables in the structure `Workspace` have the same type. If one variable has another type, then I was not able to avoid the type-instability. Of course, my example is way simpler than LabelledArrays because the “labels” are fixed and known.

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [May 6, 2020, 12:09am UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/4 "2020-05-06T00:09:09Z")

</div>

I think the same problem happens with LabelledArrays (well, not exactly the same problem) if the element types of the array are different, leading to a `Array{Any}`.

```julia
julia> x = @LArray [1,2,3,"s"] (a = 1:3, b = 4);

julia> h(x) = x.b
h (generic function with 1 method)

julia> @code_warntype h(x)
Variables
  #self#::Core.Compiler.Const(h, false)
  x::LArray{Any,1,Array{Any,1},(a = 1:3, b = 4)}

Body::Any
1 ─ %1 = Base.getproperty(x, :b)::Any
└── return %1

```

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [May 6, 2020, 12:11am UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/5 "2020-05-06T00:11:09Z")

</div>

You can’t have an array as the backing if you want to put different types into it.

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [May 6, 2020, 12:12am UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/6 "2020-05-06T00:12:49Z")

</div>

I know, but it seems that I even cannot have different types into the other structure fields. Notice that my array `x` inside `Workspace` is `Vector{Float64}`. Can it be a bug in Julia?

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [May 6, 2020, 12:33am UTC](https://discourse.julialang.org/t/help-to-remove-type-instability-when-using-getproperty/38849/7 "2020-05-06T00:33:39Z")

</div>

I found a way!

```julia
mutable struct Workspace{T}
    x::Vector{T}
    eclipse::Bool
    s_i::Vector{T}
    s_b::Vector{T}
end

# Functions to translate the state-vector into variables.
@inline Base.getproperty(a::Workspace, f::Symbol) = getindex(a, Val(f))
@inline Base.getindex(a::Workspace, s::Val) = __getindex(a,s)
@inline __getindex(a::Workspace, ::Val{:JD}) = getfield(a,:x)[1]
@inline __getindex(a::Workspace, ::Val{:w}) = view(getfield(a,:x), 2:4)
@inline __getindex(a::Workspace, ::Val{F}) where F = getfield(a,F)

```

No type instabilities 🙂 Thanks @ChrisRackauckas
