]> git.lizzy.rs Git - rust.git/commitdiff
Use VarLenSlice consistently when splitting constructors
authorNadrieril <nadrieril+git@gmail.com>
Tue, 5 Nov 2019 16:30:04 +0000 (16:30 +0000)
committerNadrieril <nadrieril+git@gmail.com>
Tue, 5 Nov 2019 18:32:26 +0000 (18:32 +0000)
The previous behaviour ignored slice lengths above a certain length
because it could not do otherwise. We now have VarLenSlice however, that
can represent the ignored lengths to make the algorithm more consistent.
This does not change the correctness of the algorithm, but makes it
easier to reason about.
As a nice side-effect, exhaustiveness errors have improved: they now
capture all missing lengths instead of only the shortest.

src/librustc_mir/hair/pattern/_match.rs
src/test/ui/pattern/usefulness/match-slice-patterns.rs
src/test/ui/pattern/usefulness/match-slice-patterns.stderr
src/test/ui/pattern/usefulness/slice-patterns.rs
src/test/ui/pattern/usefulness/slice-patterns.stderr

index 15f88334e8d5e2e6f36273bf489d61231ab94998..8d7e605f7c9aa70179a9702be474dbaec58a5e7d 100644 (file)
@@ -2042,7 +2042,7 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
                 //
                 // Of course, if fixed-length patterns exist, we must be sure
                 // that our length is large enough to miss them all, so
-                // we can pick `L = max(FIXED_LEN+1 ∪ {max(PREFIX_LEN) + max(SUFFIX_LEN)})`
+                // we can pick `L = max(max(FIXED_LEN)+1, max(PREFIX_LEN) + max(SUFFIX_LEN))`
                 //
                 // for example, with the above pair of patterns, all elements
                 // but the first and last can be added/removed, so any
@@ -2080,9 +2080,24 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
                     }
                 }
 
-                let max_slice_length = cmp::max(max_fixed_len + 1, max_prefix_len + max_suffix_len);
-                split_ctors
-                    .extend((self_prefix + self_suffix..=max_slice_length).map(FixedLenSlice))
+                // For diagnostics, we keep the prefix and suffix lengths separate, so in the case
+                // where `max_fixed_len+1` is the largest, we adapt `max_prefix_len` accordingly,
+                // so that `L = max_prefix_len + max_suffix_len`.
+                if max_fixed_len + 1 >= max_prefix_len + max_suffix_len {
+                    // The subtraction can't overflow thanks to the above check.
+                    // The new `max_prefix_len` is also guaranteed to be larger than its previous
+                    // value.
+                    max_prefix_len = max_fixed_len + 1 - max_suffix_len;
+                }
+
+                // `ctor` originally covered the range `(self_prefix + self_suffix..infinity)`. We
+                // now split it into two: lengths smaller than `max_prefix_len + max_suffix_len`
+                // are treated independently as fixed-lengths slices, and lengths above are
+                // captured by a final VarLenSlice constructor.
+                split_ctors.extend(
+                    (self_prefix + self_suffix..max_prefix_len + max_suffix_len).map(FixedLenSlice),
+                );
+                split_ctors.push(VarLenSlice(max_prefix_len, max_suffix_len));
             }
             // Any other constructor can be used unchanged.
             _ => split_ctors.push(ctor),
index afbeb61e4415af0cd799b08d37fbc2f8c7f24f7b..af7fd53a1f1e916dc505338cf469b4183ae8a094 100644 (file)
@@ -2,7 +2,7 @@
 
 fn check(list: &[Option<()>]) {
     match list {
-    //~^ ERROR `&[_, Some(_), None, _]` not covered
+    //~^ ERROR `&[_, Some(_), .., None, _]` not covered
         &[] => {},
         &[_] => {},
         &[_, _] => {},
index 24769db34c9322f252d1917967674717fc3448bb..72ae5d5fe3b33e172a1a499ee984a3d1ecc2c149 100644 (file)
@@ -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
 
index e11f11ba7524d233d9d78ff0b4315360843d68f7..da2d40caf1a4026b44558c17a383c868f554d32b 100644 (file)
@@ -37,7 +37,7 @@ fn main() {
         [.., false] => {}
     }
     match s {
-    //~^ ERROR `&[false, true]` not covered
+    //~^ ERROR `&[false, .., true]` not covered
         [] => {}
         [true, ..] => {}
         [.., false] => {}
@@ -57,18 +57,18 @@ fn main() {
         [_] => {}
     }
     match s {
-    //~^ ERROR `&[false]` not covered
+    //~^ ERROR `&[false, ..]` not covered
         [] => {}
         [true, ..] => {}
     }
     match s {
-    //~^ ERROR `&[false, _]` not covered
+    //~^ ERROR `&[false, _, ..]` not covered
         [] => {}
         [_] => {}
         [true, ..] => {}
     }
     match s {
-    //~^ ERROR `&[_, false]` not covered
+    //~^ ERROR `&[_, .., false]` not covered
         [] => {}
         [_] => {}
         [.., true] => {}
@@ -94,14 +94,14 @@ fn main() {
         [..] => {}
     }
     match s {
-    //~^ ERROR `&[_, _, true]` not covered
+    //~^ ERROR `&[_, _, .., true]` not covered
         [] => {}
         [_] => {}
         [_, _] => {}
         [.., false] => {}
     }
     match s {
-    //~^ ERROR `&[true, _, _]` not covered
+    //~^ ERROR `&[true, _, .., _]` not covered
         [] => {}
         [_] => {}
         [_, _] => {}
index 666e16627c57e0a090fd5ba542105ca4afc07c99..6afe4705b0e694c60b3943565c2a62e45a4c0f72 100644 (file)
@@ -14,11 +14,11 @@ LL |     match s3 {
    |
    = 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
+error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered
   --> $DIR/slice-patterns.rs:39:11
    |
 LL |     match s {
-   |           ^ pattern `&[false, true]` not covered
+   |           ^ pattern `&[false, .., true]` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
@@ -46,27 +46,27 @@ LL |     match s {
    |
    = 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
+error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered
   --> $DIR/slice-patterns.rs:59:11
    |
 LL |     match s {
-   |           ^ pattern `&[false]` not covered
+   |           ^ 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
+error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered
   --> $DIR/slice-patterns.rs:64:11
    |
 LL |     match s {
-   |           ^ pattern `&[false, _]` not covered
+   |           ^ 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
+error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered
   --> $DIR/slice-patterns.rs:70:11
    |
 LL |     match s {
-   |           ^ pattern `&[_, false]` not covered
+   |           ^ pattern `&[_, .., false]` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
@@ -112,19 +112,19 @@ error: unreachable pattern
 LL |         [false, true] => {}
    |         ^^^^^^^^^^^^^
 
-error[E0004]: non-exhaustive patterns: `&[_, _, true]` not covered
+error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered
   --> $DIR/slice-patterns.rs:96:11
    |
 LL |     match s {
-   |           ^ pattern `&[_, _, true]` not covered
+   |           ^ 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
+error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered
   --> $DIR/slice-patterns.rs:103:11
    |
 LL |     match s {
-   |           ^ pattern `&[true, _, _]` not covered
+   |           ^ pattern `&[true, _, .., _]` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms