I get the impression the prototypical example of a match
statement is something like this.
match an_enum {
Foo => println!("got a foo"),
Bar(x) => println!("got a bar with value {}", x),
// etc.
}
This works excellently. However, it doesn’t work quite so well for continuous categories like matching on u32
. The switch
-like case is covered…
match an_integer {
1 => { /* do something */ }
2 => { /* do something (/ }
// etc.
_ => { /* the default case */ }
}
…but I’m writing a Game Boy Advance emulator, and have a lot of code where I’m working with a u32
which I got by pulling only a few bytes from a 32-bit instruction.
let register = (instruction >> 11) & 0b1111;
match register {
0b0000 => { /* something */ }
0b0001 => { /* something */ }
0b0010 => { /* something */ }
// etc.
0b1111 => { /* something */ }
_ => unreachable!(),
}
The unreachable match arm exists here solely because the compiler can’t distinguish between a full 32-bit integer and a 32-bit integer constrained to a four-bit value. Is it possible to make the compiler smarter to cover this case?
Similarly, I’ve seen comments about something like this…
match a_number {
x where x < 0 => { /* something */ }
0 => { /* something */ }
x where x > 0 => { /* something */ }
_ => unreachable!(),
}
This too requires an unreachable match arm, in this case because the compiler can’t tell that there is no value not covered by the three clauses. (I’m assuming a_number
here is something like i32
—floats can of course be not-a-number.)