Pattern Matching
Exhaustive pattern matching with match expressions, guards, and nested patterns.
Pattern Matching
The match expression provides exhaustive pattern matching over values. The compiler checks that all cases are covered and warns about unreachable arms.
Basic matching
fn describe(x: i32) -> i64 {
match x {
0 => 0,
1 => 1,
_ => 2,
}
}
The wildcard _ matches any value and is used as a catch-all.
Matching on enums
enum Shape {
Circle(f64),
Rectangle(f64, f64),
Triangle(f64, f64, f64),
}
fn sqrt(x: f64) -> f64 { x }
fn area(s: Shape) -> f64 {
match s {
Shape::Circle(r) => 3.14159 * r * r,
Shape::Rectangle(w, h) => w * h,
Shape::Triangle(a, b, c) => {
let s = (a + b + c) / 2.0
sqrt(s * (s - a) * (s - b) * (s - c))
},
}
}
If you omit a variant, the compiler reports an error about non-exhaustive matching.
Guards
Pattern arms can include if guards for additional conditions:
fn classify_temp(celsius: f64) -> i64 {
match celsius {
t if t < 0.0 => 0,
t if t < 20.0 => 1,
t if t < 35.0 => 2,
_ => 3,
}
}
Matching on structs
struct Point { x: f64, y: f64 }
fn quadrant(p: Point) -> i64 {
match p {
Point { x, y } if x > 0.0 && y > 0.0 => 1,
Point { x, y } if x < 0.0 && y > 0.0 => 2,
Point { x, y } if x < 0.0 && y < 0.0 => 3,
Point { x, y } if x > 0.0 && y < 0.0 => 4,
_ => 0,
}
}
Current limitations
- Tuple destructuring in
letbindings (let (a, b) = pair) is not yet supported. Usematchinstead. - Nested pattern matching on deeply nested structs works but is not yet exhaustively checked in all cases.
- Or-patterns (
A | B => ...) are parsed but coverage checking for them is still maturing.