Rust For Loops

Rust's for loop iterates over anything that implements IntoIterator, from simple numeric ranges to entire collections, without manual indexing or off-by-one bugs.

Iterating Over a Range

A range like 0..5 is half-open and excludes its upper bound, producing 0, 1, 2, 3, 4. Adding an equals sign, as in 0..=5, makes the range inclusive of the final value.

Exclusive vs inclusive ranges

fn main() {
    for i in 0..5 {
        println!("i = {}", i);
    }

    for i in 1..=5 {
        print!("{} ", i);
    }
    println!();
}

Iterating Over Collections

Writing for item in &collection borrows each element by reference, leaving the collection usable afterward. Writing for item in collection (without the &) takes ownership of the collection and consumes it.

Borrowing and enumerating a Vec

fn main() {
    let fruits = vec!["apple", "banana", "cherry"];

    for fruit in &fruits {
        println!("I like {}", fruit);
    }

    for (index, fruit) in fruits.iter().enumerate() {
        println!("{}: {}", index, fruit);
    }
}
Note: Reach for .enumerate() whenever you need both the index and the value inside a loop — it's clearer and less error-prone than maintaining a separate counter variable by hand.

for Loops and Ownership

Note: for item in collection (without &) moves the collection into the loop, so it can't be used again afterward unless its element type is Copy. Default to iterating by reference unless you specifically intend to consume the values.

Reversing and stepping through a range

fn main() {
    for i in (0..10).step_by(2) {
        print!("{} ", i);
    }
    println!();

    for i in (1..=5).rev() {
        print!("{} ", i);
    }
    println!();
}
AdapterEffect
.rev()iterates in reverse order
.step_by(n)skips n - 1 elements between each iteration
.enumerate()pairs each element with its index, starting at 0
.zip(other)pairs up elements from two iterators together
  • Ranges are half-open by default (0..5 excludes 5); add = for an inclusive range (0..=5).
  • for item in &collection borrows; for item in collection takes ownership.
  • Iterator adapters like .rev(), .step_by(), and .enumerate() compose before the loop consumes them.
  • for loops never panic on out-of-bounds access, because they never index manually.

Exercise: Rust For Loops

What does the range `0..5` include when used in `for i in 0..5`?