Control Flow

while

A while loop repeatedly executes a block of code as long as a boolean condition evaluates to true. The condition is tested before each iteration begins; if the condition is false on the very first check, the loop body does not execute at all.

Basic Syntax and Execution Flow

A while loop consists of the while keyword, a condition expression of type bool (written without outer parentheses), and a brace-enclosed block { ... }:

fn main() {
    let mut countdown = 3;

    while countdown > 0 {
        println!("{countdown}...");
        countdown -= 1;
    }

    println!("Liftoff!");
}
3...
2...
1...
Liftoff!

On each cycle, Rust evaluates the condition first:

               +-----------------------------------+
               |                                   |
               v                                   |
     +--------------------+      false             |
     | Evaluate condition +---------------+        |
     +---------+----------+               |        |
               | true                     |        |
               v                          |        |
     +--------------------+               |        |
     | Execute loop body  +---------------+--------+
     +--------------------+               |
                                          v
                                +--------------------+
                                | Continue after `}` |
                                +--------------------+

If the condition starts out false, the body is skipped completely:

fn main() {
    let mut count = 10;

    while count < 5 {
        println!("This never runs");
        count += 1;
    }

    println!("Done: count = {count}");
}
Done: count = 10

Condition Requirements

Just like if, the condition of a while loop must evaluate to the exact type bool. Rust does not allow integers or pointers as while conditions:

// ❌ does not compile
fn main() {
    let mut remaining = 3;

    while remaining {
        remaining -= 1;
    }
}
error[E0308]: mismatched types
 --> src/main.rs:4:11
  |
4 |     while remaining {
  |           ^^^^^^^^^ expected `bool`, found integer

error: aborting due to 1 previous error

Write while remaining != 0 or while remaining > 0 to express the boolean test explicitly.

Using break and continue Inside while

Although a while loop has a header condition, you can still use break to exit early from the middle of an iteration or continue to jump immediately back to the condition check for the next iteration:

fn main() {
    let mut n = 0;

    while n < 10 {
        n += 1;

        if n % 2 == 0 {
            continue; // Jump back to `while n < 10` check
        }

        if n == 7 {
            println!("Stopping early at {n}");
            break; // Exit the `while` loop immediately
        }

        println!("Processed odd number: {n}");
    }
}
Processed odd number: 1
Processed odd number: 3
Processed odd number: 5
Stopping early at 7

Important: When using continue inside a while loop, make sure the loop variable (n += 1) is updated before the continue statement. If continue executes before the variable update, the condition will test the exact same value forever and cause an infinite loop.

Type of a while Expression (())

Every while loop in Rust evaluates to the unit type (). Unlike loop, a while loop cannot return a value via break value;.

Why? Because a while condition might be false on the first check, causing the loop body—and any break value; inside it—to never run. Since the compiler would have no value to produce when the loop executes zero times, break with a value is forbidden inside while:

// ❌ does not compile
fn main() {
    let mut i = 0;

    let found = while i < 5 {
        if i == 3 {
            break i * 10;
        }
        i += 1;
    };
}
error[E0571]: `break` with value from a `while` loop
 --> src/main.rs:6:13
  |
4 |     let found = while i < 5 {
  |                 ----------- you can't `break` with a value in a `while` loop
5 |         if i == 3 {
6 |             break i * 10;
  |             ^^^^^^^^^^^^ can only break with a value inside `loop` or breakable block
  |
help: use `break` on its own without a value inside this `while` loop
  |
6 -             break i * 10;
6 +             break;
  |
help: alternatively, you might have meant to use a `loop` expression
  |
4 |     let found = loop {
  |                 ~~~~

error: aborting due to 1 previous error

If you need a loop to compute and return a value via break expr, either use loop (returning Option<T> or a fallback value when terminating) or update a mutable variable declared before the while loop.

When to Use while vs loop vs for

Loop Construct Best Used When
while cond Repeating while a dynamic state condition holds (such as convergence criteria, two-pointer algorithms, or draining a state machine)
for item in iter Iterating over a known numeric range (0..n) or the elements of a collection/slice
loop Executing at least once, running an infinite server/event loop, or returning a value via break value

Example: Greatest Common Divisor (Euclidean Algorithm)

A while loop is ideal when the number of iterations is not known in advance and depends on how values evolve during each step:

fn gcd(mut a: u64, mut b: u64) -> u64 {
    while b != 0 {
        let remainder = a % b;
        a = b;
        b = remainder;
    }
    a
}

fn main() {
    println!("gcd(48, 18)   = {}", gcd(48, 18));
    println!("gcd(1071, 462) = {}", gcd(1071, 462));
}
gcd(48, 18)   = 6
gcd(1071, 462) = 21

Prefer for Over Manual Index while Loops

When iterating over a slice or array, prefer for element in slice over a manual while index < slice.len() loop. A manual while loop risks forgetting index += 1 and forces rustc to perform bounds checks on slice[index] during each iteration.