Pass PatCtxt instead of passing MatchCtxt + Ty separately

This commit is contained in:
Oli Scherer 2022-07-28 08:49:39 +00:00
parent 544de44a6b
commit 803d374f9b
2 changed files with 22 additions and 25 deletions

View File

@ -1202,35 +1202,32 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
/// Creates a new list of wildcard fields for a given constructor. The result must have a
/// length of `constructor.arity()`.
pub(super) fn wildcards(
cx: &MatchCheckCtxt<'p, 'tcx>,
ty: Ty<'tcx>,
constructor: &Constructor<'tcx>,
) -> Self {
#[instrument(level = "trace")]
pub(super) fn wildcards(pcx: &PatCtxt<'_, 'p, 'tcx>, constructor: &Constructor<'tcx>) -> Self {
let ret = match constructor {
Single | Variant(_) => match ty.kind() {
ty::Tuple(fs) => Fields::wildcards_from_tys(cx, fs.iter()),
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(cx, once(*rty)),
Single | Variant(_) => match pcx.ty.kind() {
ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter()),
ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty)),
ty::Adt(adt, substs) => {
if adt.is_box() {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
Fields::wildcards_from_tys(cx, once(substs.type_at(0)))
Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)))
} else {
let variant = &adt.variant(constructor.variant_index_for_adt(*adt));
let tys = Fields::list_variant_nonhidden_fields(cx, ty, variant)
let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant)
.map(|(_, ty)| ty);
Fields::wildcards_from_tys(cx, tys)
Fields::wildcards_from_tys(pcx.cx, tys)
}
}
_ => bug!("Unexpected type for `Single` constructor: {:?}", ty),
_ => bug!("Unexpected type for `Single` constructor: {:?}", pcx),
},
Slice(slice) => match *ty.kind() {
Slice(slice) => match *pcx.ty.kind() {
ty::Slice(ty) | ty::Array(ty, _) => {
let arity = slice.arity();
Fields::wildcards_from_tys(cx, (0..arity).map(|_| ty))
Fields::wildcards_from_tys(pcx.cx, (0..arity).map(|_| ty))
}
_ => bug!("bad slice pattern {:?} {:?}", constructor, ty),
_ => bug!("bad slice pattern {:?} {:?}", constructor, pcx),
},
Str(..)
| FloatRange(..)
@ -1243,7 +1240,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
bug!("called `Fields::wildcards` on an `Or` ctor")
}
};
debug!("Fields::wildcards({:?}, {:?}) = {:#?}", constructor, ty, ret);
debug!(?ret);
ret
}
@ -1286,7 +1283,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
/// For example, if `ctor` is a `Constructor::Variant` for `Option::Some`, we get the pattern
/// `Some(_)`.
pub(super) fn wild_from_ctor(pcx: &PatCtxt<'_, 'p, 'tcx>, ctor: Constructor<'tcx>) -> Self {
let fields = Fields::wildcards(pcx.cx, pcx.ty, &ctor);
let fields = Fields::wildcards(pcx, &ctor);
DeconstructedPat::new(ctor, fields, pcx.ty, DUMMY_SP)
}
@ -1553,13 +1550,13 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
/// `other_ctor` can be different from `self.ctor`, but must be covered by it.
pub(super) fn specialize<'a>(
&'a self,
cx: &MatchCheckCtxt<'p, 'tcx>,
pcx: &PatCtxt<'_, 'p, 'tcx>,
other_ctor: &Constructor<'tcx>,
) -> SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]> {
match (&self.ctor, other_ctor) {
(Wildcard, _) => {
// We return a wildcard for each field of `other_ctor`.
Fields::wildcards(cx, self.ty, other_ctor).iter_patterns().collect()
Fields::wildcards(pcx, other_ctor).iter_patterns().collect()
}
(Slice(self_slice), Slice(other_slice))
if self_slice.arity() != other_slice.arity() =>
@ -1578,7 +1575,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
let prefix = &self.fields.fields[..prefix];
let suffix = &self.fields.fields[self_slice.arity() - suffix..];
let wildcard: &_ =
cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
pcx.cx.pattern_arena.alloc(DeconstructedPat::wildcard(inner_ty));
let extra_wildcards = other_slice.arity() - self_slice.arity();
let extra_wildcards = (0..extra_wildcards).map(|_| wildcard);
prefix.iter().chain(extra_wildcards).chain(suffix).collect()

View File

@ -411,12 +411,12 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
/// This is roughly the inverse of `Constructor::apply`.
fn pop_head_constructor(
&self,
cx: &MatchCheckCtxt<'p, 'tcx>,
pcx: &PatCtxt<'_, 'p, 'tcx>,
ctor: &Constructor<'tcx>,
) -> PatStack<'p, 'tcx> {
// We pop the head pattern and push the new fields extracted from the arguments of
// `self.head()`.
let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(cx, ctor);
let mut new_fields: SmallVec<[_; 2]> = self.head().specialize(pcx, ctor);
new_fields.extend_from_slice(&self.pats[1..]);
PatStack::from_vec(new_fields)
}
@ -475,7 +475,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
let mut matrix = Matrix::empty();
for row in &self.patterns {
if ctor.is_covered_by(pcx, row.head().ctor()) {
let new_row = row.pop_head_constructor(pcx.cx, ctor);
let new_row = row.pop_head_constructor(pcx, ctor);
matrix.push(new_row);
}
}
@ -786,7 +786,7 @@ fn is_useful<'p, 'tcx>(
is_under_guard: bool,
is_top_level: bool,
) -> Usefulness<'p, 'tcx> {
debug!("matrix,v={:?}{:?}", matrix, v);
debug!(?matrix, ?v);
let Matrix { patterns: rows, .. } = matrix;
// The base case. We are pattern-matching on () and the return value is
@ -853,7 +853,7 @@ fn is_useful<'p, 'tcx>(
debug!("specialize({:?})", ctor);
// We cache the result of `Fields::wildcards` because it is used a lot.
let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
let v = v.pop_head_constructor(cx, &ctor);
let v = v.pop_head_constructor(pcx, &ctor);
let usefulness = ensure_sufficient_stack(|| {
is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
});