For now, this reference is a best-effort document. We strive for validity and completeness, but are not yet there. In the future, the docs and lang teams will work together to figure out how best to do this. Until then, this is a best-effort attempt. If you find something wrong or missing, file an issue or send in a pull request.

Loops

Syntax
LoopExpression :
   LoopLabel? (
         InfiniteLoopExpression
      | PredicateLoopExpression
      | PredicatePatternLoopExpression
      | IteratorLoopExpression
   )

Rust supports four loop expressions:

All four types of loop support break expressions, continue expressions, and labels. Only loop supports evaluation to non-trivial values.

Infinite loops

Syntax
InfiniteLoopExpression :
   loop BlockExpression

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

A loop expression without an associated break expression is diverging and has type !. A loop expression containing associated break expression(s) may terminate, and must have type compatible with the value of the break expression(s).

Predicate loops

Syntax
PredicateLoopExpression :
   while Expressionexcept struct expression BlockExpression

A while loop begins by evaluating the boolean loop conditional expression. If the loop conditional expression evaluates to true, the loop body block executes, then control returns to the loop conditional expression. If the loop conditional expression evaluates to false, the while expression completes.

An example:


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

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

Predicate pattern loops

Syntax
PredicatePatternLoopExpression :
   while let Pattern = Expressionexcept struct expression BlockExpression

A while let loop is semantically similar to a while loop but in place of a condition expression it expects the keyword let followed by a refutable pattern, an =, an expression and a block expression. If the value of the expression on the right hand side of the = matches the pattern, the loop body block executes then control returns to the pattern matching statement. Otherwise, the while expression completes.


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

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

Iterator loops

Syntax
IteratorLoopExpression :
   for Pattern in Expressionexcept struct expression BlockExpression

A for expression is a syntactic construct for looping over elements provided by an implementation of std::iter::IntoIterator. If the iterator yields a value, that value is given the specified name and the body of the loop is executed, 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_variables)]
#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_variables)]
#fn main() {
let mut sum = 0;
for n in 1..11 {
    sum += n;
}
assert_eq!(sum, 55);
#}

Loop labels

Syntax
LoopLabel :
   LIFETIME_OR_LABEL :

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 {}. 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.

break expressions

Syntax
BreakExpression :
   break LIFETIME_OR_LABEL? Expression?

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


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

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_variables)]
#fn main() {
'outer: loop {
    while true {
        break 'outer;
    }
}
#}

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.

continue expressions

Syntax
ContinueExpression :
   continue LIFETIME_OR_LABEL?

When continue is encountered, the current iteration of the associated loop body is immediately terminated, returning control to the loop head. In the case of a while loop, the head is the conditional expression controlling the loop. In the case of a for loop, the head is the call-expression controlling the loop.

Like break, continue is normally associated with the innermost enclosing loop, but continue 'label may be used to specify the loop affected. A continue expression is only permitted in the body of a loop.

break and loop values

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_variables)]
#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);
#}

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 ().