Inferring the type of a field of a type

I noticed that Julia cannot infer the type of fields in user-defined types. Is that a bug or a feature?

struct MyType1{T<:Real}
    x::Vector{T}
end

function foo{T<:Real}(y::MyType1{T})
    a = y.x
end

yy = MyType1(zeros(5))

Then the type of yy.x cannot be inferred.

julia> @code_warntype(foo(yy))
Variables:
  #self#::#foo
  y::MyType1{Float64}
  a::ANY

Body:
  begin 
      SSAValue(0) = (Core.getfield)(y::MyType1{Float64}, :x)::Array{Float64,1}
      return SSAValue(0)
  end::Array{Float64,1}
julia> versioninfo()
Julia Version 0.6.0-pre.beta.68
Commit e5e365c* (2017-04-07 18:50 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin15.5.0)
  CPU: Intel(R) Core(TM)2 Duo CPU     P8600  @ 2.40GHz
  WORD_SIZE: 64
  BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Penryn)
  LAPACK: libopenblas64_
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, penryn)

the same thing happens on latest master. It worked well on 0.5.

That’s weird, it shows a::Array{Float64,1} in Julia 0.5, and in 0.6 I get a::ANY like you but the return type of the function is correctly inferred as Array{Float64,1}.

I think this may be just a bug in @code_warntype, and inference is actually working. If you actually do something with the a variable, it works fine:

julia> function bar{T<:Real}(y::MyType1{T})
                  a = y.x
                  return a + 1
       end
bar (generic function with 1 method)

julia> @code_warntype bar(yy)
Variables:
  #self#::#bar
  y::MyType1{Float64}
  a::Array{Float64,1}

Body:
  begin 
      a::Array{Float64,1} = (Core.getfield)(y::MyType1{Float64}, :x)::Array{Float64,1} # line 3:
      return $(Expr(:invoke, MethodInstance for +(::Array{Float64,1}, ::Int64), :(Main.+), :(a), 1))
  end::Array{Float64,1}

a is unused so there is no need to infer it. It’s already been optimized out.

https://github.com/JuliaLang/julia/issues/20801

3 Likes