Skip to content

Commit defc66d

Browse files
committed
Incorporate varkor's review
1 parent 5badbb7 commit defc66d

File tree

1 file changed

+53
-23
lines changed

1 file changed

+53
-23
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -340,22 +340,27 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
340340
pub fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
341341
PatStack(smallvec![pat])
342342
}
343+
343344
fn empty() -> Self {
344345
PatStack(smallvec![])
345346
}
347+
346348
fn from_vec(vec: SmallVec<[&'p Pat<'tcx>; 2]>) -> Self {
347349
PatStack(vec)
348350
}
351+
349352
fn from_slice(s: &[&'p Pat<'tcx>]) -> Self {
350353
PatStack(SmallVec::from_slice(s))
351354
}
352355

353356
fn is_empty(&self) -> bool {
354357
self.0.is_empty()
355358
}
359+
356360
fn len(&self) -> usize {
357361
self.0.len()
358362
}
363+
359364
fn head<'a, 'p2>(&'a self) -> &'p2 Pat<'tcx>
360365
where
361366
'p: 'p2,
@@ -605,7 +610,7 @@ impl<'tcx> Constructor<'tcx> {
605610
match self {
606611
Wildcard => true,
607612
MissingConstructors(_) => bug!(
608-
"Not sure if MissingConstructors should be a wildcard. Shouldn't happen anyways."
613+
"not sure if MissingConstructors should be a wildcard; shouldn't happen anyways."
609614
),
610615
_ => false,
611616
}
@@ -934,6 +939,32 @@ impl<'tcx> Constructor<'tcx> {
934939
if used_ctors.iter().any(overlaps) { smallvec![] } else { smallvec![self] }
935940
}
936941
VarLenSlice(self_prefix, self_suffix) => {
942+
// Assume we have the following match:
943+
// ```
944+
// match slice {
945+
// [0] => {}
946+
// [_, _, _] => {}
947+
// [1, 2, 3, 4, 5, 6, ..] => {}
948+
// [_, _, _, _, _, _, _, _] => {}
949+
// [0, ..] => {}
950+
// }
951+
// ```
952+
// We want to know which constructors are matched by the last pattern, but are not
953+
// matched by the first four ones. Since we only speak of constructors here, we
954+
// only care about the length of the slices and not the subpatterns.
955+
// For that, we first notice that because of the third pattern, all constructors of
956+
// lengths 6 or more are covered already. `max_len` will be `Some(6)`.
957+
// Then we'll look at constructors of lengths < 6 to see which are missing. We can
958+
// ignore pattern 4 because it's longer than 6. We are left with patterns 1 and 2.
959+
// The `length` vector will therefore contain `[Start, Boundary(1), Boundary(3),
960+
// Boundary(6)]`.
961+
// The resulting list of remaining constructors will be those strictly between
962+
// those boundaries. Knowing that `self_len` is 1, we get `[FixedLenSlice(2),
963+
// FixedLenSlice(4), FixedLenSlice(5)]`.
964+
// Notice that `FixedLenSlice(0)` is not covered by any of the patterns here, but
965+
// we don't care because we only want constructors that _are_ matched by the last
966+
// pattern.
967+
937968
// Initially we cover all slice lengths starting from self_len.
938969
let self_len = self_prefix + self_suffix;
939970

@@ -962,7 +993,7 @@ impl<'tcx> Constructor<'tcx> {
962993
// of the lengths that will remain.
963994
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
964995
enum Length {
965-
Start,
996+
Start, // `Start` will be sorted before `Boundary`
966997
Boundary(u64),
967998
}
968999
use Length::*;
@@ -1000,7 +1031,7 @@ impl<'tcx> Constructor<'tcx> {
10001031

10011032
// If there was a max_len, then we're done. Otherwise, we
10021033
// still need to include all lengths starting from the longest
1003-
// one til infinity, using VarLenSlice.
1034+
// one until infinity, using VarLenSlice.
10041035
if max_len.is_none() {
10051036
let final_length = match lengths.last().unwrap() {
10061037
Start => self_len,
@@ -1137,13 +1168,15 @@ impl<'tcx> Constructor<'tcx> {
11371168
/// must have as many elements as this constructor's arity.
11381169
///
11391170
/// Examples:
1140-
/// self: Single
1141-
/// ty: tuple of 3 elements
1142-
/// pats: [10, 20, _] => (10, 20, _)
1171+
/// `self`: `Constructor::Single`
1172+
/// `ty`: `(u32, u32, u32)`
1173+
/// `pats`: `[10, 20, _]`
1174+
/// returns `(10, 20, _)`
11431175
///
1144-
/// self: Option::Some
1145-
/// ty: Option<bool>
1146-
/// pats: [false] => Some(false)
1176+
/// `self`: `Constructor::Variant(Option::Some)`
1177+
/// `ty`: `Option<bool>`
1178+
/// `pats`: `[false]`
1179+
/// returns `Some(false)`
11471180
fn apply<'a>(
11481181
&self,
11491182
cx: &MatchCheckCtxt<'a, 'tcx>,
@@ -1659,10 +1692,12 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
16591692
}
16601693
}
16611694

1662-
/// The implementation panics because this should not happen
1695+
/// This is needed for the `PartialEq` impl of `Constructor`.
1696+
/// Comparing a `Constructor::MissingConstructor` with something else
1697+
/// should however never happen, so this implementaiton panics.
16631698
impl<'tcx> PartialEq<Self> for MissingConstructors<'tcx> {
16641699
fn eq(&self, _other: &Self) -> bool {
1665-
bug!("Tried to compare MissingConstructors for equality")
1700+
bug!("tried to compare MissingConstructors for equality")
16661701
}
16671702
}
16681703

@@ -1982,18 +2017,13 @@ fn specialize_one_pattern<'p, 'a: 'p, 'p2: 'p, 'tcx>(
19822017
pat = subpattern;
19832018
}
19842019

1985-
if let MissingConstructors(_) = constructor {
1986-
// By the invariant of MissingConstructors, we know that all non-wildcard constructors
1987-
// should be discarded.
1988-
return match *pat.kind {
1989-
PatKind::Binding { .. } | PatKind::Wild => smallvec![PatStack::empty()],
1990-
_ => smallvec![],
1991-
};
1992-
} else if let Wildcard = constructor {
1993-
// If we get here, either there were only wildcards in the first component of the
1994-
// matrix, or we are in a special non_exhaustive case where we pretend the type has
1995-
// an extra `_` constructor to prevent exhaustive matching. In both cases, all
1996-
// non-wildcard constructors should be discarded.
2020+
if let Wildcard | MissingConstructors(_) = constructor {
2021+
// If `constructor` is `Wildcard`: either there were only wildcards in the first component
2022+
// of the matrix, or we are in a special non_exhaustive case where we pretend the type has
2023+
// an extra `_` constructor to prevent exhaustive matching. In both cases, all non-wildcard
2024+
// constructors should be discarded.
2025+
// If `constructor` is `MissingConstructors(_)`: by the invariant of MissingConstructors,
2026+
// we know that all non-wildcard constructors should be discarded.
19972027
return match *pat.kind {
19982028
PatKind::Binding { .. } | PatKind::Wild => smallvec![PatStack::empty()],
19992029
_ => smallvec![],

0 commit comments

Comments
 (0)