The test
call was simple enough to inline, resulting in the getindex
call being directly in outer_test
. tup
’s type only contains Int
or Float64
, so the compiler can infer that an inlined getindex
only returns a Int
or Float64
. Hypothetically the compiler could’ve leveraged the niche detail that rand((1,2))
only selects the indices with Int
, but the compiler evidently doesn’t go that far. On the other hand, if the tuple contained 4+ types, the getindex
return type is inferred as Any
. You can see the effect directly in the getindex
call:
julia> @code_warntype getindex((10, 100, 1., 2., 3.), 2)
MethodInstance for getindex(::Tuple{Int64, Int64, Float64, Float64, Float64}, ::Int64)
from getindex(t::Tuple, i::Int64) @ Base tuple.jl:31
Arguments
#self#::Core.Const(getindex)
t::Tuple{Int64, Int64, Float64, Float64, Float64}
i::Int64
Body::Union{Float64, Int64}
1 ─ nothing
│ %2 = Base.getfield(t, i, $(Expr(:boundscheck)))::Union{Float64, Int64}
└── return %2
julia> @code_warntype getindex((10, 100im, 1., 2.0im, 3.), 2)
MethodInstance for getindex(::Tuple{Int64, Complex{Int64}, Float64, ComplexF64, Float64}, ::Int64)
from getindex(t::Tuple, i::Int64) @ Base tuple.jl:31
Arguments
#self#::Core.Const(getindex)
t::Tuple{Int64, Complex{Int64}, Float64, ComplexF64, Float64}
i::Int64
Body::Any
1 ─ nothing
│ %2 = Base.getfield(t, i, $(Expr(:boundscheck)))::Any
└── return %2
If your index isn’t a literal or a constant, limiting the number of types in the tuple to 3 (a limit that can change across minor revisions) is the best you can hope for. To @time
this properly, you’d need a global variable to hold the index instead of inputting a literal, otherwise the compiler knows the exact index and type, making the type inference report above irrelevant. Note that this specialization over the literal or constant value rather than its type Int
is not a general feature, the compiler treats the underlying built-in function Core.getfield
specially.
julia> @time getindex((10, 100, 1., 2., 3.), 2);
0.000001 seconds
julia> @time getindex((10, 100im, 1., 2.0im, 3.), 2);
0.000004 seconds
julia> i::Int = 2;
julia> @time getindex((10, 100, 1., 2., 3.), i);
0.000009 seconds
julia> @time getindex((10, 100im, 1., 2.0im, 3.), i);
0.000014 seconds (1 allocation: 32 bytes)