Exaustive integer patterns


#1

I’m just working on a code where I need to match an u8 with some patterns in all its possible values. The thing is that even after matching with all possible values, the compiler still asks for the _ pattern :confused:

This is the play code: https://is.gd/heLZNf

As you can see, I match the u8 for all its possible values, from 0x00 to 0xff, but it’s still asking me for the _ pattern. Why does this happen? Shouldn’t the compiler know that there will be no number outside those ranges in u8?


#2

It’s a known issue - see https://github.com/rust-lang/rfcs/issues/1550 for some discussion.


#3

I’ve added a note to that 1550. I’d like 2018 Rust Vision to have a point about improving Rust correctness. The correctness of handling integer numbers is an important part of it.


#4

Cool. The question is how complex do you want to make the compiler, considering someone can have arbitrary expressions in the match arms that the compiler will have to evaluate. Perhaps bailing on more complex stuff and handling the more basic cases would be a Good Enough improvement, but inevitably someone will be upset that their expression isn’t handled.


#5

You can do it in stages:

The first stage is basic, if the match is on an integral value (chars too) and there are no if clauses, then exhaustiveness over the whole range of the type is easy.

The second stage is handling code like “match x & 0x03 {}”. D language is able to correctly handle constant value ranges like that, so I think Rust will be able to do the same.

As a third stage it’s still probably doable to accept code like:

fn foo(x: u8) -> bool {
    match x {
        x if x % 2 == 0 => true,
        x if x % 2 == 1 => false,
    }
}

But beyond those two stages we have diminishing returns, the compilation probably gets slower, and it becomes less easy for the programmer to guess what the compiler will accept and refuse. So I think the stages past the second will be better handled by liquid typing, Rust Belt, or other high integrity means.