Custom vector type causes runtime dispatch when used as view slicing indices

In my code there’s a custom vector type (SkipVec) that is used for indexing a matrix with @view. I recently realized (due to JET.jl) that it seems to cause runtime dispatch for some reason: src/SkipVectors.jl · main · Neven Sajko / FindMinimaxPolynomial.jl · GitLab

struct SkipVec{E <: Any, V <: AbstractVector{E}} <: AbstractVector{E}

  function SkipVec(v::V, i::Int) where {E <: Any, V <: AbstractVector{E}}
    (length(v) < 1) && error("vec too small")
    (i ∈ axes(v, 1)) || error("index out of bounds")
    new{E, V}(v, i)

Base.size(s::SkipVec) = (length(s.v) - 1,)

Base.IndexStyle(::Type{<:SkipVec}) = IndexLinear()

Base.getindex(s::SkipVec, i::Int) =
  (i < s.skip_index) ? s.v[i] : s.v[i + 1]

I realized that the type shouldn’t have a Base.axes method as it only supports one-based indexing, but removing that method definition just produces more JET.jl noise.

The motivation for creating the type is needing to compute some minors of a matrix, so the type comes in handy in an expression like this: det(@view matrix[indices1, indices2]), where both indices1 and indices2 are SkipVec. For example:

using JET, LinearAlgebra

matrix = rand(Float64, 4, 4)
inds1 = SkipVec(1:4, 3) 
inds2 = SkipVec(1:4, 2) 
d = det(@view matrix[inds1, inds2])
@report_opt det(@view matrix[inds1, inds2])

How to fix SkipVec?