diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index c024f5b42e4..715671dd452 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -574,6 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Pick out the list of unimplemented traits on the receiver. // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute. let mut unimplemented_traits = FxHashMap::default(); + let mut unimplemented_traits_only = true; for (predicate, _parent_pred, cause) in &unsatisfied_predicates { if let (ty::PredicateKind::Trait(p), Some(cause)) = (predicate.kind().skip_binder(), cause.as_ref()) @@ -596,6 +597,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + // Make sure that, if any traits other than the found ones were involved, + // we don't don't report an unimplemented trait. + // We don't want to say that `iter::Cloned` is not an interator, just + // because of some non-Clone item being iterated over. + for (predicate, _parent_pred, _cause) in &unsatisfied_predicates { + match predicate.kind().skip_binder() { + ty::PredicateKind::Trait(p) + if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {} + _ => { + unimplemented_traits_only = false; + break; + } + } + } + let mut collect_type_param_suggestions = |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| { // We don't care about regions here, so it's fine to skip the binder here. @@ -839,7 +855,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .join("\n"); let actual_prefix = actual.prefix_string(self.tcx); info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); - let (primary_message, label) = if unimplemented_traits.len() == 1 { + let (primary_message, label) = if unimplemented_traits.len() == 1 + && unimplemented_traits_only + { unimplemented_traits .into_iter() .next() diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 0252ba2eb04..17d2292baaf 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -5,6 +5,6 @@ use std::iter::once; fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); - //~^ ERROR not an iterator + //~^ ERROR the method //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index b1010171eb2..a8bcdf5efe9 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -12,11 +12,11 @@ note: required by a bound in `filter` LL | P: FnMut(&Self::Item) -> bool, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter` -error[E0599]: `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator +error[E0599]: the method `count` exists for struct `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied --> $DIR/issue-36053-2.rs:7:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | -------------- ^^^^^ `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator + | -------------- ^^^^^ method cannot be called on `Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds | | | doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool` | doesn't satisfy `_: FnMut<(&&str,)>`