Rustlers Atom 1.6: Loops: `loop`, `while`, `for`
April 18, 2026•422 words
Rust gives you three looping constructs. There’s no hidden behaviours, no accidental infinite loops, and no implicit coercions. Each kind of loop expresses a specific intent.
loop: The Infinite Primitive
loop is the most fundamental looping construct. It runs forever unless you explicitly stop it with break.
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2; // Break with a value
}
};
println!("Result: {}", result);
}
A loop is an expression, so you can break with a value and assign it to a variable.
If you don’t specify one, the break returns the unit type ().
This is handy for control flow where the exit point isn’t known in advance — like waiting on input, polling, or retrying until success. It’s Rust’s “structured goto”: explicit, visible, and type-checked.
while: Loop While a Condition Holds
while repeats as long as its condition evaluates to true.
fn main() {
let mut number = 3;
while number != 0 {
println!("{number}!");
number -= 1;
}
println!("Liftoff!");
}
This feels familiar if you’ve used C, Python, or JavaScript, but with one crucial difference: Rust checks the condition’s type at compile time, and the condition must be a bool.
for: Loop Over Iterators
for is Rust’s most idiomatic loop. It works with anything that implements the Iterator trait — arrays, slices, ranges, or your own iterator types.
fn main() {
let numbers = [10, 20, 30, 40];
for num in numbers {
println!("Number: {num}");
}
// Using a range
for i in 0..5 {
println!("i = {i}");
}
// Exclusive upper bound: 0..5 means 0,1,2,3,4
// Inclusive: 0..=5 means 0 through 5
}
A for loop takes ownership of the iterator unless you borrow explicitly. This gives you flexibility:
let data = vec!["a", "b", "c"];
// Immutable borrow
for item in &data {
println!("Item: {item}");
}
// Mutable borrow
for item in &mut data.clone() {
*item = "x";
}
Loop Labels and Nested Control
You can label loops to control which one you break or continue when nested:
fn main() {
'outer: for x in 0..3 {
for y in 0..3 {
if x == y {
continue 'outer; // skip to next x
}
println!("x = {x}, y = {y}");
}
}
}