I faced an issue with associated types... I found similar questions on SO, like these ones:
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, these traits are from a 3rd-party library so I can't update their source code (specifically, it's SeqAccess
trait from Serde library).
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 Iterator
would not be aware of this newly-added constraint and so they could pass a Generator
whose Item
type doesn't match your constraint. The signature of the function in Iterator
imposes no constraint on the type of generated items, so consumers of the trait are free to use any Generator
at all.