Skip to content

clippy::iter_without_into_iter suggestion does not compile #11692

Open
@lopopolo

Description

@lopopolo

Summary

The suggested implementation of IntoIterator does not compile.

Reproducer

I tried this code:

#![warn(clippy::all)]
#![warn(clippy::pedantic)]

pub struct Foo;

pub struct FooIter<'a>(Option<&'a Foo>);

impl<'a> Iterator for FooIter<'a> {
    type Item = &'a Foo;
    
    fn next(&mut self) -> Option<Self::Item> {
        self.0.take()
    }
}

impl Foo {
    #[must_use]
    pub fn iter(&self) -> FooIter<'_> {
        FooIter(Some(self))
    }
}


fn main() {
    println!("Hello, world!");
}

I expected to see this happen: clippy emits a clippy::iter_without_into_iter and gives a suggested fix that compiles.

Instead, this happened:

    Checking playground v0.0.1 (/playground)
warning: `iter` method without an `IntoIterator` impl for `&Foo`
  --> src/main.rs:18:5
   |
18 | /     pub fn iter(&self) -> FooIter<'_> {
19 | |         FooIter(Some(self))
20 | |     }
   | |_____^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#iter_without_into_iter
note: the lint level is defined here
  --> src/main.rs:2:9
   |
2  | #![warn(clippy::pedantic)]
   |         ^^^^^^^^^^^^^^^^
   = note: `#[warn(clippy::iter_without_into_iter)]` implied by `#[warn(clippy::pedantic)]`
help: consider implementing `IntoIterator` for `&Foo`
   |
16 + 
17 + impl IntoIterator for &Foo {
18 +     type IntoIter = FooIter<'_>;
19 +     type Iter = &Foo;
20 +     fn into_iter() -> Self::IntoIter {
21 +         self.iter()
22 +     }
23 + }
   |

warning: `playground` (bin "playground") generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.27s

Adding the suggestion results in this code:

#![warn(clippy::all)]
#![warn(clippy::pedantic)]

pub struct Foo;

pub struct FooIter<'a>(Option<&'a Foo>);

impl<'a> Iterator for FooIter<'a> {
    type Item = &'a Foo;
    
    fn next(&mut self) -> Option<Self::Item> {
        self.0.take()
    }
}

impl IntoIterator for &Foo {
    type IntoIter = FooIter<'_>;
    type Iter = &Foo;
    fn into_iter() -> Self::IntoIter {
        self.iter()
    }
}

impl Foo {
    #[must_use]
    pub fn iter(&self) -> FooIter<'_> {
        FooIter(Some(self))
    }
}


fn main() {
    println!("Hello, world!");
}

And these compilation errors:

   Compiling playground v0.0.1 (/playground)
error[E0637]: `'_` cannot be used here
  --> src/main.rs:17:29
   |
17 |     type IntoIter = FooIter<'_>;
   |                             ^^ `'_` is a reserved lifetime name

error[E0437]: type `Iter` is not a member of trait `IntoIterator`
  --> src/main.rs:18:5
   |
18 |     type Iter = &Foo;
   |     ^^^^^----^^^^^^^^
   |     |    |
   |     |    help: there is an associated type with a similar name: `Item`
   |     not a member of trait `IntoIterator`

error[E0637]: `&` without an explicit lifetime name cannot be used here
  --> src/main.rs:18:17
   |
18 |     type Iter = &Foo;
   |                 ^ explicit lifetime name needed here

error[E0424]: expected value, found module `self`
  --> src/main.rs:20:9
   |
19 |     fn into_iter() -> Self::IntoIter {
   |        --------- this function doesn't have a `self` parameter
20 |         self.iter()
   |         ^^^^ `self` value is a keyword only available in methods with a `self` parameter
   |
help: add a `self` receiver parameter to make the associated `fn` a method
   |
19 |     fn into_iter(&self) -> Self::IntoIter {
   |                  +++++

error[E0186]: method `into_iter` has a `self` declaration in the trait, but not in the impl
  --> src/main.rs:19:5
   |
19 |     fn into_iter() -> Self::IntoIter {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `self` in impl
   |
   = note: `into_iter` from trait: `fn(Self) -> <Self as IntoIterator>::IntoIter`

error[E0046]: not all trait items implemented, missing: `Item`
  --> src/main.rs:16:1
   |
16 | impl IntoIterator for &Foo {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Item` in implementation
   |
   = help: implement the missing item: `type Item = /* Type */;`

Some errors have detailed explanations: E0046, E0186, E0424, E0437, E0637.
For more information about an error, try `rustc --explain E0046`.
error: could not compile `playground` (bin "playground") due to 6 previous errors

The suggested code is:

  • missing a lifetime generic on the impl
  • uses an anonymous lifetime in an impermissible location
  • missing a named lifetime on the type Item member
  • missing the self parameter in fn into_iter
  • defining an Iter associated type that is not present on the IntoIterator trait
  • missing an Item associated type

Version

Stable channel
Build using the Stable version: 1.73.0
clippy 0.1.75 (2023-10-19 4578435)

from the playground

Additional Labels

@rustbot label +I-suggestion-causes-error

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: Clippy is not doing the correct thingI-suggestion-causes-errorIssue: The suggestions provided by this Lint cause an ICE/error when applied

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions