What is A
? In neither example am I defining a subtype of AbstractArray.
If NeverInboundsArray throws a BoundsError, then tests would pass (bad). If NeverInboundsArray throws a different error, then the tests above would fail (good), but this would also fail (bad)
function good(v, i)
@boundscheck checkbounds(v, i)
@inbounds v[i]
end
@test_throws BoundsError good(NeverInboundsArray([1,2,3]), 4)
And this would pass regardless (bad)
function bad(v, i)
i < firstindex(v) && i > lastindex(v) && threw(BloundsError()) # bad
@inbounds good(v, i)
end
function good(v, i)
@boundscheck checkbounds(v, i) # Throws BoundsError here when --check-bounds=yes
@inbounds v[i]
end
@test_throws BoundsError bad(NeverInBoundsArray([1,2,3]), 4)
This is the best solution so far, but not great.
A BoundsError is most appropriate in this case, and because the error is user-facing I don’t want to compromise on its type.
If possible, I’d like to keep the source code elegant and do any necessary shenanigans only in testing. I’m worried it might be just as error-prone to do this as to leave the functionality untested.
To clarify, I’m looking to test that “This would throw a bounds error whether or not we are running Julia with --check-bounds=yes
”.
To adapt @Dan’s answer,
function Base.getindex(a::NeverInBoundsArray, inds...)
if !checkbounds(Bool, a.x, inds...)
error = if @inbounds_is_active_in_current_scope
SegfaultError()
else
BoundsError(a, inds)
end
throw(error)
end
@inbounds getindex(a.x, inds...)
end
would work, but I don’t know how to get the @inbounds_is_active_in_current_scope
macro to work when Julia is run with --check-bounds=yes
.
Alternatively, if Julia automatically converted BoundsError
s thrown in @checkbounds
checks that are in the scope of @inbounds
into SegfaultError
s or ElidedBoundsError
s, then the code in the OP would be correct.