Skip to content

Commit

Permalink
Be more lax in .into_iter() suggestion when encountering Iterator
Browse files Browse the repository at this point in the history
… 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`.
  • Loading branch information
estebank committed Mar 1, 2024
1 parent abfd3d9 commit 6022301
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 37 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
9 changes: 0 additions & 9 deletions library/core/src/iter/traits/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)]
Expand Down
5 changes: 5 additions & 0 deletions tests/ui/iterators/vec-on-unimplemented.fixed
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 3 additions & 2 deletions tests/ui/iterators/vec-on-unimplemented.rs
Original file line number Diff line number Diff line change
@@ -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
}
17 changes: 8 additions & 9 deletions tests/ui/iterators/vec-on-unimplemented.stderr
Original file line number Diff line number Diff line change
@@ -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

Expand Down
8 changes: 8 additions & 0 deletions tests/ui/methods/issues/issue-94581.fixed
Original file line number Diff line number Diff line change
@@ -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]
}
3 changes: 2 additions & 1 deletion tests/ui/methods/issues/issue-94581.rs
Original file line number Diff line number Diff line change
@@ -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]
}
17 changes: 8 additions & 9 deletions tests/ui/methods/issues/issue-94581.stderr
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>>);
Expand Down
5 changes: 1 addition & 4 deletions tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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>`
Expand Down

0 comments on commit 6022301

Please sign in to comment.