Hi there,
I have a piece of code that is sometimes type-stable, sometimes not, and can’t understand why… I’ve been scratching my head on this for a while, a fresh look would be very much appreciated…
I’ve boiled it down to the following MWE: given
-
args
: a tuple that containsInt
s or<:AbstractVector{Int}
; -
inds
: a tuple that also contains onlyInt
s or<:AbstractVector{Int}
, whose length that matches the number of<:AbstractVector{Int}
elements ofargs
.
The following code should apply getindex
to each non-Int
element of args
with the corresponding inds
.
using Base: tail, OneTo
getindices(res, ::Tuple{}, ::Tuple{}) = res
getindices(res, args::Tuple{Int,Vararg}, inds) =
getindices((res..., first(args)), tail(args), inds)
getindices(res, args::Tuple{AbstractVector{Int},Vararg}, inds) =
getindices((res..., getindex(first(args), first(inds))), tail(args), tail(inds))
Sometimes it’s type stable
julia> args = (1, 2, OneTo(3), 4:5);
julia> inds = (2:3, 1);
julia> @code_warntype getindices((), args, inds)
MethodInstance for getindices(::Tuple{}, ::Tuple{Int64, Int64, OneTo{Int64}, UnitRange{Int64}}, ::Tuple{UnitRange{Int64}, Int64})
from getindices(res, args::Tuple{Int64, Vararg}, inds) @ Main ~/.julia/dev/minimal.jl:5
Arguments
#self#::Core.Const(getindices)
res::Core.Const(())
args::Tuple{Int64, Int64, OneTo{Int64}, UnitRange{Int64}}
inds::Tuple{UnitRange{Int64}, Int64}
Body::Tuple{Int64, Int64, UnitRange{Int64}, Int64}
1 ─ %1 = Main.first(args)::Int64
│ %2 = Core.tuple(%1)::Tuple{Int64}
│ %3 = Core._apply_iterate(Base.iterate, Core.tuple, res, %2)::Tuple{Int64}
│ %4 = Main.tail(args)::Tuple{Int64, OneTo{Int64}, UnitRange{Int64}}
│ %5 = Main.getindices(%3, %4, inds)::Tuple{Int64, Int64, UnitRange{Int64}, Int64}
└── return %5
args = (1, 2, 3, OneTo(5), -1, OneTo(6))
inds = (1, 2)
But other times it’s not
julia> args = (1, 2, 3, OneTo(5), -1, OneTo(6));
julia> inds = (1, 2:3);
julia> @code_warntype getindices((), args, inds)
MethodInstance for getindices(::Tuple{}, ::Tuple{Int64, Int64, Int64, OneTo{Int64}, Int64, OneTo{Int64}}, ::Tuple{Int64, UnitRange{Int64}})
from getindices(res, args::Tuple{Int64, Vararg}, inds) @ Main ~/.julia/dev/ProductSandbox/minimal.jl:5
Arguments
#self#::Core.Const(getindices)
res::Core.Const(())
args::Tuple{Int64, Int64, Int64, OneTo{Int64}, Int64, OneTo{Int64}}
inds::Tuple{Int64, UnitRange{Int64}}
Body::Tuple
1 ─ %1 = Main.first(args)::Int64
│ %2 = Core.tuple(%1)::Tuple{Int64}
│ %3 = Core._apply_iterate(Base.iterate, Core.tuple, res, %2)::Tuple{Int64}
│ %4 = Main.tail(args)::Tuple{Int64, Int64, OneTo{Int64}, Int64, OneTo{Int64}}
│ %5 = Main.getindices(%3, %4, inds)::Tuple
└── return %5
I’ve tried different versions of Julia (include 1.9.0-beta2), the results are the same… Thanks in advance for any tip to help me solve this!