about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2016-10-26 23:52:03 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2016-10-26 23:52:03 +0300
commit41578507a616affe87f168dbbc6d11437234bafd (patch)
tree16e71acf22135116cc8cd3dfdf89719ce63f012d /src
parent8d3e89b484bbcd1c2fec60794c196d7148dd9f5b (diff)
downloadrust-41578507a616affe87f168dbbc6d11437234bafd.tar.gz
rust-41578507a616affe87f168dbbc6d11437234bafd.zip
flatten nested slice patterns in HAIR construction
nested slice patterns have the same functionality as non-nested
ones, so flatten them in HAIR construction.

Fixes #26158.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_const_eval/pattern.rs53
-rw-r--r--src/test/compile-fail/issue-26158.rs16
-rw-r--r--src/test/run-pass/vec-matching.rs15
3 files changed, 74 insertions, 10 deletions
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index 4bd797afd06..a6c886533c8 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -117,6 +117,7 @@ impl<'a, 'gcx, 'tcx> Pattern<'tcx> {
         if !pcx.errors.is_empty() {
             span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
         }
+        debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
         result
     }
 }
@@ -346,6 +347,40 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
         pat.as_ref().map(|p| self.lower_pattern(p))
     }
 
+    fn flatten_nested_slice_patterns(
+        &mut self,
+        prefix: Vec<Pattern<'tcx>>,
+        slice: Option<Pattern<'tcx>>,
+        suffix: Vec<Pattern<'tcx>>)
+        -> (Vec<Pattern<'tcx>>, Option<Pattern<'tcx>>, Vec<Pattern<'tcx>>)
+    {
+        let orig_slice = match slice {
+            Some(orig_slice) => orig_slice,
+            None => return (prefix, slice, suffix)
+        };
+        let orig_prefix = prefix;
+        let orig_suffix = suffix;
+
+        // dance because of intentional borrow-checker stupidity.
+        let kind = *orig_slice.kind;
+        match kind {
+            PatternKind::Slice { prefix, slice, mut suffix } |
+            PatternKind::Array { prefix, slice, mut suffix } => {
+                let mut orig_prefix = orig_prefix;
+
+                orig_prefix.extend(prefix);
+                suffix.extend(orig_suffix);
+
+                (orig_prefix, slice, suffix)
+            }
+            _ => {
+                (orig_prefix, Some(Pattern {
+                    kind: box kind, ..orig_slice
+                }), orig_suffix)
+            }
+        }
+    }
+
     fn slice_or_array_pattern(
         &mut self,
         span: Span,
@@ -355,24 +390,22 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
         suffix: &[P<hir::Pat>])
         -> PatternKind<'tcx>
     {
+        let prefix = self.lower_patterns(prefix);
+        let slice = self.lower_opt_pattern(slice);
+        let suffix = self.lower_patterns(suffix);
+        let (prefix, slice, suffix) =
+            self.flatten_nested_slice_patterns(prefix, slice, suffix);
+
         match ty.sty {
             ty::TySlice(..) => {
                 // matching a slice or fixed-length array
-                PatternKind::Slice {
-                    prefix: self.lower_patterns(prefix),
-                    slice: self.lower_opt_pattern(slice),
-                    suffix: self.lower_patterns(suffix),
-                }
+                PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix }
             }
 
             ty::TyArray(_, len) => {
                 // fixed-length array
                 assert!(len >= prefix.len() + suffix.len());
-                PatternKind::Array {
-                    prefix: self.lower_patterns(prefix),
-                    slice: self.lower_opt_pattern(slice),
-                    suffix: self.lower_patterns(suffix),
-                }
+                PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
             }
 
             _ => {
diff --git a/src/test/compile-fail/issue-26158.rs b/src/test/compile-fail/issue-26158.rs
new file mode 100644
index 00000000000..54f5313aed1
--- /dev/null
+++ b/src/test/compile-fail/issue-26158.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 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.
+
+#![feature(slice_patterns)]
+
+fn main() {
+    let x: &[u32] = &[];
+    let &[[ref _a, ref _b..]..] = x; //~ ERROR refutable pattern
+}
diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs
index 97006f54cd9..bd0731a555c 100644
--- a/src/test/run-pass/vec-matching.rs
+++ b/src/test/run-pass/vec-matching.rs
@@ -144,6 +144,20 @@ fn e() {
     assert_eq!(c, 1);
 }
 
+fn f() {
+    let x = &[1, 2, 3, 4, 5];
+    let [a, [b, [c, ..].., d].., e] = *x;
+    assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
+
+    let x: &[isize] = x;
+    let (a, b, c, d, e) = match *x {
+        [a, [b, [c, ..].., d].., e] => (a, b, c, d, e),
+        _ => unimplemented!()
+    };
+
+    assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
+}
+
 pub fn main() {
     a();
     b();
@@ -151,4 +165,5 @@ pub fn main() {
     c();
     d();
     e();
+    f();
 }