It's hard to say exactly, since the question is nuanced even for bounds checks. Is bounds checking a cost "of Rust" when, say, C++'s vector::at has the same check as Rust's Vec::index?
The best way is to assert! your preconditions so that the compiler has more information.
pub fn demo3(x: &[i32]) -> i32 {
let x = &x[..3];
x[0] + x[1] + x[2]
}
Optimizers are really powerful, and what may look like "more work" can actually be faster if it tells them useful things.
(The reason it can't optimize the first one more is that the panic message for indexing includes the out-of-bounds index, so it needs all the checks to show the "correct" index. The others check a condition that encapsulates the individual index checks, so the optimizer knows those will never fail and can remove them.)
I didn't see that one coming… Not that scottmcm's demo2 and demo3 shout it out, but at least they feature a line that makes you wonder.
Where it really matters, is there a way to express such performance expectations/considerations in readable code, other than a comment? An attribute maybe?
If it's an implementation detail in one place, you make sure you have a criterion benchmark for the performance of the method, so that people are free to change it, but the benchmarks will notice if what they removed was actually important.
You rewrite it in a way that doesn't actually need to do those checks.
pub fn demo4(x: &[i32]) -> i32 {
if let [a, b, c, ..] = *x {
a + b + c
} else {
panic!("not enough elements")
}
}
which also only does one bounds check. Often this can take the form of rewriting to iterators instead.
If it's something that needs to be more pervasive, then you find a way to encode the necessary information in the type system somehow so it's known later -- like how once you have a &str you don't need to do UTF-8 checks any more.
For example, arrays have known length so often remove bounds checks easier than slices -- here's my favourite example of that one https://rust.godbolt.org/z/3MPGdE8sr.
For the silly demo, you can rephrase the question to "I'd like a 3-element array from the beginning", because indexing that is clearly fine. So that could be something like https://rust.godbolt.org/z/YqbzafMh6, which is also only one bounds check:
to this. The assertion -- which can have a nice meaningful message on failure, not just a context-less "uh, bad index" -- is helpful to both the computers and the humans.