Skip to content

Commit 48217d6

Browse files
committed
mir: Don't lose sub-patterns inside slice patterns.
1 parent 355abcb commit 48217d6

File tree

4 files changed

+42
-11
lines changed

4 files changed

+42
-11
lines changed

src/librustc_mir/build/matches/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,13 @@ pub struct MatchPair<'pat, 'tcx:'pat> {
238238

239239
// ... must match this pattern.
240240
pattern: &'pat Pattern<'tcx>,
241+
242+
// HACK(eddyb) This is used to toggle whether a Slice pattern
243+
// has had its length checked. This is only necessary because
244+
// the "rest" part of the pattern right now has type &[T] and
245+
// as such, it requires an Rvalue::Slice to be generated.
246+
// See RFC 495 / issue #23121 for the eventual (proper) solution.
247+
slice_len_checked: bool
241248
}
242249

243250
#[derive(Clone, Debug, PartialEq)]

src/librustc_mir/build/matches/simplify.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,18 @@ impl<'a,'tcx> Builder<'a,'tcx> {
9595
Err(match_pair)
9696
}
9797

98-
PatternKind::Array { ref prefix, ref slice, ref suffix } => {
98+
PatternKind::Range { .. } |
99+
PatternKind::Variant { .. } => {
100+
// cannot simplify, test is required
101+
Err(match_pair)
102+
}
103+
104+
PatternKind::Slice { .. } if !match_pair.slice_len_checked => {
105+
Err(match_pair)
106+
}
107+
108+
PatternKind::Array { ref prefix, ref slice, ref suffix } |
109+
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
99110
unpack!(block = self.prefix_suffix_slice(&mut candidate.match_pairs,
100111
block,
101112
match_pair.lvalue.clone(),
@@ -105,13 +116,6 @@ impl<'a,'tcx> Builder<'a,'tcx> {
105116
Ok(block)
106117
}
107118

108-
PatternKind::Slice { .. } |
109-
PatternKind::Range { .. } |
110-
PatternKind::Variant { .. } => {
111-
// cannot simplify, test is required
112-
Err(match_pair)
113-
}
114-
115119
PatternKind::Leaf { ref subpatterns } => {
116120
// tuple struct, match subpats (if any)
117121
candidate.match_pairs

src/librustc_mir/build/matches/test.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
7575
}
7676
}
7777

78-
PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
78+
PatternKind::Slice { ref prefix, ref slice, ref suffix }
79+
if !match_pair.slice_len_checked => {
7980
let len = prefix.len() + suffix.len();
8081
let op = if slice.is_some() {
8182
BinOp::Ge
@@ -89,6 +90,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
8990
}
9091

9192
PatternKind::Array { .. } |
93+
PatternKind::Slice { .. } |
9294
PatternKind::Wild |
9395
PatternKind::Binding { .. } |
9496
PatternKind::Leaf { .. } |
@@ -413,9 +415,26 @@ impl<'a,'tcx> Builder<'a,'tcx> {
413415
}
414416
}
415417

416-
TestKind::Eq { .. } |
417-
TestKind::Range { .. } |
418+
// If we are performing a length check, then this
419+
// informs slice patterns, but nothing else.
418420
TestKind::Len { .. } => {
421+
let pattern_test = self.test(&match_pair);
422+
match *match_pair.pattern.kind {
423+
PatternKind::Slice { .. } if pattern_test.kind == test.kind => {
424+
let mut new_candidate = candidate.clone();
425+
426+
// Set up the MatchKind to simplify this like an array.
427+
new_candidate.match_pairs[match_pair_index]
428+
.slice_len_checked = true;
429+
resulting_candidates[0].push(new_candidate);
430+
true
431+
}
432+
_ => false
433+
}
434+
}
435+
436+
TestKind::Eq { .. } |
437+
TestKind::Range { .. } => {
419438
// These are all binary tests.
420439
//
421440
// FIXME(#29623) we can be more clever here

src/librustc_mir/build/matches/util.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
118118
MatchPair {
119119
lvalue: lvalue,
120120
pattern: pattern,
121+
slice_len_checked: false,
121122
}
122123
}
123124
}

0 commit comments

Comments
 (0)