Auto merge of #11696 - y21:iter_without_into_iter_suggestion, r=xFrednet

[`iter_without_into_iter`]: fix papercuts in suggestion and restrict linting to exported types

See #11692 for more context.

tldr: the lint `iter_without_into_iter` has suggestions that don't compile, which imo isn't that problematic because it does have the appropriate `Applicability` that tells external tools that it shouldn't be auto-applied.
However there were some obvious "errors" in the suggestion that really should've been included in my initial PR adding the lint, which is fixed by this PR:
- `IntoIterator::into_iter` needs a `self` argument.
- `IntoIterator::Iter` associated type doesn't exist. This should've just been `Item`.

This still doesn't make it machine applicable, and the remaining things are imho quite non-trivial to implement, as I've explained in https://github.com/rust-lang/rust-clippy/issues/11692#issuecomment-1773886111.
I personally think it's fine to leave it there and let the user change the remaining errors when copy-pasting the suggestion (e.g. errors caused by lifetimes that were permitted in fn return-position but are not in associated types).
This is how many of our other lint suggestions already work.

Also, we now restrict linting to only exported types. This required moving basically all of the tests around since they were previously in the `main` function. Same for `into_iter_without_iter`. The git diff is a bit useless here...

changelog: [`iter_without_into_iter`]: fix papercuts in suggestion and restrict linting to exported types

(cc `@lopopolo,` figured I should mention you since you created the issue)
This commit is contained in:
bors 2023-10-28 14:50:51 +00:00
commit f8409ef85f
5 changed files with 370 additions and 355 deletions

View file

@ -19,6 +19,11 @@ declare_clippy_lint! {
/// It's not bad, but having them is idiomatic and allows the type to be used in for loops directly
/// (`for val in &iter {}`), without having to first call `iter()` or `iter_mut()`.
///
/// ### Limitations
/// This lint focuses on providing an idiomatic API. Therefore, it will only
/// lint on types which are accessible outside of the crate. For internal types,
/// the `IntoIterator` trait can be implemented on demand if it is actually needed.
///
/// ### Example
/// ```no_run
/// struct MySlice<'a>(&'a [u8]);
@ -61,6 +66,14 @@ declare_clippy_lint! {
/// by just calling `.iter()`, instead of the more awkward `<&Type>::into_iter` or `(&val).into_iter()` syntax
/// in case of ambiguity with another `IntoIterator` impl.
///
/// ### Limitations
/// This lint focuses on providing an idiomatic API. Therefore, it will only
/// lint on types which are accessible outside of the crate. For internal types,
/// these methods can be added on demand if they are actually needed. Otherwise,
/// it would trigger the [`dead_code`] lint for the unused method.
///
/// [`dead_code`]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#dead-code
///
/// ### Example
/// ```no_run
/// struct MySlice<'a>(&'a [u8]);
@ -104,6 +117,12 @@ fn is_nameable_in_impl_trait(ty: &rustc_hir::Ty<'_>) -> bool {
!matches!(ty.kind, TyKind::OpaqueDef(..))
}
fn is_ty_exported(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
ty.ty_adt_def()
.and_then(|adt| adt.did().as_local())
.is_some_and(|did| cx.effective_visibilities.is_exported(did))
}
/// Returns the deref chain of a type, starting with the type itself.
fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl Iterator<Item = Ty<'tcx>> + 'cx {
iter::successors(Some(ty), |&ty| {
@ -154,6 +173,7 @@ impl LateLintPass<'_> for IterWithoutIntoIter {
None
}
})
&& is_ty_exported(cx, ty)
{
span_lint_and_then(
cx,
@ -226,6 +246,7 @@ impl {self_ty_without_ref} {{
)
// Only lint if the `IntoIterator` impl doesn't actually exist
&& !implements_trait(cx, ref_ty, into_iter_did, &[])
&& is_ty_exported(cx, ref_ty.peel_refs())
{
let self_ty_snippet = format!("{borrow_prefix}{}", snippet(cx, imp.self_ty.span, ".."));
@ -247,8 +268,8 @@ impl {self_ty_without_ref} {{
"
impl IntoIterator for {self_ty_snippet} {{
type IntoIter = {ret_ty};
type Iter = {iter_ty};
fn into_iter() -> Self::IntoIter {{
type Item = {iter_ty};
fn into_iter(self) -> Self::IntoIter {{
self.iter()
}}
}}

View file

@ -3,127 +3,117 @@
use std::iter::IntoIterator;
fn main() {
{
struct S;
impl<'a> IntoIterator for &'a S {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
type IntoIter = std::slice::Iter<'a, u8>;
type Item = &'a u8;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a> IntoIterator for &'a mut S {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
type IntoIter = std::slice::IterMut<'a, u8>;
type Item = &'a mut u8;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
pub struct S1;
impl<'a> IntoIterator for &'a S1 {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
type IntoIter = std::slice::Iter<'a, u8>;
type Item = &'a u8;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
{
struct S<T>(T);
impl<'a, T> IntoIterator for &'a S<T> {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a, T> IntoIterator for &'a mut S<T> {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
}
{
// Both iter and iter_mut methods exist, don't lint
struct S<'a, T>(&'a T);
impl<'a, T> S<'a, T> {
fn iter(&self) -> std::slice::Iter<'a, T> {
todo!()
}
fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
todo!()
}
}
impl<'a, T> IntoIterator for &S<'a, T> {
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a, T> IntoIterator for &mut S<'a, T> {
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
}
{
// Only `iter` exists, no `iter_mut`
struct S<'a, T>(&'a T);
impl<'a, T> S<'a, T> {
fn iter(&self) -> std::slice::Iter<'a, T> {
todo!()
}
}
impl<'a, T> IntoIterator for &S<'a, T> {
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a, T> IntoIterator for &mut S<'a, T> {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
}
{
// `iter` exists, but `IntoIterator` is implemented for an alias. inherent_impls doesn't "normalize"
// aliases so that `inherent_impls(Alias)` where `type Alias = S` returns nothing, so this can lead
// to fun FPs. Make sure it doesn't happen here (we're using type_of, which should skip the alias).
struct S;
impl S {
fn iter(&self) -> std::slice::Iter<'static, u8> {
todo!()
}
}
type Alias = S;
impl IntoIterator for &Alias {
type IntoIter = std::slice::Iter<'static, u8>;
type Item = &'static u8;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
}
impl<'a> IntoIterator for &'a mut S1 {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
type IntoIter = std::slice::IterMut<'a, u8>;
type Item = &'a mut u8;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
fn issue11635() {
pub struct S2<T>(T);
impl<'a, T> IntoIterator for &'a S2<T> {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter` method
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a, T> IntoIterator for &'a mut S2<T> {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
// Both iter and iter_mut methods exist, don't lint
pub struct S3<'a, T>(&'a T);
impl<'a, T> S3<'a, T> {
fn iter(&self) -> std::slice::Iter<'a, T> {
todo!()
}
fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
todo!()
}
}
impl<'a, T> IntoIterator for &S3<'a, T> {
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a, T> IntoIterator for &mut S3<'a, T> {
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
// Only `iter` exists, no `iter_mut`
pub struct S4<'a, T>(&'a T);
impl<'a, T> S4<'a, T> {
fn iter(&self) -> std::slice::Iter<'a, T> {
todo!()
}
}
impl<'a, T> IntoIterator for &S4<'a, T> {
type IntoIter = std::slice::Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
impl<'a, T> IntoIterator for &mut S4<'a, T> {
//~^ ERROR: `IntoIterator` implemented for a reference type without an `iter_mut` method
type IntoIter = std::slice::IterMut<'a, T>;
type Item = &'a mut T;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
// `iter` exists, but `IntoIterator` is implemented for an alias. inherent_impls doesn't "normalize"
// aliases so that `inherent_impls(Alias)` where `type Alias = S` returns nothing, so this can lead
// to fun FPs. Make sure it doesn't happen here (we're using type_of, which should skip the alias).
pub struct S5;
impl S5 {
fn iter(&self) -> std::slice::Iter<'static, u8> {
todo!()
}
}
pub type Alias = S5;
impl IntoIterator for &Alias {
type IntoIter = std::slice::Iter<'static, u8>;
type Item = &'static u8;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
fn main() {}
pub mod issue11635 {
// A little more involved than the original repro in the issue, but this tests that it correctly
// works for more than one deref step

View file

@ -1,21 +1,21 @@
error: `IntoIterator` implemented for a reference type without an `iter` method
--> $DIR/into_iter_without_iter.rs:10:9
--> $DIR/into_iter_without_iter.rs:7:1
|
LL | / impl<'a> IntoIterator for &'a S {
LL | / impl<'a> IntoIterator for &'a S1 {
LL | |
LL | | type IntoIter = std::slice::Iter<'a, u8>;
LL | | type Item = &'a u8;
LL | | type IntoIter = std::slice::Iter<'a, u8>;
LL | | type Item = &'a u8;
... |
LL | | }
LL | | }
| |_________^
LL | | }
LL | | }
| |_^
|
= note: `-D clippy::into-iter-without-iter` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::into_iter_without_iter)]`
help: consider implementing `iter`
|
LL ~
LL + impl S {
LL +
LL + impl S1 {
LL + fn iter(&self) -> std::slice::Iter<'a, u8> {
LL + <&Self as IntoIterator>::into_iter(self)
LL + }
@ -23,21 +23,21 @@ LL + }
|
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
--> $DIR/into_iter_without_iter.rs:18:9
--> $DIR/into_iter_without_iter.rs:15:1
|
LL | / impl<'a> IntoIterator for &'a mut S {
LL | / impl<'a> IntoIterator for &'a mut S1 {
LL | |
LL | | type IntoIter = std::slice::IterMut<'a, u8>;
LL | | type Item = &'a mut u8;
LL | | type IntoIter = std::slice::IterMut<'a, u8>;
LL | | type Item = &'a mut u8;
... |
LL | | }
LL | | }
| |_________^
LL | | }
LL | | }
| |_^
|
help: consider implementing `iter_mut`
|
LL ~
LL + impl S {
LL +
LL + impl S1 {
LL + fn iter_mut(&mut self) -> std::slice::IterMut<'a, u8> {
LL + <&mut Self as IntoIterator>::into_iter(self)
LL + }
@ -45,21 +45,21 @@ LL + }
|
error: `IntoIterator` implemented for a reference type without an `iter` method
--> $DIR/into_iter_without_iter.rs:29:9
--> $DIR/into_iter_without_iter.rs:25:1
|
LL | / impl<'a, T> IntoIterator for &'a S<T> {
LL | / impl<'a, T> IntoIterator for &'a S2<T> {
LL | |
LL | | type IntoIter = std::slice::Iter<'a, T>;
LL | | type Item = &'a T;
LL | | type IntoIter = std::slice::Iter<'a, T>;
LL | | type Item = &'a T;
... |
LL | | }
LL | | }
| |_________^
LL | | }
LL | | }
| |_^
|
help: consider implementing `iter`
|
LL ~
LL + impl S<T> {
LL +
LL + impl S2<T> {
LL + fn iter(&self) -> std::slice::Iter<'a, T> {
LL + <&Self as IntoIterator>::into_iter(self)
LL + }
@ -67,21 +67,21 @@ LL + }
|
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
--> $DIR/into_iter_without_iter.rs:37:9
--> $DIR/into_iter_without_iter.rs:33:1
|
LL | / impl<'a, T> IntoIterator for &'a mut S<T> {
LL | / impl<'a, T> IntoIterator for &'a mut S2<T> {
LL | |
LL | | type IntoIter = std::slice::IterMut<'a, T>;
LL | | type Item = &'a mut T;
LL | | type IntoIter = std::slice::IterMut<'a, T>;
LL | | type Item = &'a mut T;
... |
LL | | }
LL | | }
| |_________^
LL | | }
LL | | }
| |_^
|
help: consider implementing `iter_mut`
|
LL ~
LL + impl S<T> {
LL +
LL + impl S2<T> {
LL + fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
LL + <&mut Self as IntoIterator>::into_iter(self)
LL + }
@ -89,21 +89,21 @@ LL + }
|
error: `IntoIterator` implemented for a reference type without an `iter_mut` method
--> $DIR/into_iter_without_iter.rs:93:9
--> $DIR/into_iter_without_iter.rs:84:1
|
LL | / impl<'a, T> IntoIterator for &mut S<'a, T> {
LL | / impl<'a, T> IntoIterator for &mut S4<'a, T> {
LL | |
LL | | type IntoIter = std::slice::IterMut<'a, T>;
LL | | type Item = &'a mut T;
LL | | type IntoIter = std::slice::IterMut<'a, T>;
LL | | type Item = &'a mut T;
... |
LL | | }
LL | | }
| |_________^
LL | | }
LL | | }
| |_^
|
help: consider implementing `iter_mut`
|
LL ~
LL + impl S<'a, T> {
LL +
LL + impl S4<'a, T> {
LL + fn iter_mut(&mut self) -> std::slice::IterMut<'a, T> {
LL + <&mut Self as IntoIterator>::into_iter(self)
LL + }

View file

@ -1,120 +1,124 @@
//@no-rustfix
#![warn(clippy::iter_without_into_iter)]
fn main() {
{
struct S;
impl S {
pub fn iter(&self) -> std::slice::Iter<'_, u8> {
//~^ ERROR: `iter` method without an `IntoIterator` impl
[].iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
//~^ ERROR: `iter_mut` method without an `IntoIterator` impl
[].iter_mut()
}
}
pub struct S1;
impl S1 {
pub fn iter(&self) -> std::slice::Iter<'_, u8> {
//~^ ERROR: `iter` method without an `IntoIterator` impl
[].iter()
}
{
struct S;
impl S {
pub fn iter(&self) -> impl Iterator<Item = &u8> {
// RPITIT is not stable, so we can't generally suggest it here yet
[].iter()
}
}
}
{
struct S<'a>(&'a mut [u8]);
impl<'a> S<'a> {
pub fn iter(&self) -> std::slice::Iter<'_, u8> {
//~^ ERROR: `iter` method without an `IntoIterator` impl
self.0.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
//~^ ERROR: `iter_mut` method without an `IntoIterator` impl
self.0.iter_mut()
}
}
}
{
// Incompatible signatures
struct S;
impl S {
pub fn iter(self) -> std::slice::Iter<'static, u8> {
todo!()
}
}
struct S2;
impl S2 {
pub async fn iter(&self) -> std::slice::Iter<'static, u8> {
todo!()
}
}
struct S3;
impl S3 {
pub fn iter(&self, _additional_param: ()) -> std::slice::Iter<'static, u8> {
todo!()
}
}
struct S4<T>(T);
impl<T> S4<T> {
pub fn iter<U>(&self) -> std::slice::Iter<'static, (T, U)> {
todo!()
}
}
struct S5<T>(T);
impl<T> S5<T> {
pub fn iter(&self) -> std::slice::Iter<'static, T> {
todo!()
}
}
}
{
struct S<T>(T);
impl<T> S<T> {
pub fn iter(&self) -> std::slice::Iter<'_, T> {
//~^ ERROR: `iter` method without an `IntoIterator` impl
todo!()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
//~^ ERROR: `iter_mut` method without an `IntoIterator` impl
todo!()
}
}
}
{
struct S<T>(T);
impl<T> S<T> {
pub fn iter(&self) -> std::slice::Iter<'_, T> {
// Don't lint, there's an existing (wrong) IntoIterator impl
todo!()
}
}
impl<'a, T> IntoIterator for &'a S<T> {
type Item = &'a String;
type IntoIter = std::slice::Iter<'a, String>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
}
{
struct S<T>(T);
impl<T> S<T> {
pub fn iter_mut(&self) -> std::slice::IterMut<'_, T> {
// Don't lint, there's an existing (wrong) IntoIterator impl
todo!()
}
}
impl<'a, T> IntoIterator for &'a mut S<T> {
type Item = &'a mut String;
type IntoIter = std::slice::IterMut<'a, String>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
//~^ ERROR: `iter_mut` method without an `IntoIterator` impl
[].iter_mut()
}
}
pub struct S2;
impl S2 {
pub fn iter(&self) -> impl Iterator<Item = &u8> {
// RPITIT is not stable, so we can't generally suggest it here yet
[].iter()
}
}
pub struct S3<'a>(&'a mut [u8]);
impl<'a> S3<'a> {
pub fn iter(&self) -> std::slice::Iter<'_, u8> {
//~^ ERROR: `iter` method without an `IntoIterator` impl
self.0.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
//~^ ERROR: `iter_mut` method without an `IntoIterator` impl
self.0.iter_mut()
}
}
// Incompatible signatures
pub struct S4;
impl S4 {
pub fn iter(self) -> std::slice::Iter<'static, u8> {
todo!()
}
}
pub struct S5;
impl S5 {
pub async fn iter(&self) -> std::slice::Iter<'static, u8> {
todo!()
}
}
pub struct S6;
impl S6 {
pub fn iter(&self, _additional_param: ()) -> std::slice::Iter<'static, u8> {
todo!()
}
}
pub struct S7<T>(T);
impl<T> S7<T> {
pub fn iter<U>(&self) -> std::slice::Iter<'static, (T, U)> {
todo!()
}
}
pub struct S8<T>(T);
impl<T> S8<T> {
pub fn iter(&self) -> std::slice::Iter<'static, T> {
todo!()
}
}
// ===========================
pub struct S9<T>(T);
impl<T> S9<T> {
pub fn iter(&self) -> std::slice::Iter<'_, T> {
//~^ ERROR: `iter` method without an `IntoIterator` impl
todo!()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
//~^ ERROR: `iter_mut` method without an `IntoIterator` impl
todo!()
}
}
pub struct S10<T>(T);
impl<T> S10<T> {
pub fn iter(&self) -> std::slice::Iter<'_, T> {
// Don't lint, there's an existing (wrong) IntoIterator impl
todo!()
}
}
impl<'a, T> IntoIterator for &'a S10<T> {
type Item = &'a String;
type IntoIter = std::slice::Iter<'a, String>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
pub struct S11<T>(T);
impl<T> S11<T> {
pub fn iter_mut(&self) -> std::slice::IterMut<'_, T> {
// Don't lint, there's an existing (wrong) IntoIterator impl
todo!()
}
}
impl<'a, T> IntoIterator for &'a mut S11<T> {
type Item = &'a mut String;
type IntoIter = std::slice::IterMut<'a, String>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
// Private type not exported: don't lint
struct S12;
impl S12 {
fn iter(&self) -> std::slice::Iter<'_, u8> {
todo!()
}
}
fn main() {}

View file

@ -1,146 +1,146 @@
error: `iter` method without an `IntoIterator` impl for `&S`
--> $DIR/iter_without_into_iter.rs:8:13
error: `iter` method without an `IntoIterator` impl for `&S1`
--> $DIR/iter_without_into_iter.rs:6:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | |
LL | | [].iter()
LL | | }
| |_____________^
LL | | [].iter()
LL | | }
| |_____^
|
= note: `-D clippy::iter-without-into-iter` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::iter_without_into_iter)]`
help: consider implementing `IntoIterator` for `&S`
help: consider implementing `IntoIterator` for `&S1`
|
LL ~
LL + impl IntoIterator for &S {
LL +
LL + impl IntoIterator for &S1 {
LL + type IntoIter = std::slice::Iter<'_, u8>;
LL + type Iter = &u8;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &u8;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }
|
error: `iter_mut` method without an `IntoIterator` impl for `&mut S`
--> $DIR/iter_without_into_iter.rs:12:13
error: `iter_mut` method without an `IntoIterator` impl for `&mut S1`
--> $DIR/iter_without_into_iter.rs:10:5
|
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
LL | |
LL | | [].iter_mut()
LL | | }
| |_____________^
LL | | [].iter_mut()
LL | | }
| |_____^
|
help: consider implementing `IntoIterator` for `&mut S`
help: consider implementing `IntoIterator` for `&mut S1`
|
LL ~
LL + impl IntoIterator for &mut S {
LL +
LL + impl IntoIterator for &mut S1 {
LL + type IntoIter = std::slice::IterMut<'_, u8>;
LL + type Iter = &mut u8;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &mut u8;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }
|
error: `iter` method without an `IntoIterator` impl for `&S<'a>`
--> $DIR/iter_without_into_iter.rs:30:13
error: `iter` method without an `IntoIterator` impl for `&S3<'a>`
--> $DIR/iter_without_into_iter.rs:26:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | / pub fn iter(&self) -> std::slice::Iter<'_, u8> {
LL | |
LL | | self.0.iter()
LL | | }
| |_____________^
LL | | self.0.iter()
LL | | }
| |_____^
|
help: consider implementing `IntoIterator` for `&S<'a>`
help: consider implementing `IntoIterator` for `&S3<'a>`
|
LL ~
LL + impl IntoIterator for &S<'a> {
LL +
LL + impl IntoIterator for &S3<'a> {
LL + type IntoIter = std::slice::Iter<'_, u8>;
LL + type Iter = &u8;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &u8;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }
|
error: `iter_mut` method without an `IntoIterator` impl for `&mut S<'a>`
--> $DIR/iter_without_into_iter.rs:34:13
error: `iter_mut` method without an `IntoIterator` impl for `&mut S3<'a>`
--> $DIR/iter_without_into_iter.rs:30:5
|
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, u8> {
LL | |
LL | | self.0.iter_mut()
LL | | }
| |_____________^
LL | | self.0.iter_mut()
LL | | }
| |_____^
|
help: consider implementing `IntoIterator` for `&mut S<'a>`
help: consider implementing `IntoIterator` for `&mut S3<'a>`
|
LL ~
LL + impl IntoIterator for &mut S<'a> {
LL +
LL + impl IntoIterator for &mut S3<'a> {
LL + type IntoIter = std::slice::IterMut<'_, u8>;
LL + type Iter = &mut u8;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &mut u8;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }
|
error: `iter` method without an `IntoIterator` impl for `&S5<T>`
--> $DIR/iter_without_into_iter.rs:68:13
error: `iter` method without an `IntoIterator` impl for `&S8<T>`
--> $DIR/iter_without_into_iter.rs:67:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> {
LL | | todo!()
LL | | }
| |_____________^
LL | / pub fn iter(&self) -> std::slice::Iter<'static, T> {
LL | | todo!()
LL | | }
| |_____^
|
help: consider implementing `IntoIterator` for `&S5<T>`
help: consider implementing `IntoIterator` for `&S8<T>`
|
LL ~
LL + impl IntoIterator for &S5<T> {
LL +
LL + impl IntoIterator for &S8<T> {
LL + type IntoIter = std::slice::Iter<'static, T>;
LL + type Iter = &T;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &T;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }
|
error: `iter` method without an `IntoIterator` impl for `&S<T>`
--> $DIR/iter_without_into_iter.rs:76:13
error: `iter` method without an `IntoIterator` impl for `&S9<T>`
--> $DIR/iter_without_into_iter.rs:75:5
|
LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> {
LL | / pub fn iter(&self) -> std::slice::Iter<'_, T> {
LL | |
LL | | todo!()
LL | | }
| |_____________^
LL | | todo!()
LL | | }
| |_____^
|
help: consider implementing `IntoIterator` for `&S<T>`
help: consider implementing `IntoIterator` for `&S9<T>`
|
LL ~
LL + impl IntoIterator for &S<T> {
LL +
LL + impl IntoIterator for &S9<T> {
LL + type IntoIter = std::slice::Iter<'_, T>;
LL + type Iter = &T;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &T;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }
|
error: `iter_mut` method without an `IntoIterator` impl for `&mut S<T>`
--> $DIR/iter_without_into_iter.rs:80:13
error: `iter_mut` method without an `IntoIterator` impl for `&mut S9<T>`
--> $DIR/iter_without_into_iter.rs:79:5
|
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
LL | / pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
LL | |
LL | | todo!()
LL | | }
| |_____________^
LL | | todo!()
LL | | }
| |_____^
|
help: consider implementing `IntoIterator` for `&mut S<T>`
help: consider implementing `IntoIterator` for `&mut S9<T>`
|
LL ~
LL + impl IntoIterator for &mut S<T> {
LL +
LL + impl IntoIterator for &mut S9<T> {
LL + type IntoIter = std::slice::IterMut<'_, T>;
LL + type Iter = &mut T;
LL + fn into_iter() -> Self::IntoIter {
LL + type Item = &mut T;
LL + fn into_iter(self) -> Self::IntoIter {
LL + self.iter()
LL + }
LL + }