Skip to content

E0599 suggests "call .into_iter() first" on non-mutable reference #155365

@DanielEScherzer

Description

@DanielEScherzer

Code

struct Demo {
    contents: Vec<u32>,
}

impl Demo {
    fn new() -> Self {
        Demo { contents: vec![ 1, 2, 3 ] }
    }
    
    fn count_odds(&self) -> usize {
        self.contents.filter(|v| *v % 2 == 1).count()
    }
}

Current output

Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `filter` found for struct `Vec<u32>` in the current scope
  --> src/lib.rs:11:23
   |
11 |         self.contents.filter(|v| *v % 2 == 1).count()
   |                       ^^^^^^ `Vec<u32>` is not an iterator
   |
help: call `.into_iter()` first
   |
11 |         self.contents.into_iter().filter(|v| *v % 2 == 1).count()
   |                       ++++++++++++

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` (lib) due to 1 previous error

Desired output

Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `filter` found for struct `Vec<u32>` in the current scope
  --> src/lib.rs:11:23
   |
11 |         self.contents.filter(|v| *v % 2 == 1).count()
   |                       ^^^^^^ `Vec<u32>` is not an iterator
   |
help: call `.iter()` first
   |
11 |         self.contents.iter().filter(|v| *v % 2 == 1).count()
   |                       +++++++

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` (lib) due to 1 previous error

Rationale and extra context

If into_iter() is added, there is a new error:

   Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `self.contents` which is behind a shared reference
   --> src/lib.rs:11:9
    |
 11 |         self.contents.into_iter().filter(|v| *v % 2 == 1).count()
    |         ^^^^^^^^^^^^^ ----------- `self.contents` moved due to this method call
    |         |
    |         move occurs because `self.contents` has type `Vec<u32>`, which does not implement the `Copy` trait
    |
note: `into_iter` takes ownership of the receiver `self`, which moves `self.contents`
   --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:310:18
    |
310 |     fn into_iter(self) -> Self::IntoIter;
    |                  ^^^^
help: you can `clone` the value and consume it, but this might not be your desired behavior
    |
 11 |         <Vec<u32> as Clone>::clone(&self.contents).into_iter().filter(|v| *v % 2 == 1).count()
    |         ++++++++++++++++++++++++++++             +
help: consider cloning the value if the performance cost is acceptable
    |
 11 |         self.contents.clone().into_iter().filter(|v| *v % 2 == 1).count()
    |                      ++++++++

For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground` (lib) due to 1 previous error

Other cases

For a non-method where the vector is a function parameter, .into_iter() works fine though, so the suggestion on

fn count_odds(contents: &Vec<u32>) -> usize {
    contents.filter(|v| *v % 2 == 1).count()
}

is fine

Rust Version

1.94.1

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsD-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions