Good evening,
I have been facing a (slightly) annoying type inference issue when writing a function which returns a tuple.
Here is a minimal working example:
f(v, ::Val{N}) where {N} = ntuple(i -> sum(v[1]), N) # type unstable
g(v, ::Val{N}) where {N} = ntuple(i -> v[1][1], N) # type stable
For instance, set v = [[1,2,3], [4,5,6]]
.
We have:
julia> @code_warntype f(v, Val(3))
Variables
#self#::Core.Compiler.Const(f, false)
v::Array{Array{Int64,1},1}
#unused#::Core.Compiler.Const(Val{3}(), false)
#11::var"#11#12"{Array{Array{Int64,1},1}}
Body::Tuple{Vararg{Int64,N} where N}
1 ─ %1 = Main.:(var"#11#12")::Core.Compiler.Const(var"#11#12", false)
│ %2 = Core.typeof(v)::Core.Compiler.Const(Array{Array{Int64,1},1}, false)
│ %3 = Core.apply_type(%1, %2)::Core.Compiler.Const(var"#11#12"{Array{Array{Int64,1},1}}, false)
│ (#11 = %new(%3, v))
│ %5 = #11::var"#11#12"{Array{Array{Int64,1},1}}
│ %6 = Main.ntuple(%5, $(Expr(:static_parameter, 1)))::Tuple{Vararg{Int64,N} where N}
└── return %6
However, g
is type stable:
julia> @code_warntype g(v, Val(3))
Variables
#self#::Core.Compiler.Const(g, false)
v::Array{Array{Int64,1},1}
#unused#::Core.Compiler.Const(Val{3}(), false)
#9::var"#9#10"{Array{Array{Int64,1},1}}
Body::Tuple{Int64,Int64,Int64}
1 ─ %1 = Main.:(var"#9#10")::Core.Compiler.Const(var"#9#10", false)
│ %2 = Core.typeof(v)::Core.Compiler.Const(Array{Array{Int64,1},1}, false)
│ %3 = Core.apply_type(%1, %2)::Core.Compiler.Const(var"#9#10"{Array{Array{Int64,1},1}}, false)
│ (#9 = %new(%3, v))
│ %5 = #9::var"#9#10"{Array{Array{Int64,1},1}}
│ %6 = Main.ntuple(%5, $(Expr(:static_parameter, 1)))::Tuple{Int64,Int64,Int64}
└── return %6
In my code, the needed tuple is used in a loop so I resolved this type instability via function barrier.
Although, why the compiler could not find out the length of the tuple returned by f
? Indeed, it knows what sum
does and the length N
is given as a type.
EDIT: I should mention that I am using Julia 1.5.2. Moreover, in case this relates, the function
h(v::Vector{Vector{Int}}) = ntuple(i -> sum(v[1]), 3)
is also type unstable.