Getter function of `Ref` field not inferred

bug
inference

#1

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?


#2

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.


#3

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?


#4

You can always define something like:

to make your own RefValue.


#5

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)


#6

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.