mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
migrate: for_loops_over_fallibles.rs
This commit is contained in:
parent
3c1a1f3643
commit
ca7df9a2a9
@ -16,6 +16,13 @@ lint_enum_intrinsics_mem_variant =
|
||||
lint_expectation = this lint expectation is unfulfilled
|
||||
.note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
|
||||
lint_for_loops_over_fallibles =
|
||||
for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
|
||||
.suggestion = consider using `if let` to clear intent
|
||||
.remove_next = to iterate over `{$recv_snip}` remove the call to `next`
|
||||
.use_while_let = to check pattern in a loop use `while let`
|
||||
.use_question_mark = consider unwrapping the `Result` with `?` to iterate over its contents
|
||||
|
||||
lint_non_binding_let_on_sync_lock =
|
||||
non-binding let on a synchronization lock
|
||||
|
||||
|
@ -1,7 +1,14 @@
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use crate::{
|
||||
lints::{
|
||||
ForLoopsOverFalliblesDiag, ForLoopsOverFalliblesLoopSub, ForLoopsOverFalliblesQuestionMark,
|
||||
ForLoopsOverFalliblesSuggestion,
|
||||
},
|
||||
LateContext, LateLintPass, LintContext,
|
||||
};
|
||||
|
||||
use hir::{Expr, Pat};
|
||||
use rustc_errors::{Applicability, DelayDm};
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause};
|
||||
use rustc_middle::ty::{self, List};
|
||||
@ -53,53 +60,29 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let msg = DelayDm(|| {
|
||||
format!(
|
||||
"for loop over {article} `{ty}`. This is more readably written as an `if let` statement",
|
||||
)
|
||||
});
|
||||
|
||||
cx.struct_span_lint(FOR_LOOPS_OVER_FALLIBLES, arg.span, msg, |lint| {
|
||||
if let Some(recv) = extract_iterator_next_call(cx, arg)
|
||||
let sub = if let Some(recv) = extract_iterator_next_call(cx, arg)
|
||||
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
|
||||
{
|
||||
lint.span_suggestion(
|
||||
recv.span.between(arg.span.shrink_to_hi()),
|
||||
format!("to iterate over `{recv_snip}` remove the call to `next`"),
|
||||
".by_ref()",
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
ForLoopsOverFalliblesLoopSub::RemoveNext { suggestion: recv.span.between(arg.span.shrink_to_hi()), recv_snip }
|
||||
} else {
|
||||
lint.multipart_suggestion_verbose(
|
||||
"to check pattern in a loop use `while let`",
|
||||
vec![
|
||||
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
|
||||
(expr.span.with_hi(pat.span.lo()), format!("while let {var}(")),
|
||||
(pat.span.between(arg.span), ") = ".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect
|
||||
);
|
||||
}
|
||||
ForLoopsOverFalliblesLoopSub::UseWhileLet { start_span: expr.span.with_hi(pat.span.lo()), end_span: pat.span.between(arg.span), var }
|
||||
} ;
|
||||
let question_mark = if suggest_question_mark(cx, adt, substs, expr.span) {
|
||||
Some(ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let suggestion = ForLoopsOverFalliblesSuggestion {
|
||||
var,
|
||||
start_span: expr.span.with_hi(pat.span.lo()),
|
||||
end_span: pat.span.between(arg.span),
|
||||
};
|
||||
|
||||
if suggest_question_mark(cx, adt, substs, expr.span) {
|
||||
lint.span_suggestion(
|
||||
arg.span.shrink_to_hi(),
|
||||
"consider unwrapping the `Result` with `?` to iterate over its contents",
|
||||
"?",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
lint.multipart_suggestion_verbose(
|
||||
"consider using `if let` to clear intent",
|
||||
vec![
|
||||
// NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
|
||||
(expr.span.with_hi(pat.span.lo()), format!("if let {var}(")),
|
||||
(pat.span.between(arg.span), ") = ".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
})
|
||||
cx.emit_spanned_lint(
|
||||
FOR_LOOPS_OVER_FALLIBLES,
|
||||
arg.span,
|
||||
ForLoopsOverFalliblesDiag { article, ty, sub, question_mark, suggestion },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,6 +333,55 @@ impl<'a> DecorateLint<'a, ()> for Expectation<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
// for_loops_over_fallibles.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_for_loops_over_fallibles)]
|
||||
pub struct ForLoopsOverFalliblesDiag<'a> {
|
||||
pub article: &'static str,
|
||||
pub ty: &'static str,
|
||||
#[subdiagnostic]
|
||||
pub sub: ForLoopsOverFalliblesLoopSub<'a>,
|
||||
#[subdiagnostic]
|
||||
pub question_mark: Option<ForLoopsOverFalliblesQuestionMark>,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: ForLoopsOverFalliblesSuggestion<'a>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub enum ForLoopsOverFalliblesLoopSub<'a> {
|
||||
#[suggestion(remove_next, code = ".by_ref()", applicability = "maybe-incorrect")]
|
||||
RemoveNext {
|
||||
#[primary_span]
|
||||
suggestion: Span,
|
||||
recv_snip: String,
|
||||
},
|
||||
#[multipart_suggestion(use_while_let, applicability = "maybe-incorrect")]
|
||||
UseWhileLet {
|
||||
#[suggestion_part(code = "while let {var}(")]
|
||||
start_span: Span,
|
||||
#[suggestion_part(code = ") = ")]
|
||||
end_span: Span,
|
||||
var: &'a str,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(use_question_mark, code = "?", applicability = "maybe-incorrect")]
|
||||
pub struct ForLoopsOverFalliblesQuestionMark {
|
||||
#[primary_span]
|
||||
pub suggestion: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
|
||||
pub struct ForLoopsOverFalliblesSuggestion<'a> {
|
||||
pub var: &'a str,
|
||||
#[suggestion_part(code = "if let {var}(")]
|
||||
pub start_span: Span,
|
||||
#[suggestion_part(code = ") = ")]
|
||||
pub end_span: Span,
|
||||
}
|
||||
|
||||
// internal.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_default_hash_types)]
|
||||
|
Loading…
Reference in New Issue
Block a user