Getter function of `Ref` field not inferred

Using Ref{T} to get a mutable field in an otherwise immutable struct is causing inference problems (Julia v1.03/v1.1.0), MWE:

using Test
struct A
    i::Ref{Int}
end
get_i(x) = x.i[]
@inferred get_i(A(2)) # ERROR: return type Int64 does not match inferred return type Any

Should I file an issue or is there more idiomatic way to do this?

The issue is

julia> isabstracttype(Ref)
true

julia> typeof(Ref(3))
Base.RefValue{Int64}

If you change your definition to

struct A
    i::Base.RefValue{Int}
end

then you’ll find it’s inferred.

2 Likes

Thank you!

Silly me I just took for granted that Ref{T} is concrete.

For the curious: try subtypes(Ref), dump(Ref(1)), dump(Ref([1,2],1)) to find out more.

Since RefValue is undocumented now I guess breaking it in future 1.x releases is possible?

1 Like

You can always define something like:

to make your own RefValue.

Since adding indirection is rather slow anyways, it hasn’t been of much important to optimize this. Doing mutable struct A should have much better performance that defining struct A and declaring some of the fields to be pointers, even if those pointers are concretely typed (with ScalarWrapper or RefValue or the like)

Ok, but there are reasons other than performance to make fields non-mutable. It might just be semantically correct, and having to disable immutability on all fields is unfortunate.