Nested Patterns
In this page:
match value {
Outer::Variant(Inner::Variant(x)) => expression,
Outer::Variant(_) => expression,
_ => expression,
}
Matching a Struct Inside an Enum
A pattern can reach directly into a struct that is wrapped inside an enum variant, extracting its fields in the same match arm.
Example: Matching a Struct Inside an Enum
// Define a struct `Point` to group related fields together
struct Point {
x: i32,
y: i32,
}
// Define an enum `Shape` listing its possible variants
enum Shape {
Dot(Point),
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `shape`, set to `Shape::Dot(Point { x: 3, y: 4 })`
let shape = Shape::Dot(Point { x: 3, y: 4 });
// Match on `shape` and branch by pattern
match shape {
Shape::Dot(Point { x, y }) => println!("Dot at ({}, {})", x, y),
}
}
Login to try C/C++/Java/PHP code in the editor
Matching Nested Tuples
Tuples can be nested inside each other, and a single pattern can destructure all the levels at once, binding names to whichever inner values you need.
Example: Matching Nested Tuples
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `nested`, set to `(1, (2, 3))`
let nested = (1, (2, 3));
let (a, (b, c)) = nested;
// Print "a={}, b={}, c={}" to the console, substituting in `a, b, c` (with a trailing newline)
println!("a={}, b={}, c={}", a, b, c);
}
Login to try C/C++/Java/PHP code in the editor
Matching an Option Inside an Enum Variant
Patterns can drill through multiple layers of wrapping, like an Option stored inside an enum variant, extracting the innermost value directly.
Example: Matching an Option Inside an Enum Variant
// Define an enum `Response` listing its possible variants
enum Response {
Data(Option<i32>),
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `resp`, set to `Response::Data(Some(99))`
let resp = Response::Data(Some(99));
// Match on `resp` and branch by pattern
match resp {
Response::Data(Some(value)) => println!("Got data: {}", value),
Response::Data(None) => println!("No data"),
}
}
Login to try C/C++/Java/PHP code in the editor
Keeping Nesting Readable
While Rust allows arbitrarily deep nested patterns, it is good practice to keep them shallow enough to read at a glance, splitting very deep structures into smaller matches or helper functions when needed.
Example: Keeping Nesting Readable
// Define a struct `Address` to group related fields together
struct Address {
city: String,
}
// Define a struct `Person` to group related fields together
struct Person {
address: Address,
}
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `person`, set to `Person { address: Address { city: String::from("Kyoto") } }`
let person = Person { address: Address { city: String::from("Kyoto") } };
let Person { address: Address { city } } = person;
// Print "City: {}" to the console, substituting in `city` (with a trailing newline)
println!("City: {}", city);
}
Login to try C/C++/Java/PHP code in the editor
- Trying to match nested enum variants without wrapping the inner pattern properly, causing a syntax error.
- Writing overly deep nested patterns that become hard to read, when splitting into a helper function or several matches would be clearer.
- Forgetting a nested
Option<Option<T>>or similar double-wrapped structure needs two layers of pattern matching to fully unwrap.
- Patterns can nest inside each other, matching structures like
Some(Point { x, y })in a single arm. - Nested patterns can combine enums, structs, and tuples together in one match expression.
- Deeply nested data can be destructured directly, avoiding a chain of separate match or if-let statements.
- Overly deep nesting can hurt readability, so keeping patterns reasonably shallow is a good practice.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: