mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-30 22:01:37 +00:00
Generally optimize diagnostics performance
This commit is contained in:
parent
94e38261b3
commit
531a270d91
15 changed files with 115 additions and 85 deletions
|
@ -191,45 +191,45 @@ impl ExprValidator {
|
|||
let pattern_arena = Arena::new();
|
||||
let mut m_arms = Vec::with_capacity(arms.len());
|
||||
let mut has_lowering_errors = false;
|
||||
// Note: Skipping the entire diagnostic rather than just not including a faulty match arm is
|
||||
// preferred to avoid the chance of false positives.
|
||||
for arm in arms {
|
||||
if let Some(pat_ty) = self.infer.type_of_pat.get(arm.pat) {
|
||||
// We only include patterns whose type matches the type
|
||||
// of the scrutinee expression. If we had an InvalidMatchArmPattern
|
||||
// diagnostic or similar we could raise that in an else
|
||||
// block here.
|
||||
//
|
||||
// When comparing the types, we also have to consider that rustc
|
||||
// will automatically de-reference the scrutinee expression type if
|
||||
// necessary.
|
||||
//
|
||||
// FIXME we should use the type checker for this.
|
||||
if (pat_ty == scrut_ty
|
||||
|| scrut_ty
|
||||
.as_reference()
|
||||
.map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
|
||||
.unwrap_or(false))
|
||||
&& types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer)
|
||||
{
|
||||
// If we had a NotUsefulMatchArm diagnostic, we could
|
||||
// check the usefulness of each pattern as we added it
|
||||
// to the matrix here.
|
||||
let pat = self.lower_pattern(&cx, arm.pat, db, &mut has_lowering_errors);
|
||||
let m_arm = pat_analysis::MatchArm {
|
||||
pat: pattern_arena.alloc(pat),
|
||||
has_guard: arm.guard.is_some(),
|
||||
arm_data: (),
|
||||
};
|
||||
m_arms.push(m_arm);
|
||||
if !has_lowering_errors {
|
||||
continue;
|
||||
}
|
||||
let Some(pat_ty) = self.infer.type_of_pat.get(arm.pat) else {
|
||||
return;
|
||||
};
|
||||
|
||||
// We only include patterns whose type matches the type
|
||||
// of the scrutinee expression. If we had an InvalidMatchArmPattern
|
||||
// diagnostic or similar we could raise that in an else
|
||||
// block here.
|
||||
//
|
||||
// When comparing the types, we also have to consider that rustc
|
||||
// will automatically de-reference the scrutinee expression type if
|
||||
// necessary.
|
||||
//
|
||||
// FIXME we should use the type checker for this.
|
||||
if (pat_ty == scrut_ty
|
||||
|| scrut_ty
|
||||
.as_reference()
|
||||
.map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
|
||||
.unwrap_or(false))
|
||||
&& types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer)
|
||||
{
|
||||
// If we had a NotUsefulMatchArm diagnostic, we could
|
||||
// check the usefulness of each pattern as we added it
|
||||
// to the matrix here.
|
||||
let pat = self.lower_pattern(&cx, arm.pat, db, &mut has_lowering_errors);
|
||||
let m_arm = pat_analysis::MatchArm {
|
||||
pat: pattern_arena.alloc(pat),
|
||||
has_guard: arm.guard.is_some(),
|
||||
arm_data: (),
|
||||
};
|
||||
m_arms.push(m_arm);
|
||||
if !has_lowering_errors {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't resolve the type of a pattern, or the pattern type doesn't
|
||||
// fit the match expression, we skip this diagnostic. Skipping the entire
|
||||
// diagnostic rather than just not including this match arm is preferred
|
||||
// to avoid the chance of false positives.
|
||||
// If the pattern type doesn't fit the match expression, we skip this diagnostic.
|
||||
cov_mark::hit!(validate_match_bailed_out);
|
||||
return;
|
||||
}
|
||||
|
@ -534,8 +534,16 @@ fn types_of_subpatterns_do_match(pat: PatId, body: &Body, infer: &InferenceResul
|
|||
fn walk(pat: PatId, body: &Body, infer: &InferenceResult, has_type_mismatches: &mut bool) {
|
||||
match infer.type_mismatch_for_pat(pat) {
|
||||
Some(_) => *has_type_mismatches = true,
|
||||
None if *has_type_mismatches => (),
|
||||
None => {
|
||||
body[pat].walk_child_pats(|subpat| walk(subpat, body, infer, has_type_mismatches))
|
||||
let pat = &body[pat];
|
||||
if let Pat::ConstBlock(expr) | Pat::Lit(expr) = *pat {
|
||||
*has_type_mismatches |= infer.type_mismatch_for_expr(expr).is_some();
|
||||
if *has_type_mismatches {
|
||||
return;
|
||||
}
|
||||
}
|
||||
pat.walk_child_pats(|subpat| walk(subpat, body, infer, has_type_mismatches))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue