diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2019-11-17 19:08:01 +0000 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2019-11-17 19:25:03 +0000 |
| commit | bd0e3ccd0bf81b57f115b344dcf424a3ed626cab (patch) | |
| tree | ee191bde89d778b9a9e543e133301384b0065d9f | |
| parent | daa117eab715f38d08facfb826b04116bc9fe0b7 (diff) | |
| download | rust-bd0e3ccd0bf81b57f115b344dcf424a3ed626cab.tar.gz rust-bd0e3ccd0bf81b57f115b344dcf424a3ed626cab.zip | |
Store SliceKinds directly when subtracting
| -rw-r--r-- | src/librustc_mir/hair/pattern/_match.rs | 111 |
1 files changed, 58 insertions, 53 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index d379f606da4..182c9e22e41 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -594,43 +594,9 @@ enum SliceKind { VarLen(u64, u64), } -/// A constructor for array and slice patterns. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -struct Slice { - /// `None` if the matched value is a slice, `Some(n)` if it is an array of size `n`. - array_len: Option<u64>, - /// The kind of pattern it is: fixed-length `[x, y]` or variable length `[x, .., y]`. - kind: SliceKind, -} - -impl Slice { - /// Returns what patterns this constructor covers: either fixed-length patterns or - /// variable-length patterns. - fn pattern_kind(self) -> SliceKind { - match self { - Slice { array_len: Some(len), kind: VarLen(prefix, suffix) } - if prefix + suffix == len => - { - FixedLen(len) - } - _ => self.kind, - } - } - - /// Returns what values this constructor covers: either values of only one given length, or - /// values of length above a given length. - /// This is different from `pattern_kind()` because in some cases the pattern only takes into - /// account a subset of the entries of the array, but still only captures values of a given - /// length. - fn value_kind(self) -> SliceKind { - match self { - Slice { array_len: Some(len), kind: VarLen(_, _) } => FixedLen(len), - _ => self.kind, - } - } - +impl SliceKind { fn arity(self) -> u64 { - match self.pattern_kind() { + match self { FixedLen(length) => length, VarLen(prefix, suffix) => prefix + suffix, } @@ -638,7 +604,7 @@ impl Slice { /// Whether this pattern includes patterns of length `other_len`. fn covers_length(self, other_len: u64) -> bool { - match self.value_kind() { + match self { FixedLen(len) => len == other_len, VarLen(prefix, suffix) => prefix + suffix <= other_len, } @@ -649,7 +615,7 @@ impl Slice { fn subtract(self, other: Self) -> SmallVec<[Self; 1]> { // Remember, `VarLen(i, j)` covers the union of `FixedLen` from `i + j` to infinity. // Naming: we remove the "neg" constructors from the "pos" ones. - match self.value_kind() { + match self { FixedLen(pos_len) => { if other.covers_length(pos_len) { smallvec![] @@ -659,7 +625,7 @@ impl Slice { } VarLen(pos_prefix, pos_suffix) => { let pos_len = pos_prefix + pos_suffix; - match other.value_kind() { + match other { FixedLen(neg_len) => { if neg_len < pos_len { smallvec![self] @@ -668,7 +634,6 @@ impl Slice { .map(FixedLen) // We know that `neg_len + 1 >= pos_len >= pos_suffix`. .chain(Some(VarLen(neg_len + 1 - pos_suffix, pos_suffix))) - .map(|kind| Slice { array_len: None, kind }) .collect() } } @@ -677,10 +642,7 @@ impl Slice { if neg_len <= pos_len { smallvec![] } else { - (pos_len..neg_len) - .map(FixedLen) - .map(|kind| Slice { array_len: None, kind }) - .collect() + (pos_len..neg_len).map(FixedLen).collect() } } } @@ -689,6 +651,46 @@ impl Slice { } } +/// A constructor for array and slice patterns. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +struct Slice { + /// `None` if the matched value is a slice, `Some(n)` if it is an array of size `n`. + array_len: Option<u64>, + /// The kind of pattern it is: fixed-length `[x, y]` or variable length `[x, .., y]`. + kind: SliceKind, +} + +impl Slice { + /// Returns what patterns this constructor covers: either fixed-length patterns or + /// variable-length patterns. + fn pattern_kind(self) -> SliceKind { + match self { + Slice { array_len: Some(len), kind: VarLen(prefix, suffix) } + if prefix + suffix == len => + { + FixedLen(len) + } + _ => self.kind, + } + } + + /// Returns what values this constructor covers: either values of only one given length, or + /// values of length above a given length. + /// This is different from `pattern_kind()` because in some cases the pattern only takes into + /// account a subset of the entries of the array, but still only captures values of a given + /// length. + fn value_kind(self) -> SliceKind { + match self { + Slice { array_len: Some(len), kind: VarLen(_, _) } => FixedLen(len), + _ => self.kind, + } + } + + fn arity(self) -> u64 { + self.pattern_kind().arity() + } +} + #[derive(Clone, Debug, PartialEq)] enum Constructor<'tcx> { /// The constructor of all patterns that don't vary by constructor, @@ -743,26 +745,25 @@ impl<'tcx> Constructor<'tcx> { &Slice(slice) => match slice.value_kind() { FixedLen(self_len) => { let overlaps = |c: &Constructor<'_>| match *c { - Slice(other_slice) => other_slice.covers_length(self_len), + Slice(other_slice) => other_slice.value_kind().covers_length(self_len), _ => false, }; if other_ctors.iter().any(overlaps) { vec![] } else { vec![Slice(slice)] } } VarLen(..) => { - let mut remaining_slices = vec![slice]; + let mut remaining_slices = vec![slice.value_kind()]; // For each used slice, subtract from the current set of slices. - // Naming: we remove the "neg" constructors from the "pos" ones. - for neg_ctor in other_ctors { - let neg_slice = match neg_ctor { - Slice(slice) => *slice, - // FIXME(#65413): If `neg_ctor` is not a slice, we assume it doesn't + for other_ctor in other_ctors { + let other_slice = match other_ctor { + Slice(slice) => slice.value_kind(), + // FIXME(#65413): If `other_ctor` is not a slice, we assume it doesn't // cover any value here. _ => continue, }; remaining_slices = remaining_slices .into_iter() - .flat_map(|pos_slice| pos_slice.subtract(neg_slice)) + .flat_map(|remaining_slice| remaining_slice.subtract(other_slice)) .collect(); // If the constructors that have been considered so far already cover @@ -772,7 +773,11 @@ impl<'tcx> Constructor<'tcx> { } } - remaining_slices.into_iter().map(Slice).collect() + remaining_slices + .into_iter() + .map(|kind| Slice { array_len: slice.array_len, kind }) + .map(Slice) + .collect() } }, IntRange(self_range) => { |
