Skip to content

Commit 4157850

Browse files
committed
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.
1 parent 8d3e89b commit 4157850

File tree

3 files changed

+74
-10
lines changed

3 files changed

+74
-10
lines changed

src/librustc_const_eval/pattern.rs

+43-10
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ impl<'a, 'gcx, 'tcx> Pattern<'tcx> {
117117
if !pcx.errors.is_empty() {
118118
span_bug!(pat.span, "encountered errors lowering pattern: {:?}", pcx.errors)
119119
}
120+
debug!("Pattern::from_hir({:?}) = {:?}", pat, result);
120121
result
121122
}
122123
}
@@ -346,6 +347,40 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
346347
pat.as_ref().map(|p| self.lower_pattern(p))
347348
}
348349

350+
fn flatten_nested_slice_patterns(
351+
&mut self,
352+
prefix: Vec<Pattern<'tcx>>,
353+
slice: Option<Pattern<'tcx>>,
354+
suffix: Vec<Pattern<'tcx>>)
355+
-> (Vec<Pattern<'tcx>>, Option<Pattern<'tcx>>, Vec<Pattern<'tcx>>)
356+
{
357+
let orig_slice = match slice {
358+
Some(orig_slice) => orig_slice,
359+
None => return (prefix, slice, suffix)
360+
};
361+
let orig_prefix = prefix;
362+
let orig_suffix = suffix;
363+
364+
// dance because of intentional borrow-checker stupidity.
365+
let kind = *orig_slice.kind;
366+
match kind {
367+
PatternKind::Slice { prefix, slice, mut suffix } |
368+
PatternKind::Array { prefix, slice, mut suffix } => {
369+
let mut orig_prefix = orig_prefix;
370+
371+
orig_prefix.extend(prefix);
372+
suffix.extend(orig_suffix);
373+
374+
(orig_prefix, slice, suffix)
375+
}
376+
_ => {
377+
(orig_prefix, Some(Pattern {
378+
kind: box kind, ..orig_slice
379+
}), orig_suffix)
380+
}
381+
}
382+
}
383+
349384
fn slice_or_array_pattern(
350385
&mut self,
351386
span: Span,
@@ -355,24 +390,22 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
355390
suffix: &[P<hir::Pat>])
356391
-> PatternKind<'tcx>
357392
{
393+
let prefix = self.lower_patterns(prefix);
394+
let slice = self.lower_opt_pattern(slice);
395+
let suffix = self.lower_patterns(suffix);
396+
let (prefix, slice, suffix) =
397+
self.flatten_nested_slice_patterns(prefix, slice, suffix);
398+
358399
match ty.sty {
359400
ty::TySlice(..) => {
360401
// matching a slice or fixed-length array
361-
PatternKind::Slice {
362-
prefix: self.lower_patterns(prefix),
363-
slice: self.lower_opt_pattern(slice),
364-
suffix: self.lower_patterns(suffix),
365-
}
402+
PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix }
366403
}
367404

368405
ty::TyArray(_, len) => {
369406
// fixed-length array
370407
assert!(len >= prefix.len() + suffix.len());
371-
PatternKind::Array {
372-
prefix: self.lower_patterns(prefix),
373-
slice: self.lower_opt_pattern(slice),
374-
suffix: self.lower_patterns(suffix),
375-
}
408+
PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
376409
}
377410

378411
_ => {

src/test/compile-fail/issue-26158.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(slice_patterns)]
12+
13+
fn main() {
14+
let x: &[u32] = &[];
15+
let &[[ref _a, ref _b..]..] = x; //~ ERROR refutable pattern
16+
}

src/test/run-pass/vec-matching.rs

+15
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,26 @@ fn e() {
144144
assert_eq!(c, 1);
145145
}
146146

147+
fn f() {
148+
let x = &[1, 2, 3, 4, 5];
149+
let [a, [b, [c, ..].., d].., e] = *x;
150+
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
151+
152+
let x: &[isize] = x;
153+
let (a, b, c, d, e) = match *x {
154+
[a, [b, [c, ..].., d].., e] => (a, b, c, d, e),
155+
_ => unimplemented!()
156+
};
157+
158+
assert_eq!((a, b, c, d, e), (1, 2, 3, 4, 5));
159+
}
160+
147161
pub fn main() {
148162
a();
149163
b();
150164
b_slice();
151165
c();
152166
d();
153167
e();
168+
f();
154169
}

0 commit comments

Comments
 (0)