Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-exhaustive match i32 even if it is

Rust compiler complains about the following 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 => {}
  }
}
like image 455
rafoo Avatar asked Sep 14 '25 14:09

rafoo


2 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:

  • Why is a match pattern with a guard clause not exhaustive?
like image 189
loganfsmyth Avatar answered Sep 17 '25 20:09

loganfsmyth


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.

like image 22
L. F. Avatar answered Sep 17 '25 20:09

L. F.