Skip to content
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

Refactor pattern-matching usefulness algorithm #65160

Closed
wants to merge 87 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
c9b33ee
Run `rustfmt`
Nadrieril Sep 21, 2019
3ea9c9c
Remove mention of old slice pattern syntax
Nadrieril Sep 26, 2019
f983460
Clarify and fix the explanation of the algorithm
Nadrieril Sep 23, 2019
77e3a95
Abstract out pattern stacks to make the code more legible
Nadrieril Sep 26, 2019
e1b7627
Remove some redundancy
Nadrieril Sep 23, 2019
a075db8
Remove duplicate logic in compute_missing_constructors
Nadrieril Sep 23, 2019
7ee9cb7
Extract constructor application as a Constructor method
Nadrieril Sep 23, 2019
a150d97
Refactor "wild constructor" construction
Nadrieril Sep 23, 2019
f0e8c78
Clarify some variable names
Nadrieril Sep 23, 2019
8a2274b
`specialize` conceptually operates on a single pattern
Nadrieril Sep 23, 2019
0f5e02e
Wording
Nadrieril Sep 23, 2019
c95b7ae
Add some slice-pattern exhaustiveness tests
Nadrieril Sep 23, 2019
ea3fe4e
Rename Constructor::Slice to FixedLenSlice
Nadrieril Sep 23, 2019
d4cc125
IntRange::from_pat is redundant with pat_constructors
Nadrieril Sep 26, 2019
501cf3a
split_grouped_constructors only needs access to the list of used cons…
Nadrieril Sep 26, 2019
b2ae93c
Share computation of used_ctors
Nadrieril Sep 26, 2019
89df721
Rework the exhaustiveness algorithm to better integrate meta-construc…
Nadrieril Sep 27, 2019
1bd18d2
Define a MissingConstructors struct for cleanliness
Nadrieril Sep 27, 2019
ad28919
Move is_non_exhaustive into MissingConstructors
Nadrieril Sep 27, 2019
ec57a89
Allow Constructor::apply to return more than one pattern
Nadrieril Sep 27, 2019
6d9a35d
Define MissingConstructors meta-constructor and use it for witness re…
Nadrieril Sep 27, 2019
6e392f0
Match constructor first instead of type first in various functions
Nadrieril Sep 27, 2019
d9871b8
Move constructor_sub_pattern_tys into wildcard_subpatterns
Nadrieril Sep 27, 2019
cf90304
Replace wildcard-specific code paths with generalized specialization
Nadrieril Sep 28, 2019
931d7a9
Factor out some bits
Nadrieril Sep 28, 2019
142df8b
Extract constructor splitting as a Constructor method
Nadrieril Sep 28, 2019
cb4715d
Rename pop_constructor back to specialize
Nadrieril Sep 28, 2019
a1b3800
Add Wildcard meta-constructor
Nadrieril Sep 28, 2019
6337864
pat_constructors now returns Wildcard when relevant
Nadrieril Sep 28, 2019
c0359ce
Avoid allocating in the common case of a single pattern
Nadrieril Sep 28, 2019
33273f2
Invert condition for clarity
Nadrieril Sep 28, 2019
cb3452c
Clarify handling of uninhabited types
Nadrieril Sep 28, 2019
ad78eff
Gather together usefulness tests
Nadrieril Sep 28, 2019
a91cdd4
MatchCheckCtxt::byte_array_map is unused since 7df1d9f6564cafca3758e5…
Nadrieril Sep 30, 2019
8e89f3c
No need to mutate MatchCheckCtxt anymore
Nadrieril Sep 30, 2019
9ae4c52
Add comment about non_exhaustive feature
Nadrieril Sep 30, 2019
b3de6fd
Use Wildcard instead of MissingConstructors when relevant
Nadrieril Sep 30, 2019
4be3802
Make IntRange::subtract_from work on a single constructor
Nadrieril Sep 30, 2019
d12b172
Factor out constructor subtraction
Nadrieril Sep 30, 2019
2687140
subtract_meta_constructor: match on constructor first
Nadrieril Oct 1, 2019
1f8d93c
Extract constructor_intersects_pattern function
Nadrieril Oct 6, 2019
1b65bec
Inline constructor_covered_by_range and IntRange::from_pat
Nadrieril Oct 1, 2019
12bb3b7
Use question mark instead of custom macro
Nadrieril Oct 1, 2019
022c620
Regroup similar code paths
Nadrieril Oct 1, 2019
0ab764b
Add a few more slice pattern usefulness tests
Nadrieril Oct 2, 2019
956838d
Add variable-length slice metaconstructor
Nadrieril Oct 2, 2019
1793ad5
Don't use max_slice_length when subtracting from VarLenSlice
Nadrieril Oct 2, 2019
527fe65
Faster code path for subtracting from FixedLenSlice
Nadrieril Oct 2, 2019
0d58ead
Faster code path for subtracting from VarLenSlice
Nadrieril Oct 5, 2019
0b353b3
Make exhaustiveness error message more consistent for slice patterns
Nadrieril Oct 5, 2019
cf4dc88
Prepare return types for or-patterns
Nadrieril Oct 5, 2019
1e43487
MissingConstructors should not be compared for equality, but we need …
Nadrieril Oct 5, 2019
c8ac41e
Add example run of the algorithm
Nadrieril Oct 5, 2019
244ac8d
Tidy up
Nadrieril Oct 5, 2019
ad09cc5
Store both prefix and suffix length in VarLenSlice
Nadrieril Oct 5, 2019
47ee628
max_slice_length only needs to look at constructors
Nadrieril Oct 5, 2019
c6d1cad
Inline max_slice_length
Nadrieril Oct 5, 2019
0c0fe9f
Add some test cases
Nadrieril Oct 5, 2019
6b4426a
Splitting variable-length slices now respects the required invariant
Nadrieril Oct 5, 2019
72c3a68
PatCtxt is not useful anymore
Nadrieril Oct 6, 2019
f5d833f
Cleanup comments
Nadrieril Oct 5, 2019
94227f5
Store Const in ConstantRange
Nadrieril Oct 6, 2019
60021ce
Cleanup constructor_intersects_pattern
Nadrieril Oct 6, 2019
3d0945d
Implement nnethercote's suggestion
Nadrieril Oct 7, 2019
5badbb7
Implement Centril's suggestion
Nadrieril Oct 7, 2019
defc66d
Incorporate varkor's review
Nadrieril Oct 11, 2019
d8b71d4
Be more consistent in terminology
Nadrieril Oct 11, 2019
66dac52
Move range exhaustiveness check to IntRange::intersection
Nadrieril Oct 11, 2019
b85e4be
Introduce IntRange meta-constructor
Nadrieril Oct 11, 2019
eea0b79
We no longer construct any ConstantValue or ConstantRange for non-int…
Nadrieril Oct 11, 2019
34b0774
Remove some unnecessary conversions between Constructor and IntRange
Nadrieril Oct 11, 2019
087adfe
Ungate improved slice patterns diagnostics
Nadrieril Oct 12, 2019
a66dcd5
Simplify slice subtraction as suggested by arielb1
Nadrieril Oct 12, 2019
a2624f2
Rewrite constructor_intersects_pattern as a match
Nadrieril Oct 12, 2019
79efdb4
Remove unnecessary Const conversion
Nadrieril Oct 12, 2019
1f6a5a5
Clarify why the naive algorithm may not terminate
Nadrieril Oct 12, 2019
455095a
Remove unneeded lifetime extensions
Nadrieril Oct 14, 2019
d379a43
Use special `Captures` trait to solve issues with impl Iterator
Nadrieril Oct 14, 2019
1de1683
`pat_constructors` doesn't need a `ty` parameter
Nadrieril Oct 16, 2019
3aa5fb3
Extract head constructors construction
Nadrieril Oct 17, 2019
c956c65
Name the field of PatStack
Nadrieril Oct 17, 2019
368c71b
Cache `pat_constructors` invocations
Nadrieril Oct 17, 2019
6df1815
Compute constructors on PatStack construction
Nadrieril Oct 17, 2019
ed3ea67
Restore performance
Nadrieril Oct 17, 2019
9c3682f
Don't rebuild the same matrix twice
Nadrieril Oct 17, 2019
b052036
Don't use SmallVec when we could use Option
Nadrieril Oct 18, 2019
fd3ec66
Integrate comment fixes suggested by arielb1
Nadrieril Oct 18, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,775 changes: 1,524 additions & 1,251 deletions src/librustc_mir/hair/pattern/_match.rs

Large diffs are not rendered by default.

252 changes: 137 additions & 115 deletions src/librustc_mir/hair/pattern/check_match.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/test/ui/consts/const_let_refutable.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _]` not covered
error[E0005]: refutable pattern in function argument: `&[]`, `&[_]` and `&[_, _, _, ..]` not covered
--> $DIR/const_let_refutable.rs:3:16
|
LL | const fn slice([a, b]: &[i32]) -> i32 {
| ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _]` not covered
| ^^^^^^ patterns `&[]`, `&[_]` and `&[_, _, _, ..]` not covered

error[E0723]: can only call other `const fn` within a `const fn`, but `const <&i32 as std::ops::Add>::add` is not stable as `const fn`
--> $DIR/const_let_refutable.rs:4:5
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
error[E0004]: non-exhaustive patterns: `(true, false)` not covered
--> $DIR/match-argm-statics-2.rs:17:11
--> $DIR/match-arm-statics-2.rs:17:11
|
LL | match (true, false) {
| ^^^^^^^^^^^^^ pattern `(true, false)` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `Some(Some(West))` not covered
--> $DIR/match-argm-statics-2.rs:29:11
--> $DIR/match-arm-statics-2.rs:29:11
|
LL | match Some(Some(North)) {
| ^^^^^^^^^^^^^^^^^ pattern `Some(Some(West))` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }` not covered
--> $DIR/match-argm-statics-2.rs:48:11
--> $DIR/match-arm-statics-2.rs:48:11
|
LL | / struct Foo {
LL | | bar: Option<Direction>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ LL | match buf {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
error[E0004]: non-exhaustive patterns: `&[..]` not covered
--> $DIR/match-byte-array-patterns-2.rs:10:11
|
LL | match buf {
| ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 3 more not covered
| ^^^ pattern `&[..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

fn check(list: &[Option<()>]) {
match list {
//~^ ERROR `&[_, Some(_), None, _]` not covered
//~^ ERROR `&[_, Some(_), .., None, _]` not covered
Nadrieril marked this conversation as resolved.
Show resolved Hide resolved
&[] => {},
&[_] => {},
&[_, _] => {},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0004]: non-exhaustive patterns: `&[_, Some(_), None, _]` not covered
error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered
--> $DIR/match-slice-patterns.rs:4:11
|
LL | match list {
| ^^^^ pattern `&[_, Some(_), None, _]` not covered
| ^^^^ pattern `&[_, Some(_), .., None, _]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ fn main() {
}
let vec = vec![0.5f32];
let vec: &[f32] = &vec;
match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _]` not covered
match *vec { //~ ERROR non-exhaustive patterns: `[_, _, _, _, ..]` not covered
Nadrieril marked this conversation as resolved.
Show resolved Hide resolved
[0.1, 0.2, 0.3] => (),
[0.1, 0.2] => (),
[0.1] => (),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ LL | match *vec {
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `[_, _, _, _]` not covered
error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered
--> $DIR/non-exhaustive-match.rs:47:11
|
LL | match *vec {
| ^^^^ pattern `[_, _, _, _]` not covered
| ^^^^ pattern `[_, _, _, _, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

Expand Down
110 changes: 110 additions & 0 deletions src/test/ui/pattern/usefulness/slice-patterns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#![feature(slice_patterns)]
#![deny(unreachable_patterns)]

fn main() {
let s: &[bool] = &[true; 0];
let s0: &[bool; 0] = &[];
let s1: &[bool; 1] = &[false; 1];
let s2: &[bool; 2] = &[false; 2];
let s3: &[bool; 3] = &[false; 3];

let [] = s0;
let [_] = s1;
let [_, _] = s2;

let [..] = s;
let [..] = s0;
let [..] = s1;
let [..] = s2;
let [..] = s3;

let [_, _, ..] = s2;
let [_, .., _] = s2;
let [.., _, _] = s2;

match s1 {
[true, ..] => {}
[.., false] => {}
}
match s2 {
//~^ ERROR `&[false, true]` not covered
[true, ..] => {}
[.., false] => {}
}
match s3 {
//~^ ERROR `&[false, _, true]` not covered
[true, ..] => {}
[.., false] => {}
}
match s {
//~^ ERROR `&[false, .., true]` not covered
[] => {}
[true, ..] => {}
[.., false] => {}
}

match s3 {
//~^ ERROR `&[false, _, _]` not covered
[true, .., true] => {}
}
match s {
//~^ ERROR `&[_, ..]` not covered
[] => {}
}
match s {
//~^ ERROR `&[_, _, ..]` not covered
[] => {}
[_] => {}
}
match s {
//~^ ERROR `&[false, ..]` not covered
[] => {}
[true, ..] => {}
}
match s {
//~^ ERROR `&[false, _, ..]` not covered
[] => {}
[_] => {}
[true, ..] => {}
}
match s {
//~^ ERROR `&[_, .., false]` not covered
[] => {}
[_] => {}
[.., true] => {}
}

match s {
[true, ..] => {}
[true, ..] => {} //~ ERROR unreachable pattern
[true] => {} //~ ERROR unreachable pattern
[..] => {}
}
match s {
[.., true] => {}
[.., true] => {} //~ ERROR unreachable pattern
[true] => {} //~ ERROR unreachable pattern
[..] => {}
}
match s {
[false, .., true] => {}
[false, .., true] => {} //~ ERROR unreachable pattern
[false, true] => {} //~ ERROR unreachable pattern
[false] => {}
[..] => {}
}
match s {
//~^ ERROR `&[_, _, .., true]` not covered
[] => {}
[_] => {}
[_, _] => {}
[.., false] => {}
}
match s {
//~^ ERROR `&[true, _, .., _]` not covered
[] => {}
[_] => {}
[_, _] => {}
[false, .., false] => {}
}
}
133 changes: 133 additions & 0 deletions src/test/ui/pattern/usefulness/slice-patterns.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
error[E0004]: non-exhaustive patterns: `&[false, true]` not covered
--> $DIR/slice-patterns.rs:29:11
|
LL | match s2 {
| ^^ pattern `&[false, true]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[false, _, true]` not covered
--> $DIR/slice-patterns.rs:34:11
|
LL | match s3 {
| ^^ pattern `&[false, _, true]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
--> $DIR/slice-patterns.rs:39:11
|
LL | match s {
| ^ pattern `&[false, .., true]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[false, _, _]` not covered
--> $DIR/slice-patterns.rs:46:11
|
LL | match s3 {
| ^^ pattern `&[false, _, _]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/slice-patterns.rs:50:11
|
LL | match s {
| ^ pattern `&[_, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
--> $DIR/slice-patterns.rs:54:11
|
LL | match s {
| ^ pattern `&[_, _, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
--> $DIR/slice-patterns.rs:59:11
|
LL | match s {
| ^ pattern `&[false, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
--> $DIR/slice-patterns.rs:64:11
|
LL | match s {
| ^ pattern `&[false, _, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
--> $DIR/slice-patterns.rs:70:11
|
LL | match s {
| ^ pattern `&[_, .., false]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error: unreachable pattern
--> $DIR/slice-patterns.rs:79:9
|
LL | [true, ..] => {}
| ^^^^^^^^^^
|
note: lint level defined here
--> $DIR/slice-patterns.rs:2:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/slice-patterns.rs:80:9
|
LL | [true] => {}
| ^^^^^^

error: unreachable pattern
--> $DIR/slice-patterns.rs:85:9
|
LL | [.., true] => {}
| ^^^^^^^^^^

error: unreachable pattern
--> $DIR/slice-patterns.rs:86:9
|
LL | [true] => {}
| ^^^^^^

error: unreachable pattern
--> $DIR/slice-patterns.rs:91:9
|
LL | [false, .., true] => {}
| ^^^^^^^^^^^^^^^^^

error: unreachable pattern
--> $DIR/slice-patterns.rs:92:9
|
LL | [false, true] => {}
| ^^^^^^^^^^^^^

error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
--> $DIR/slice-patterns.rs:96:11
|
LL | match s {
| ^ pattern `&[_, _, .., true]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
--> $DIR/slice-patterns.rs:103:11
|
LL | match s {
| ^ pattern `&[true, _, .., _]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error: aborting due to 17 previous errors

For more information about this error, try `rustc --explain E0004`.
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ LL | let _ = match x {};
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

error[E0004]: non-exhaustive patterns: `&[_]` not covered
error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
--> $DIR/uninhabited-matches-feature-gated.rs:21:19
|
LL | let _ = match x {
| ^ pattern `&[_]` not covered
| ^ pattern `&[_, ..]` not covered
|
= help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms

Expand Down