Use span before macro expansion in lint for-loops-over-falibles

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
xizheyin 2025-05-08 21:12:02 +08:00
parent c0f0b5157f
commit 88c1796384
3 changed files with 15 additions and 21 deletions

View File

@ -49,6 +49,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let Some((pat, arg)) = extract_for_loop(expr) else { return }; let Some((pat, arg)) = extract_for_loop(expr) else { return };
let arg_span = arg.span.source_callsite();
let ty = cx.typeck_results().expr_ty(arg); let ty = cx.typeck_results().expr_ty(arg);
let (adt, args, ref_mutability) = match ty.kind() { let (adt, args, ref_mutability) = match ty.kind() {
@ -78,27 +80,27 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
&& let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
{ {
ForLoopsOverFalliblesLoopSub::RemoveNext { ForLoopsOverFalliblesLoopSub::RemoveNext {
suggestion: recv.span.between(arg.span.shrink_to_hi()), suggestion: recv.span.between(arg_span.shrink_to_hi()),
recv_snip, recv_snip,
} }
} else { } else {
ForLoopsOverFalliblesLoopSub::UseWhileLet { ForLoopsOverFalliblesLoopSub::UseWhileLet {
start_span: expr.span.with_hi(pat.span.lo()), start_span: expr.span.with_hi(pat.span.lo()),
end_span: pat.span.between(arg.span), end_span: pat.span.between(arg_span),
var, var,
} }
}; };
let question_mark = suggest_question_mark(cx, adt, args, expr.span) let question_mark = suggest_question_mark(cx, adt, args, expr.span)
.then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg.span.shrink_to_hi() }); .then(|| ForLoopsOverFalliblesQuestionMark { suggestion: arg_span.shrink_to_hi() });
let suggestion = ForLoopsOverFalliblesSuggestion { let suggestion = ForLoopsOverFalliblesSuggestion {
var, var,
start_span: expr.span.with_hi(pat.span.lo()), start_span: expr.span.with_hi(pat.span.lo()),
end_span: pat.span.between(arg.span), end_span: pat.span.between(arg_span),
}; };
cx.emit_span_lint( cx.emit_span_lint(
FOR_LOOPS_OVER_FALLIBLES, FOR_LOOPS_OVER_FALLIBLES,
arg.span, arg_span,
ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion }, ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion },
); );
} }

View File

@ -3,8 +3,8 @@
fn main() { fn main() {
macro_rules! x { macro_rules! x {
() => { () => {
None::<i32> //~ ERROR for loop over an `Option`. This is more readably written as an `if let` statement [for_loops_over_fallibles] None::<i32>
}; };
} }
for _ in x! {} {} for _ in x! {} {} //~ ERROR for loop over an `Option`. This is more readably written as an `if let` statement [for_loops_over_fallibles]
} }

View File

@ -1,31 +1,23 @@
error: for loop over an `Option`. This is more readably written as an `if let` statement error: for loop over an `Option`. This is more readably written as an `if let` statement
--> $DIR/macro-issue-140747.rs:6:13 --> $DIR/macro-issue-140747.rs:9:14
| |
LL | None::<i32>
| ^^^^^^^^^^^
...
LL | for _ in x! {} {} LL | for _ in x! {} {}
| ----- in this macro invocation | ^^^^^
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/macro-issue-140747.rs:1:11 --> $DIR/macro-issue-140747.rs:1:11
| |
LL | #![forbid(for_loops_over_fallibles)] LL | #![forbid(for_loops_over_fallibles)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `x` (in Nightly builds, run with -Z macro-backtrace for more info)
help: to check pattern in a loop use `while let` help: to check pattern in a loop use `while let`
| |
LL ~ ) = LL - for _ in x! {} {}
LL | }; LL + while let Some(_) = x! {} {}
LL | }
LL ~ while let Some(_ in x! {} {}
| |
help: consider using `if let` to clear intent help: consider using `if let` to clear intent
| |
LL ~ ) = LL - for _ in x! {} {}
LL | }; LL + if let Some(_) = x! {} {}
LL | }
LL ~ if let Some(_ in x! {} {}
| |
error: aborting due to 1 previous error error: aborting due to 1 previous error