mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
mir: Don't lose sub-patterns inside slice patterns.
This commit is contained in:
parent
41499f4563
commit
cf4daf7889
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -118,6 +118,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
|
||||
MatchPair {
|
||||
lvalue: lvalue,
|
||||
pattern: pattern,
|
||||
slice_len_checked: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user