Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An Or pattern in Rust is a structural matching construct denoted by the pipe operator (|) that allows a single pattern-matching arm to evaluate against multiple alternative patterns. If the scrutinized value matches any of the specified alternatives, the overall pattern match succeeds.
pattern_1 | pattern_2 | ... | pattern_n => expression,

Core Mechanics and Evaluation

Or patterns evaluate strictly from left to right. The compiler utilizes short-circuit evaluation; the first alternative that successfully matches the scrutinized value terminates the pattern evaluation, and the associated code block is executed. While Or patterns are valid in any pattern-matching context (including match, if let, and while let), their use in let statements and function parameters carries a strict irrefutability requirement. Because let bindings and function parameters cannot handle match failures, the Or pattern used in these contexts must be irrefutable (guaranteed to match all possible values of the type). Most Or patterns, such as matching specific integers, are refutable and will cause a compile-time error in these contexts.
let x = 2;

// Refutable context: match expression
match x {
    1 | 2 | 3 => println!("Matched 1, 2, or 3"),
    _ => println!("Matched something else"),
}

// Refutable context: if let expression
if let 4 | 5 = x {
    println!("Matched 4 or 5");
}

// Irrefutable context: let statement
// VALID: The Or pattern exhaustively covers both variants of Result<i32, i32>
let Ok(val) | Err(val) = Result::<i32, i32>::Ok(10);

// INVALID: Refutable pattern in a let statement causes a compile-time error
// let 1 | 2 = x; 

Variable Binding Uniformity

The most strict compiler constraint regarding Or patterns is binding uniformity. If an Or pattern binds variables to extract data from the scrutinized value, every alternative within that Or pattern must bind the exact same set of variables. Furthermore, the bound variables must resolve to the exact same type and utilize the exact same binding mode (mut, ref, ref mut, or by value) across all alternatives.
enum Node {
    Leaf(i32),
    Branch(i32, i32),
}

let node = Node::Leaf(5);

match node {
    // VALID: `val` is bound in both alternatives, is of type `i32` in both, 
    // and is bound by value in both.
    Node::Leaf(val) | Node::Branch(val, _) => println!("Value: {}", val),
}
Violating these constraints results in specific compile-time errors:
  • Failing to bind the same variables yields E0408: variable is not bound in all patterns.
  • Using different binding modes yields E0409: variable is bound inconsistently.
let opt = Some(10);

match opt {
    // INVALID (E0408): `x` is bound in the first alternative, but not the second.
    // Some(x) | None => println!("Value"), 

    // INVALID (E0409): `x` is bound by value in the first alternative, 
    // but by `mut` in the second alternative.
    // Some(x) | Some(mut x) => println!("Value"),

    _ => ()
}

Nested Or Patterns

Or patterns can be nested arbitrarily deep within other structural patterns (such as tuples, slices, structs, or enum variants). You do not need to duplicate the outer structure to match against multiple inner values.
let result: Result<Option<i32>, &str> = Ok(Some(42));

match result {
    // The Or pattern (1 | 2 | 42) is nested inside the Option, 
    // which is nested inside the Result.
    Ok(Some(1 | 2 | 42)) => println!("Matched specific inner values"),
    Ok(None) | Err(_) => println!("Matched other states"),
    _ => ()
}

Precedence and Grouping

The | operator has low precedence in pattern syntax. When combining Or patterns with other pattern features, such as range patterns (..=) or reference modifiers (&, ref), the Or pattern applies to the entire pattern on either side of the pipe. Parentheses must be used to explicitly group Or patterns to control precedence and restrict the scope of the alternation.
let reference = &1;

match reference {
    // VALID: Parentheses group the Or pattern. 
    // This matches a reference to `0` OR a reference to `1`.
    &(0 | 1) => println!("Matched a reference to 0 or 1"),
    
    // INVALID PRECEDENCE: Without parentheses, `&0 | 1` is parsed as:
    // (&0) | (1)
    // This attempts to match either a reference to 0, or the integer 1.
    // This causes a type mismatch error because the alternatives have different types.
    // &0 | 1 => println!("Will not compile"),
    
    _ => ()
}
Master Rust with Deep Grasping Methodology!Learn More