Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"is not an iterator" diagnostic through blanket implementation, when the type is actually an iterator but is missing a marker #127511

Closed
progval opened this issue Jul 9, 2024 · 2 comments · Fixed by #132760
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@progval
Copy link
Contributor

progval commented Jul 9, 2024

Code

(inspired by rayon's ParallelBridge)

pub trait ParallelBridge: Sized {
    // Required method
    fn par_bridge(self) -> ();
}

impl<T: Iterator + Send> ParallelBridge for T
where
    T::Item: Send,
{
    fn par_bridge(self) -> () {
        unimplemented!("par_bridge");
    }
}


fn f(it: impl Iterator<Item=u64>) {
    it.map(|i| i+1).par_bridge()
}

fn main() -> std::io::Result<()> {
    let (_tx, rx) = std::sync::mpsc::sync_channel(1000);
    f(rx.iter());

    Ok(())
}

playground

Current output

Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `par_bridge` found for struct `Map<impl Iterator<Item = u64>, {closure@src/main.rs:17:12: 17:15}>` in the current scope
  --> src/main.rs:17:21
   |
17 |     it.map(|i| i+1).par_bridge()
   |                     ^^^^^^^^^^ `Map<impl Iterator<Item = u64>, {closure@src/main.rs:17:12: 17:15}>` is not an iterator
   |
help: call `.into_iter()` first
   |
17 |     it.map(|i| i+1).into_iter().par_bridge()
   |                     ++++++++++++

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

Desired output

The same error there is when removing the .map()

   Compiling playground v0.0.1 (/playground)
error[E0599]: no method named `par_bridge` found for type parameter `impl Iterator<Item = u64>` in the current scope
  --> src/main.rs:17:8
   |
16 | fn f(it: impl Iterator<Item=u64>) {
   |          ----------------------- method `par_bridge` not found for this type parameter
17 |     it.map(|i| i+1).par_bridge()
   |        ^^^^^^^^^^ method cannot be called on `impl Iterator<Item = u64>` due to unsatisfied trait bounds
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `par_bridge`, perhaps you need to restrict type parameter `impl Iterator<Item = u64>` with it:
   |
16 | fn f(it: impl Iterator<Item=u64> + ParallelBridge) {
   |                                  ++++++++++++++++

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

Rationale and extra context

The error indicated the type does not implement Iterator, even though it does and Send is the one that is missing.

Other cases

No response

Rust Version

rustc 1.79.0

Anything else?

No response

@progval progval added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jul 9, 2024
@GrigorenkoPV
Copy link
Contributor

Similar to #124802?

@kpreid
Copy link
Contributor

kpreid commented Jul 11, 2024

Here is a slightly smaller reproduction that only uses core and has a more egregious error message (“impl Iterator is not an iterator”). Reduced from a case found by @zakarumych.

trait Missing {}
trait HasMethod {
    fn foo(self);
}
impl<T: Iterator + Missing> HasMethod for T {
    fn foo(self) {}
}

fn get_iter() -> impl Iterator {
    // any Iterator impl will do
    core::iter::once(())
}

fn main() {
    get_iter().foo();
}
error[E0599]: no method named `foo` found for opaque type `impl Iterator` in the current scope
  --> src/main.rs:15:16
   |
15 |     get_iter().foo();
   |                ^^^ `impl Iterator` is not an iterator
   |
help: call `.into_iter()` first
   |
15 |     get_iter().into_iter().foo();
   |                ++++++++++++

@bors bors closed this as completed in b598849 Nov 9, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Nov 9, 2024
Rollup merge of rust-lang#132760 - dianne:iter-into-iter, r=lcnr

Don't suggest `.into_iter()` on iterators

This makes the the suggestion to call `.into_iter()` only consider unsatisfied `Iterator` bounds for the receiver type itself. That way, it ignores predicates generated by trying to auto-ref the receiver (the result of which usually won't implement `Iterator`).

Fixes rust-lang#127511

Unfortunately, the error in that case is still confusing: it labels `Iterator` as an unsatisfied bound because `&impl Iterator: Iterator` can't be satisfied, despite that not being required or helpful. I'd like to handle that in a separate PR. ~~I'm hoping fixing rust-lang#124802 will fix it too.~~ It doesn't look connected to that issue. Still, I think it'd be clearest to visually distinguish unsatisfied predicates from different attempts at `pick_method`; I'll make a PR for that soon.
mati865 pushed a commit to mati865/rust that referenced this issue Nov 12, 2024
Don't suggest `.into_iter()` on iterators

This makes the the suggestion to call `.into_iter()` only consider unsatisfied `Iterator` bounds for the receiver type itself. That way, it ignores predicates generated by trying to auto-ref the receiver (the result of which usually won't implement `Iterator`).

Fixes rust-lang#127511

Unfortunately, the error in that case is still confusing: it labels `Iterator` as an unsatisfied bound because `&impl Iterator: Iterator` can't be satisfied, despite that not being required or helpful. I'd like to handle that in a separate PR. ~~I'm hoping fixing rust-lang#124802 will fix it too.~~ It doesn't look connected to that issue. Still, I think it'd be clearest to visually distinguish unsatisfied predicates from different attempts at `pick_method`; I'll make a PR for that soon.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants