I faced an issue wit associated types... I found similar questions on SO, like these ones:
- Expected type parameter, found opaque type
- Matching a generic parameter to an associated type in an impl
But while being pretty close to my case, they are not the same...
So I have a trait with associated type:
trait Generator {
type Item;
fn next(&mut self) -> Self::Item;
}
And another trait with generic method which takes first one as a type parameter:
trait Iterator {
fn iterate<T>(&self, generator: T) -> T::Item
where T: Generator;
}
So far everything OK.
Now i want to make a struct and implement Iterator trait for it.
struct Baz<R> { // I want my struct to keep data of the same type as my associated type
data: Vec<R>, // So i make my struct generic
}
impl<R> Iterator for Baz<R>
{
fn iterate<T>(&self, generator: T) -> T::Item
where T: Generator<Item = R> // And specify associated type constraint for generic method
{
generator.next()
}
}
And now I'm getting an error:
error[E0271]: type mismatch resolving `<T as Generator>::Item == R`
--> src/main.rs:20:28
|
17 | impl<R> Iterator for Baz<R>
| - this type parameter
...
20 | where T: Generator<Item = R>
| ^^^^^^^^ expected associated type, found type parameter `R`
|
= note: expected associated type `<T as Generator>::Item`
found type parameter `R`
= note: you might be missing a type parameter or trait bound
note: the requirement `<T as Generator>::Item == R` appears on the `impl`'s method `iterate` but not on the corresponding trait's method
--> src/main.rs:9:8
|
8 | trait Iterator {
| -------- in this trait
9 | fn iterate<T>(&self, generator: T) -> T::Item
| ^^^^^^^ this trait's method doesn't have the requirement `<T as Generator>::Item == R`
I figured out that to fix it, i have to make my Iterator trait generic and specify constraint in trait definition:
trait Iterator<R> {
fn iterate<T>(&self, generator: T) -> T::Item
where T: Generator<Item = R>;
}
And also update impl block:
impl<R> Iterator<R> for Baz<R>
{
...
}
But unfortunately this traits are from 3-rd-party lib so I cant update their source code (to be more specific, it's SeqAccess trait from serde library)
So my question is: is there any way to declare associated type constraint in such a case without adding type parameter to trait itself?
No, this is not something you can do. Consider that other functions accepting
impl Iteratorwould not be aware of this newly-added constraint and so they could pass aGeneratorwhoseItemtype doesn't match your constraint. The signature of the function inIteratorimposes no constraint on the type of generated items, so consumers of the trait are free to use anyGeneratorat all.