Simplify slice splitting a bit
This commit is contained in:
parent
cd4c7144de
commit
766ab78a1c
|
@ -620,21 +620,17 @@ struct Slice {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Slice {
|
impl Slice {
|
||||||
/// Returns what patterns this constructor covers: either fixed-length patterns or
|
fn new(array_len: Option<u64>, kind: SliceKind) -> Self {
|
||||||
/// variable-length patterns.
|
let kind = match (array_len, kind) {
|
||||||
fn kind(self) -> SliceKind {
|
// If the middle `..` is empty, we effectively have a fixed-length pattern.
|
||||||
match self {
|
(Some(len), VarLen(prefix, suffix)) if prefix + suffix >= len => FixedLen(len),
|
||||||
Slice { array_len: Some(len), kind: VarLen(prefix, suffix) }
|
_ => kind,
|
||||||
if prefix + suffix == len =>
|
};
|
||||||
{
|
Slice { array_len, kind }
|
||||||
FixedLen(len)
|
|
||||||
}
|
|
||||||
_ => self.kind,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arity(self) -> u64 {
|
fn arity(self) -> u64 {
|
||||||
self.kind().arity()
|
self.kind.arity()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The exhaustiveness-checking paper does not include any details on
|
/// The exhaustiveness-checking paper does not include any details on
|
||||||
|
@ -701,10 +697,8 @@ impl Slice {
|
||||||
/// witness of length ≥2 (say, `[false, false, true]`) can be
|
/// witness of length ≥2 (say, `[false, false, true]`) can be
|
||||||
/// turned to a witness from any other length ≥2.
|
/// turned to a witness from any other length ≥2.
|
||||||
fn split<'p, 'tcx>(self, pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
|
fn split<'p, 'tcx>(self, pcx: PatCtxt<'_, 'p, 'tcx>) -> SmallVec<[Constructor<'tcx>; 1]> {
|
||||||
let (array_len, self_prefix, self_suffix) = match self {
|
let (self_prefix, self_suffix) = match self.kind {
|
||||||
Slice { array_len, kind: VarLen(self_prefix, self_suffix) } => {
|
VarLen(self_prefix, self_suffix) => (self_prefix, self_suffix),
|
||||||
(array_len, self_prefix, self_suffix)
|
|
||||||
}
|
|
||||||
_ => return smallvec![Slice(self)],
|
_ => return smallvec![Slice(self)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -716,7 +710,7 @@ impl Slice {
|
||||||
|
|
||||||
for ctor in head_ctors {
|
for ctor in head_ctors {
|
||||||
if let Slice(slice) = ctor {
|
if let Slice(slice) = ctor {
|
||||||
match slice.kind() {
|
match slice.kind {
|
||||||
FixedLen(len) => {
|
FixedLen(len) => {
|
||||||
max_fixed_len = cmp::max(max_fixed_len, len);
|
max_fixed_len = cmp::max(max_fixed_len, len);
|
||||||
}
|
}
|
||||||
|
@ -725,6 +719,8 @@ impl Slice {
|
||||||
max_suffix_len = cmp::max(max_suffix_len, suffix);
|
max_suffix_len = cmp::max(max_suffix_len, suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bug!("unexpected ctor for slice type: {:?}", ctor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -738,27 +734,19 @@ impl Slice {
|
||||||
max_prefix_len = max_fixed_len + 1 - max_suffix_len;
|
max_prefix_len = max_fixed_len + 1 - max_suffix_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
match array_len {
|
let final_slice = VarLen(max_prefix_len, max_suffix_len);
|
||||||
Some(len) => {
|
let final_slice = Slice::new(self.array_len, final_slice);
|
||||||
let kind = if max_prefix_len + max_suffix_len < len {
|
match self.array_len {
|
||||||
VarLen(max_prefix_len, max_suffix_len)
|
Some(_) => smallvec![Slice(final_slice)],
|
||||||
} else {
|
|
||||||
FixedLen(len)
|
|
||||||
};
|
|
||||||
smallvec![Slice(Slice { array_len, kind })]
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
// `ctor` originally covered the range `(self_prefix +
|
// `self` originally covered the range `(self.arity()..infinity)`. We split that
|
||||||
// self_suffix..infinity)`. We now split it into two: lengths smaller than
|
// range into two: lengths smaller than `final_slice.arity()` are treated
|
||||||
// `max_prefix_len + max_suffix_len` are treated independently as
|
// independently as fixed-lengths slices, and lengths above are captured by
|
||||||
// fixed-lengths slices, and lengths above are captured by a final VarLen
|
// `final_slice`.
|
||||||
// constructor.
|
let smaller_lengths = (self.arity()..final_slice.arity()).map(FixedLen);
|
||||||
let smaller_lengths =
|
|
||||||
(self_prefix + self_suffix..max_prefix_len + max_suffix_len).map(FixedLen);
|
|
||||||
let final_slice = VarLen(max_prefix_len, max_suffix_len);
|
|
||||||
smaller_lengths
|
smaller_lengths
|
||||||
|
.map(|kind| Slice::new(self.array_len, kind))
|
||||||
.chain(Some(final_slice))
|
.chain(Some(final_slice))
|
||||||
.map(|kind| Slice { array_len, kind })
|
|
||||||
.map(Slice)
|
.map(Slice)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -767,7 +755,7 @@ impl Slice {
|
||||||
|
|
||||||
/// See `Constructor::is_covered_by`
|
/// See `Constructor::is_covered_by`
|
||||||
fn is_covered_by(self, other: Self) -> bool {
|
fn is_covered_by(self, other: Self) -> bool {
|
||||||
other.kind().covers_length(self.arity())
|
other.kind.covers_length(self.arity())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,7 +922,6 @@ impl<'tcx> Constructor<'tcx> {
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
|
(Slice(self_slice), Slice(other_slice)) => self_slice.is_covered_by(*other_slice),
|
||||||
|
|
||||||
// We are trying to inspect an opaque constant. Thus we skip the row.
|
// We are trying to inspect an opaque constant. Thus we skip the row.
|
||||||
|
@ -1029,7 +1016,7 @@ impl<'tcx> Constructor<'tcx> {
|
||||||
ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, pcx.ty),
|
ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, pcx.ty),
|
||||||
_ => PatKind::Wild,
|
_ => PatKind::Wild,
|
||||||
},
|
},
|
||||||
Slice(slice) => match slice.kind() {
|
Slice(slice) => match slice.kind {
|
||||||
FixedLen(_) => {
|
FixedLen(_) => {
|
||||||
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
|
PatKind::Slice { prefix: subpatterns.collect(), slice: None, suffix: vec![] }
|
||||||
}
|
}
|
||||||
|
@ -1533,13 +1520,13 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
|
||||||
if len != 0 && cx.is_uninhabited(sub_ty) {
|
if len != 0 && cx.is_uninhabited(sub_ty) {
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
vec![Slice(Slice { array_len: Some(len), kind: VarLen(0, 0) })]
|
vec![Slice(Slice::new(Some(len), VarLen(0, 0)))]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Treat arrays of a constant but unknown length like slices.
|
// Treat arrays of a constant but unknown length like slices.
|
||||||
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
|
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
|
||||||
let kind = if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
|
let kind = if cx.is_uninhabited(sub_ty) { FixedLen(0) } else { VarLen(0, 0) };
|
||||||
vec![Slice(Slice { array_len: None, kind })]
|
vec![Slice(Slice::new(None, kind))]
|
||||||
}
|
}
|
||||||
ty::Adt(def, substs) if def.is_enum() => {
|
ty::Adt(def, substs) if def.is_enum() => {
|
||||||
// If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
|
// If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an
|
||||||
|
@ -2224,7 +2211,7 @@ fn pat_constructor<'p, 'tcx>(
|
||||||
let suffix = suffix.len() as u64;
|
let suffix = suffix.len() as u64;
|
||||||
let kind =
|
let kind =
|
||||||
if slice.is_some() { VarLen(prefix, suffix) } else { FixedLen(prefix + suffix) };
|
if slice.is_some() { VarLen(prefix, suffix) } else { FixedLen(prefix + suffix) };
|
||||||
Slice(Slice { array_len, kind })
|
Slice(Slice::new(array_len, kind))
|
||||||
}
|
}
|
||||||
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
|
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue