diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index eaf40a193a634..cb20a1d7c7b69 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -100,9 +100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, span: Span, unsatisfied_predicates: &Vec<( - ty::Predicate<'_>, - Option>, - Option>, + ty::Predicate<'tcx>, + Option>, + Option>, )>, ) -> bool { fn predicate_bounds_generic_param<'tcx>( @@ -131,15 +131,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool { + let is_iterator_predicate = |predicate: ty::Predicate<'tcx>| -> bool { if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = predicate.kind().as_ref().skip_binder() { - tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id) + self.tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id) + // ignore unsatisfied predicates generated from trying to auto-ref ty (#127511) + && trait_pred.trait_ref.self_ty() == ty } else { false } - } + }; // Does the `ty` implement `IntoIterator`? let Some(into_iterator_trait) = self.tcx.get_diagnostic_item(sym::IntoIterator) else { @@ -164,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { generics, generic_param, self.tcx, - ) && is_iterator_predicate(unsatisfied.0, self.tcx) + ) && is_iterator_predicate(unsatisfied.0) { return true; } @@ -172,7 +174,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::Opaque, _) => { for unsatisfied in unsatisfied_predicates.iter() { - if is_iterator_predicate(unsatisfied.0, self.tcx) { + if is_iterator_predicate(unsatisfied.0) { return true; } } diff --git a/tests/ui/iterators/iterator-does-not-need-into-iter.rs b/tests/ui/iterators/iterator-does-not-need-into-iter.rs new file mode 100644 index 0000000000000..29196449e307c --- /dev/null +++ b/tests/ui/iterators/iterator-does-not-need-into-iter.rs @@ -0,0 +1,18 @@ +//! regression test for #127511: don't suggest `.into_iter()` on iterators + +trait Missing {} +trait HasMethod { + fn foo(self); +} +impl HasMethod for T { + fn foo(self) {} +} + +fn get_iter() -> impl Iterator { + core::iter::once(()) +} + +fn main() { + get_iter().foo(); + //~^ ERROR the method `foo` exists for opaque type `impl Iterator`, but its trait bounds were not satisfied [E0599] +} diff --git a/tests/ui/iterators/iterator-does-not-need-into-iter.stderr b/tests/ui/iterators/iterator-does-not-need-into-iter.stderr new file mode 100644 index 0000000000000..3d3861e959f82 --- /dev/null +++ b/tests/ui/iterators/iterator-does-not-need-into-iter.stderr @@ -0,0 +1,28 @@ +error[E0599]: the method `foo` exists for opaque type `impl Iterator`, but its trait bounds were not satisfied + --> $DIR/iterator-does-not-need-into-iter.rs:16:16 + | +LL | get_iter().foo(); + | ^^^ method cannot be called on `impl Iterator` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&impl Iterator: Iterator` + `&impl Iterator: Missing` + `&mut impl Iterator: Missing` + `impl Iterator: Missing` + --> $DIR/iterator-does-not-need-into-iter.rs:7:9 + | +LL | impl HasMethod for T { + | ^^^^^^^^ ^^^^^^^ --------- - + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `HasMethod` defines an item `foo`, perhaps you need to implement it + --> $DIR/iterator-does-not-need-into-iter.rs:4:1 + | +LL | trait HasMethod { + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`.