From 89a3c198321f33b5c9efb54eb48d354c4bd5c614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 1 Mar 2024 21:37:56 +0000 Subject: [PATCH] Be more lax in `.into_iter()` suggestion when encountering `Iterator` methods on non-`Iterator` ``` error[E0599]: no method named `map` found for struct `Vec` in the current scope --> $DIR/vec-on-unimplemented.rs:3:23 | LL | vec![true, false].map(|v| !v).collect::>(); | ^^^ `Vec` is not an iterator | help: call `.into_iter()` first | LL | vec![true, false].into_iter().map(|v| !v).collect::>(); | ++++++++++++ ``` 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`. --- compiler/rustc_hir_typeck/src/method/suggest.rs | 4 ++-- library/core/src/iter/traits/iterator.rs | 9 --------- tests/ui/iterators/vec-on-unimplemented.fixed | 5 +++++ tests/ui/iterators/vec-on-unimplemented.rs | 5 +++-- tests/ui/iterators/vec-on-unimplemented.stderr | 17 ++++++++--------- tests/ui/methods/issues/issue-94581.fixed | 8 ++++++++ tests/ui/methods/issues/issue-94581.rs | 3 ++- tests/ui/methods/issues/issue-94581.stderr | 17 ++++++++--------- .../issue-104884-trait-impl-sugg-err.rs | 2 +- .../issue-104884-trait-impl-sugg-err.stderr | 5 +---- 10 files changed, 38 insertions(+), 37 deletions(-) create mode 100644 tests/ui/iterators/vec-on-unimplemented.fixed create mode 100644 tests/ui/methods/issues/issue-94581.fixed diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 440d0ad1140..893b3f9534d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -166,7 +166,7 @@ fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool 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(¶m, self.tcx); @@ -184,7 +184,7 @@ fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool } } } - 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; diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 74f9e7f9446..e1904ed220c 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -34,15 +34,6 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} _Self = "core::ops::range::RangeToInclusive", 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", - label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`" - ), label = "`{Self}` is not an iterator", message = "`{Self}` is not an iterator" )] diff --git a/tests/ui/iterators/vec-on-unimplemented.fixed b/tests/ui/iterators/vec-on-unimplemented.fixed new file mode 100644 index 00000000000..cc46bd67f9a --- /dev/null +++ b/tests/ui/iterators/vec-on-unimplemented.fixed @@ -0,0 +1,5 @@ +//@ run-rustfix +fn main() { + let _ = vec![true, false].into_iter().map(|v| !v).collect::>(); + //~^ ERROR no method named `map` found for struct `Vec` in the current scope +} diff --git a/tests/ui/iterators/vec-on-unimplemented.rs b/tests/ui/iterators/vec-on-unimplemented.rs index 42b5d36bfad..7367fd4c9cd 100644 --- a/tests/ui/iterators/vec-on-unimplemented.rs +++ b/tests/ui/iterators/vec-on-unimplemented.rs @@ -1,4 +1,5 @@ +//@ run-rustfix fn main() { - vec![true, false].map(|v| !v).collect::>(); - //~^ ERROR `Vec` is not an iterator + let _ = vec![true, false].map(|v| !v).collect::>(); + //~^ ERROR no method named `map` found for struct `Vec` in the current scope } diff --git a/tests/ui/iterators/vec-on-unimplemented.stderr b/tests/ui/iterators/vec-on-unimplemented.stderr index 29b19d5e3b4..d6f4bfa1cde 100644 --- a/tests/ui/iterators/vec-on-unimplemented.stderr +++ b/tests/ui/iterators/vec-on-unimplemented.stderr @@ -1,14 +1,13 @@ -error[E0599]: `Vec` is not an iterator - --> $DIR/vec-on-unimplemented.rs:2:23 +error[E0599]: no method named `map` found for struct `Vec` in the current scope + --> $DIR/vec-on-unimplemented.rs:3:31 | -LL | vec![true, false].map(|v| !v).collect::>(); - | ^^^ `Vec` is not an iterator; try calling `.into_iter()` or `.iter()` +LL | let _ = vec![true, false].map(|v| !v).collect::>(); + | ^^^ `Vec` is not an iterator | - = note: the following trait bounds were not satisfied: - `Vec: Iterator` - which is required by `&mut Vec: 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::>(); + | ++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/methods/issues/issue-94581.fixed b/tests/ui/methods/issues/issue-94581.fixed new file mode 100644 index 00000000000..ff2bbeba27c --- /dev/null +++ b/tests/ui/methods/issues/issue-94581.fixed @@ -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] +} diff --git a/tests/ui/methods/issues/issue-94581.rs b/tests/ui/methods/issues/issue-94581.rs index df393e91db0..535d3249eb9 100644 --- a/tests/ui/methods/issues/issue-94581.rs +++ b/tests/ui/methods/issues/issue-94581.rs @@ -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] } diff --git a/tests/ui/methods/issues/issue-94581.stderr b/tests/ui/methods/issues/issue-94581.stderr index ae7446d4833..d04d6ca5e3c 100644 --- a/tests/ui/methods/issues/issue-94581.stderr +++ b/tests/ui/methods/issues/issue-94581.stderr @@ -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 diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index 8567d812e4f..29793e9f734 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -14,7 +14,7 @@ struct PriorityQueueEntry { //~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` //~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied //~| ERROR can't compare `T` with `T` -//~| ERROR `BinaryHeap>` is not an iterator +//~| ERROR no method named `cmp` found for struct `BinaryHeap>` //~| ERROR no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index 6fa639877d3..0fe560afcb5 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -46,15 +46,12 @@ LL | struct PriorityQueue(BinaryHeap>); = help: the trait `PartialOrd<_>` is not implemented for `BinaryHeap>` = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0599]: `BinaryHeap>` is not an iterator +error[E0599]: no method named `cmp` found for struct `BinaryHeap>` in the current scope --> $DIR/issue-104884-trait-impl-sugg-err.rs:13:22 | LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ `BinaryHeap>` is not an iterator | - = note: the following trait bounds were not satisfied: - `BinaryHeap>: Iterator` - which is required by `&mut BinaryHeap>: 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`