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.