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<'_>) {
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 (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)
{
ForLoopsOverFalliblesLoopSub::RemoveNext {
suggestion: recv.span.between(arg.span.shrink_to_hi()),
suggestion: recv.span.between(arg_span.shrink_to_hi()),
recv_snip,
}
} else {
ForLoopsOverFalliblesLoopSub::UseWhileLet {
start_span: expr.span.with_hi(pat.span.lo()),
end_span: pat.span.between(arg.span),
end_span: pat.span.between(arg_span),
var,
}
};
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 {
var,
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(
FOR_LOOPS_OVER_FALLIBLES,
arg.span,
arg_span,
ForLoopsOverFalliblesDiag { article, ref_prefix, ty, sub, question_mark, suggestion },
);
}

View File

@ -3,8 +3,8 @@
fn main() {
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
--> $DIR/macro-issue-140747.rs:6:13
--> $DIR/macro-issue-140747.rs:9:14
|
LL | None::<i32>
| ^^^^^^^^^^^
...
LL | for _ in x! {} {}
| ----- in this macro invocation
| ^^^^^
|
note: the lint level is defined here
--> $DIR/macro-issue-140747.rs:1:11
|
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`
|
LL ~ ) =
LL | };
LL | }
LL ~ while let Some(_ in x! {} {}
LL - for _ in x! {} {}
LL + while let Some(_) = x! {} {}
|
help: consider using `if let` to clear intent
|
LL ~ ) =
LL | };
LL | }
LL ~ if let Some(_ in x! {} {}
LL - for _ in x! {} {}
LL + if let Some(_) = x! {} {}
|
error: aborting due to 1 previous error