Non-exhaustive match i32 even if it is

Viewed 376

Rust complain about that match being non-exhaustive. Is it a limit of Rust or do I miss something ?

fn main() {
  let x = 10;
  match x {
     1 => {},
     y if y < 1 => {},
     y if y > 1 => {}
  }
}
3 Answers

Rust won't process if expressions when validating exhaustiveness. Given that, you would either need to add a catch-all match that you mark as unreachable, e.g.

fn main() {
  let x = 10;
  match x {
    1 => {},
    y if y < 1 => {},
    y if y > 1 => {}
    _ => unreachable!()
  }
}

or given your logic, the better option would be to not include the last if at all, e.g.

fn main() {
  let x = 10;
  match x {
    1 => {},
    y if y < 1 => {},
    y => {}
  }
}

because it will only reach the last match if the earlier one fails.

Related:

A cleaner but more verbose alternative is to use three-way comparison via cmp:

use std::cmp::Ordering;
 
match x.cmp(&1) {
    Ordering::Less => { /* ... */ },
    Ordering::Equal => { /* ... */ },
    Ordering::Greater => { /* ... */ },
}

(playground)

The exhaustiveness of the match is checked by the compiler. In particular, the cmp method is unavailable for types that implement PartialOrd but not Ord, so the failure to handle incomparable values will be caught at compile time.

This is mentioned in the Comparing the Guess to the Secret Number section of the Programming a Guessing Game chapter in the book.

Related