about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSeiichi Uchida <seuchida@gmail.com>2018-01-12 13:12:30 +0900
committerSeiichi Uchida <seuchida@gmail.com>2018-01-17 12:22:17 +0900
commit604a54f3d9e2e959ab856d9c8dbfbc6903ef2503 (patch)
tree8b217c163137d3e3875ef14d39b5c13b2bdd2f22
parent73ac5d6a80f26c692f1e084b72d69637d7de2c8c (diff)
downloadrust-604a54f3d9e2e959ab856d9c8dbfbc6903ef2503.tar.gz
rust-604a54f3d9e2e959ab856d9c8dbfbc6903ef2503.zip
Simplify irrefutable slice patterns
Closes #47096.
-rw-r--r--src/librustc_const_eval/pattern.rs4
-rw-r--r--src/librustc_mir/build/matches/simplify.rs17
-rw-r--r--src/test/run-pass/irrefutable-slice-patterns.rs24
3 files changed, 42 insertions, 3 deletions
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index cfbb9623f7d..d06cc4bb508 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -92,7 +92,9 @@ pub enum PatternKind<'tcx> {
         end: RangeEnd,
     },
 
-    /// matches against a slice, checking the length and extracting elements
+    /// matches against a slice, checking the length and extracting elements.
+    /// irrefutable when there is a slice pattern and both `prefix` and `suffix` are empty.
+    /// e.g. `&[ref xs..]`.
     Slice {
         prefix: Vec<Pattern<'tcx>>,
         slice: Option<Pattern<'tcx>>,
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index 4ae373c7c82..b16d7ed2365 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -92,11 +92,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 Err(match_pair)
             }
 
-            PatternKind::Range { .. } |
-            PatternKind::Slice { .. } => {
+            PatternKind::Range { .. } => {
                 Err(match_pair)
             }
 
+            PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
+                if prefix.is_empty() && slice.is_some() && suffix.is_empty() {
+                    // irrefutable
+                    self.prefix_slice_suffix(&mut candidate.match_pairs,
+                                             &match_pair.place,
+                                             prefix,
+                                             slice.as_ref(),
+                                             suffix);
+                    Ok(())
+                } else {
+                    Err(match_pair)
+                }
+            }
+
             PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => {
                 let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
                     i == variant_index || {
diff --git a/src/test/run-pass/irrefutable-slice-patterns.rs b/src/test/run-pass/irrefutable-slice-patterns.rs
new file mode 100644
index 00000000000..c2e95eb54f9
--- /dev/null
+++ b/src/test/run-pass/irrefutable-slice-patterns.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// #47096
+
+#![feature(slice_patterns)]
+
+fn foo(s: &[i32]) -> &[i32] {
+    let &[ref xs..] = s;
+    xs
+}
+
+fn main() {
+    let x = [1, 2, 3];
+    let y = foo(&x);
+    assert_eq!(x, y);
+}