Skip to content

Commit

Permalink
Don't suggest .into_iter() on iterators
Browse files Browse the repository at this point in the history
  • Loading branch information
dianne committed Nov 9, 2024
1 parent 59cec72 commit cea82ed
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 8 deletions.
18 changes: 10 additions & 8 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
span: Span,
unsatisfied_predicates: &Vec<(
ty::Predicate<'_>,
Option<ty::Predicate<'_>>,
Option<ObligationCause<'_>>,
ty::Predicate<'tcx>,
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)>,
) -> bool {
fn predicate_bounds_generic_param<'tcx>(
Expand Down Expand Up @@ -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 {
Expand All @@ -164,15 +166,15 @@ 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;
}
}
}
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;
}
}
Expand Down
18 changes: 18 additions & 0 deletions tests/ui/iterators/iterator-does-not-need-into-iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! regression test for #127511: don't suggest `.into_iter()` on iterators

trait Missing {}
trait HasMethod {
fn foo(self);
}
impl<T: Iterator + Missing> 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]
}
28 changes: 28 additions & 0 deletions tests/ui/iterators/iterator-does-not-need-into-iter.stderr
Original file line number Diff line number Diff line change
@@ -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<T: Iterator + Missing> 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`.

0 comments on commit cea82ed

Please sign in to comment.