Rollup merge of #140801 - xizheyin:issue-140747, r=SparrowLii
Use span before macro expansion in lint for-loops-over-falibles Fixes #140747 I think there are going to be a lot of cases where macros are expanded in the compiler resulting in span offsets, and I'd like to know how that's typically handled. Does it have to be handled specially every time?
This commit is contained in:
commit
b165a4c280
3 changed files with 41 additions and 5 deletions
|
|
@ -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 },
|
||||
);
|
||||
}
|
||||
|
|
|
|||
10
tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs
Normal file
10
tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#![forbid(for_loops_over_fallibles)]
|
||||
|
||||
fn main() {
|
||||
macro_rules! x {
|
||||
() => {
|
||||
None::<i32>
|
||||
};
|
||||
}
|
||||
for _ in x! {} {} //~ ERROR for loop over an `Option`. This is more readably written as an `if let` statement [for_loops_over_fallibles]
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
error: for loop over an `Option`. This is more readably written as an `if let` statement
|
||||
--> $DIR/macro-issue-140747.rs:9:14
|
||||
|
|
||||
LL | for _ in x! {} {}
|
||||
| ^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro-issue-140747.rs:1:11
|
||||
|
|
||||
LL | #![forbid(for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: to check pattern in a loop use `while let`
|
||||
|
|
||||
LL - for _ in x! {} {}
|
||||
LL + while let Some(_) = x! {} {}
|
||||
|
|
||||
help: consider using `if let` to clear intent
|
||||
|
|
||||
LL - for _ in x! {} {}
|
||||
LL + if let Some(_) = x! {} {}
|
||||
|
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue