-
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 integer matching #50912
Merged
Merged
Exhaustive integer matching #50912
Changes from all commits
Commits
Show all changes
47 commits
Select commit
Hold shift + click to select a range
e3357d9
Implement interval checking
varkor b3d2baf
Give correct suggestions
varkor 384db4f
Add support for all integer types
varkor ed5a4d5
Add feature gate and refactor
varkor b8702a0
Add feature gate test
varkor 121fa8d
Fix handling of signed integers
varkor 7476ba4
Add semi-exhaustive tests for exhaustiveness
varkor 9778a81
Improve macros with reduced repetition
varkor a20cb10
Require just the Unicode Scalar Values to be matched for a char
varkor 7f72030
Fix range splitting
varkor c00fd8f
Refactor interval conditions
varkor 7695bd0
Use bit operators for min_max_ty
varkor a553fa7
Fix integer overflow
varkor 8389972
Add singleton patterns to test
varkor f4af3b0
Refactor to remove explicit integer type matching
varkor a9f2c5a
Fix sign conversion arithmetic errors
varkor effb3d0
Improve the comments
varkor c388c11
Special-case (RangeEnd::Included, Ordering::Equal) in lower_pattern_u…
varkor 97a032e
Simplify bitwise operations
varkor be12b24
Fix print_miri_value for signed integers
varkor 72cc4bd
Inline encode and decode methods
varkor 1aa7494
Introduce signed_bias method
varkor 732d638
Replace ... with ..= in suggestions
varkor 6c21a03
Refactor after miri api changes
varkor d27c21c
Refactor for less allocation
varkor 07064de
No longer return value_constructors for all_constructors
varkor 25ba911
Add guarded arms to tests
varkor af366b0
Refactor condition
varkor bfc0807
Add some comments
varkor 4aa929c
Move witnesses inside push_wild_constructor
varkor 5959a35
Move logic from push_wild_constructor to apply_constructor
varkor bfc8ce3
Add a test for integer products
varkor 99754ad
Some reformatting
varkor 400cb14
Add a summary of the algorithm to the file
varkor 9e9e023
More formatting improvements
varkor 527cccb
Add some more compound exhaustiveness tests
varkor e9c8361
Add equivalence class splitting for range constructors
varkor 1dbc781
Handle equivalence classes of length-1 ranges
varkor 0383539
Fix handling of floating-point ranges
varkor 798b9ff
Tweak comments
varkor 87463c3
Improve some comments
varkor 6e8a625
Remove pattern consideration from split_grouped_constructors
varkor c421af9
Add assertion to constructor_intersects_pattern
varkor 61b6363
Add more detail to the split_grouped_constructors comment
varkor 6a957e1
Add a test case for u128::MAX - 1
varkor dec5563
Use a boundary method instead of an endpoint method for split_grouped…
varkor 6971c5d
Add some extra edge case tests
varkor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
#![feature(exhaustive_integer_patterns)] | ||
#![feature(exclusive_range_pattern)] | ||
#![deny(unreachable_patterns)] | ||
|
||
use std::{char, usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128}; | ||
|
||
fn main() { | ||
let x: u8 = 0; | ||
|
||
// A single range covering the entire domain. | ||
match x { | ||
0 ..= 255 => {} // ok | ||
} | ||
|
||
// A combination of ranges and values. | ||
// These are currently allowed to be overlapping. | ||
match x { | ||
0 ..= 32 => {} | ||
33 => {} | ||
34 .. 128 => {} | ||
100 ..= 200 => {} | ||
200 => {} //~ ERROR unreachable pattern | ||
201 ..= 255 => {} | ||
} | ||
|
||
// An incomplete set of values. | ||
match x { //~ ERROR non-exhaustive patterns | ||
0 .. 128 => {} | ||
} | ||
|
||
// A more incomplete set of values. | ||
match x { //~ ERROR non-exhaustive patterns | ||
0 ..= 10 => {} | ||
20 ..= 30 => {} | ||
35 => {} | ||
70 .. 255 => {} | ||
} | ||
|
||
let x: i8 = 0; | ||
match x { //~ ERROR non-exhaustive patterns | ||
-7 => {} | ||
-5..=120 => {} | ||
-2..=20 => {} //~ ERROR unreachable pattern | ||
125 => {} | ||
} | ||
|
||
// Let's test other types too! | ||
let c: char = '\u{0}'; | ||
match c { | ||
'\u{0}' ..= char::MAX => {} // ok | ||
} | ||
|
||
// We can actually get away with just covering the | ||
// following two ranges, which correspond to all | ||
// valid Unicode Scalar Values. | ||
match c { | ||
'\u{0000}' ..= '\u{D7FF}' => {} | ||
'\u{E000}' ..= '\u{10_FFFF}' => {} | ||
} | ||
|
||
match 0usize { | ||
0 ..= usize::MAX => {} // ok | ||
} | ||
|
||
match 0u16 { | ||
0 ..= u16::MAX => {} // ok | ||
} | ||
|
||
match 0u32 { | ||
0 ..= u32::MAX => {} // ok | ||
} | ||
|
||
match 0u64 { | ||
0 ..= u64::MAX => {} // ok | ||
} | ||
|
||
match 0u128 { | ||
0 ..= u128::MAX => {} // ok | ||
} | ||
|
||
match 0isize { | ||
isize::MIN ..= isize::MAX => {} // ok | ||
} | ||
|
||
match 0i8 { | ||
-128 ..= 127 => {} // ok | ||
} | ||
|
||
match 0i8 { //~ ERROR non-exhaustive patterns | ||
-127 ..= 127 => {} | ||
} | ||
|
||
match 0i16 { | ||
i16::MIN ..= i16::MAX => {} // ok | ||
} | ||
|
||
match 0i16 { //~ ERROR non-exhaustive patterns | ||
i16::MIN ..= -1 => {} | ||
1 ..= i16::MAX => {} | ||
} | ||
|
||
match 0i32 { | ||
i32::MIN ..= i32::MAX => {} // ok | ||
} | ||
|
||
match 0i64 { | ||
i64::MIN ..= i64::MAX => {} // ok | ||
} | ||
|
||
match 0i128 { | ||
i128::MIN ..= i128::MAX => {} // ok | ||
} | ||
|
||
// Make sure that guards don't factor into the exhaustiveness checks. | ||
match 0u8 { //~ ERROR non-exhaustive patterns | ||
0 .. 128 => {} | ||
128 ..= 255 if true => {} | ||
} | ||
|
||
match 0u8 { | ||
0 .. 128 => {} | ||
128 ..= 255 if false => {} | ||
128 ..= 255 => {} // ok, because previous arm was guarded | ||
} | ||
|
||
// Now things start getting a bit more interesting. Testing products! | ||
match (0u8, Some(())) { //~ ERROR non-exhaustive patterns | ||
(1, _) => {} | ||
(_, None) => {} | ||
} | ||
|
||
match (0u8, true) { //~ ERROR non-exhaustive patterns | ||
(0 ..= 125, false) => {} | ||
(128 ..= 255, false) => {} | ||
(0 ..= 255, true) => {} | ||
} | ||
|
||
match (0u8, true) { // ok | ||
(0 ..= 125, false) => {} | ||
(128 ..= 255, false) => {} | ||
(0 ..= 255, true) => {} | ||
(125 .. 128, false) => {} | ||
} | ||
|
||
match 0u8 { // ok | ||
0 .. 2 => {} | ||
1 ..= 2 => {} | ||
_ => {} | ||
} | ||
|
||
const LIM: u128 = u128::MAX - 1; | ||
match 0u128 { //~ ERROR non-exhaustive patterns | ||
0 ..= LIM => {} | ||
} | ||
|
||
match 0u128 { //~ ERROR non-exhaustive patterns | ||
0 ..= 4 => {} | ||
} | ||
|
||
match 0u128 { //~ ERROR non-exhaustive patterns | ||
4 ..= u128::MAX => {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
error: unreachable pattern | ||
--> $DIR/exhaustive_integer_patterns.rs:32:9 | ||
| | ||
LL | 200 => {} //~ ERROR unreachable pattern | ||
| ^^^ | ||
| | ||
note: lint level defined here | ||
--> $DIR/exhaustive_integer_patterns.rs:13:9 | ||
| | ||
LL | #![deny(unreachable_patterns)] | ||
| ^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:37:11 | ||
| | ||
LL | match x { //~ ERROR non-exhaustive patterns | ||
| ^ pattern `128u8..=255u8` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:42:11 | ||
| | ||
LL | match x { //~ ERROR non-exhaustive patterns | ||
| ^ patterns `11u8..=19u8`, `31u8..=34u8`, `36u8..=69u8` and 1 more not covered | ||
|
||
error: unreachable pattern | ||
--> $DIR/exhaustive_integer_patterns.rs:53:9 | ||
| | ||
LL | -2..=20 => {} //~ ERROR unreachable pattern | ||
| ^^^^^^^ | ||
|
||
error[E0004]: non-exhaustive patterns: `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:50:11 | ||
| | ||
LL | match x { //~ ERROR non-exhaustive patterns | ||
| ^ patterns `-128i8..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `-128i8` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:99:11 | ||
| | ||
LL | match 0i8 { //~ ERROR non-exhaustive patterns | ||
| ^^^ pattern `-128i8` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `0i16` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:107:11 | ||
| | ||
LL | match 0i16 { //~ ERROR non-exhaustive patterns | ||
| ^^^^ pattern `0i16` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `128u8..=255u8` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:125:11 | ||
| | ||
LL | match 0u8 { //~ ERROR non-exhaustive patterns | ||
| ^^^ pattern `128u8..=255u8` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:137:11 | ||
| | ||
LL | match (0u8, Some(())) { //~ ERROR non-exhaustive patterns | ||
| ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=255u8, Some(_))` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:142:11 | ||
| | ||
LL | match (0u8, true) { //~ ERROR non-exhaustive patterns | ||
| ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211455u128` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:162:11 | ||
| | ||
LL | match 0u128 { //~ ERROR non-exhaustive patterns | ||
| ^^^^^ pattern `340282366920938463463374607431768211455u128` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `5u128..=340282366920938463463374607431768211455u128` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:166:11 | ||
| | ||
LL | match 0u128 { //~ ERROR non-exhaustive patterns | ||
| ^^^^^ pattern `5u128..=340282366920938463463374607431768211455u128` not covered | ||
|
||
error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered | ||
--> $DIR/exhaustive_integer_patterns.rs:170:11 | ||
| | ||
LL | match 0u128 { //~ ERROR non-exhaustive patterns | ||
| ^^^^^ pattern `0u128..=3u128` not covered | ||
|
||
error: aborting due to 13 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0004`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
fn main() { | ||
let x: u8 = 0; | ||
match x { //~ ERROR non-exhaustive patterns: `_` not covered | ||
0 ..= 255 => {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0004]: non-exhaustive patterns: `_` not covered | ||
--> $DIR/feature-gate-exhaustive_integer_patterns.rs:13:11 | ||
| | ||
LL | match x { //~ ERROR non-exhaustive patterns: `_` not covered | ||
| ^ pattern `_` not covered | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0004`. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as resolved.
Sorry, something went wrong.