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
continueinside awhileloop, make sure the loop variable (n += 1) is updated before thecontinuestatement. Ifcontinueexecutes 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.