Iterators do indeed not force the removal of bounds check, but that's simply because they don't exist to remove in the first place. That's because iterators actually do use `unsafe` internally. They are a safe abstraction.
// This is unidiomatic. Don't do this.
for i in 0..100 {
// Oops! Array indexing. Here's a nasty bounds check!
array[i] * 2
}
// Very unidiomatic. Never do this! Not even as an
// optimization. You should properly use safe abstractions
// in stead.
for i in 1..100 {
// Oh, NOOOO! This isn't supposed to be C!
unsafe { array.get_unchecked(i) * 2 }
}
// This is still unidiomatic unless you want to use
// it to explicitly show your code has side-effects.
// However, we're completely rid of the bounds check and
// yet it's perfectly safe perfectly safe.
// The only way this could be unsafe is if rustbelt's
// formal proofs, reviews, audits
// and (probably) MLOC of thoroughly tested and
// possibly fuzzed code using this in practice
// have all somehow missed an unsoundness bug
// in one of the more used safe abstractions in the
// core library for years.
for a in array {
// Look, Ma! No indexing, therefore no bounds check!
// Internally `get_unchecked` is (conceptually) used
// but it's perfectly safe!
a * 2
}
// This is idiomatic Rust. Again, there's no bounds check
// to start with, since the save abstraction knows
// exactly how many elements are in the array and
// that the borrow checker will ensure nobody can
// possibly invalidate its indexing.
// Ditto what was said above that the safe abstraction
// is pretty much guaranteed to be sound.
a.iter().map(|a| a * 2).collect()