Pattern matching is one of the most important language mechanisms in Rust, derived from functional languages. It allows for declarative, concise, and safe handling of complex value variants, including using additional conditions (guard expressions), providing flexibility and control over logic.
Without exhaustiveness checking, some scenarios powered by pattern matching may lead to errors. Additionally, without understanding the order of branches and guard expressions, one might err in either logic or performance.
In Rust, the compiler checks that all enum variants (or simpler pattern structures) are covered, or there is a catch-all branch _. A branch can be further constrained by a guard expression (if after the pattern), and only if the condition is met does it "trigger". Remaining variants are not captured. The order of branches is important: they are checked top to bottom.
Code example:
enum Message { Hello, Data(i32), Quit, } fn handle(msg: Message) -> &'static str { match msg { Data(n) if n > 10 => "Big Data", Data(_) => "Some Data", Hello => "Greet!", Quit => "Bye", } }
Key features:
Does a branch with a guard activate if the pattern matches but the condition fails?
No, in that case the check proceeds to the next suitable branch. Pattern + guard is an atomic "filter"; only when both match does the branch body execute.
Does the order of branches in a match affect performance?
Yes. Especially with numerous similar patterns with guards: the compiler checks branches top to bottom, which impacts the speed of checks at runtime — more frequently encountered values should be processed earlier.
Can exhaustiveness checking be bypassed by using only the _ branch?
Technically yes — this is permissible, but it sacrifices reliability: if the type excludes (or adds) new elements, the compiler won’t warn about unhandled cases. It’s better to explicitly handle important cases, and use _ only as a last resort.
_.A match code for an enum with guard expressions, where the pattern with a guard is last but most values go directly through an early _ branch, and the necessary handling never reaches.
Pros:
_.Cons:
Start by listing the most frequent and important variants (with guards), then exhaustively cover the rest — without unnecessary code in _.
Pros:
Cons: