Be more lax in .into_iter() suggestion when encountering Iterator methods on non-Iterator

```
error[E0599]: no method named `map` found for struct `Vec<bool>` in the current scope
  --> $DIR/vec-on-unimplemented.rs:3:23
   |
LL |     vec![true, false].map(|v| !v).collect::<Vec<_>>();
   |                       ^^^ `Vec<bool>` is not an iterator
   |
help: call `.into_iter()` first
   |
LL |     vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
   |                       ++++++++++++
```

We used to provide some help through `rustc_on_unimplemented` on non-`impl Trait` and non-type-params, but this lets us get rid of some otherwise unnecessary conditions in the annotation on `Iterator`.
This commit is contained in:
Esteban Küber 2024-03-01 21:37:56 +00:00
parent f0c93117ed
commit 89a3c19832
10 changed files with 38 additions and 37 deletions

View File

@ -166,7 +166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return false;
}
match ty.kind() {
match ty.peel_refs().kind() {
ty::Param(param) => {
let generics = self.tcx.generics_of(self.body_id);
let generic_param = generics.type_param(&param, self.tcx);
@ -184,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
ty::Alias(ty::AliasKind::Opaque, _) => {
ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::AliasKind::Opaque, _) => {
for unsatisfied in unsatisfied_predicates.iter() {
if is_iterator_predicate(unsatisfied.0, self.tcx) {
return true;

View File

@ -34,15 +34,6 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
_Self = "core::ops::range::RangeToInclusive<Idx>",
note = "you might have meant to use a bounded `RangeInclusive`"
),
on(
_Self = "[]",
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
on(
_Self = "alloc::vec::Vec<T, A>",
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
label = "`{Self}` is not an iterator",
message = "`{Self}` is not an iterator"
)]

View File

@ -0,0 +1,5 @@
//@ run-rustfix
fn main() {
let _ = vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
//~^ ERROR no method named `map` found for struct `Vec<bool>` in the current scope
}

View File

@ -1,4 +1,5 @@
//@ run-rustfix
fn main() {
vec![true, false].map(|v| !v).collect::<Vec<_>>();
//~^ ERROR `Vec<bool>` is not an iterator
let _ = vec![true, false].map(|v| !v).collect::<Vec<_>>();
//~^ ERROR no method named `map` found for struct `Vec<bool>` in the current scope
}

View File

@ -1,14 +1,13 @@
error[E0599]: `Vec<bool>` is not an iterator
--> $DIR/vec-on-unimplemented.rs:2:23
error[E0599]: no method named `map` found for struct `Vec<bool>` in the current scope
--> $DIR/vec-on-unimplemented.rs:3:31
|
LL | vec![true, false].map(|v| !v).collect::<Vec<_>>();
| ^^^ `Vec<bool>` is not an iterator; try calling `.into_iter()` or `.iter()`
LL | let _ = vec![true, false].map(|v| !v).collect::<Vec<_>>();
| ^^^ `Vec<bool>` is not an iterator
|
= note: the following trait bounds were not satisfied:
`Vec<bool>: Iterator`
which is required by `&mut Vec<bool>: Iterator`
`[bool]: Iterator`
which is required by `&mut [bool]: Iterator`
help: call `.into_iter()` first
|
LL | let _ = vec![true, false].into_iter().map(|v| !v).collect::<Vec<_>>();
| ++++++++++++
error: aborting due to 1 previous error

View File

@ -0,0 +1,8 @@
//@ run-rustfix
fn get_slice() -> &'static [i32] {
&[1, 2, 3, 4]
}
fn main() {
let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum(); //~ ERROR [E0599]
}

View File

@ -1,7 +1,8 @@
//@ run-rustfix
fn get_slice() -> &'static [i32] {
&[1, 2, 3, 4]
}
fn main() {
let sqsum = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599]
let _sqsum: i32 = get_slice().map(|i| i * i).sum(); //~ ERROR [E0599]
}

View File

@ -1,14 +1,13 @@
error[E0599]: `&'static [i32]` is not an iterator
--> $DIR/issue-94581.rs:6:29
error[E0599]: no method named `map` found for reference `&'static [i32]` in the current scope
--> $DIR/issue-94581.rs:7:35
|
LL | let sqsum = get_slice().map(|i| i * i).sum();
| ^^^ `&'static [i32]` is not an iterator; try calling `.iter()`
LL | let _sqsum: i32 = get_slice().map(|i| i * i).sum();
| ^^^ `&'static [i32]` is not an iterator
|
= note: the following trait bounds were not satisfied:
`&'static [i32]: Iterator`
which is required by `&mut &'static [i32]: Iterator`
`[i32]: Iterator`
which is required by `&mut [i32]: Iterator`
help: call `.into_iter()` first
|
LL | let _sqsum: i32 = get_slice().into_iter().map(|i| i * i).sum();
| ++++++++++++
error: aborting due to 1 previous error

View File

@ -14,7 +14,7 @@ struct PriorityQueueEntry<T> {
//~^ ERROR can't compare `PriorityQueue<T>` with `PriorityQueue<T>`
//~| ERROR the trait bound `PriorityQueue<T>: Eq` is not satisfied
//~| ERROR can't compare `T` with `T`
//~| ERROR `BinaryHeap<PriorityQueueEntry<T>>` is not an iterator
//~| ERROR no method named `cmp` found for struct `BinaryHeap<PriorityQueueEntry<T>>`
//~| ERROR no field `height` on type `&PriorityQueue<T>`
struct PriorityQueue<T>(BinaryHeap<PriorityQueueEntry<T>>);

View File

@ -46,15 +46,12 @@ LL | struct PriorityQueue<T>(BinaryHeap<PriorityQueueEntry<T>>);
= help: the trait `PartialOrd<_>` is not implemented for `BinaryHeap<PriorityQueueEntry<T>>`
= note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0599]: `BinaryHeap<PriorityQueueEntry<T>>` is not an iterator
error[E0599]: no method named `cmp` found for struct `BinaryHeap<PriorityQueueEntry<T>>` in the current scope
--> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22
|
LL | #[derive(PartialOrd, AddImpl)]
| ^^^^^^^ `BinaryHeap<PriorityQueueEntry<T>>` is not an iterator
|
= note: the following trait bounds were not satisfied:
`BinaryHeap<PriorityQueueEntry<T>>: Iterator`
which is required by `&mut BinaryHeap<PriorityQueueEntry<T>>: Iterator`
= note: this error originates in the derive macro `AddImpl` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0609]: no field `height` on type `&PriorityQueue<T>`