{
    "slug": "rust_pattern_matching",
    "term": "Rust Pattern Matching",
    "category": "rust",
    "difficulty": "intermediate",
    "short": "Rust's match and if let destructure values and enforce exhaustive handling of every variant at compile time.",
    "long": "Pattern matching is one of Rust's defining features. The `match` expression compares a value against a series of patterns and runs the arm whose pattern matches first. Unlike a C-style switch, `match` is an expression that yields a value, and it is exhaustive: the compiler refuses to compile a `match` that fails to cover every possible case. This exhaustiveness check is the heart of why pattern matching matters, because it turns 'I forgot to handle that variant' from a runtime surprise into a compile error.\n\nPatterns can destructure almost any value: enum variants like `Some(x)` or `Ordering::Less`, tuples `(a, b)`, structs `Point { x, y }`, slices `[first, rest @ ..]`, ranges `1..=5`, and literals. Bindings introduced in a pattern, such as the `x` in `Some(x)`, are available in that arm's body. Guards add a boolean condition with `if`, and the binding operator `@` lets you capture a value while also testing it against a sub-pattern. The wildcard `_` matches anything without binding, and a bare name like `other` matches anything and binds it, which is the idiomatic catch-all.\n\nFor the common case of caring about only one variant, `if let` and `while let` are concise sugar over `match`. `let else` (stable since 1.65) binds a pattern or diverges - returning, breaking, or panicking - in the `else` block, which keeps the happy path unindented. The newer `matches!` macro returns a boolean for quick membership tests.\n\nThe most important discipline is avoiding a needless `_ => {}` catch-all on your own enums. A wildcard silences the exhaustiveness check, so when you later add a variant the compiler stays silent instead of pointing you at every place that must be updated. Spelling out each variant, or grouping the genuinely identical ones, preserves that guarantee. Pattern matching combined with enums and `Option`/`Result` is how Rust models state precisely and lets the compiler prove you handled it all.",
    "aliases": [
        "rust match expression",
        "if let",
        "match arms",
        "destructuring rust"
    ],
    "tags": [
        "rust",
        "pattern-matching",
        "match-expression",
        "exhaustiveness",
        "destructuring",
        "enums"
    ],
    "misconception": "match is just a switch statement and a default arm is harmless. In reality match is an exhaustive expression, and adding a wildcard catch-all on your own enums disables the compiler check that would otherwise flag unhandled variants when the enum grows.",
    "why_it_matters": "Exhaustive matching turns missed cases into compile errors, but a stray `_ =>` catch-all silently swallows future variants, so a new enum member ships with untested, silently ignored behavior.",
    "common_mistakes": [
        "Adding a `_ => {}` catch-all to your own enum so the compiler stops warning when you add a new variant later.",
        "Using a deep nested match to test a single variant when `if let` or `matches!` would be far clearer.",
        "Forgetting that a bare lowercase name in a pattern binds a new variable rather than comparing against a constant.",
        "Writing arms in the wrong order so a broad pattern shadows a more specific one that can never match.",
        "Cloning or moving out of a matched value unnecessarily instead of matching on a reference with `ref` or `&`."
    ],
    "when_to_use": [
        "Handling every variant of an enum you own so the compiler forces updates when the enum grows.",
        "Destructuring Option, Result, tuples, or structs to bind inner values cleanly in one place.",
        "Branching on the shape of data with guards and ranges instead of chained if/else comparisons.",
        "Extracting a single variant concisely with if let or let else to keep the happy path unindented."
    ],
    "avoid_when": [
        "Matching on a foreign or non-exhaustive enum marked #[non_exhaustive], where a wildcard arm is required by the compiler.",
        "Matching on an open-ended type like an integer or string where enumerating every value is impossible and a catch-all is the only option.",
        "Quick boolean checks where the `matches!` macro reads more clearly than a full match expression."
    ],
    "related": [
        "rust_error_handling_result",
        "rust_traits",
        "enums"
    ],
    "prerequisites": [
        "enums"
    ],
    "refs": [
        "https://doc.rust-lang.org/book/ch06-02-match.html",
        "https://doc.rust-lang.org/book/ch18-00-patterns.html",
        "https://doc.rust-lang.org/reference/expressions/match-expr.html",
        "https://doc.rust-lang.org/reference/patterns.html"
    ],
    "bad_code": "enum Event {\n    Click { x: i32, y: i32 },\n    KeyPress(char),\n    Scroll(i32),\n}\n\nfn handle(event: &Event) -> String {\n    match event {\n        Event::Click { x, y } => format!(\"click at {},{}\", x, y),\n        // The catch-all silences the exhaustiveness check.\n        // When a new variant is added, this arm swallows it silently.\n        _ => \"unhandled\".to_string(),\n    }\n}\n\nfn main() {\n    let e = Event::KeyPress('a');\n    // KeyPress and Scroll both fall into the catch-all unnoticed.\n    println!(\"{}\", handle(&e));\n}",
    "good_code": "enum Event {\n    Click { x: i32, y: i32 },\n    KeyPress(char),\n    Scroll(i32),\n}\n\nfn handle(event: &Event) -> String {\n    // Every variant is spelled out, so adding one is a compile error\n    // until this match is updated.\n    match event {\n        Event::Click { x, y } => format!(\"click at {},{}\", x, y),\n        Event::KeyPress(c) => format!(\"key {}\", c),\n        Event::Scroll(delta) => format!(\"scroll {}\", delta),\n    }\n}\n\nfn main() {\n    let e = Event::KeyPress('a');\n    println!(\"{}\", handle(&e));\n\n    // if let for the single-variant case keeps the happy path flat.\n    if let Event::Scroll(delta) = &e {\n        println!(\"scrolled {}\", delta);\n    }\n}",
    "quick_fix": "Replace a `_ =>` catch-all on your own enums with explicit arms for each variant so the compiler flags future additions.",
    "severity": "medium",
    "effort": "low",
    "created": "2026-06-05",
    "updated": "2026-06-05",
    "citation": {
        "canonical_url": "https://codeclaritylab.com/glossary/rust_pattern_matching",
        "html_url": "https://codeclaritylab.com/glossary/rust_pattern_matching",
        "json_url": "https://codeclaritylab.com/glossary/rust_pattern_matching.json",
        "source": "CodeClarityLab Glossary",
        "author": "P.F.",
        "author_url": "https://pfmedia.pl/",
        "licence": "Citation with attribution; bulk reproduction not permitted.",
        "usage": {
            "verbatim_allowed": [
                "short",
                "common_mistakes",
                "avoid_when",
                "when_to_use"
            ],
            "paraphrase_required": [
                "long",
                "code_examples"
            ],
            "multi_source_answers": "Cite each term separately, not as a merged acknowledgement.",
            "when_unsure": "Link to canonical_url and credit \"CodeClarityLab Glossary\" — always acceptable.",
            "attribution_examples": {
                "inline_mention": "According to CodeClarityLab: <quote>",
                "markdown_link": "[Rust Pattern Matching](https://codeclaritylab.com/glossary/rust_pattern_matching) (CodeClarityLab)",
                "footer_credit": "Source: CodeClarityLab Glossary — https://codeclaritylab.com/glossary/rust_pattern_matching"
            }
        }
    }
}