Skip to content

Commit 317f684

Browse files
committed
diagnostics: do not spurriously claim something is "not an iterator"
Fixes a minor regression caused by rust-lang#94746, where iter::Filter is spurriously declared "not an iterator."
1 parent 335ffbf commit 317f684

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

compiler/rustc_typeck/src/check/method/suggest.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
574574
// Pick out the list of unimplemented traits on the receiver.
575575
// This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
576576
let mut unimplemented_traits = FxHashMap::default();
577+
let mut unimplemented_traits_only = true;
577578
for (predicate, _parent_pred, cause) in &unsatisfied_predicates {
578579
if let (ty::PredicateKind::Trait(p), Some(cause)) =
579580
(predicate.kind().skip_binder(), cause.as_ref())
@@ -596,6 +597,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
596597
}
597598
}
598599

600+
// Make sure that, if any traits other than the found ones were involved,
601+
// we don't don't report an unimplemented trait.
602+
// We don't want to say that `iter::Cloned` is not an interator, just
603+
// because of some non-Clone item being iterated over.
604+
for (predicate, _parent_pred, _cause) in &unsatisfied_predicates {
605+
match predicate.kind().skip_binder() {
606+
ty::PredicateKind::Trait(p)
607+
if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
608+
_ => {
609+
unimplemented_traits_only = false;
610+
break;
611+
}
612+
}
613+
}
614+
599615
let mut collect_type_param_suggestions =
600616
|self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
601617
// 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> {
839855
.join("\n");
840856
let actual_prefix = actual.prefix_string(self.tcx);
841857
info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
842-
let (primary_message, label) = if unimplemented_traits.len() == 1 {
858+
let (primary_message, label) = if unimplemented_traits.len() == 1
859+
&& unimplemented_traits_only
860+
{
843861
unimplemented_traits
844862
.into_iter()
845863
.next()

src/test/ui/mismatched_types/issue-36053-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
use std::iter::once;
66
fn main() {
77
once::<&str>("str").fuse().filter(|a: &str| true).count();
8-
//~^ ERROR not an iterator
8+
//~^ ERROR the method
99
//~| ERROR type mismatch in closure arguments
1010
}

src/test/ui/mismatched_types/issue-36053-2.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ note: required by a bound in `filter`
1212
LL | P: FnMut(&Self::Item) -> bool,
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `filter`
1414

15-
error[E0599]: `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator
15+
error[E0599]: the method `count` exists for struct `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`, but its trait bounds were not satisfied
1616
--> $DIR/issue-36053-2.rs:7:55
1717
|
1818
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
19-
| -------------- ^^^^^ `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` is not an iterator
19+
| -------------- ^^^^^ method cannot be called on `Filter<Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` due to unsatisfied trait bounds
2020
| |
2121
| doesn't satisfy `<_ as FnOnce<(&&str,)>>::Output = bool`
2222
| doesn't satisfy `_: FnMut<(&&str,)>`

0 commit comments

Comments
 (0)