Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The for loop in Rust is an iteration construct that executes a block of code for each element yielded by an iterator. It operates as syntactic sugar for an infinite loop that continuously invokes the next method on an Iterator trait implementation, automatically matching on the Option::None variant to safely terminate execution.
fn main() {
    let iterable = [1, 2, 3];
    
    for pattern in iterable {
        println!("{}", pattern);
    }
}

Trait Mechanics

The for loop strictly requires the iterable expression to implement the IntoIterator trait. Upon initialization, the compiler implicitly invokes IntoIterator::into_iter(iterable) to construct the underlying iterator. During each iteration, the loop evaluates Iterator::next(). If the method returns Some(value), the value is destructured or bound to the specified pattern, and the loop body executes. If it returns None, the loop terminates.

Desugared Representation

To understand the exact control flow and lifetime semantics, a standard for loop translates to a lower-level match expression during compilation. Using a match block rather than a let binding is a critical semantic distinction: it safely extends the lifetime of any temporary values evaluated in the iterator expression for the entire duration of the loop. This prevents borrow checker errors that would occur if a temporary were dropped at the end of a standard let statement.
fn main() {
    let iterable = vec![1, 2, 3];

    // Standard for loop
    for val in iterable.clone() {
        println!("{}", val);
    }

    // Desugared equivalent
    match IntoIterator::into_iter(iterable) {
        mut iter => loop {
            match iter.next() {
                Some(val) => {
                    println!("{}", val);
                },
                None => break,
            }
        }
    }
}

Ownership and Borrowing Semantics

Because the for loop consumes the iterator via into_iter(), the ownership state of the yielded elements is dictated by the reference type of the iterable provided:
  • By Value (iterable): Consumes the collection. IntoIterator yields owned values (T). The original collection is moved and becomes inaccessible after the loop.
  • By Immutable Reference (&iterable): Borrows the collection. IntoIterator yields immutable references (&T). This is semantically equivalent to calling .iter().
  • By Mutable Reference (&mut iterable): Mutably borrows the collection. IntoIterator yields mutable references (&mut T). This is semantically equivalent to calling .iter_mut().
fn main() {
    let mut collection = vec![1, 2, 3];

    // Yields &T (Borrows collection)
    for val in &collection {
        println!("Read-only: {}", val);
    }

    // Yields &mut T (Mutably borrows collection)
    for val in &mut collection {
        *val += 1;
    }

    // Yields T (Moves collection)
    for val in collection {
        println!("Owned: {}", val);
    }
    // 'collection' is no longer accessible here
}

Control Flow Modifiers

The execution of a for loop can be manually altered using standard control flow keywords:
  • continue: Bypasses the remaining statements in the current iteration block and immediately evaluates the next Iterator::next() call.
  • break: Immediately halts the loop, dropping the iterator. Unlike the loop construct, break inside a for loop cannot return a value; a for loop always evaluates to the unit type ().

Loop Labels

For nested iteration, for loops can be annotated with lifetime-like labels. This allows break and continue statements to target specific outer loops rather than the immediate enclosing loop.
struct Element {
    value: i32,
}

impl Element {
    fn is_invalid(&self) -> bool {
        self.value < 0
    }
}

fn main() {
    let matrix = vec![
        vec![Element { value: 1 }, Element { value: 2 }],
        vec![Element { value: -1 }, Element { value: 3 }],
        vec![Element { value: 4 }, Element { value: 5 }],
    ];

    'outer: for x in &matrix {
        for y in x {
            if y.is_invalid() {
                println!("Invalid element found, skipping row.");
                continue 'outer;
            }
            println!("Processing: {}", y.value);
        }
    }
}
Master Rust with Deep Grasping Methodology!Learn More