-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Exhaustive match of number treated as non-exhaustive #12483
Comments
I assume this is the same issue: fn main() {
println!("{}", match 1i {
n if n > 0 => "greater",
n if n < 0 => "less",
n if n == 0 => "equal",
});
}
// error: non-exhaustive patterns: `_` not covered [E0004] |
Whilst I agree that your example is exhaustive, it's not a good example.
This is effectively the same, except it compiles. Keep in mind
you would just drop the 'if (n == 0)' from that last clause. |
Doing the test for n==0 is less efficient, but IMHO more readable. I would probably use your pattern but leave n==0 commented out. |
The compiler is never going to be able to fully determine these kinds of things, as they would involve evaluating certain things at compile time. For example:
This arm would be equivalent, but would report as non-exhaustive, too. As such, I'm giving this a close. I don't think we can improve this. |
@steveklabnik I disagree with your closing of this issue; could you please open it again? The issue is entirely genuine, is blocking correct code (though admittedly there is an easy workaround: change the last pattern to an Moreover, your fabricated example is invalid, because you can’t do arithmetic in patterns. @jkleint Your example is a completely different issue and is not solvable. |
@chris-morgan I'm not understanding how this issue is solvable. To grok the range, we need to evaluate code at compile time, it can't work. |
@steveklabnik it’s a pattern, so the numbers are literals or constants. No additional evaluation required. The compiler needs to know them in order to compile the code anyway. |
@chris-morgan aren't |
I've written a POC script that compares a set of ranges with 1 or more exhaustive ranges for the respective type and outputs any ranges that are not covered: https://gist.github.com/aarzee/4395cb34eef31ea4e5c4 I'm interested in implementing this logic in the compiler but looking at check_match.rs I have absolutely no idea how I would do this. Also, this code has opportunities to take advantage of more types in the future, as currently floats aren't supported by it, and specialization and native inclusive ranges have not yet been added to the language. |
Implementing this would cause the following to fail to compile since the last arm is unreachable: match 0u8 {
0...255 => {}
_ => {}
} Should a warning be emitted first? Is an RFC needed? Should this be ignored without warning, like it is now? Make it a deny-by-default Lint to prevent breaking dependencies? So many questions! |
To be sure, implementing this will cause certain code that compiles now to cease to compile, but it was bad code to begin with and a bug in the compiler is being fixed. And it is very unlikely to actually affect anyone in practice, because I doubt that anyone has actually written such code. Thus it fits easily inside the stability-retention guidelines. I do not believe any RFC is required, nor any ability to disable the new behaviour. |
Not this exact code, sure. But maybe an opcode dispatch switch that handles all possible byte values? Or one that handles all undefined opcodes with an arm like |
Hmm, good point. I myself have just changed the last branch into |
I wrote a bit of code that at least seems to work semi-correctly for a few test cases: https://play.rust-lang.org/?gist=f3d4e2e9559d84319432&version=stable It's Feel free to |
For reference, @quantheory wrote an RFC about this - rust-lang/rfcs#880, it was postponed. He wrote some implementation too https://github.com/quantheory/int_range_check. |
FWIW, GCC can do this: https://goo.gl/4f1i6H (no warning, but a warning appears if you change 255 to something else). Clang can't tell the difference. |
I'm going to close this in favor of an RFC, as this would be a pretty big change. @quantheory's might be a good starting point! |
Rust's exhaustiveness checking is based entirely on enums and never values, so this fails because u8 simply isn't an enum type. error[E0004]: non-exhaustive patterns: `_` not covered --> src/main.rs:39:26 | 39 | let op_bytes = match op_code { | ^^^^^^^ pattern `_` not covered rust-lang/rust#12483
fix methods in pub trait generated by macro cannot be completed Fix rust-lang#12483 Check if the container is trait and inherit the visibility to associate items during collection.
The following function does not compile because rustc determines that the patterns in the match statement are non-exhaustive. However, the pattern matches every possible value of the integer type, and the compiler should be able to detect this.
The text was updated successfully, but these errors were encountered: