2
fn foo(ok: bool) -> Result<i32, i32> {
    if ok { Ok(0) } else { Err(0) }
}

fn main() {
    let Ok(x) | Err(x) = foo(true); // rust-analyzer error: top-level or-patterns are not allowed in `let` bindings

    if let Ok(x) | Err(x) = foo(true) { // rust-analyzer warn: irrefutable `if let` pattern
        println!("Working!");
    }
}

Or is this a rust-analyzer bug? I tried to Google but couldn't find anything.

1
  • 4
    You should always look at what the compiler tells you to get the full picture (in this case you'll see that it suggests a fix for your code so that it will compile). Just looking at the errors in the tooltip or problem list in your IDE will only give you partial information.
    – Herohtar
    Commented Jan 31, 2022 at 17:50

1 Answer 1

7

The reason that top-level or-patterns aren't allowed is because it would cause certain macro_rules! macros to break. The pattern in a let expression should be matchable by a single $p:pat, but without requiring it to be parenthesized, a $p:pat would only consume the first part of the or-pattern.

Note that you can work around this easily, as the compiler suggests when you try this:

error: top-level or-patterns are not allowed in `let` bindings
 --> src/main.rs:6:9
  |
6 |     let Ok(x) | Err(x) = foo(true);
  |         ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(x) | Err(x))`

Wrapping the or-expression in brackets fixes this, since now a bracket expression is the top-level expression:

let (Ok(x) | Err(x)) = foo(true);

Not the answer you're looking for? Browse other questions tagged or ask your own question.