Consider the following functions:
@inline function f1(n)
@boundscheck n == 0 && error("zero")
n
end
@inline function f2(n; m = 0)
@boundscheck n == 0 && error("zero")
n+m
end
g1(n) = @inbounds f1(n)
g2(n) = @inbounds f2(n)
g3(n) = @inbounds f2(n; m = 0)
I thought that g1(0)
, g2(0)
and g3(0)
would all return 0
. However,
julia> g1(0)
0
julia> g2(0)
ERROR: zero
julia> g3(0)
ERROR: zero
Is this a bug, or am I missing anything here? I couldn’t find anything in the documentation suggesting that @inbounds
doesn’t work for functions with keyword arguments.
I think @inline
is not sufficient to ellide the boundchecks. Try with @propagate_inbounds
instead.
1 Like
Yes, with @propagate_inbounds
I get g2(0) == g3(0) == 0
. But at the same time, this applies @inbounds
to all functions called in f2
. This may not be desired. Example: Keep g1
, g2
and g3
and define
@inline function f0(n)
@boundscheck n == 0 && error("zero")
n
end
@inline function f1(n)
@boundscheck n == 0 && error("zero")
f0(n)
end
Base.@propagate_inbounds function f2(n; m = 0)
@boundscheck n == 0 && error("zero")
f0(n+m)
end
Now
julia> g1(0)
ERROR: zero
julia> g2(0)
0
I think there should be a way to disable bounds checking in f2
without disabling it in all functions called from f2
. In this sense, I’m still asking myself whether the current behavior is intended or a bug.
I think this is effectively Functions with default arguments with `@boundscheck` can be confusing · Issue #30411 · JuliaLang/julia · GitHub — @inbounds
only propagates through one function call but kwargs (and default positional args) are implemented with two function calls.
4 Likes
Yes, that explains it. Since the issue you referenced is still open, I wonder what the developers are planning. Wouldn’t the problem disappear if the compiler automatically added @propagate_inbounds
to every additional function it needs to handle keyword and default arguments?