Rust If Let
if let is the short form of a match that cares about one case. The block runs when the value fits the pattern.
The long way: a full match for one case
A whole match can test one case and ignore the rest:
let found: Option<i32> = Some(9);
match found {
Some(n) => println!("found {n}"),
None => println!("nothing found"),
}One case is all you need
if let runs the block only when the value fits the pattern. Add an else block when the other case also needs code:
let found: Option<i32> = Some(9);
if let Some(n) = found {
println!("found {n}");
} else {
println!("nothing found");
}while let loops until the pattern fails
pop() hands back an Option each round. while let keeps going while it is Some — and when None arrives, the loop ends by itself:
let mut words = vec!["a", "b"];
while let Some(w) = words.pop() {
println!("word {w}");
}if let tests shape, not equality
Door is a small enum with no derives. Comparing two Door values with == fails, because == needs PartialEq. if let asks only about shape, so it works either way:
let door = Door::Open;
if door == Door::Open {
println!("open");
}
// error E0369: binary operation `==` cannot be applied to type `Door`Join tests with && — let chains
On the 2024 edition, several let tests can join with &&, and a plain test can join them too. (On the 2021 edition the same code is an error.) The block runs only when every test passes:
let first = Some(3);
let second = Some(20);
if let Some(x) = first && let Some(y) = second && y > x {
println!("both present, sum {}", x + y);
}Example
fn main() {
let mut stack = vec![1, 2, 3];
while let Some(top) = stack.pop() {
print!("{} ", top);
}
println!();
let config: Option<&str> = Some("dark-mode");
if let Some(mode) = config { println!("mode = {}", mode); }
}Key points
- Use let ... else to handle the "wrong" case early (usually by returning), keeping the main path flat
- if let gives up a safety net.
- Unlike match, it does not check that every case was handled.
- That choice belongs to the programmer.
- while let has no else.
- When its pattern fails, the loop simply ends.
- That ending is the whole point of the loop.
In this example, stack is a Vec holding 1, 2, 3. stack.pop() removes the last item and returns it as an Option: Some(3), then Some(2), then Some(1), then None. while let Some(top) = stack.pop() keeps the loop going while the pattern matches, printing 3 2 1. When pop finally returns None, the pattern fails and the loop ends by itself. Below, if let checks one Option once: it is Some("dark-mode"), so the mode line prints.
Note
if let is not a weaker match — it is the same pattern test, written briefly.
Reach for match when every case truly matters, like with Result.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
When is if let a better choice than match?