loop_break_value

The tracking issue for this feature is: #37339

Documentation to be appended to section G of the book.


Loops as expressions

Like most things in Rust, loops are expressions, and have a value; normally () unless the loop never exits. A loop can instead evaluate to a useful value via break with value:

# #![allow(unused_variables)]
#![feature(loop_break_value)]

#fn main() {
// Find the first square number over 1000:
let mut n = 1;
let square = loop {
    if n * n > 1000 {
        break n * n;
    }
    n += 1;
};

#}

The evaluation type may be specified externally:

# #![allow(unused_variables)]
#![feature(loop_break_value)]

#fn main() {
// Declare that value returned is unsigned 64-bit:
let n: u64 = loop {
    break 1;
};

#}

It is an error if types do not agree, either between a "break" value and an external requirement, or between multiple "break" values:

#![feature(loop_break_value)]

loop {
    if true {
        break 1u32;
    } else {
        break 0u8;  // error: types do not agree
    }
};

let n: i32 = loop {
    break 0u32; // error: type does not agree with external requirement
};

Break: label, value

Four forms of break are available, where EXPR is some expression which evaluates to a value:

  1. break;
  2. break 'label;
  3. break EXPR;
  4. break 'label EXPR;

When no value is given, the value () is assumed, thus break; is equivalent to break ();.

Using a label allows returning a value from an inner loop:

# #![allow(unused_variables)]
#![feature(loop_break_value)]

#fn main() {
let result = 'outer: loop {
    for n in 1..10 {
        if n > 4 {
            break 'outer n;
        }
    }
};

#}