Remove unneeded indirection on PatCtxt

This commit is contained in:
Dawer 2021-04-29 10:04:24 +05:00
parent 26baab5d28
commit f4a95c93fe
3 changed files with 24 additions and 24 deletions

View file

@ -373,12 +373,12 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) = let (body, source_map): (Arc<Body>, Arc<BodySourceMap>) =
db.body_with_source_map(self.owner); db.body_with_source_map(self.owner);
let match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() { let _match_expr_ty = if infer.type_of_expr[match_expr].is_unknown() {
return; return;
} else { } else {
&infer.type_of_expr[match_expr] &infer.type_of_expr[match_expr]
}; };
// eprintln!("ExprValidator::validate_match2({:?})", match_expr_ty.kind(&Interner)); // eprintln!("ExprValidator::validate_match2({:?})", _match_expr_ty.kind(&Interner));
let pattern_arena = usefulness::PatternArena::clone_from(&body.pats); let pattern_arena = usefulness::PatternArena::clone_from(&body.pats);
let cx = usefulness::MatchCheckCtx { let cx = usefulness::MatchCheckCtx {

View file

@ -143,7 +143,7 @@ impl Constructor {
/// matrix, unless all of them are. /// matrix, unless all of them are.
pub(super) fn split<'a>( pub(super) fn split<'a>(
&self, &self,
pcx: &PatCtxt<'_>, pcx: PatCtxt<'_>,
ctors: impl Iterator<Item = &'a Constructor> + Clone, ctors: impl Iterator<Item = &'a Constructor> + Clone,
) -> SmallVec<[Self; 1]> { ) -> SmallVec<[Self; 1]> {
match self { match self {
@ -166,7 +166,7 @@ impl Constructor {
/// this checks for inclusion. /// this checks for inclusion.
// We inline because this has a single call site in `Matrix::specialize_constructor`. // We inline because this has a single call site in `Matrix::specialize_constructor`.
#[inline] #[inline]
pub(super) fn is_covered_by(&self, pcx: &PatCtxt<'_>, other: &Self) -> bool { pub(super) fn is_covered_by(&self, pcx: PatCtxt<'_>, other: &Self) -> bool {
// This must be kept in sync with `is_covered_by_any`. // This must be kept in sync with `is_covered_by_any`.
match (self, other) { match (self, other) {
// Wildcards cover anything // Wildcards cover anything
@ -188,7 +188,7 @@ impl Constructor {
/// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is /// Faster version of `is_covered_by` when applied to many constructors. `used_ctors` is
/// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is /// assumed to be built from `matrix.head_ctors()` with wildcards filtered out, and `self` is
/// assumed to have been split from a wildcard. /// assumed to have been split from a wildcard.
fn is_covered_by_any(&self, pcx: &PatCtxt<'_>, used_ctors: &[Constructor]) -> bool { fn is_covered_by_any(&self, pcx: PatCtxt<'_>, used_ctors: &[Constructor]) -> bool {
if used_ctors.is_empty() { if used_ctors.is_empty() {
return false; return false;
} }
@ -236,7 +236,7 @@ pub(super) struct SplitWildcard {
} }
impl SplitWildcard { impl SplitWildcard {
pub(super) fn new(pcx: &PatCtxt<'_>) -> Self { pub(super) fn new(pcx: PatCtxt<'_>) -> Self {
// let cx = pcx.cx; // let cx = pcx.cx;
// let make_range = |start, end| IntRange(todo!()); // let make_range = |start, end| IntRange(todo!());
@ -260,7 +260,7 @@ impl SplitWildcard {
/// do what you want. /// do what you want.
pub(super) fn split<'a>( pub(super) fn split<'a>(
&mut self, &mut self,
pcx: &PatCtxt<'_>, pcx: PatCtxt<'_>,
ctors: impl Iterator<Item = &'a Constructor> + Clone, ctors: impl Iterator<Item = &'a Constructor> + Clone,
) { ) {
// Since `all_ctors` never contains wildcards, this won't recurse further. // Since `all_ctors` never contains wildcards, this won't recurse further.
@ -270,21 +270,21 @@ impl SplitWildcard {
} }
/// Whether there are any value constructors for this type that are not present in the matrix. /// Whether there are any value constructors for this type that are not present in the matrix.
fn any_missing(&self, pcx: &PatCtxt<'_>) -> bool { fn any_missing(&self, pcx: PatCtxt<'_>) -> bool {
self.iter_missing(pcx).next().is_some() self.iter_missing(pcx).next().is_some()
} }
/// Iterate over the constructors for this type that are not present in the matrix. /// Iterate over the constructors for this type that are not present in the matrix.
pub(super) fn iter_missing<'a>( pub(super) fn iter_missing<'a>(
&'a self, &'a self,
pcx: &'a PatCtxt<'_>, pcx: PatCtxt<'a>,
) -> impl Iterator<Item = &'a Constructor> { ) -> impl Iterator<Item = &'a Constructor> {
self.all_ctors.iter().filter(move |ctor| !ctor.is_covered_by_any(pcx, &self.matrix_ctors)) self.all_ctors.iter().filter(move |ctor| !ctor.is_covered_by_any(pcx, &self.matrix_ctors))
} }
/// Return the set of constructors resulting from splitting the wildcard. As explained at the /// Return the set of constructors resulting from splitting the wildcard. As explained at the
/// top of the file, if any constructors are missing we can ignore the present ones. /// top of the file, if any constructors are missing we can ignore the present ones.
fn into_ctors(self, pcx: &PatCtxt<'_>) -> SmallVec<[Constructor; 1]> { fn into_ctors(self, pcx: PatCtxt<'_>) -> SmallVec<[Constructor; 1]> {
if self.any_missing(pcx) { if self.any_missing(pcx) {
// Some constructors are missing, thus we can specialize with the special `Missing` // Some constructors are missing, thus we can specialize with the special `Missing`
// constructor, which stands for those constructors that are not seen in the matrix, // constructor, which stands for those constructors that are not seen in the matrix,
@ -313,7 +313,7 @@ impl SplitWildcard {
// //
// The exception is: if we are at the top-level, for example in an empty match, we // The exception is: if we are at the top-level, for example in an empty match, we
// sometimes prefer reporting the list of constructors instead of just `_`. // sometimes prefer reporting the list of constructors instead of just `_`.
let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(&pcx.ty); let report_when_all_missing = pcx.is_top_level && !IntRange::is_integral(pcx.ty);
let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing { let ctor = if !self.matrix_ctors.is_empty() || report_when_all_missing {
Missing Missing
} else { } else {
@ -381,8 +381,8 @@ impl Fields {
Fields::Vec(pats) Fields::Vec(pats)
} }
pub(crate) fn wildcards(pcx: &PatCtxt<'_>, constructor: &Constructor) -> Self { pub(crate) fn wildcards(pcx: PatCtxt<'_>, constructor: &Constructor) -> Self {
let ty = &pcx.ty; let ty = pcx.ty;
let cx = pcx.cx; let cx = pcx.cx;
let wildcard_from_ty = |ty| cx.alloc_pat(Pat::Wild, ty); let wildcard_from_ty = |ty| cx.alloc_pat(Pat::Wild, ty);
@ -446,7 +446,7 @@ impl Fields {
/// `ty`: `Option<bool>` /// `ty`: `Option<bool>`
/// `self`: `[false]` /// `self`: `[false]`
/// returns `Some(false)` /// returns `Some(false)`
pub(super) fn apply(self, pcx: &PatCtxt<'_>, ctor: &Constructor) -> Pat { pub(super) fn apply(self, pcx: PatCtxt<'_>, ctor: &Constructor) -> Pat {
let subpatterns_and_indices = self.patterns_and_indices(); let subpatterns_and_indices = self.patterns_and_indices();
let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p); let mut subpatterns = subpatterns_and_indices.iter().map(|&(_, p)| p);

View file

@ -51,11 +51,11 @@ impl<'a> MatchCheckCtx<'a> {
} }
} }
#[derive(Clone)] #[derive(Copy, Clone)]
pub(super) struct PatCtxt<'a> { pub(super) struct PatCtxt<'a> {
pub(super) cx: &'a MatchCheckCtx<'a>, pub(super) cx: &'a MatchCheckCtx<'a>,
/// Type of the current column under investigation. /// Type of the current column under investigation.
pub(super) ty: Ty, pub(super) ty: &'a Ty,
/// Whether the current pattern is the whole pattern as found in a match arm, or if it's a /// Whether the current pattern is the whole pattern as found in a match arm, or if it's a
/// subpattern. /// subpattern.
pub(super) is_top_level: bool, pub(super) is_top_level: bool,
@ -223,7 +223,7 @@ impl Matrix {
/// This computes `S(constructor, self)`. See top of the file for explanations. /// This computes `S(constructor, self)`. See top of the file for explanations.
fn specialize_constructor( fn specialize_constructor(
&self, &self,
pcx: &PatCtxt<'_>, pcx: PatCtxt<'_>,
ctor: &Constructor, ctor: &Constructor,
ctor_wild_subpatterns: &Fields, ctor_wild_subpatterns: &Fields,
) -> Matrix { ) -> Matrix {
@ -447,7 +447,7 @@ impl Usefulness {
/// with the results of specializing with the other constructors. /// with the results of specializing with the other constructors.
fn apply_constructor( fn apply_constructor(
self, self,
pcx: &PatCtxt<'_>, pcx: PatCtxt<'_>,
matrix: &Matrix, matrix: &Matrix,
ctor: &Constructor, ctor: &Constructor,
ctor_wild_subpatterns: &Fields, ctor_wild_subpatterns: &Fields,
@ -555,7 +555,7 @@ impl Witness {
/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 } /// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
fn apply_constructor( fn apply_constructor(
mut self, mut self,
pcx: &PatCtxt<'_>, pcx: PatCtxt<'_>,
ctor: &Constructor, ctor: &Constructor,
ctor_wild_subpatterns: &Fields, ctor_wild_subpatterns: &Fields,
) -> Self { ) -> Self {
@ -623,7 +623,7 @@ fn is_useful(
// FIXME(Nadrieril): Hack to work around type normalization issues (see rust-lang/rust#72476). // FIXME(Nadrieril): Hack to work around type normalization issues (see rust-lang/rust#72476).
// TODO(iDawer): ty.strip_references() ? // TODO(iDawer): ty.strip_references() ?
let ty = matrix.heads().next().map_or(cx.type_of(v.head()), |r| cx.type_of(r)); let ty = matrix.heads().next().map_or(cx.type_of(v.head()), |r| cx.type_of(r));
let pcx = PatCtxt { cx, ty, is_top_level }; let pcx = PatCtxt { cx, ty: &ty, is_top_level };
// If the first pattern is an or-pattern, expand it. // If the first pattern is an or-pattern, expand it.
let ret = if v.head().is_or_pat(cx) { let ret = if v.head().is_or_pat(cx) {
@ -657,20 +657,20 @@ fn is_useful(
// } // }
// We split the head constructor of `v`. // We split the head constructor of `v`.
let split_ctors = v_ctor.split(&pcx, matrix.head_ctors(cx)); let split_ctors = v_ctor.split(pcx, matrix.head_ctors(cx));
// For each constructor, we compute whether there's a value that starts with it that would // For each constructor, we compute whether there's a value that starts with it that would
// witness the usefulness of `v`. // witness the usefulness of `v`.
let start_matrix = matrix; let start_matrix = matrix;
let usefulnesses = split_ctors.into_iter().map(|ctor| { let usefulnesses = split_ctors.into_iter().map(|ctor| {
// debug!("specialize({:?})", ctor); // debug!("specialize({:?})", ctor);
// We cache the result of `Fields::wildcards` because it is used a lot. // We cache the result of `Fields::wildcards` because it is used a lot.
let ctor_wild_subpatterns = Fields::wildcards(&pcx, &ctor); let ctor_wild_subpatterns = Fields::wildcards(pcx, &ctor);
let spec_matrix = let spec_matrix =
start_matrix.specialize_constructor(&pcx, &ctor, &ctor_wild_subpatterns); start_matrix.specialize_constructor(pcx, &ctor, &ctor_wild_subpatterns);
let v = v.pop_head_constructor(&ctor_wild_subpatterns, cx); let v = v.pop_head_constructor(&ctor_wild_subpatterns, cx);
let usefulness = let usefulness =
is_useful(cx, &spec_matrix, &v, witness_preference, is_under_guard, false); is_useful(cx, &spec_matrix, &v, witness_preference, is_under_guard, false);
usefulness.apply_constructor(&pcx, start_matrix, &ctor, &ctor_wild_subpatterns) usefulness.apply_constructor(pcx, start_matrix, &ctor, &ctor_wild_subpatterns)
}); });
Usefulness::merge(witness_preference, usefulnesses) Usefulness::merge(witness_preference, usefulnesses)
}; };