Earlier quoted context omitted.
I don't think that's always possible in practice: consider Vec , whose size is only known at runtime. A Vec 's iterator can only do runtime bounds checking to avoid walking past the end. That said, this is unavoidable in C/C++ too.
I think we're suffering from some fuzziness about what bounds checks we're referring to. Even in your example, you only need to check the size of the Vec when you instantiate the iterator, not each time the iterator accesses an element, because at the time the iterator over the Vec 's contents is instantiated, the Vec 's size is known, and it can't change over the life of the iterator (because mutation is disallowed…
let mut it = vec.iter();
println!(it.next());
println!(it.next());
println!(it.next());
This needs to do bounds checking on each call to next() to either return Some(a) or None (assuming the length of vec is unknown at compile time). (hhttps://doc.rust-lang.org/beta/src/core/slice/iter/macros.rs....)You are right that theoretically a range-based for loop that uses iterators does not need to do bounds checking because a compiler can infer the invariant that the iterator is always valid. In practice I don't know enough about LLVM or rustc to know whether this optimization is actually happening.