From b66973043e555f3a24a50a227db76b0a069ea037 Mon Sep 17 00:00:00 2001
From: Nadrieril <nadrieril+git@gmail.com>
Date: Sun, 3 Nov 2019 23:10:33 +0000
Subject: [PATCH] Don't use max_slice_length when subtracting from VarLenSlice

This alters error messages slightly, but that'll be improved later
---
 src/librustc_mir/hair/pattern/_match.rs       | 33 ++++++++++++-------
 .../match-byte-array-patterns-2.stderr        |  4 +--
 2 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 31984daa5df..902d9b610ce 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -658,7 +658,6 @@ impl<'tcx> Constructor<'tcx> {
     // anything in `other_ctors`.
     fn subtract_ctors(
         &self,
-        pcx: PatCtxt<'tcx>,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         other_ctors: &Vec<Constructor<'tcx>>,
@@ -681,11 +680,7 @@ impl<'tcx> Constructor<'tcx> {
                 if other_ctors.iter().any(overlaps) { vec![] } else { vec![self.clone()] }
             }
             VarLenSlice(_) => {
-                let mut remaining_ctors = if let VarLenSlice(len) = self {
-                    (*len..pcx.max_slice_length + 1).map(FixedLenSlice).collect()
-                } else {
-                    vec![self.clone()]
-                };
+                let mut remaining_ctors = vec![self.clone()];
 
                 // For each used ctor, subtract from the current set of constructors.
                 // Naming: we remove the "neg" constructors from the "pos" ones.
@@ -704,6 +699,23 @@ impl<'tcx> Constructor<'tcx> {
                                         smallvec![pos_ctor]
                                     }
                                 }
+                                (VarLenSlice(pos_len), VarLenSlice(neg_len)) => {
+                                    if neg_len <= pos_len {
+                                        smallvec![]
+                                    } else {
+                                        (*pos_len..*neg_len).map(FixedLenSlice).collect()
+                                    }
+                                }
+                                (VarLenSlice(pos_len), FixedLenSlice(neg_len)) => {
+                                    if neg_len < pos_len {
+                                        smallvec![pos_ctor]
+                                    } else {
+                                        (*pos_len..*neg_len)
+                                            .map(FixedLenSlice)
+                                            .chain(Some(VarLenSlice(neg_len + 1)))
+                                            .collect()
+                                    }
+                                }
                                 _ if pos_ctor == *neg_ctor => smallvec![],
                                 _ => smallvec![pos_ctor],
                             }
@@ -1456,7 +1468,6 @@ impl<'tcx> IntRange<'tcx> {
 
 // A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`.
 struct MissingConstructors<'tcx> {
-    pcx: PatCtxt<'tcx>,
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     all_ctors: Vec<Constructor<'tcx>>,
@@ -1465,13 +1476,12 @@ struct MissingConstructors<'tcx> {
 
 impl<'tcx> MissingConstructors<'tcx> {
     fn new(
-        pcx: PatCtxt<'tcx>,
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         all_ctors: Vec<Constructor<'tcx>>,
         used_ctors: Vec<Constructor<'tcx>>,
     ) -> Self {
-        MissingConstructors { pcx, tcx, param_env, all_ctors, used_ctors }
+        MissingConstructors { tcx, param_env, all_ctors, used_ctors }
     }
 
     fn into_inner(self) -> (Vec<Constructor<'tcx>>, Vec<Constructor<'tcx>>) {
@@ -1490,7 +1500,7 @@ impl<'tcx> MissingConstructors<'tcx> {
     /// Iterate over all_ctors \ used_ctors
     fn iter<'a>(&'a self) -> impl Iterator<Item = Constructor<'tcx>> + Captures<'a> {
         self.all_ctors.iter().flat_map(move |req_ctor| {
-            req_ctor.subtract_ctors(self.pcx, self.tcx, self.param_env, &self.used_ctors)
+            req_ctor.subtract_ctors(self.tcx, self.param_env, &self.used_ctors)
         })
     }
 }
@@ -1633,8 +1643,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
         // non-wildcard patterns in the current column. To determine if
         // the set is empty, we can check that `.peek().is_none()`, so
         // we only fully construct them on-demand, because they're rarely used and can be big.
-        let missing_ctors =
-            MissingConstructors::new(pcx, cx.tcx, cx.param_env, all_ctors, used_ctors);
+        let missing_ctors = MissingConstructors::new(cx.tcx, cx.param_env, all_ctors, used_ctors);
 
         debug!(
             "missing_ctors.empty()={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}",
diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
index d53e2e25b3d..9938c9c284d 100644
--- a/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
+++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
@@ -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