From bb6fb6137f8465fa2422fb4159f5610127cad084 Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Mon, 3 Nov 2025 14:21:35 -0500 Subject: [PATCH] Adjust spans into the `for` loops context before creating the pattern and `into_iter` call spans. --- compiler/rustc_ast_lowering/src/expr.rs | 10 ++++-- tests/ui/for/iter_from_mac_call.rs | 26 ++++++++++++++ tests/ui/for/iter_from_mac_call.stderr | 35 +++++++++++++++++++ .../invalid-suggest-deref-issue-127590.stderr | 26 +++++++++++++- 4 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 tests/ui/for/iter_from_mac_call.rs create mode 100644 tests/ui/for/iter_from_mac_call.stderr diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 2be2fca87c3c5..c6f24c1a19b48 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1771,8 +1771,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let pat = self.lower_pat(pat); let for_span = self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None); - let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None); - let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None); + let for_ctxt = for_span.ctxt(); + + // Try to point both the head and pat spans to their position in the for loop + // rather than inside a macro. + let head_span = + head.span.find_ancestor_in_same_ctxt(e.span).unwrap_or(head.span).with_ctxt(for_ctxt); + let pat_span = + pat.span.find_ancestor_in_same_ctxt(e.span).unwrap_or(pat.span).with_ctxt(for_ctxt); let loop_hir_id = self.lower_node_id(e.id); let label = self.lower_label(opt_label, e.id, loop_hir_id); diff --git a/tests/ui/for/iter_from_mac_call.rs b/tests/ui/for/iter_from_mac_call.rs new file mode 100644 index 0000000000000..8df21456222c4 --- /dev/null +++ b/tests/ui/for/iter_from_mac_call.rs @@ -0,0 +1,26 @@ +macro_rules! deref { + ($e:expr) => { *$e }; +} + +fn f1<'a>(mut iter: Box>) { + for item in deref!(iter) { *item = 0 } + //~^ ERROR `dyn Iterator` is not an iterator +} + +fn f2(x: &mut i32) { + for _item in deref!(x) {} + //~^ ERROR `i32` is not an iterator +} + +struct Wrapped(i32); + +macro_rules! borrow_deref { + ($e:expr) => { &mut *$e }; +} + +fn f3<'a>(mut iter: Box>) { + for Wrapped(item) in borrow_deref!(iter) { *item = 0 } + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/for/iter_from_mac_call.stderr b/tests/ui/for/iter_from_mac_call.stderr new file mode 100644 index 0000000000000..e62efb250e299 --- /dev/null +++ b/tests/ui/for/iter_from_mac_call.stderr @@ -0,0 +1,35 @@ +error[E0277]: `dyn Iterator` is not an iterator + --> $DIR/iter_from_mac_call.rs:6:17 + | +LL | for item in deref!(iter) { *item = 0 } + | ^^^^^^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator` + | + = note: the trait bound `dyn Iterator: IntoIterator` is not satisfied + = note: required for `dyn Iterator` to implement `IntoIterator` +help: consider mutably borrowing here + | +LL | for item in &mut deref!(iter) { *item = 0 } + | ++++ + +error[E0277]: `i32` is not an iterator + --> $DIR/iter_from_mac_call.rs:11:18 + | +LL | for _item in deref!(x) {} + | ^^^^^^^^^ `i32` is not an iterator + | + = help: the trait `Iterator` is not implemented for `i32` + = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end` + = note: required for `i32` to implement `IntoIterator` + +error[E0308]: mismatched types + --> $DIR/iter_from_mac_call.rs:22:9 + | +LL | for Wrapped(item) in borrow_deref!(iter) { *item = 0 } + | ^^^^^^^^^^^^^ ------------------- this is an iterator with items of type `&mut i32` + | | + | expected `i32`, found `Wrapped` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr index 103fb7bbfe11c..5a4e0c699733f 100644 --- a/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr +++ b/tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr @@ -60,6 +60,30 @@ help: the trait `Iterator` is implemented for `std::slice::Iter<'_, T>` = note: required for `Zip, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` = note: this error originates in the macro `iterator` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/invalid-suggest-deref-issue-127590.rs:6:24 + | +LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>` +help: the trait `Iterator` is implemented for `std::slice::Iter<'_, T>` + --> $SRC_DIR/core/src/slice/iter.rs:LL:COL + = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` + = note: this error originates in the macro `iterator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator + --> $DIR/invalid-suggest-deref-issue-127590.rs:13:24 + | +LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator + | + = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>` +help: the trait `Iterator` is implemented for `std::slice::Iter<'_, T>` + --> $SRC_DIR/core/src/slice/iter.rs:LL:COL + = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` + = note: this error originates in the macro `iterator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0277`.