Warntype_last() outputs red ::Ref{Float64}

Unfortunately, I have not managed to create an MVE, but I think I can ask a good question:

I use a Ref to make a Float64 mutable within a struct. Using a mutable struct arguably makes more sense, and resolves my issue, I checked, but I want to learn. This part of a larger code

struct OUTstaticX{Tλ,Tλx} 
    Lλ    :: Tλ
    Lλx   :: Tλx 
    α     :: Ref{Float64}
out.α[]    = min(out.α[],α)

run with Profile and examined with warntype_last() outputs

│   %26 = Base.getproperty(out, :α)::Ref{Float64} # the type is typeset in red!!!
│   %27 = Base.getindex(%26)::Any

where ::Ref{Float64} is typeset in red. This puzzles my neuron:

  1. I assume that warntype_last() wraps @code_warntype, and that the later uses red to emphasize variables resolved to an abstract type by the compiler. Yet Ref{Float64} is a concrete type. Under what conditions can my assumption be wrong?
  2. How can a Ref{Float64} dereference to Any?
    …and I am sure both surprises are related.
1 Like

The surprise is here:

julia> isconcretetype(Ref{Float64})

And indeed

julia> subtypes(Ref)
6-element Vector{Any}:

You were probably meant to annotate the field as Base.RefValue instead of Ref:

julia> typeof(Ref(1))

Spot on!

I actually had to type isconcretetype(Ref{Float64}) to check what you said :laughing:. I dare say the manual should be specific on which types that it describes are abstract or concrete.

Annoting the field in my struct as Base.RefValue{Int64} indeed makes the code typestable. :sunglasses: :sunny:

Hjertelig tusen takk!


You may also consider making your struct mutable, and then annotate the non-changing fields const. I’d argue it’s more idiomatic, although that may incur a performance pentalty in some situations.

1 Like

That’s how I actually fixed my code… But it was worth asking: understanding that Ref{X} is always abstract is important.

1 Like