Type instability when indexing

The last example will also become type-unstable if you increase d (and the length of the tuple).

julia> @code_warntype foo3(bar{11}(),(1,2,3,4,5,6,7,8,9,0,1,2))
Variables
  #self#::Core.Const(foo3)
  a::Core.Const(bar{11}())
  x::NTuple{12, Int64}
  #1::var"#1#2"{NTuple{12, Int64}}

Body::Tuple{Vararg{Int64, N} where N}
1 ─ %1 = Main.:(var"#1#2")::Core.Const(var"#1#2")
│   %2 = Core.typeof(x)::Core.Const(NTuple{12, Int64})
│   %3 = Core.apply_type(%1, %2)::Core.Const(var"#1#2"{NTuple{12, Int64}})
│        (#1 = %new(%3, x))
│   %5 = #1::var"#1#2"{NTuple{12, Int64}}
│   %6 = Main.ntuple(%5, $(Expr(:static_parameter, 1)))::Tuple{Vararg{Int64, N} where N}
└──      return %6

The first example is type-stable while the other one is not since it’s handled differently in getindex, see https://github.com/JuliaLang/julia/blob/399f8ba175b1add5f8b8286097afd2deaada0a41/base/range.jl#L301-L314. Whenever the first and/or last index of the tuple are included in the range, there is a special case. The general case is just more demanding for the compiler. As @bramtayl wrote above, it might be possible to write another version based on recursion (similar to Base.front and Base.tail).

1 Like