Skip to content

Incorrect trait bound handling for IntoIterator<IntoIter = I, Item = T> #137185

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

Open
DJDuque opened this issue Feb 17, 2025 · 3 comments
Open

Incorrect trait bound handling for IntoIterator<IntoIter = I, Item = T> #137185

DJDuque opened this issue Feb 17, 2025 · 3 comments
Labels
A-trait-system Area: Trait system C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@DJDuque
Copy link

DJDuque commented Feb 17, 2025

I tried this code:

pub struct Positive<F>(F);

struct MyStruct<F, I> {
    first: Option<F>,
    iter: I,
}

impl<F, I> MyStruct<F, I> {
    fn new<T>(iter: T) -> Self
    where
        T: IntoIterator<IntoIter = I, Item = Positive<F>>,
    {
        let mut iter = iter.into_iter();
        let first = iter.next().map(|Positive(t)| t);
        
        Self { iter, first }
    }
}

I expected it to compile just like this does:

pub struct Positive<F>(F);

struct MyStruct<F, I> {
    first: Option<F>,
    iter: I,
}

impl<F, I> MyStruct<F, I> {
    fn new<T>(iter: T) -> Self
    where
        T: IntoIterator<IntoIter = I>,
        I: Iterator<Item = Positive<F>>,
    {
        let mut iter = iter.into_iter();
        let first = iter.next().map(|Positive(t)| t);
        
        Self { iter, first }
    }
}

Instead, it complains:

error[E0599]: no method named `next` found for type parameter `I` in the current scope
  --> src/main.rs:15:26
   |
8  | impl<F, I> MyStruct<F, I> {
   |         - method `next` not found for this type parameter
...
15 |         let first = iter.next().map(|Positive(t)| t);
   |                          ^^^^ method not found in `I`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait
help: the following trait defines an item `next`, perhaps you need to restrict type parameter `I` with it:
   |
8  | impl<F, I: Iterator> MyStruct<F, I> {
   |          ++++++++++

Meta

rustc --version --verbose:

~> rustc --version --verbose
rustc 1.82.0 (f6e511eec 2024-10-15)
binary: rustc
commit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14
commit-date: 2024-10-15
host: x86_64-unknown-linux-gnu
release: 1.82.0
LLVM version: 19.1.1
@DJDuque DJDuque added the C-bug Category: This is a bug. label Feb 17, 2025
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Feb 17, 2025
@fmease fmease added A-trait-system Area: Trait system T-types Relevant to the types team, which will review and decide on the PR/issue. labels Feb 17, 2025
@fmease
Copy link
Member

fmease commented Feb 17, 2025

I'm almost certain that we have an open issue for that already. I just can't find it.

You can sort of summarize this issue as "the trait solver forgets item bounds on associated types if they are equated with a type parameter" or probably more correctly as "associated type eagerly normalized to in-scope type parameter and thus the trait solver can't see the item bounds anymore".

Smaller:

trait Trait { type A: Clone; }

fn f<T: Trait<A = A>, A>(x: T::A) {
    x.clone(); //~ ERROR no method named `clone` found for type parameter `A`
}

Whereas the following compiles:

trait Trait { type A: Clone; }

fn f<T: Trait>(x: T::A) {
    x.clone();
}

@DJDuque
Copy link
Author

DJDuque commented Feb 18, 2025

Am I hitting this same issue here again, or is it something else? It feels similar but I don't understand 100% to be sure:

I have:

mod sealed {
    pub trait SealedIterator: Iterator {}
}

pub struct Thing<F>(F);

pub trait Generator: sealed::SealedIterator<Item = Thing<Self::Type>> {
    type Type;
}

And this doesn't compile:

pub struct MyGenerator<T> {
    gens: Vec<Box<dyn Generator<Type = T>>>,
}

But this does:

pub struct MyGenerator<T> {
    gens: Vec<Box<dyn Generator<Type = T, Item = f64>>>,
}

I kind of expected Type to be enough in the first case, but more surprising to me is why an arbitrary Item compile in the second case.

@QuineDot
Copy link

I'm almost certain that we have an open issue for that already. I just can't find it.

#109845 which links to this comment (but I don't know if those two issues are dupes of each other or not).

@jieyouxu jieyouxu removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Apr 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system C-bug Category: This is a bug. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants