From 7ec77fd4d5cb035b81a8477c50763c727ceb09c1 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Mar 2026 20:29:39 +0900 Subject: [PATCH 1/3] Fix invalid suggestion on `for-loops-over-fallibles` --- .../src/for_loops_over_fallibles.rs | 2 ++ .../macro-iterator-next.rs | 21 ++++++++++++++++ .../macro-iterator-next.stderr | 24 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/ui/lint/for-loops-over-falibles/macro-iterator-next.rs create mode 100644 tests/ui/lint/for-loops-over-falibles/macro-iterator-next.stderr diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index fe95a682c6376..24220e035b1dd 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -77,6 +77,8 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles { }; let sub = if let Some(recv) = extract_iterator_next_call(cx, arg) + && recv.span.can_be_used_for_suggestions() + && recv.span.between(arg_span.shrink_to_hi()).can_be_used_for_suggestions() && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span) { ForLoopsOverFalliblesLoopSub::RemoveNext { diff --git a/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.rs b/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.rs new file mode 100644 index 0000000000000..0fe88734099c7 --- /dev/null +++ b/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.rs @@ -0,0 +1,21 @@ +// This test ensures that the `for-loops-over-fallibles` lint doesn't suggest +// removing `next`. +// ref. + +#![forbid(for_loops_over_fallibles)] +//~^ NOTE: the lint level is defined here + +fn main() { + macro_rules! mac { + (next $e:expr) => { + $e.iter().next() + }; + } + + for _ in mac!(next [1, 2]) {} + //~^ ERROR: for loop over an `Option`. This is more readably written as an `if let` statement + //~| NOTE: in this expansion of desugaring of `for` loop + //~| NOTE: in this expansion of desugaring of `for` loop + //~| HELP: to check pattern in a loop use `while let` + //~| HELP: consider using `if let` to clear intent +} diff --git a/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.stderr b/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.stderr new file mode 100644 index 0000000000000..36848fffa4394 --- /dev/null +++ b/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.stderr @@ -0,0 +1,24 @@ +error: for loop over an `Option`. This is more readably written as an `if let` statement + --> $DIR/macro-iterator-next.rs:15:14 + | +LL | for _ in mac!(next [1, 2]) {} + | ^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/macro-iterator-next.rs:5:11 + | +LL | #![forbid(for_loops_over_fallibles)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +help: to check pattern in a loop use `while let` + | +LL - for _ in mac!(next [1, 2]) {} +LL + while let Some(_) = mac!(next [1, 2]) {} + | +help: consider using `if let` to clear intent + | +LL - for _ in mac!(next [1, 2]) {} +LL + if let Some(_) = mac!(next [1, 2]) {} + | + +error: aborting due to 1 previous error + From b4c1677fff43d9ea04002de85aef77915092be7d Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Mar 2026 20:34:25 +0900 Subject: [PATCH 2/3] Do not lint `for-loops-over-fallibles` on external macros --- .../rustc_lint/src/for_loops_over_fallibles.rs | 5 +++++ tests/crashes/147973.rs | 14 -------------- .../auxiliary/external-macro-issue-148114.rs | 13 +++++++++++++ .../external-macro-issue-148114.rs | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) delete mode 100644 tests/crashes/147973.rs create mode 100644 tests/ui/lint/for-loops-over-falibles/auxiliary/external-macro-issue-148114.rs create mode 100644 tests/ui/lint/for-loops-over-falibles/external-macro-issue-148114.rs diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 24220e035b1dd..a7c5943c250b8 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -49,6 +49,11 @@ 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 }; + // Do not put suggestions for external macros. + if pat.span.from_expansion() { + return; + } + let arg_span = arg.span.source_callsite(); let ty = cx.typeck_results().expr_ty(arg); diff --git a/tests/crashes/147973.rs b/tests/crashes/147973.rs deleted file mode 100644 index 7271c54846f15..0000000000000 --- a/tests/crashes/147973.rs +++ /dev/null @@ -1,14 +0,0 @@ -// This is part of series of regression tests for some diagnostics ICEs encountered in the wild with -// suggestions having overlapping parts under https://github.com/rust-lang/rust/pull/146121. -// This is one MCVE from the beta crater run regressions from issue 147973. - -//@ needs-rustc-debug-assertions -//@ known-bug: #147973 - -//@ aux-build: overlapping_spans_helper.rs -extern crate overlapping_spans_helper; - -fn main() { - let _name = Some(1); - overlapping_spans_helper::do_loop!(_name); -} diff --git a/tests/ui/lint/for-loops-over-falibles/auxiliary/external-macro-issue-148114.rs b/tests/ui/lint/for-loops-over-falibles/auxiliary/external-macro-issue-148114.rs new file mode 100644 index 0000000000000..68eff33cb3f10 --- /dev/null +++ b/tests/ui/lint/for-loops-over-falibles/auxiliary/external-macro-issue-148114.rs @@ -0,0 +1,13 @@ +#[macro_export] +macro_rules! identity { + ($x:ident) => { + $x + }; +} + +#[macro_export] +macro_rules! do_loop { + ($x:ident) => { + for $crate::identity!($x) in $x {} + }; +} diff --git a/tests/ui/lint/for-loops-over-falibles/external-macro-issue-148114.rs b/tests/ui/lint/for-loops-over-falibles/external-macro-issue-148114.rs new file mode 100644 index 0000000000000..ca3ac3b9a8647 --- /dev/null +++ b/tests/ui/lint/for-loops-over-falibles/external-macro-issue-148114.rs @@ -0,0 +1,14 @@ +//@ check-pass +//@ aux-build:external-macro-issue-148114.rs + +// This test ensures we do not trigger the lint on external macros +// ref. + +#![deny(for_loops_over_fallibles)] + +extern crate external_macro_issue_148114 as dep; + +fn main() { + let _name = Some(1); + dep::do_loop!(_name); +} From cfe18cfd37e3aefe0a9a653d3faac825c3a7868a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 15 Mar 2026 20:35:16 +0900 Subject: [PATCH 3/3] Correct dir name --- .../auxiliary/external-macro-issue-148114.rs | 0 .../external-macro-issue-148114.rs | 0 .../macro-issue-140747.rs | 0 .../macro-issue-140747.stderr | 0 .../macro-iterator-next.rs | 0 .../macro-iterator-next.stderr | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/lint/{for-loops-over-falibles => for-loops-over-fallibles}/auxiliary/external-macro-issue-148114.rs (100%) rename tests/ui/lint/{for-loops-over-falibles => for-loops-over-fallibles}/external-macro-issue-148114.rs (100%) rename tests/ui/lint/{for-loops-over-falibles => for-loops-over-fallibles}/macro-issue-140747.rs (100%) rename tests/ui/lint/{for-loops-over-falibles => for-loops-over-fallibles}/macro-issue-140747.stderr (100%) rename tests/ui/lint/{for-loops-over-falibles => for-loops-over-fallibles}/macro-iterator-next.rs (100%) rename tests/ui/lint/{for-loops-over-falibles => for-loops-over-fallibles}/macro-iterator-next.stderr (100%) diff --git a/tests/ui/lint/for-loops-over-falibles/auxiliary/external-macro-issue-148114.rs b/tests/ui/lint/for-loops-over-fallibles/auxiliary/external-macro-issue-148114.rs similarity index 100% rename from tests/ui/lint/for-loops-over-falibles/auxiliary/external-macro-issue-148114.rs rename to tests/ui/lint/for-loops-over-fallibles/auxiliary/external-macro-issue-148114.rs diff --git a/tests/ui/lint/for-loops-over-falibles/external-macro-issue-148114.rs b/tests/ui/lint/for-loops-over-fallibles/external-macro-issue-148114.rs similarity index 100% rename from tests/ui/lint/for-loops-over-falibles/external-macro-issue-148114.rs rename to tests/ui/lint/for-loops-over-fallibles/external-macro-issue-148114.rs diff --git a/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs b/tests/ui/lint/for-loops-over-fallibles/macro-issue-140747.rs similarity index 100% rename from tests/ui/lint/for-loops-over-falibles/macro-issue-140747.rs rename to tests/ui/lint/for-loops-over-fallibles/macro-issue-140747.rs diff --git a/tests/ui/lint/for-loops-over-falibles/macro-issue-140747.stderr b/tests/ui/lint/for-loops-over-fallibles/macro-issue-140747.stderr similarity index 100% rename from tests/ui/lint/for-loops-over-falibles/macro-issue-140747.stderr rename to tests/ui/lint/for-loops-over-fallibles/macro-issue-140747.stderr diff --git a/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.rs b/tests/ui/lint/for-loops-over-fallibles/macro-iterator-next.rs similarity index 100% rename from tests/ui/lint/for-loops-over-falibles/macro-iterator-next.rs rename to tests/ui/lint/for-loops-over-fallibles/macro-iterator-next.rs diff --git a/tests/ui/lint/for-loops-over-falibles/macro-iterator-next.stderr b/tests/ui/lint/for-loops-over-fallibles/macro-iterator-next.stderr similarity index 100% rename from tests/ui/lint/for-loops-over-falibles/macro-iterator-next.stderr rename to tests/ui/lint/for-loops-over-fallibles/macro-iterator-next.stderr