In theory the compiler should be able to detect that the following range is exhaustive and not error about non-exaustive match:
fn wont_compile(x : u8) {
match (x) {
0x00 ... 0xff => { }
}
}
Proposed (as a side-portion) in #880
Discussed in https://github.com/rust-lang/rust/issues/12483 and https://github.com/rust-lang/rust/issues/32381
The following will then error due to _ being unreachable, but it currently is allowed. So we'd need some way to prevent "new" unreachable patterns from being a hard error.
match x {
0x00...0xFF => {},
_ => {},
}
@oli-obk We could just warn in that case (and make it a lint so people can #[deny] or #[allow] it, depending on what they want)
Are there any new discussion/plans on this? Adding a warning which can be turned off for legacy code seems like the most elegant solution to me. If that aligns with the consensus, I'd try and take a shot at this during my spring vacation and send a pull request
It's another issue, and likely unsolvable, but this also fails the range exhaustiveness check:
match x & 0x03 {
0 .. 3 => ..
}
@igor-krawczuk Unreachable patterns have already been downgraded from errors to warnings in https://github.com/rust-lang/rust/pull/38069 I believe, so that sounds reasonable to me.
Perhaps it's time to remove the "postponed" tag.
"match x & 0x03 {}" can be solved with a small amount of value range analysis, that will benefit other parts of Rust.
I'd also like to see discussion start on this again. I ran into this today and was very surprised to see that Rust can't determine that all ranges of a given integer type were covered. I had to add a _ => unreachable!() arm instead.
Determining the completeness of a set of guards/pattern matches over a given domain is a fairly non-trivial problem. I ran into it writing my thesis and it requires applications of the Simplex Algorithm to solve what is effectively a linear programming problem.
It's not impossible to solve, but the complexity of doing so needs to be weighed against the possible ergonomic benefits.
Step 1: perform this conservatively, on integral ranges only and only if there are no guards. This is a common case in low-level code. Benefits: avoided a class of bugs, etc.
Yes, this problem in general is very much non-trivial, but the case outlined by @leonardo-m covers my use case and is certainly doable.
This could be particularly elegant for char:
match c {
'\u{0000}'..='\u{D7FF}' => ...
'\u{E000}'..='\u{10_FFFF}' => ...
// No wildcard needed; all legal USVs are covered
}
I have an implementation of this (specifically: interval exhaustiveness checking over integer types). If we need to write up an RFC before integrating it, I'll try to do so in a couple of weeks or so (or if anyone'd like to accelerate the process and write one sooner, that'd be great too)!
Edit: Actually, I'm going to try merged it under a feature flag immediately, as it seems like a straightforward extension to the existing exhaustiveness checks, but it may require an RFC to stabilise.
I've created a tracking issue here: https://github.com/rust-lang/rust/issues/50907 and the pull request is at: https://github.com/rust-lang/rust/pull/50912.
This has been implemented in https://github.com/rust-lang/rust/pull/50912 as #![feature(exhaustive_integer_patterns)] (tracking issue). We can probably close this issue now.
Most helpful comment
I have an implementation of this (specifically: interval exhaustiveness checking over integer types). If we need to write up an RFC before integrating it, I'll try to do so in a couple of weeks or so (or if anyone'd like to accelerate the process and write one sooner, that'd be great too)!
Edit: Actually, I'm going to try merged it under a feature flag immediately, as it seems like a straightforward extension to the existing exhaustiveness checks, but it may require an RFC to stabilise.
I've created a tracking issue here: https://github.com/rust-lang/rust/issues/50907 and the pull request is at: https://github.com/rust-lang/rust/pull/50912.