Presumably you could write a macro to do this for you. For example,
using MacroTools: @capture, postwalk
function add_inbounds_everywhere(ex)
postwalk(ex) do x
@capture(x, a_[b__]) || return x
return :(@inbounds $x)
end
end
macro add_inbounds_everywhere(ex)
return add_inbounds_everywhere(ex)
end
Of course, it’s not quite as easy as you only want to add @inbounds on getindex, not on setindex!, e.g. you don’t want to end up with @inbounds(x[1]) = 0. So you need corrections like:
function move_assignment_inbounds(ex)
return postwalk(ex) do x
@capture(x, @inbounds(a_[b__]) = c__) || return x
return :(@inbounds($a[$(b...)] = $(c...)))
end
end
function move_broadcasted_assignment_inbounds(ex)
return postwalk(ex) do x
@capture(x, @inbounds(a_[b__]) .= c__) || return x
return :(@inbounds($a[$(b...)] .= $(c...)))
end
end
function move_view_in_front_of_inbounds(ex)
return postwalk(ex) do x
@capture(x, @view(@inbounds(a_))) || return x
return :(@inbounds(@view($a)))
end
end
carefully_add_inbounds = move_view_in_front_of_inbounds ∘ move_broadcasted_assignment_inbounds ∘ move_assignment_inbounds ∘ add_inbounds_everywhere
Presumably there are plenty of cases still missing, but if you
include(carefully_add_inbounds, "script.jl")
for a file script.jl containing
function f(x)
x[4] = -100
sum(x[i] for i = 1:4)
# Note that @inbounds sum(x[i] for i = 1:4) would not work;
# you need sum(@inbounds x[i] for i = 1:4).
end
println(f(rand(3)))
function g(x, y)
x[1:5] .= @view y[1:5]
end
g(zeros(4), rand(10))
you get something like
-99.202880576623
5-element view(::Vector{Float64}, 1:5) with eltype Float64:
0.1550523932721809
0.16183646229915816
0.6185234401813514
0.6716336573001286
0.12471934509214788
as output, without BoundsErrors.