Loop expressions - The Rust Reference

## Keyboard shortcuts

Press `←` or `→` to navigate between chapters

Press `S` or `/` to search in the book

Press `?` to show this help

Press `Esc` to hide this help

[expr.loop]

# Loops and other breakable expressions

[expr.loop.syntax]

Syntax
LoopExpression →
LoopLabel? (
InfiniteLoopExpression
| PredicateLoopExpression
| IteratorLoopExpression
| LabelBlockExpression
)

[expr.loop.intro]

Rust supports four loop expressions:

- A `loop` expression denotes an infinite loop.
- A `while` expression loops until a predicate is false.
- A `for` expression extracts values from an iterator, looping until the iterator is empty.
- A labeled block expression runs a loop exactly once, but allows exiting the loop early with `break`.

[expr.loop.break-label]

All four types of loop support `break` expressions, and labels.

[expr.loop.continue-label]

All except labeled block expressions support `continue` expressions.

[expr.loop.explicit-result]

Only `loop` and labeled block expressions support evaluation to non-trivial values.

[expr.loop.infinite]

## Infinite loops

[expr.loop.infinite.syntax]

Syntax
InfiniteLoopExpression → loop BlockExpression

[expr.loop.infinite.intro]

A `loop` expression repeats execution of its body continuously: `loop { println!("I live."); }`.

[expr.loop.infinite.diverging]

A `loop` expression without an associated `break` expression is diverging and has type `!`.

[expr.loop.infinite.break]

A `loop` expression containing associated `break` expression(s) may terminate, and must have type compatible with the value of the `break` expression(s).

[expr.loop.while]

## Predicate loops

[expr.loop.while.grammar]

Syntax
PredicateLoopExpression → while Conditions BlockExpression

[expr.loop.while.intro]

A `while` loop expression allows repeating the evaluation of a block while a set of conditions remain true.

[expr.loop.while.syntax]

The syntax of a `while` expression is a sequence of one or more condition operands separated by `&&`, followed by a BlockExpression.

[expr.loop.while.condition]

Condition operands must be either an Expression with a boolean type or a conditional `let` match. If all of the condition operands evaluate to `true` and all of the `let` patterns successfully match their scrutinees, then the loop body block executes.

[expr.loop.while.repeat]

After the loop body successfully executes, the condition operands are re-evaluated to determine if the body should be executed again.

[expr.loop.while.exit]

If any condition operand evaluates to `false` or any `let` pattern does not match its scrutinee, the body is not executed and execution continues after the `while` expression.

[expr.loop.while.eval]

A `while` expression evaluates to `()`.

An example:

    #![allow(unused)]
    fn main() {
    let mut i = 0;

    while i < 10 {
        println!("hello");
        i = i + 1;
    }
    }

[expr.loop.while.let]

### `while let` patterns

[expr.loop.while.let.intro]

`let` patterns in a `while` condition allow binding new variables into scope when the pattern matches successfully. The following examples illustrate bindings using `let` patterns:

    #![allow(unused)]
    fn main() {
    let mut x = vec![1, 2, 3];

    while let Some(y) = x.pop() {
        println!("y = {}", y);
    }

    while let _ = 5 {
        println!("Irrefutable patterns are always true");
        break;
    }
    }

[expr.loop.while.let.desugar]

A `while let` loop is equivalent to a `loop` expression containing a `match` expression as follows.

    'label: while let PATS = EXPR {
        /* loop body */
    }

is equivalent to

    'label: loop {
        match EXPR {
            PATS => { /* loop body */ },
            _ => break,
        }
    }

[expr.loop.while.let.or-pattern]

Multiple patterns may be specified with the `|` operator. This has the same semantics as with `|` in `match` expressions:

    #![allow(unused)]
    fn main() {
    let mut vals = vec![2, 3, 1, 2, 2];
    while let Some(v @ 1) | Some(v @ 2) = vals.pop() {
        // Prints 2, 2, then 1
        println!("{}", v);
    }
    }

[expr.loop.while.chains]

### `while` condition chains

[expr.loop.while.chains.intro]

Multiple condition operands can be separated with `&&`. These have the same semantics and restrictions as `if` condition chains.

The following is an example of chaining multiple expressions, mixing `let` bindings and boolean expressions, and with expressions able to reference pattern bindings from previous expressions:

    fn main() {
        let outer_opt = Some(Some(1i32));

        while let Some(inner_opt) = outer_opt
            && let Some(number) = inner_opt
            && number == 1
        {
            println!("Peek a boo");
            break;
        }
    }

[expr.loop.for]

## Iterator loops

[expr.loop.for.syntax]

Syntax
IteratorLoopExpression →
for Pattern in Expressionexcept StructExpression BlockExpression

[expr.loop.for.intro]

A `for` expression is a syntactic construct for looping over elements provided by an implementation of `std::iter::IntoIterator`.

[expr.loop.for.condition]

If the iterator yields a value, that value is matched against the irrefutable pattern, the body of the loop is executed, and then control returns to the head of the `for` loop. If the iterator is empty, the `for` expression completes.

An example of a `for` loop over the contents of an array:

    #![allow(unused)]
    fn main() {
    let v = &["apples", "cake", "coffee"];

    for text in v {
        println!("I like {}.", text);
    }
    }

An example of a for loop over a series of integers:

    #![allow(unused)]
    fn main() {
    let mut sum = 0;
    for n in 1..11 {
        sum += n;
    }
    assert_eq!(sum, 55);
    }

[expr.loop.for.desugar]

A `for` loop is equivalent to a `loop` expression containing a `match` expression as follows:

    'label: for PATTERN in iter_expr {
        /* loop body */
    }

is equivalent to

    {
        let result = match IntoIterator::into_iter(iter_expr) {
            mut iter => 'label: loop {
                let mut next;
                match Iterator::next(&mut iter) {
                    Option::Some(val) => next = val,
                    Option::None => break,
                };
                let PATTERN = next;
                let () = { /* loop body */ };
            },
        };
        result
    }

[expr.loop.for.lang-items]

`IntoIterator`, `Iterator`, and `Option` are always the standard library items here, not whatever those names resolve to in the current scope.

The variable names `next`, `iter`, and `val` are for exposition only, they do not actually have names the user can type.

> Note

> The outer `match` is used to ensure that any temporary values in `iter_expr` don’t get dropped before the loop is finished. `next` is declared before being assigned because it results in types being inferred correctly more often.

[expr.loop.label]

## Loop labels

[expr.loop.label.syntax]

Syntax
LoopLabel → LIFETIME_OR_LABEL :

[expr.loop.label.intro]

A loop expression may optionally have a label. The label is written as a lifetime preceding the loop expression, as in `'foo: loop { break 'foo; }`, `'bar: while false {}`, `'humbug: for _ in 0..0 {}`.

[expr.loop.label.control-flow]

If a label is present, then labeled `break` and `continue` expressions nested within this loop may exit out of this loop or return control to its head. See break expressions and continue expressions.

[expr.loop.label.ref]

Labels follow the hygiene and shadowing rules of local variables. For example, this code will print “outer loop”:

    #![allow(unused)]
    fn main() {
    'a: loop {
        'a: loop {
            break 'a;
        }
        print!("outer loop");
        break 'a;
    }
    }

`'_` is not a valid loop label.

[expr.loop.break]

## `break` expressions

[expr.loop.break.syntax]

Syntax
BreakExpression → break LIFETIME_OR_LABEL? Expression?

[expr.loop.break.intro]

When `break` is encountered, execution of the associated loop body is immediately terminated, for example:

    #![allow(unused)]
    fn main() {
    let mut last = 0;
    for x in 1..100 {
        if x > 12 {
            break;
        }
        last = x;
    }
    assert_eq!(last, 12);
    }

[expr.loop.break.label]

A `break` expression is normally associated with the innermost `loop`, `for` or `while` loop enclosing the `break` expression, but a label can be used to specify which enclosing loop is affected. Example:

    #![allow(unused)]
    fn main() {
    'outer: loop {
        while true {
            break 'outer;
        }
    }
    }

[expr.loop.break.value]

A `break` expression is only permitted in the body of a loop, and has one of the forms `break`, `break 'label` or (see below) `break EXPR` or `break 'label EXPR`.

[expr.loop.block-labels]

## Labeled block expressions

[expr.loop.block-labels.syntax]

Syntax
LabelBlockExpression → BlockExpression

[expr.loop.block-labels.intro]

Labeled block expressions are exactly like block expressions, except that they allow using `break` expressions within the block.

[expr.loop.block-labels.break]

Unlike loops, `break` expressions within a labeled block expression must have a label (i.e. the label is not optional).

[expr.loop.block-labels.label-required]

Similarly, labeled block expressions must begin with a label.

    #![allow(unused)]
    fn main() {
    fn do_thing() {}
    fn condition_not_met() -> bool { true }
    fn do_next_thing() {}
    fn do_last_thing() {}
    let result = 'block: {
        do_thing();
        if condition_not_met() {
            break 'block 1;
        }
        do_next_thing();
        if condition_not_met() {
            break 'block 2;
        }
        do_last_thing();
        3
    };
    }

[expr.loop.continue]

## `continue` expressions

[expr.loop.continue.syntax]

Syntax
ContinueExpression → continue LIFETIME_OR_LABEL?

[expr.loop.continue.intro]

When `continue` is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop head.

[expr.loop.continue.while]

In the case of a `while` loop, the head is the conditional operands controlling the loop.

[expr.loop.continue.for]

In the case of a `for` loop, the head is the call-expression controlling the loop.

[expr.loop.continue.label]

Like `break`, `continue` is normally associated with the innermost enclosing loop, but `continue 'label` may be used to specify the loop affected.

[expr.loop.continue.in-loop-only]

A `continue` expression is only permitted in the body of a loop.

[expr.loop.break-value]

## `break` and loop values

[expr.loop.break-value.intro]

When associated with a `loop`, a break expression may be used to return a value from that loop, via one of the forms `break EXPR` or `break 'label EXPR`, where `EXPR` is an expression whose result is returned from the `loop`. For example:

    #![allow(unused)]
    fn main() {
    let (mut a, mut b) = (1, 1);
    let result = loop {
        if b > 10 {
            break b;
        }
        let c = a + b;
        a = b;
        b = c;
    };
    // first number in Fibonacci sequence over 10:
    assert_eq!(result, 13);
    }

[expr.loop.break-value.loop]

In the case a `loop` has an associated `break`, it is not considered diverging, and the `loop` must have a type compatible with each `break` expression. `break` without an expression is considered identical to `break` with expression `()`.