Julia allows to access the last index in the axis of an array using the end keyword by lowering it to lastindex in a rather predictable way:
A = rand(5, 5, 2)
A[1:end - 1, end ÷ 2, :] # lowers to A[1:lastindex(A, 1) - 1, lastindex(A, 2) ÷ 2, :]
This silently assumes that all indices are one-dimensional, which leads to extremely sneaky errors
mask = rand(5, 5) .> 0.5
A[mask, end] # BoundsError, because `end` lowers to `lastindex(A, 2)` == 5
Now, this is likely a known issue, it is even raised in the docs, though only for CartesianIndex. However, since these types of errors are silent (so if A had shape (5, 5, 10) by sheer bad luck, I would have gotten wrong results without any error), so I believe we can’t just leave it this way.
Probably a good idea is update the docs to make more emphasis on this issue: make the warning message brighter and move it to the part where the end keyword is introduced. Another idea is changing how code like this is lowered (and probably implement it in JuliaLowering.jl), I can see how it can be done in two ways:
- Make this behavior throw an error. For example, we can wrap
Ainto a struct likeRequire1DIndexingand override itsgetindex/setindexto check if all indices are one-dimensional. - Check the dimensionality of each index on the lowering stage: create a local variable
index_dim::Int = 1, then take the first index and replaceendwithlastindex(A, index_dim), then increaseindex_dimby the dimensionality of the first index, rinse, repeat.
Which is the better way to solve it here?