Why is that? I think we can write code like this without any problems:
trait Generator {
type Yield;
type Result;
fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Result>;
fn try_iter<Y, T, E>(self) -> GeneratorTryWrapper<Y, T, E, Self>
where Self: Generator<Yield=Y, Result=Result<T, E>> + Sized
{
GeneratorTryWrapper { gen: self }
}
}
struct GeneratorTryWrapper<Y, T, E, G>
where G: Generator<Yield=Y, Result=Result<T, E>> + Sized
{
gen: G,
}
impl<Y, T, E, G> Iterator for GeneratorTryWrapper<Y, T, E, G>
where G: Generator<Yield=Y, Result=Result<T, E>> + Sized
{
type Item = Result<Y, E>;
fn next(&mut self) -> Option<Self::Item> {
match self.gen.resume() {
GeneratorState::Complete(Ok(_)) => None,
GeneratorState::Complete(Err(err)) => Some(Err(err)),
GeneratorState::Yielded(val) => Some(Ok(val)),
}
}
}
Though I would prefer to hide GeneratorTryWrapper behind impl Trait if possible.
UPD: Small offtopic: I think using Iterator instead of a more general Generator (or maybe even generator with a parametrised resume?) was one of the mistakes of Rust 1.0 release. Coupled with trait aliases ergonomic impact would’ve been negligible and code could’ve been more expressive and flexible. But right now ecosystem is too Iterator-centric, and making Iterator an alias for Generator<T, ()> in a backwards-compatible way will be very difficult, if not impossible.
At the very least we will have to start with renaming Yield to Item before Generator stabilisation.