Bounds checking removal

I am trying to provide @inbounds functionality for a custom type.

After reading the docs, I have experimented with various combinations of checkbounds with @inline and @propagate_inbounds. But still I can’t seem to get it to work, and I have a feeling I’m doing something quite stupid.

Why in the example below, doesn’t @inbounds A[2] work as expected?
(It returns nothing)

# Julia v0.6.0

struct MyType end

#Base.checkbounds(A::MyType, i::Integer) = println("checking bounds ...")
Base.checkbounds(A::MyType, i::Integer) = i < 0 && throw(BoundsError(A, i))

@inline function Base.getindex(A::MyType, i::Integer)
    @boundscheck checkbounds(A, i)
    return 17
end

A = MyType()
A[2]
@inbounds A[2]

  1. @inbounds gives the compiler the freedom to remove the bound check. There’s no guarantee that it’ll actually do it. In particular, it’s not done in global scope where inlining is disabled.
  2. @inbounds return nothing now but might change later.
1 Like

Thank you Yichao.

yasm (Yet Another Stupid Mistake)

For the record, here’s a modified example showing @inbounds working as expected.

struct MyType end

Base.checkbounds(A::MyType, i::Integer) = println("checking bounds ...")

function Base.getindex(A::MyType, i::Integer)
    @boundscheck checkbounds(A, i)
    return 17
end

function f(A::MyType)
    s = 0
    for i in 1:10
        s += A[i]
    end
    return s
end

function g(A::MyType)
    s = 0
    for i in 1:10
        @inbounds s += A[i]
    end
    return s
end

A = MyType()
f(A)    # performs bounds checking
g(A)   # does not perform bounds checking