Skip to content

Commit d0cfef3

Browse files
committed
Unify the various slice constructors
1 parent 5b420a9 commit d0cfef3

File tree

1 file changed

+99
-82
lines changed

1 file changed

+99
-82
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 99 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
/// anything special (because we know none of the integers are actually wildcards: i.e., we
226226
/// can't span wildcards using ranges).
227227
use self::Constructor::*;
228+
use self::SliceKind::*;
228229
use self::Usefulness::*;
229230
use self::WitnessPreference::*;
230231

@@ -582,6 +583,23 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
582583
}
583584
}
584585

586+
#[derive(Copy, Clone, Debug, PartialEq)]
587+
enum SliceKind {
588+
/// Array patterns of length `n`.
589+
FixedLen(u64),
590+
/// Slice patterns. Captures any array constructor of `length >= i + j`.
591+
VarLen(u64, u64),
592+
}
593+
594+
impl SliceKind {
595+
fn arity(self) -> u64 {
596+
match self {
597+
FixedLen(length) => length,
598+
VarLen(prefix, suffix) => prefix + suffix,
599+
}
600+
}
601+
}
602+
585603
#[derive(Clone, Debug, PartialEq)]
586604
enum Constructor<'tcx> {
587605
/// The constructor of all patterns that don't vary by constructor,
@@ -595,26 +613,20 @@ enum Constructor<'tcx> {
595613
IntRange(IntRange<'tcx>),
596614
/// Ranges of floating-point literal values (`2.0..=5.2`).
597615
FloatRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd),
598-
/// Array patterns of length `n`.
599-
FixedLenSlice(u64),
600-
/// Array patterns of length `len`, but for which we only care about the `prefix` first values
601-
/// and the `suffix` last values. This avoids unnecessarily going through values we know to be
602-
/// uninteresting, which can be a major problem for large arrays.
603-
LazyFixedLenSlice {
604-
len: u64, // The actual length of the array
605-
prefix: u64,
606-
suffix: u64,
616+
/// Array and slice patterns.
617+
Slice {
618+
// The length of the type of the pattern, if fixed.
619+
type_len: Option<u64>,
620+
kind: SliceKind,
607621
},
608-
/// Slice patterns. Captures any array constructor of `length >= i + j`.
609-
VarLenSlice(u64, u64),
610622
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
611623
NonExhaustive,
612624
}
613625

614626
impl<'tcx> Constructor<'tcx> {
615627
fn is_slice(&self) -> bool {
616628
match self {
617-
FixedLenSlice { .. } | LazyFixedLenSlice { .. } | VarLenSlice { .. } => true,
629+
Slice { .. } => true,
618630
_ => false,
619631
}
620632
}
@@ -643,71 +655,89 @@ impl<'tcx> Constructor<'tcx> {
643655
Single | Variant(_) | ConstantValue(..) | FloatRange(..) => {
644656
if other_ctors.iter().any(|c| c == self) { vec![] } else { vec![self.clone()] }
645657
}
646-
&FixedLenSlice(self_len) | &LazyFixedLenSlice { len: self_len, .. } => {
658+
&Slice { type_len: Some(self_len), .. } | &Slice { kind: FixedLen(self_len), .. } => {
647659
let overlaps = |c: &Constructor<'_>| match *c {
648-
FixedLenSlice(len) | LazyFixedLenSlice { len, .. } => len == self_len,
649-
VarLenSlice(prefix, suffix) => prefix + suffix <= self_len,
660+
Slice { type_len: Some(len), .. } | Slice { kind: FixedLen(len), .. } => {
661+
len == self_len
662+
}
663+
Slice { type_len: None, kind: VarLen(prefix, suffix) } => {
664+
prefix + suffix <= self_len
665+
}
650666
_ => false,
651667
};
652668
if other_ctors.iter().any(overlaps) { vec![] } else { vec![self.clone()] }
653669
}
654-
VarLenSlice(..) => {
670+
Slice { type_len: None, kind: VarLen(..) } => {
655671
let mut remaining_ctors = vec![self.clone()];
656672

657673
// For each used ctor, subtract from the current set of constructors.
658674
// Naming: we remove the "neg" constructors from the "pos" ones.
659-
// Remember, `VarLenSlice(i, j)` covers the union of `FixedLenSlice` from
675+
// Remember, `VarLen(i, j)` covers the union of `FixedLen` from
660676
// `i + j` to infinity.
661677
for neg_ctor in other_ctors {
662678
remaining_ctors = remaining_ctors
663679
.into_iter()
664680
.flat_map(|pos_ctor| -> SmallVec<[Constructor<'tcx>; 1]> {
665681
// Compute `pos_ctor \ neg_ctor`.
666682
match pos_ctor {
667-
FixedLenSlice(pos_len) => match *neg_ctor {
668-
FixedLenSlice(neg_len)
669-
| LazyFixedLenSlice { len: neg_len, .. }
683+
Slice { type_len: Some(pos_len), .. }
684+
| Slice { kind: FixedLen(pos_len), .. } => match *neg_ctor {
685+
Slice { type_len: Some(neg_len), .. }
686+
| Slice { kind: FixedLen(neg_len), .. }
670687
if neg_len == pos_len =>
671688
{
672689
smallvec![]
673690
}
674-
VarLenSlice(neg_prefix, neg_suffix)
675-
if neg_prefix + neg_suffix <= pos_len =>
676-
{
677-
smallvec![]
678-
}
691+
Slice {
692+
type_len: None,
693+
kind: VarLen(neg_prefix, neg_suffix),
694+
} if neg_prefix + neg_suffix <= pos_len => smallvec![],
679695
_ => smallvec![pos_ctor],
680696
},
681-
VarLenSlice(pos_prefix, pos_suffix) => {
697+
Slice { type_len: None, kind: VarLen(pos_prefix, pos_suffix) } => {
682698
let pos_len = pos_prefix + pos_suffix;
683699
match *neg_ctor {
684-
FixedLenSlice(neg_len)
685-
| LazyFixedLenSlice { len: neg_len, .. }
700+
Slice { type_len: Some(neg_len), .. }
701+
| Slice { kind: FixedLen(neg_len), .. }
686702
if neg_len >= pos_len =>
687703
{
688704
(pos_len..neg_len)
689-
.map(FixedLenSlice)
705+
.map(|l| Slice {
706+
type_len: None,
707+
kind: FixedLen(l),
708+
})
690709
// We know that `neg_len + 1 >= pos_len >=
691710
// pos_suffix`.
692-
.chain(Some(VarLenSlice(
693-
neg_len + 1 - pos_suffix,
694-
pos_suffix,
695-
)))
711+
.chain(Some(Slice {
712+
type_len: None,
713+
kind: VarLen(
714+
neg_len + 1 - pos_suffix,
715+
pos_suffix,
716+
),
717+
}))
696718
.collect()
697719
}
698-
VarLenSlice(neg_prefix, neg_suffix) => {
720+
Slice {
721+
type_len: None,
722+
kind: VarLen(neg_prefix, neg_suffix),
723+
} => {
699724
let neg_len = neg_prefix + neg_suffix;
700725
if neg_len <= pos_len {
701726
smallvec![]
702727
} else {
703-
(pos_len..neg_len).map(FixedLenSlice).collect()
728+
(pos_len..neg_len)
729+
.map(|l| Slice {
730+
type_len: None,
731+
kind: FixedLen(l),
732+
})
733+
.collect()
704734
}
705735
}
706736
_ => smallvec![pos_ctor],
707737
}
708738
}
709739
_ => bug!(
710-
"unexpected ctor while subtracting from VarLenSlice: {:?}",
740+
"unexpected ctor while subtracting from VarLen: {:?}",
711741
pos_ctor
712742
),
713743
}
@@ -815,7 +845,7 @@ impl<'tcx> Constructor<'tcx> {
815845
}
816846
_ => vec![],
817847
},
818-
FixedLenSlice(_) | LazyFixedLenSlice { .. } | VarLenSlice(..) => match ty.kind {
848+
Slice { .. } => match ty.kind {
819849
ty::Slice(ty) | ty::Array(ty, _) => {
820850
let arity = self.arity(cx, ty);
821851
(0..arity).map(|_| Pat::wildcard_from_ty(ty)).collect()
@@ -845,10 +875,7 @@ impl<'tcx> Constructor<'tcx> {
845875
}
846876
_ => 0,
847877
},
848-
FixedLenSlice(length) => *length,
849-
VarLenSlice(prefix, suffix) | LazyFixedLenSlice { prefix, suffix, .. } => {
850-
prefix + suffix
851-
}
878+
Slice { kind, .. } => kind.arity(),
852879
ConstantValue(..) | FloatRange(..) | IntRange(..) | NonExhaustive => 0,
853880
}
854881
}
@@ -903,13 +930,15 @@ impl<'tcx> Constructor<'tcx> {
903930
ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty),
904931
_ => PatKind::Wild,
905932
},
906-
FixedLenSlice(_) => {
933+
Slice { kind: FixedLen(_), .. } => {
907934
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
908935
}
909-
LazyFixedLenSlice { len, prefix, suffix } if prefix + suffix == *len => {
936+
Slice { type_len: Some(len), kind: VarLen(prefix, suffix) }
937+
if prefix + suffix == *len =>
938+
{
910939
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
911940
}
912-
VarLenSlice(prefix, _) | LazyFixedLenSlice { prefix, .. } => {
941+
Slice { kind: VarLen(prefix, _), .. } => {
913942
let prefix = subpatterns.by_ref().take(*prefix as usize).collect();
914943
let suffix = subpatterns.collect();
915944
let wild = Pat::wildcard_from_ty(ty);
@@ -1130,15 +1159,15 @@ fn all_constructors<'a, 'tcx>(
11301159
if len != 0 && cx.is_uninhabited(sub_ty) {
11311160
vec![]
11321161
} else {
1133-
vec![LazyFixedLenSlice { len, prefix: 0, suffix: 0 }]
1162+
vec![Slice { type_len: Some(len), kind: VarLen(0, 0) }]
11341163
}
11351164
}
11361165
// Treat arrays of a constant but unknown length like slices.
11371166
ty::Array(ref sub_ty, _) | ty::Slice(ref sub_ty) => {
11381167
if cx.is_uninhabited(sub_ty) {
1139-
vec![FixedLenSlice(0)]
1168+
vec![Slice { type_len: None, kind: FixedLen(0) }]
11401169
} else {
1141-
vec![VarLenSlice(0, 0)]
1170+
vec![Slice { type_len: None, kind: VarLen(0, 0) }]
11421171
}
11431172
}
11441173
ty::Adt(def, substs) if def.is_enum() => {
@@ -1719,27 +1748,18 @@ fn pat_constructor<'tcx>(
17191748
Some(FloatRange(lo, hi, end))
17201749
}
17211750
}
1722-
PatKind::Array { ref prefix, ref slice, ref suffix } => {
1723-
let len = match pat.ty.kind {
1724-
ty::Array(_, length) => length.eval_usize(tcx, param_env),
1725-
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pat.ty),
1751+
PatKind::Array { ref prefix, ref slice, ref suffix }
1752+
| PatKind::Slice { ref prefix, ref slice, ref suffix } => {
1753+
let type_len = match pat.ty.kind {
1754+
ty::Array(_, length) => Some(length.eval_usize(tcx, param_env)),
1755+
ty::Slice(_) => None,
1756+
_ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
17261757
};
17271758
let prefix = prefix.len() as u64;
17281759
let suffix = suffix.len() as u64;
1729-
if slice.is_some() {
1730-
Some(LazyFixedLenSlice { len, prefix, suffix })
1731-
} else {
1732-
Some(FixedLenSlice(len))
1733-
}
1734-
}
1735-
PatKind::Slice { ref prefix, ref slice, ref suffix } => {
1736-
let prefix = prefix.len() as u64;
1737-
let suffix = suffix.len() as u64;
1738-
if slice.is_some() {
1739-
Some(VarLenSlice(prefix, suffix))
1740-
} else {
1741-
Some(FixedLenSlice(prefix + suffix))
1742-
}
1760+
let kind =
1761+
if slice.is_some() { VarLen(prefix, suffix) } else { FixedLen(prefix + suffix) };
1762+
Some(Slice { type_len, kind })
17431763
}
17441764
PatKind::Or { .. } => {
17451765
bug!("support for or-patterns has not been fully implemented yet.");
@@ -1955,8 +1975,7 @@ fn split_grouped_constructors<'p, 'tcx>(
19551975
.map(IntRange),
19561976
);
19571977
}
1958-
VarLenSlice(self_prefix, self_suffix)
1959-
| LazyFixedLenSlice { prefix: self_prefix, suffix: self_suffix, .. } => {
1978+
Slice { kind: VarLen(self_prefix, self_suffix), type_len } => {
19601979
// The exhaustiveness-checking paper does not include any details on
19611980
// checking variable-length slice patterns. However, they are matched
19621981
// by an infinite collection of fixed-length array patterns.
@@ -2065,28 +2084,26 @@ fn split_grouped_constructors<'p, 'tcx>(
20652084
max_prefix_len = max_fixed_len + 1 - max_suffix_len;
20662085
}
20672086

2068-
match ctor {
2069-
LazyFixedLenSlice { len, .. } => {
2070-
if max_prefix_len + max_suffix_len < len {
2071-
split_ctors.push(LazyFixedLenSlice {
2072-
len,
2073-
prefix: max_prefix_len,
2074-
suffix: max_suffix_len,
2075-
});
2087+
match type_len {
2088+
Some(len) => {
2089+
let kind = if max_prefix_len + max_suffix_len < len {
2090+
VarLen(max_prefix_len, max_suffix_len)
20762091
} else {
2077-
split_ctors.push(FixedLenSlice(len));
2078-
}
2092+
FixedLen(len)
2093+
};
2094+
split_ctors.push(Slice { type_len, kind });
20792095
}
2080-
_ => {
2096+
None => {
20812097
// `ctor` originally covered the range `(self_prefix + self_suffix..infinity)`. We
20822098
// now split it into two: lengths smaller than `max_prefix_len + max_suffix_len`
20832099
// are treated independently as fixed-lengths slices, and lengths above are
2084-
// captured by a final VarLenSlice constructor.
2100+
// captured by a final VarLen constructor.
20852101
split_ctors.extend(
20862102
(self_prefix + self_suffix..max_prefix_len + max_suffix_len)
2087-
.map(FixedLenSlice),
2103+
.map(|len| Slice { type_len, kind: FixedLen(len) }),
20882104
);
2089-
split_ctors.push(VarLenSlice(max_prefix_len, max_suffix_len));
2105+
split_ctors
2106+
.push(Slice { type_len, kind: VarLen(max_prefix_len, max_suffix_len) });
20902107
}
20912108
}
20922109
}
@@ -2307,7 +2324,7 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
23072324

23082325
PatKind::Array { ref prefix, ref slice, ref suffix }
23092326
| PatKind::Slice { ref prefix, ref slice, ref suffix } => match *constructor {
2310-
FixedLenSlice(..) | LazyFixedLenSlice { .. } | VarLenSlice(..) => {
2327+
Slice { .. } => {
23112328
let pat_len = prefix.len() + suffix.len();
23122329
if let Some(slice_count) = ctor_wild_subpatterns.len().checked_sub(pat_len) {
23132330
if slice_count == 0 || slice.is_some() {

0 commit comments

Comments
 (0)