let else Statements
For the common case of matching a pattern and returning from the function, use let else. The “else” case must diverge (return, break, or panic - anything but falling off the end of the block).
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> {
let s = if let Some(s) = maybe_string {
s
} else {
return Err(String::from("got None"));
};
let first_byte_char = if let Some(first) = s.chars().next() {
first
} else {
return Err(String::from("got empty string"));
};
let digit = if let Some(digit) = first_byte_char.to_digit(16) {
digit
} else {
return Err(String::from("not a hex digit"));
};
Ok(digit)
}
fn main() {
println!("result: {:?}", hex_or_die_trying(Some(String::from("foo"))));
}
The rewritten version is:
#![allow(unused)]
fn main() {
// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> {
let Some(s) = maybe_string else {
return Err(String::from("got None"));
};
let Some(first_byte_char) = s.chars().next() else {
return Err(String::from("got empty string"));
};
let Some(digit) = first_byte_char.to_digit(16) else {
return Err(String::from("not a hex digit"));
};
Ok(digit)
}
}
More to Explore
- This early return-based control flow is common in Rust error handling code, where you try to get a value out of a
Result, returning an error if theResultwasErr. - If students ask, you can also demonstrate how real error handling code would be written with
?.