21.15 if let
Chains (Rust 2024+)
Stabilized in the Rust 2024 Edition, if let
chains (previously known as let_chains
) allow combining multiple if let
patterns and regular boolean conditions within a single if
statement using the logical AND operator (&&
).
21.15.1 Motivation
Without let_chains
, checking multiple patterns or conditions required nesting:
// Pre-Rust 2024: Nested structure
fn process_nested(opt_a: Option<i32>, opt_b: Option<&str>, flag: bool) {
if let Some(a) = opt_a {
if a > 10 {
if let Some(b) = opt_b {
if b.starts_with("prefix") {
if flag {
println!("All conditions met: a={}, b={}", a, b);
}
}
}
}
}
}
21.15.2 Example with if let
Chains
The if let
chain feature significantly improves the ergonomics of handling multiple optional values and conditions. A basic form of if let
chains (allowing a single let
followed by boolean conditions like if let Some(x) = option && x > 0
) was stabilized with Rust 1.76.0 (and is part of the Rust 2024 Edition).
Full support for chaining multiple let
expressions together (e.g., if let Some(a) = opt_a && ... && let Some(b) = opt_b && ...
), as demonstrated in the example below, has been finalized and is anticipated to be fully available on stable Rust starting with version 1.88 (expected around June 2025).
Therefore, to compile and run the following advanced example using a stable Rust compiler, version 1.88 or newer will be required. If you are using an earlier stable version (such as 1.87.0, which is current in some playgrounds as of May 2025), you will need to switch to the Nightly compiler channel.
The equivalent code becomes much flatter and arguably more readable:
// This advanced `if let` chain syntax, with multiple `let` bindings, // requires Rust 1.88+ (stable, Rust 2024 Edition). // If using a Rust stable compiler version prior to 1.88 (e.g., 1.87), // you will need to switch to the Nightly compiler channel. fn process_chained(opt_a: Option<i32>, opt_b: Option<&str>, flag: bool) { // Combine `if let` and boolean conditions with `&&` if let Some(a) = opt_a && a > 10 && let Some(b) = opt_b && b.starts_with("prefix") && flag { println!("All conditions met: a={}, b={}", a, b); } else { println!("Conditions not fully met."); } } fn main() { process_chained(Some(20), Some("prefix_data"), true); // Output: All conditions met: a=20, b=prefix_data process_chained(Some(5), Some("prefix_data"), true); // Output: Conditions not fully met. (a > 10 fails) process_chained(Some(20), Some("other_data"), true); // Output: Conditions not fully met. (b.starts_with fails) process_chained(Some(20), Some("prefix_data"), false); // Output: Conditions not fully met. (flag fails) process_chained(None, Some("prefix_data"), true); // Output: Conditions not fully met. (opt_a is None) }
The conditions are evaluated left-to-right. If any let
pattern fails to match or any boolean expression is false, the entire if
condition short-circuits to false, and the else
block (if present) is executed.
- Local Development: To compile this example, ensure your project uses the Rust 2024 Edition (
edition = "2024"
inCargo.toml
) and that your Rust stable compiler is version 1.88 or newer. - Online Playgrounds /
mdbook
: If the environment is using a stable Rust compiler older than 1.88 (e.g., 1.87.0), you will likely encounter a compiler error (E0658
). The workaround is to switch the compiler channel in the playground to Nightly. Using#![feature(let_chains)]
will not work on stable compilers for this feature