-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Precise range exhaustiveness check for match on integer patterns #1550
Comments
The following will then error due to match x {
0x00...0xFF => {},
_ => {},
} |
@oli-obk We could just warn in that case (and make it a lint so people can |
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:
|
@igor-krawczuk Unreachable patterns have already been downgraded from errors to warnings in rust-lang/rust#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 |
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 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: rust-lang/rust#50907 and the pull request is at: rust-lang/rust#50912. |
Exhaustive integer matching This adds a new feature flag `exhaustive_integer_patterns` that enables exhaustive matching of integer types by their values. For example, the following is now accepted: ```rust #![feature(exhaustive_integer_patterns)] #![feature(exclusive_range_pattern)] fn matcher(x: u8) { match x { // ok 0 .. 32 => { /* foo */ } 32 => { /* bar */ } 33 ..= 255 => { /* baz */ } } } ``` This matching is permitted on all integer (signed/unsigned and char) types. Sensible error messages are also provided. For example: ```rust fn matcher(x: u8) { match x { //~ ERROR 0 .. 32 => { /* foo */ } } } ``` results in: ``` error[E0004]: non-exhaustive patterns: `32u8...255u8` not covered --> matches.rs:3:9 | 6 | match x { | ^ pattern `32u8...255u8` not covered ``` This implements rust-lang/rfcs#1550 for #50907. While there hasn't been a full RFC for this feature, it was suggested that this might be a feature that obviously complements the existing exhaustiveness checks (e.g. for `bool`) and so a feature gate would be sufficient for now.
This has been implemented in rust-lang/rust#50912 as |
In theory the compiler should be able to detect that the following range is exhaustive and not error about non-exaustive match:
Proposed (as a side-portion) in #880
Discussed in rust-lang/rust#12483 and rust-lang/rust#32381
The text was updated successfully, but these errors were encountered: