about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-11-28 14:22:47 +0000
committerbors <bors@rust-lang.org>2019-11-28 14:22:47 +0000
commitf453d1127d9095cf3c3356655d9e8502ceeb8373 (patch)
tree939f5268cd2439debbdb10ac71d51f0d51435641
parent4752c05af4a5f392de026f9ae1877eae030be359 (diff)
parent3f917120a09459c649cccf903752b2addb1c9a01 (diff)
downloadrust-f453d1127d9095cf3c3356655d9e8502ceeb8373.tar.gz
rust-f453d1127d9095cf3c3356655d9e8502ceeb8373.zip
Auto merge of #66603 - Nadrieril:fix-65413, r=varkor
Fix #65413

#65413 was due to an oversight in `pat_constructor` that didn't check if a particular const value was maybe a slice/array const.
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs66
-rw-r--r--src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs15
-rw-r--r--src/test/ui/pattern/usefulness/match-byte-array-patterns-2.stderr8
-rw-r--r--src/test/ui/pattern/usefulness/slice-pattern-const.rs7
-rw-r--r--src/test/ui/pattern/usefulness/slice-pattern-const.stderr8
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs22
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr26
-rw-r--r--src/test/ui/pattern/usefulness/slice-patterns-reachability.rs2
8 files changed, 111 insertions, 43 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 5e7a7f01e7a..5db567dae29 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -347,6 +347,7 @@ impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
             ) => bug!("cannot deref {:#?}, {} -> {}", val, crty, rty),
 
             (_, &PatKind::Binding { subpattern: Some(ref s), .. }) => s.fold_with(self),
+            (_, &PatKind::AscribeUserType { subpattern: ref s, .. }) => s.fold_with(self),
             _ => pat.super_fold_with(self),
         }
     }
@@ -747,7 +748,7 @@ impl<'tcx> Constructor<'tcx> {
                     .iter()
                     .filter_map(|c: &Constructor<'_>| match c {
                         Slice(slice) => Some(*slice),
-                        // FIXME(#65413): We ignore `ConstantValue`s here.
+                        // FIXME(oli-obk): implement `deref` for `ConstValue`
                         ConstantValue(..) => None,
                         _ => bug!("bad slice pattern constructor {:?}", c),
                     })
@@ -1759,9 +1760,7 @@ fn pat_constructor<'tcx>(
     pat: &Pat<'tcx>,
 ) -> Option<Constructor<'tcx>> {
     match *pat.kind {
-        PatKind::AscribeUserType { ref subpattern, .. } => {
-            pat_constructor(tcx, param_env, subpattern)
-        }
+        PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
         PatKind::Binding { .. } | PatKind::Wild => None,
         PatKind::Leaf { .. } | PatKind::Deref { .. } => Some(Single),
         PatKind::Variant { adt_def, variant_index, .. } => {
@@ -1771,7 +1770,19 @@ fn pat_constructor<'tcx>(
             if let Some(int_range) = IntRange::from_const(tcx, param_env, value, pat.span) {
                 Some(IntRange(int_range))
             } else {
-                Some(ConstantValue(value))
+                match (value.val, &value.ty.kind) {
+                    (_, ty::Array(_, n)) => {
+                        let len = n.eval_usize(tcx, param_env);
+                        Some(Slice(Slice { array_len: Some(len), kind: FixedLen(len) }))
+                    }
+                    (ty::ConstKind::Value(ConstValue::Slice { start, end, .. }), ty::Slice(_)) => {
+                        let len = (end - start) as u64;
+                        Some(Slice(Slice { array_len: None, kind: FixedLen(len) }))
+                    }
+                    // FIXME(oli-obk): implement `deref` for `ConstValue`
+                    // (ty::ConstKind::Value(ConstValue::ByRef { .. }), ty::Slice(_)) => { ... }
+                    _ => Some(ConstantValue(value)),
+                }
             }
         }
         PatKind::Range(PatRange { lo, hi, end }) => {
@@ -2085,32 +2096,19 @@ fn split_grouped_constructors<'p, 'tcx>(
                 let mut max_suffix_len = self_suffix;
                 let mut max_fixed_len = 0;
 
-                for row in matrix.heads() {
-                    match *row.kind {
-                        PatKind::Constant { value } => {
-                            // extract the length of an array/slice from a constant
-                            match (value.val, &value.ty.kind) {
-                                (_, ty::Array(_, n)) => {
-                                    max_fixed_len =
-                                        cmp::max(max_fixed_len, n.eval_usize(tcx, param_env))
-                                }
-                                (
-                                    ty::ConstKind::Value(ConstValue::Slice { start, end, .. }),
-                                    ty::Slice(_),
-                                ) => max_fixed_len = cmp::max(max_fixed_len, (end - start) as u64),
-                                _ => {}
+                let head_ctors =
+                    matrix.heads().filter_map(|pat| pat_constructor(tcx, param_env, pat));
+                for ctor in head_ctors {
+                    match ctor {
+                        Slice(slice) => match slice.pattern_kind() {
+                            FixedLen(len) => {
+                                max_fixed_len = cmp::max(max_fixed_len, len);
                             }
-                        }
-                        PatKind::Slice { ref prefix, slice: None, ref suffix }
-                        | PatKind::Array { ref prefix, slice: None, ref suffix } => {
-                            let fixed_len = prefix.len() as u64 + suffix.len() as u64;
-                            max_fixed_len = cmp::max(max_fixed_len, fixed_len);
-                        }
-                        PatKind::Slice { ref prefix, slice: Some(_), ref suffix }
-                        | PatKind::Array { ref prefix, slice: Some(_), ref suffix } => {
-                            max_prefix_len = cmp::max(max_prefix_len, prefix.len() as u64);
-                            max_suffix_len = cmp::max(max_suffix_len, suffix.len() as u64);
-                        }
+                            VarLen(prefix, suffix) => {
+                                max_prefix_len = cmp::max(max_prefix_len, prefix);
+                                max_suffix_len = cmp::max(max_suffix_len, suffix);
+                            }
+                        },
                         _ => {}
                     }
                 }
@@ -2250,21 +2248,17 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx>(
 /// fields filled with wild patterns.
 fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
-    mut pat: &'q Pat<'tcx>,
+    pat: &'q Pat<'tcx>,
     constructor: &Constructor<'tcx>,
     ctor_wild_subpatterns: &[&'p Pat<'tcx>],
 ) -> Option<PatStack<'p, 'tcx>> {
-    while let PatKind::AscribeUserType { ref subpattern, .. } = *pat.kind {
-        pat = subpattern;
-    }
-
     if let NonExhaustive = constructor {
         // Only a wildcard pattern can match the special extra constructor
         return if pat.is_wildcard() { Some(PatStack::default()) } else { None };
     }
 
     let result = match *pat.kind {
-        PatKind::AscribeUserType { .. } => bug!(), // Handled above
+        PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
 
         PatKind::Binding { .. } | PatKind::Wild => {
             Some(PatStack::from_slice(ctor_wild_subpatterns))
diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs
new file mode 100644
index 00000000000..6c54c938bf1
--- /dev/null
+++ b/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs
@@ -0,0 +1,15 @@
+// check-pass
+#![feature(slice_patterns)]
+#![deny(unreachable_patterns)]
+
+const C0: &'static [u8] = b"\x00";
+
+fn main() {
+    let x: &[u8] = &[0];
+    match x {
+        &[] => {}
+        &[1..=255] => {}
+        C0 => {}
+        &[_, _, ..] => {}
+    }
+}
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 63ed49094fc..539aa854f9e 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
@@ -1,16 +1,16 @@
-error[E0004]: non-exhaustive patterns: `&[..]` not covered
+error[E0004]: non-exhaustive patterns: `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` not covered
   --> $DIR/match-byte-array-patterns-2.rs:4:11
    |
 LL |     match buf {
-   |           ^^^ pattern `&[..]` not covered
+   |           ^^^ patterns `&[0u8..=64u8, _, _, _]` and `&[66u8..=std::u8::MAX, _, _, _]` 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
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
   --> $DIR/match-byte-array-patterns-2.rs:10:11
    |
 LL |     match buf {
-   |           ^^^ pattern `&[..]` not covered
+   |           ^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 2 more not covered
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
diff --git a/src/test/ui/pattern/usefulness/slice-pattern-const.rs b/src/test/ui/pattern/usefulness/slice-pattern-const.rs
index f0a04513f91..89195d5b11e 100644
--- a/src/test/ui/pattern/usefulness/slice-pattern-const.rs
+++ b/src/test/ui/pattern/usefulness/slice-pattern-const.rs
@@ -44,4 +44,11 @@ fn main() {
         b"" => (), //~ ERROR unreachable pattern
         _ => (), //~ ERROR unreachable pattern
     }
+
+    const CONST1: &[bool; 1] = &[true];
+    match &[false] {
+        CONST1 => {}
+        [true] => {} //~ ERROR unreachable pattern
+        [false] => {}
+    }
 }
diff --git a/src/test/ui/pattern/usefulness/slice-pattern-const.stderr b/src/test/ui/pattern/usefulness/slice-pattern-const.stderr
index 2dd10a0478a..d274d6d7c67 100644
--- a/src/test/ui/pattern/usefulness/slice-pattern-const.stderr
+++ b/src/test/ui/pattern/usefulness/slice-pattern-const.stderr
@@ -52,5 +52,11 @@ error: unreachable pattern
 LL |         _ => (),
    |         ^
 
-error: aborting due to 8 previous errors
+error: unreachable pattern
+  --> $DIR/slice-pattern-const.rs:51:9
+   |
+LL |         [true] => {}
+   |         ^^^^^^
+
+error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
index eb3dfac950f..41ba2cc4501 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs
@@ -82,4 +82,26 @@ fn main() {
         [_, _] => {}
         [false, .., false] => {}
     }
+
+    const CONST: &[bool] = &[true];
+    match s {
+    //~^ ERROR `&[..]` not covered
+        CONST => {}
+    }
+    match s {
+    //~^ ERROR `&[true]` not covered
+        [] => {},
+        [false] => {},
+        CONST => {},
+        [_, _, ..] => {}
+    }
+    const CONST1: &[bool; 1] = &[true];
+    match s1 {
+    //~^ ERROR `&[false]` not covered
+        CONST1 => {}
+    }
+    match s1 {
+        CONST1 => {}
+        [false] => {}
+    }
 }
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
index ebadedccfea..8cb342f33df 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
+++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
@@ -102,6 +102,30 @@ LL |     match s {
    |
    = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
 
-error: aborting due to 13 previous errors
+error[E0004]: non-exhaustive patterns: `&[..]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:87: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: `&[true]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:91: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: `&[false]` not covered
+  --> $DIR/slice-patterns-exhaustiveness.rs:99:11
+   |
+LL |     match s1 {
+   |           ^^ pattern `&[false]` not covered
+   |
+   = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
+
+error: aborting due to 16 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
index 35d9dc91aee..cd229a0fcbe 100644
--- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
+++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs
@@ -2,7 +2,7 @@
 #![deny(unreachable_patterns)]
 
 fn main() {
-    let s: &[bool] = &[true; 0];
+    let s: &[bool] = &[];
 
     match s {
         [true, ..] => {}