Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exhaustive integer matching

Tags:

rust

I try to exhaustively match integers like this:

fn main() {
    for test in range(std::u8::MIN, std::u8::MAX) {
        match test {
            0x00..0xff => {},
        }
    }
}

But the compiler complains:

all.rs:3:9: 6:10 error: non-exhaustive patterns: `_` not covered [E0004]
all.rs:3         match test {
all.rs:4             0x00..0xff => {},
all.rs:5         }
error: aborting due to previous error

However, all possible values are covered. A quick check confirms this:

fn main() {
    for test in range(std::u8::MIN, std::u8::MAX) {
        match test {
            0x00..0xff => {},
            _ => fail!("impossible"),
        }
    }
}

And now compile and run it:

$ rustc all.rs
$ ./all
$

All possible values are covered, so why does rustc still want the obviously unreachable _ arm?

like image 235
main-- Avatar asked Aug 03 '14 22:08

main--


People also ask

What is exhaustive pattern matching and why is it important?

Finally, exhaustive pattern matching is a valuable tool for ensuring that code stays correct as requirements change, or during refactoring. Let’s say that the requirements change and we need to handle a third type of error: “Indeterminate”.

Why is exhaustive matching done in a compiler?

The fact that exhaustive matching is always done means that certain common errors will be detected by the compiler immediately: A missing case (often caused when a new choice has been added due to changed requirements or refactoring).

What is an exhaustive set of cases?

A proof that the set of cases is exhaustive; i.e., that each instance of the statement to be proved matches the conditions of (at least) one of the cases. A proof of each of the cases.

Why do we need to match all possible cases?

We briefly noted earlier that when pattern matching there is a requirement to match all possible cases. This turns out be a very powerful technique to ensure correctness. Let’s compare some C# to F# again.


2 Answers

Exhaustive integer matching was stabilised in Rust 1.33.0. The original example in the question now works (updated to use the modern syntax for ranges).

fn main() {
    for i in std::u8::MIN..=std::u8::MAX {
        match i {
            0x00..=0xff => {}
        }
    }
}
like image 159
varkor Avatar answered Nov 15 '22 08:11

varkor


As discussed in the referenced issue, Rust's exhaustiveness checking is based entirely on enums and never values, so this fails because u8 simply isn't an enum type.

like image 44
main-- Avatar answered Nov 15 '22 09:11

main--