]> git.lizzy.rs Git - rust.git/commitdiff
Implement destructuring for all aggregates and for references
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Wed, 1 Jul 2020 13:10:51 +0000 (15:10 +0200)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Sun, 20 Sep 2020 11:28:18 +0000 (13:28 +0200)
18 files changed:
compiler/rustc_mir/src/const_eval/mod.rs
compiler/rustc_mir_build/src/build/matches/test.rs
compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
library/std/src/ffi/os_str.rs
src/test/ui/consts/consts-in-patterns.rs
src/test/ui/consts/match_ice.rs
src/test/ui/consts/match_ice.stderr
src/test/ui/match/pattern-deref-miscompile.rs [new file with mode: 0644]
src/test/ui/pattern/const-pat-ice.rs
src/test/ui/pattern/const-pat-ice.stderr [deleted file]
src/test/ui/pattern/usefulness/exhaustive_integer_patterns.rs
src/test/ui/pattern/usefulness/exhaustive_integer_patterns.stderr
src/test/ui/pattern/usefulness/slice-pattern-const-2.rs
src/test/ui/pattern/usefulness/slice-pattern-const-2.stderr
src/test/ui/pattern/usefulness/slice-pattern-const-3.rs
src/test/ui/pattern/usefulness/slice-pattern-const-3.stderr
src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr

index 451fa1458fda82b6310a09a6adb625774ca826ad..978d2fe000468bc81535b66543a42eb1a3b50da2 100644 (file)
@@ -93,8 +93,7 @@ pub(crate) fn deref_const<'tcx>(
         MemPlaceMeta::None => mplace.layout.ty,
         MemPlaceMeta::Poison => bug!("poison metadata in `deref_const`: {:#?}", mplace),
         // In case of unsized types, figure out the real type behind.
-        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind {
-            ty::Dynamic(..) => ecx.read_drop_type_from_vtable(scalar).unwrap().1,
+        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
             ty::Str => bug!("there's no sized equivalent of a `str`"),
             ty::Slice(elem_ty) => tcx.mk_array(elem_ty, scalar.to_machine_usize(&tcx).unwrap()),
             _ => bug!(
index d81c3b68f4853d27f3c1ce63d821a9b3f64013d4..796815cf2168c9f98d5398f7768f7a288c604445 100644 (file)
@@ -409,7 +409,40 @@ fn non_scalar_compare(
 
         let deref_ty = match *ty.kind() {
             ty::Ref(_, deref_ty, _) => deref_ty,
-            _ => bug!("non_scalar_compare called on non-reference type: {}", ty),
+            _ => {
+                trace!("non_scalar_compare called on non-reference type: {}", ty);
+                // Backcompat hack: due to non-structural matches not being a hard error, we can
+                // reach this for types that have manual `Eq` or `PartialEq` impls.
+                assert!(!ty.is_structural_eq_shallow(self.hir.tcx()));
+                let ref_ty = self.hir.tcx().mk_imm_ref(self.hir.tcx().lifetimes.re_erased, ty);
+                // let y = &place;
+                let y = self.temp(ref_ty, source_info.span);
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    y,
+                    Rvalue::Ref(self.hir.tcx().lifetimes.re_erased, BorrowKind::Shared, place),
+                );
+                val = Operand::Move(y);
+                // let temp = expect;
+                let temp = self.temp(ty, source_info.span);
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    temp,
+                    Rvalue::Use(expect),
+                );
+                // reftemp = &temp;
+                let reftemp = self.temp(ref_ty, source_info.span);
+                self.cfg.push_assign(
+                    block,
+                    source_info,
+                    reftemp,
+                    Rvalue::Ref(self.hir.tcx().lifetimes.re_erased, BorrowKind::Shared, temp),
+                );
+                expect = Operand::Move(reftemp);
+                ty
+            },
         };
 
         let eq_def_id = self.hir.tcx().require_lang_item(LangItem::PartialEq, None);
index 55b583842981048c5bd155096285f2ba2da41512..d47c3e7e3aba1c1534d46dd1269f00db0e3e239c 100644 (file)
@@ -28,10 +28,13 @@ pub(super) fn const_to_pat(
         debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
         debug!("const_to_pat: cv.ty={:?} span={:?}", cv.ty, span);
 
-        self.tcx.infer_ctxt().enter(|infcx| {
+        let pat = self.tcx.infer_ctxt().enter(|infcx| {
             let mut convert = ConstToPat::new(self, id, span, infcx);
             convert.to_pat(cv, mir_structural_match_violation)
-        })
+        });
+
+        debug!("const_to_pat: pat={:?}", pat);
+        pat
     }
 }
 
@@ -45,6 +48,10 @@ struct ConstToPat<'a, 'tcx> {
     // value.
     saw_const_match_error: Cell<bool>,
 
+    // For backcompat we need to keep allowing non-structurally-eq types behind references.
+    // See also all the `cant-hide-behind` tests.
+    behind_reference: Cell<bool>,
+
     // inference context used for checking `T: Structural` bounds.
     infcx: InferCtxt<'a, 'tcx>,
 
@@ -65,6 +72,7 @@ fn new(
             param_env: pat_ctxt.param_env,
             include_lint_checks: pat_ctxt.include_lint_checks,
             saw_const_match_error: Cell::new(false),
+            behind_reference: Cell::new(false),
         }
     }
 
@@ -233,7 +241,18 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
                 tcx.sess.span_err(span, "cannot use unions in constant patterns");
                 PatKind::Wild
             }
-            // keep old code until future-compat upgraded to errors.
+            // If the type is not structurally comparable, just emit the constant directly,
+            // causing the pattern match code to treat it opaquely.
+            // FIXME: This code doesn't emit errors itself, the caller emits the errors.
+            // So instead of specific errors, you just get blanket errors about the whole
+            // const type. See
+            // https://github.com/rust-lang/rust/pull/70743#discussion_r404701963 for
+            // details.
+            // Backwards compatibility hack because we can't cause hard errors on these
+            // types, so we compare them via `PartialEq::eq` at runtime.
+            ty::Adt(..) if !self.type_marked_structural(cv.ty) && self.behind_reference.get() => {
+                PatKind::Constant { value: cv }
+            }
             ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty) => {
                 debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, cv.ty);
                 let path = tcx.def_path_str(adt_def.did);
@@ -246,28 +265,6 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
                 tcx.sess.span_err(span, &msg);
                 PatKind::Wild
             }
-            // keep old code until future-compat upgraded to errors.
-            ty::Ref(_, adt_ty, _) if adt_ty.is_adt() && !self.type_marked_structural(adt_ty) => {
-                let adt_def =
-                    if let ty::Adt(adt_def, _) = adt_ty.kind() { adt_def } else { unreachable!() };
-
-                debug!(
-                    "adt_def {:?} has !type_marked_structural for adt_ty: {:?}",
-                    adt_def, adt_ty
-                );
-
-                // HACK(estebank): Side-step ICE #53708, but anything other than erroring here
-                // would be wrong. Returnging `PatKind::Wild` is not technically correct.
-                let path = tcx.def_path_str(adt_def.did);
-                let msg = format!(
-                    "to use a constant of type `{}` in a pattern, \
-                     `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                    path, path,
-                );
-                self.saw_const_match_error.set(true);
-                tcx.sess.span_err(span, &msg);
-                PatKind::Wild
-            }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
                 let destructured = tcx.destructure_const(param_env.and(cv));
                 PatKind::Variant {
@@ -293,7 +290,68 @@ fn recur(&self, cv: &'tcx ty::Const<'tcx>) -> Pat<'tcx> {
                 slice: None,
                 suffix: Vec::new(),
             },
-            _ => PatKind::Constant { value: cv },
+            ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
+                // These are not allowed and will error elsewhere anyway.
+                ty::Dynamic(..) => PatKind::Constant { value: cv },
+                // `&str` and `&[u8]` are represented as `ConstValue::Slice`, let's keep using this
+                // optimization for now.
+                ty::Str => PatKind::Constant { value: cv },
+                ty::Slice(elem_ty) if elem_ty == tcx.types.u8 => PatKind::Constant { value: cv },
+                // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
+                // matching against references, you can only use byte string literals.
+                // FIXME: clean this up, likely by permitting array patterns when matching on slices
+                ty::Array(elem_ty, _) if elem_ty == tcx.types.u8 => PatKind::Constant { value: cv },
+                // Cannot merge this with the catch all branch below, because the `const_deref`
+                // changes the type from slice to array, and slice patterns behave differently from
+                // array patterns.
+                ty::Slice(..) => {
+                    let old = self.behind_reference.replace(true);
+                    let array = tcx.deref_const(self.param_env.and(cv));
+                    let val = PatKind::Deref {
+                        subpattern: Pat {
+                            kind: Box::new(PatKind::Slice {
+                                prefix: tcx
+                                    .destructure_const(param_env.and(array))
+                                    .fields
+                                    .iter()
+                                    .map(|val| self.recur(val))
+                                    .collect(),
+                                slice: None,
+                                suffix: vec![],
+                            }),
+                            span,
+                            ty: pointee_ty,
+                        },
+                    };
+                    self.behind_reference.set(old);
+                    val
+                }
+                // Backwards compatibility hack. Don't take away the reference, since
+                // `PartialEq::eq` takes a reference, this makes the rest of the matching logic
+                // simpler.
+                ty::Adt(..) if !self.type_marked_structural(pointee_ty) => {
+                    PatKind::Constant { value: cv }
+                }
+                _ => {
+                    let old = self.behind_reference.replace(true);
+                    let val = PatKind::Deref {
+                        subpattern: self.recur(tcx.deref_const(self.param_env.and(cv))),
+                    };
+                    self.behind_reference.set(old);
+                    val
+                }
+            },
+            ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
+                PatKind::Constant { value: cv }
+            }
+            // FIXME: these can have very suprising behaviour where optimization levels or other
+            // compilation choices change the runtime behaviour of the match.
+            // See https://github.com/rust-lang/rust/issues/70861 for examples.
+            ty::FnPtr(..) | ty::RawPtr(..) => PatKind::Constant { value: cv },
+            _ => {
+                tcx.sess.delay_span_bug(span, &format!("cannot make a pattern out of {}", cv.ty));
+                PatKind::Wild
+            }
         };
 
         Pat { span, ty: cv.ty, kind: Box::new(kind) }
index c83e996634c8a6e79ca4a9637c898f106fdad6ee..2663f682a1de82ab490e61e70bedf21c5ced597d 100644 (file)
@@ -94,7 +94,7 @@ pub struct OsString {
 // `OsStr::from_inner` current implementation relies
 // on `OsStr` being layout-compatible with `Slice`.
 // When attribute privacy is implemented, `OsStr` should be annotated as `#[repr(transparent)]`.
-// Anyway, `OsStr` representation and layout are considered implementation detail, are
+// Anyway, `OsStr` representation and layout are considered implementation details, are
 // not documented and must not be relied upon.
 pub struct OsStr {
     inner: Slice,
index d51215447d6cac05dae1319b45ccecbdc63d0bea..0295204c879ca8d12c1863b8c94c3140c8264e97 100644 (file)
@@ -19,8 +19,6 @@ pub fn main() {
     assert_eq!(y, 2);
     let z = match &() {
         ZST => 9,
-        // FIXME: this should not be required
-        _ => 42,
     };
     assert_eq!(z, 9);
     let z = match b"" {
index 1e495438e836cde041550816c42937d560bcc265..008c03ecddcc6f775e73377d13a12086188d10cd 100644 (file)
@@ -10,10 +10,9 @@ fn main() {
     match C {
         C => {}
         //~^ ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
-        //~| ERROR to use a constant of type `S` in a pattern, `S` must be annotated with
     }
     const K: &T = &T;
-    match K { //~ ERROR non-exhaustive patterns: `&T` not covered
+    match K {
         K => {}
     }
 }
index 5477170fb1e4162cd9659629ff11ad0b13b5cc6c..699b4a5e200e41311cfaabfdde075b812b89098e 100644 (file)
@@ -4,24 +4,5 @@ error: to use a constant of type `S` in a pattern, `S` must be annotated with `#
 LL |         C => {}
    |         ^
 
-error[E0004]: non-exhaustive patterns: `&T` not covered
-  --> $DIR/match_ice.rs:16:11
-   |
-LL | struct T;
-   | --------- `T` defined here
-...
-LL |     match K {
-   |           ^ pattern `&T` not covered
-   |
-   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
-   = note: the matched value is of type `&T`
-
-error: to use a constant of type `S` in a pattern, `S` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/match_ice.rs:11:9
-   |
-LL |         C => {}
-   |         ^
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/match/pattern-deref-miscompile.rs b/src/test/ui/match/pattern-deref-miscompile.rs
new file mode 100644 (file)
index 0000000..caa6d18
--- /dev/null
@@ -0,0 +1,46 @@
+// run-pass
+
+fn main() {
+    match b"." as &[u8] {
+        b"." if true => {},
+        b"." => panic!(),
+        b".." => panic!(),
+        b"" => panic!(),
+        _ => panic!(),
+    }
+    match b"." as &[u8] {
+        b"." if false => panic!(),
+        b"." => {},
+        b".." => panic!(),
+        b"" => panic!(),
+        _ => panic!(),
+    }
+    match b".." as &[u8] {
+        b"." if true => panic!(), // the miscompile caused this arm to be reached
+        b"." => panic!(),
+        b".." => {},
+        b"" => panic!(),
+        _ => panic!(),
+    }
+    match b".." as &[u8] {
+        b"." if false => panic!(),
+        b"." => panic!(),
+        b".." => {},
+        b"" => panic!(),
+        _ => panic!(),
+    }
+    match b"" as &[u8] {
+        b"." if true => panic!(),
+        b"." => panic!(),
+        b".." => panic!(),
+        b"" => {},
+        _ => panic!(),
+    }
+    match b"" as &[u8] {
+        b"." if false => panic!(),
+        b"." => panic!(),
+        b".." => panic!(),
+        b"" => {},
+        _ => panic!(),
+    }
+}
index 06558767882148d3f1159b7e199c8035e29f3e40..abfacf3936b6dd61d00415f37fcaa0d74a456769 100644 (file)
@@ -1,10 +1,4 @@
-// failure-status: 101
-// rustc-env:RUST_BACKTRACE=0
-// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET"
-// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS"
-// normalize-stderr-test "/_match.rs:[0-9]+:[0-9]+" -> "/_match.rs:LL:CC"
-
-// This is a repro test for an ICE in our pattern handling of constants.
+// check-pass
 
 const FOO: &&&u32 = &&&42;
 
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
deleted file mode 100644 (file)
index 6b42c0e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', compiler/rustc_mir_build/src/thir/pattern/_match.rs:LL:CC
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
-
-note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md
-
-note: rustc VERSION running on TARGET
-
-note: compiler flags: FLAGS
-
index d379dc44bf10b86682f460e9a3139eb885c6eb36..78cc0d28fb0375b56f314e9079ef3815eabde3eb 100644 (file)
@@ -160,7 +160,7 @@ fn main() {
     match &0 {
         &42 => {}
         &FOO => {} //~ ERROR unreachable pattern
-        BAR => {} // Not detected as unreachable because `try_eval_bits` fails on `BAR`.
+        BAR => {} //~ ERROR unreachable pattern
         _ => {}
     }
 
index de8315205980c14b08209b2341dcac78baa66280..9f076c50a8f09999c167d3aaf5ea37918c39d397 100644 (file)
@@ -135,6 +135,12 @@ error: unreachable pattern
 LL |         &FOO => {}
    |         ^^^^
 
-error: aborting due to 15 previous errors
+error: unreachable pattern
+  --> $DIR/exhaustive_integer_patterns.rs:163:9
+   |
+LL |         BAR => {}
+   |         ^^^
+
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
index a36c550f530a9a0f90113cb0f112b4db701a1532..4bf8d0fd2d306064ca283b6dc13e36c9e800d22a 100644 (file)
@@ -6,19 +6,19 @@ fn main() {
     match s {
         MAGIC_TEST => (),
         [0x00, 0x00, 0x00, 0x00] => (),
-        [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
+        [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         [0x00, 0x00, 0x00, 0x00] => (),
         MAGIC_TEST => (),
-        [4, 5, 6, 7] => (), // FIXME(oli-obk): this should warn, but currently does not
+        [4, 5, 6, 7] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         [0x00, 0x00, 0x00, 0x00] => (),
         [4, 5, 6, 7] => (),
-        MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+        MAGIC_TEST => (), //~ ERROR unreachable pattern
         _ => (),
     }
     const FOO: [u32; 1] = [4];
index cd0cb2e887691b927636d87356657a11ac8c6e86..dcad11a38a7ebadd8bc0b6350afd8f355a450b1c 100644 (file)
@@ -1,8 +1,8 @@
 error: unreachable pattern
-  --> $DIR/slice-pattern-const-2.rs:28:9
+  --> $DIR/slice-pattern-const-2.rs:9:9
    |
-LL |         FOO => (),
-   |         ^^^
+LL |         [4, 5, 6, 7] => (),
+   |         ^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/slice-pattern-const-2.rs:1:9
@@ -10,5 +10,23 @@ note: the lint level is defined here
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:15:9
+   |
+LL |         [4, 5, 6, 7] => (),
+   |         ^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:21:9
+   |
+LL |         MAGIC_TEST => (),
+   |         ^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-2.rs:28:9
+   |
+LL |         FOO => (),
+   |         ^^^
+
+error: aborting due to 4 previous errors
 
index 8805c43ba0283bdabe7f46093ee46b6be341470b..2ca8323f00295dfb780efa71683b002a5c7c24e8 100644 (file)
@@ -6,19 +6,19 @@ fn main() {
     match s {
         MAGIC_TEST => (),
         ["0x00", "0x00", "0x00", "0x00"] => (),
-        ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
+        ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         ["0x00", "0x00", "0x00", "0x00"] => (),
         MAGIC_TEST => (),
-        ["4", "5", "6", "7"] => (), // FIXME(oli-obk): this should warn, but currently does not
+        ["4", "5", "6", "7"] => (), //~ ERROR unreachable pattern
         _ => (),
     }
     match s {
         ["0x00", "0x00", "0x00", "0x00"] => (),
         ["4", "5", "6", "7"] => (),
-        MAGIC_TEST => (), // FIXME(oli-obk): this should warn, but currently does not
+        MAGIC_TEST => (), //~ ERROR unreachable pattern
         _ => (),
     }
     const FOO: [&str; 1] = ["boo"];
index 3ba01b9eba3cef24932178cdb7d1ca41eef0341a..b90b3a88a18602cb72bed06fa7dc92c6fa9f57a1 100644 (file)
@@ -1,8 +1,8 @@
 error: unreachable pattern
-  --> $DIR/slice-pattern-const-3.rs:28:9
+  --> $DIR/slice-pattern-const-3.rs:9:9
    |
-LL |         FOO => (),
-   |         ^^^
+LL |         ["4", "5", "6", "7"] => (),
+   |         ^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
   --> $DIR/slice-pattern-const-3.rs:1:9
@@ -10,5 +10,23 @@ note: the lint level is defined here
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-3.rs:15:9
+   |
+LL |         ["4", "5", "6", "7"] => (),
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-3.rs:21:9
+   |
+LL |         MAGIC_TEST => (),
+   |         ^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/slice-pattern-const-3.rs:28:9
+   |
+LL |         FOO => (),
+   |         ^^^
+
+error: aborting due to 4 previous errors
 
index 52d1320dad153435950e8e4e5a30a92eff785d42..46e0da5be9b4fdf126f3c7041fb16c28b6245568 100644 (file)
@@ -6,15 +6,15 @@ fn main() {
     let s10: &[bool; 10] = &[false; 10];
 
     match s2 {
-    //~^ ERROR `&[false, _]` not covered
+        //~^ ERROR `&[false, _]` not covered
         [true, .., true] => {}
     }
     match s3 {
-    //~^ ERROR `&[false, ..]` not covered
+        //~^ ERROR `&[false, ..]` not covered
         [true, .., true] => {}
     }
     match s10 {
-    //~^ ERROR `&[false, ..]` not covered
+        //~^ ERROR `&[false, ..]` not covered
         [true, .., true] => {}
     }
 
@@ -23,58 +23,58 @@ fn main() {
         [.., false] => {}
     }
     match s2 {
-    //~^ ERROR `&[false, true]` not covered
+        //~^ ERROR `&[false, true]` not covered
         [true, ..] => {}
         [.., false] => {}
     }
     match s3 {
-    //~^ ERROR `&[false, .., true]` not covered
+        //~^ ERROR `&[false, .., true]` not covered
         [true, ..] => {}
         [.., false] => {}
     }
     match s {
-    //~^ ERROR `&[false, .., true]` not covered
+        //~^ ERROR `&[false, .., true]` not covered
         [] => {}
         [true, ..] => {}
         [.., false] => {}
     }
 
     match s {
-    //~^ ERROR `&[_, ..]` not covered
+        //~^ ERROR `&[_, ..]` not covered
         [] => {}
     }
     match s {
-    //~^ ERROR `&[_, _, ..]` not covered
+        //~^ ERROR `&[_, _, ..]` not covered
         [] => {}
         [_] => {}
     }
     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] => {}
     }
 
     match s {
-    //~^ ERROR `&[_, _, .., true]` not covered
+        //~^ ERROR `&[_, _, .., true]` not covered
         [] => {}
         [_] => {}
         [_, _] => {}
         [.., false] => {}
     }
     match s {
-    //~^ ERROR `&[true, _, .., _]` not covered
+        //~^ ERROR `&[true, _, .., _]` not covered
         [] => {}
         [_] => {}
         [_, _] => {}
@@ -83,19 +83,43 @@ fn main() {
 
     const CONST: &[bool] = &[true];
     match s {
-    //~^ ERROR `&[..]` not covered
+        //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+        &[true] => {}
+    }
+    match s {
+        //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+        CONST => {}
+    }
+    match s {
+        //~^ ERROR `&[]` and `&[_, _, ..]` not covered
         CONST => {}
+        &[false] => {}
     }
     match s {
-    //~^ ERROR `&[true]` not covered
-        [] => {},
-        [false] => {},
-        CONST => {},
+        //~^ ERROR `&[]` and `&[_, _, ..]` not covered
+        &[false] => {}
+        CONST => {}
+    }
+    match s {
+        //~^ ERROR `&[_, _, ..]` not covered
+        &[] => {}
+        CONST => {}
+    }
+    match s {
+        //~^ ERROR `&[false]` not covered
+        &[] => {}
+        CONST => {}
+        &[_, _, ..] => {}
+    }
+    match s {
+        [] => {}
+        [false] => {}
+        CONST => {}
         [_, _, ..] => {}
     }
     const CONST1: &[bool; 1] = &[true];
     match s1 {
-    //~^ ERROR `&[false]` not covered
+        //~^ ERROR `&[false]` not covered
         CONST1 => {}
     }
     match s1 {
index 8b85eaeda0acf0cc5f51f83cc7ff6d3279931773..e34770fb912e79437a0b98a901590bc3eaecacb8 100644 (file)
@@ -115,26 +115,62 @@ LL |     match s {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
 
-error[E0004]: non-exhaustive patterns: `&[..]` not covered
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:85:11
    |
 LL |     match s {
-   |           ^ pattern `&[..]` not covered
+   |           ^ patterns `&[]` and `&[_, _, ..]` not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool]`
 
-error[E0004]: non-exhaustive patterns: `&[true]` not covered
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
   --> $DIR/slice-patterns-exhaustiveness.rs:89:11
    |
 LL |     match s {
-   |           ^ pattern `&[true]` not covered
+   |           ^ patterns `&[]` and `&[_, _, ..]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&[bool]`
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:93:11
+   |
+LL |     match s {
+   |           ^ patterns `&[]` and `&[_, _, ..]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&[bool]`
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:98:11
+   |
+LL |     match s {
+   |           ^ patterns `&[]` and `&[_, _, ..]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&[bool]`
+
+error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:103:11
+   |
+LL |     match s {
+   |           ^ pattern `&[_, _, ..]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+   = note: the matched value is of type `&[bool]`
+
+error[E0004]: non-exhaustive patterns: `&[false]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:108: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
    = note: the matched value is of type `&[bool]`
 
 error[E0004]: non-exhaustive patterns: `&[false]` not covered
-  --> $DIR/slice-patterns-exhaustiveness.rs:97:11
+  --> $DIR/slice-patterns-exhaustiveness.rs:121:11
    |
 LL |     match s1 {
    |           ^^ pattern `&[false]` not covered
@@ -142,6 +178,6 @@ LL |     match s1 {
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
    = note: the matched value is of type `&[bool; 1]`
 
-error: aborting due to 16 previous errors
+error: aborting due to 20 previous errors
 
 For more information about this error, try `rustc --explain E0004`.