mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Remove unneeded indirection on PatCtxt
This commit is contained in:
parent
26baab5d28
commit
f4a95c93fe
3 changed files with 24 additions and 24 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue