mir: Don't lose sub-patterns inside slice patterns.

This commit is contained in:
Eduard Burtescu 2016-03-09 14:21:31 +02:00
parent 41499f4563
commit cf4daf7889
4 changed files with 42 additions and 11 deletions

View File

@ -238,6 +238,13 @@ pub struct MatchPair<'pat, 'tcx:'pat> {
// ... must match this pattern.
pattern: &'pat Pattern<'tcx>,
// HACK(eddyb) This is used to toggle whether a Slice pattern
// has had its length checked. This is only necessary because
// the "rest" part of the pattern right now has type &[T] and
// as such, it requires an Rvalue::Slice to be generated.
// See RFC 495 / issue #23121 for the eventual (proper) solution.
slice_len_checked: bool
}
#[derive(Clone, Debug, PartialEq)]

View File

@ -95,7 +95,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
Err(match_pair)
}
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
PatternKind::Range { .. } |
PatternKind::Variant { .. } => {
// cannot simplify, test is required
Err(match_pair)
}
PatternKind::Slice { .. } if !match_pair.slice_len_checked => {
Err(match_pair)
}
PatternKind::Array { ref prefix, ref slice, ref suffix } |
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs,
block,
match_pair.lvalue.clone(),
@ -105,13 +116,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
Ok(block)
}
PatternKind::Slice { .. } |
PatternKind::Range { .. } |
PatternKind::Variant { .. } => {
// cannot simplify, test is required
Err(match_pair)
}
PatternKind::Leaf { ref subpatterns } => {
// tuple struct, match subpats (if any)
candidate.match_pairs

View File

@ -75,7 +75,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
}
}
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
PatternKind::Slice { ref prefix, ref slice, ref suffix }
if !match_pair.slice_len_checked => {
let len = prefix.len() + suffix.len();
let op = if slice.is_some() {
BinOp::Ge
@ -89,6 +90,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
}
PatternKind::Array { .. } |
PatternKind::Slice { .. } |
PatternKind::Wild |
PatternKind::Binding { .. } |
PatternKind::Leaf { .. } |
@ -413,9 +415,26 @@ impl<'a,'tcx> Builder<'a,'tcx> {
}
}
TestKind::Eq { .. } |
TestKind::Range { .. } |
// If we are performing a length check, then this
// informs slice patterns, but nothing else.
TestKind::Len { .. } => {
let pattern_test = self.test(&match_pair);
match *match_pair.pattern.kind {
PatternKind::Slice { .. } if pattern_test.kind == test.kind => {
let mut new_candidate = candidate.clone();
// Set up the MatchKind to simplify this like an array.
new_candidate.match_pairs[match_pair_index]
.slice_len_checked = true;
resulting_candidates[0].push(new_candidate);
true
}
_ => false
}
}
TestKind::Eq { .. } |
TestKind::Range { .. } => {
// These are all binary tests.
//
// FIXME(#29623) we can be more clever here

View File

@ -118,6 +118,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
MatchPair {
lvalue: lvalue,
pattern: pattern,
slice_len_checked: false,
}
}
}