Why match on usize::MIN/MAX is not exaustive?

Hi, I really don't get this:

fn foo(x: usize) {
        match x {
                usize::MIN..=usize::MAX => todo!(),
        }
}

Error:

error[E0004]: non-exhaustive patterns: `usize::MAX..` not covered
  --> src/main.rs:18:15
   |
18 |         match x {
   |               ^ pattern `usize::MAX..` not covered
   |
   = note: the matched value is of type `usize`
   = note: `usize` does not have a fixed maximum value, so half-open ranges are necessary to match exhaustively
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
   |
19 ~                 usize::MIN..=usize::MAX => todo!(),
20 ~                 usize::MAX.. => todo!(),
   |

It suggests usize::MAX.. like there is something bigger than it... but in case usize::MAX is not the max value?

Thx!

1 Like

Please post the full error you see in the terminal.

ready

1 Like

Quoting from this PR:

usize and isize are special for pattern matching because their range might depend on the platform. To make code portable across platforms, the following is never considered exhaustive:

let x: usize = ...; match x { 0..=18446744073709551615 => {} }

Because of how rust handles constants, this also unfortunately counts 0..=usize::MAX as non-exhaustive.

2 Likes

I still don't get why ..=usize::MAX is not exhaustive, it depends on the platform, but when is compiled for a specific one usize::MAX will be determinate, so what is the issue?

to understand why here are some points you need to consider:

  • Rust does not consider usize::MIN..=usize::MAX as multiple values, it's considered as one range,
  • the usize can hold up to 2^64 values so the comiler doesn't attempt to enumerate every value + a usize can be infinitely splittable,
  • the rust exhaustivness work at a structural level not an arithmetic one
  • the compiler tries to be more general

You can argue that small integers such as u8 have an exhaustive range 0..=255, the general structure of an u8 is known and not that complicated, so the compiler can enumerate all these small values explicitly while usize is too large to enumerate

It wouldn't be impossible to support, but usize::MAX specifically would have to be some sort of special case in the compiler.

I don't know the implementation details or team mindset to explain why that wasn't done beyond what I quoted.

1 Like

usize and isize are already an exception to several rules, so I thought that would be already implemented.