-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Description
This kind of function, where @inbounds
affects the value returned, used to be inferred as consistent in v1.10, but is not in v1.11 and above:
julia> function f()
@boundscheck return true
false
end
f (generic function with 1 method)
julia> Base.infer_effects(f, Tuple{})
(!c,+e,+n,+t,+s,+m,+u,+o,+r)
Given that it's not consistent any more, should that pattern be avoided?
More specifically, things like this are relatively common:
@boundscheck checkbounds(Bool, A, index) || return false
return additional_error_check(...)
Should the @boundscheck
annotation be removed from code like that, while keeping all error checks, to allow constant folding?
The @boundscheck
doc string also needs to be clarified I think.
Examples of the usage of this pattern in Base
:
EDIT: now I realize consistent
is impossible for most of these anyway.
julia/base/strings/substring.jl
Lines 106 to 110 in 1117df6
function isvalid(s::SubString, i::Integer) | |
ib = true | |
@boundscheck ib = checkbounds(Bool, s, i) | |
@inbounds return ib && isvalid(s.string, s.offset + i)::Bool | |
end |
Lines 106 to 111 in 1117df6
# multi arg case will be overwritten later. This is needed for bootstrapping | |
function isassigned(a::GenericMemory, i::Int) | |
@inline | |
@boundscheck (i - 1)%UInt < length(a)%UInt || return false | |
return @inbounds memoryref_isassigned(memoryref(a, i), default_access_order(a), false) | |
end |
julia/base/permuteddimsarray.jl
Lines 79 to 83 in 1117df6
function Base.isassigned(A::PermutedDimsArray{T,N,perm,iperm}, I::Vararg{Int,N}) where {T,N,perm,iperm} | |
@boundscheck checkbounds(Bool, A, I...) || return false | |
@inbounds x = isassigned(A.parent, genperm(I, iperm)...) | |
x | |
end |
Lines 411 to 428 in 1117df6
function isassigned(V::SubArray{T,N}, I::Vararg{Int,N}) where {T,N} | |
@inline | |
@boundscheck checkbounds(Bool, V, I...) || return false | |
@inbounds r = isassigned(V.parent, reindex(V.indices, I)...) | |
r | |
end | |
function isassigned(V::FastSubArray, i::Int) | |
@inline | |
@boundscheck checkbounds(Bool, V, i) || return false | |
@inbounds r = isassigned(V.parent, _reindexlinear(V, i)) | |
r | |
end | |
function isassigned(V::FastSubArray{<:Any, 1}, i::Int) | |
@inline | |
@boundscheck checkbounds(Bool, V, i) || return false | |
@inbounds r = isassigned(V.parent, _reindexlinear(V, i)) | |
r | |
end |
Lines 237 to 250 in 1117df6
function isassigned(a::Array, i::Int...) | |
@inline | |
@_noub_if_noinbounds_meta | |
@boundscheck checkbounds(Bool, a, i...) || return false | |
ii = _sub2ind(size(a), i...) | |
return @inbounds isassigned(memoryrefnew(a.ref, ii, false)) | |
end | |
function isassigned(a::Vector, i::Int) # slight compiler simplification for the most common case | |
@inline | |
@_noub_if_noinbounds_meta | |
@boundscheck checkbounds(Bool, a, i) || return false | |
return @inbounds isassigned(memoryrefnew(a.ref, i, false)) | |
end |
Lines 280 to 292 in 1117df6
@inline function isassigned(A::ReshapedArrayLF, index::Int) | |
@boundscheck checkbounds(Bool, A, index) || return false | |
indexparent = index - firstindex(A) + firstindex(parent(A)) | |
@inbounds ret = isassigned(parent(A), indexparent) | |
ret | |
end | |
@inline function isassigned(A::ReshapedArray{T,N}, indices::Vararg{Int, N}) where {T,N} | |
@boundscheck checkbounds(Bool, A, indices...) || return false | |
axp = axes(A.parent) | |
i = offset_if_vec(_sub2ind(size(A), indices...), axp) | |
I = ind2sub_rs(axp, A.mi, i) | |
@inbounds isassigned(A.parent, I...) | |
end |
julia/base/multidimensional.jl
Lines 369 to 374 in 1117df6
@propagate_inbounds function isassigned(iter::CartesianIndices{N,R}, I::Vararg{Int, N}) where {N,R} | |
for i in 1:N | |
isassigned(iter.indices[i], I[i]) || return false | |
end | |
return true | |
end |
julia/base/multidimensional.jl
Lines 1627 to 1641 in 1117df6
@generated function isassigned(B::BitArray, I_0::Int, I::Int...) | |
N = length(I) | |
quote | |
@nexprs $N d->(I_d = I[d]) | |
stride = 1 | |
index = I_0 | |
@nexprs $N d->begin | |
l = size(B,d) | |
stride *= l | |
@boundscheck 1 <= I_{d-1} <= l || return false | |
index += (I_d - 1) * stride | |
end | |
return isassigned(B, index) | |
end | |
end |
julia/base/multidimensional.jl
Lines 1647 to 1669 in 1117df6
@inline function isassigned(A::AbstractArray, i::Integer...) | |
# convert to valid indices, checking for Bool | |
inds = to_indices(A, i) | |
@boundscheck checkbounds(Bool, A, inds...) || return false | |
S = IndexStyle(A) | |
ninds = length(inds) | |
if (isa(S, IndexLinear) && ninds != 1) | |
return @inbounds isassigned(A, _to_linear_index(A, inds...)) | |
elseif (!isa(S, IndexLinear) && ninds != ndims(A)) | |
return @inbounds isassigned(A, _to_subscript_indices(A, inds...)...) | |
else | |
try | |
A[inds...] | |
true | |
catch e | |
if isa(e, BoundsError) || isa(e, UndefRefError) | |
return false | |
else | |
rethrow() | |
end | |
end | |
end | |
end |
Lines 1027 to 1030 in 1117df6
function isassigned(v::SimpleVector, i::Int) | |
@boundscheck 1 <= i <= length(v) || return false | |
return true | |
end |