Skip to content

Commit

Permalink
flatten nested slice patterns in HAIR construction
Browse files Browse the repository at this point in the history
nested slice patterns have the same functionality as non-nested
ones, so flatten them in HAIR construction.

Fixes #26158.
  • Loading branch information
arielb1 committed Oct 26, 2016
1 parent 8d3e89b commit 4157850
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 10 deletions.
53 changes: 43 additions & 10 deletions src/librustc_const_eval/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down Expand Up @@ -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,
Expand All @@ -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 }
}

_ => {
Expand Down
16 changes: 16 additions & 0 deletions src/test/compile-fail/issue-26158.rs
Original file line number Diff line number Diff line change
@@ -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
}
15 changes: 15 additions & 0 deletions src/test/run-pass/vec-matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,26 @@ 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();
b_slice();
c();
d();
e();
f();
}

0 comments on commit 4157850

Please sign in to comment.