Migrate leading/trailing irrefutable let pattern diagnostics

This commit is contained in:
TheOddGarlic 2022-08-28 21:48:09 +03:00 committed by mejrs
parent 4b70784176
commit 6f82a00aa1
3 changed files with 52 additions and 25 deletions

View file

@ -207,3 +207,29 @@ mir_build_lower_range_bound_must_be_less_than_or_equal_to_upper =
.teach_note = When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
mir_build_lower_range_bound_must_be_less_than_upper = lower range bound must be less than upper
mir_build_leading_irrefutable_let_patterns = leading irrefutable {$count ->
[one] pattern
*[other] patterns
} in let chain
.note = {$count ->
[one] this pattern
*[other] these patterns
} will always match
.help = consider moving {$count ->
[one] it
*[other] them
} outside of the construct
mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
[one] pattern
*[other] patterns
} in let chain
.note = {$count ->
[one] this pattern
*[other] these patterns
} will always match
.help = consider moving {$count ->
[one] it
*[other] them
} into the body

View file

@ -497,3 +497,19 @@ pub struct LowerRangeBoundMustBeLessThanUpper {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
#[diag(mir_build::leading_irrefutable_let_patterns)]
#[note]
#[help]
pub struct LeadingIrrefutableLetPatterns {
pub count: usize,
}
#[derive(LintDiagnostic)]
#[diag(mir_build::trailing_irrefutable_let_patterns)]
#[note]
#[help]
pub struct TrailingIrrefutableLetPatterns {
pub count: usize,
}

View file

@ -339,29 +339,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
);
return true;
}
let lint_affix = |affix: &[Option<(Span, bool)>], kind, suggestion| {
let span_start = affix[0].unwrap().0;
let span_end = affix.last().unwrap().unwrap().0;
let span = span_start.to(span_end);
let cnt = affix.len();
let s = pluralize!(cnt);
cx.tcx.struct_span_lint_hir(
IRREFUTABLE_LET_PATTERNS,
top,
span,
format!("{kind} irrefutable pattern{s} in let chain"),
|lint| {
lint.note(format!(
"{these} pattern{s} will always match",
these = pluralize!("this", cnt),
))
.help(format!(
"consider moving {} {suggestion}",
if cnt > 1 { "them" } else { "it" }
))
},
);
};
if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
// The chain has a non-zero prefix of irrefutable `let` statements.
@ -375,13 +352,21 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
// Emit the lint
let prefix = &chain_refutabilities[..until];
lint_affix(prefix, "leading", "outside of the construct");
let span_start = prefix[0].unwrap().0;
let span_end = prefix.last().unwrap().unwrap().0;
let span = span_start.to(span_end);
let count = prefix.len();
cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count });
}
}
if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) {
// The chain has a non-empty suffix of irrefutable `let` statements
let suffix = &chain_refutabilities[from + 1..];
lint_affix(suffix, "trailing", "into the body");
let span_start = suffix[0].unwrap().0;
let span_end = suffix.last().unwrap().unwrap().0;
let span = span_start.to(span_end);
let count = suffix.len();
cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count });
}
true
}