Rust's async iterator could be defined like this
#[required(or(poll_next, next))]
pub trait AsyncIterator {
type Item;
// required methods: either poll_next or next
fn poll_next(
self: Pin<&mut Self>,
cx: &mut Context<'_>
) -> Poll<Option<Self::Item>>;
async fn next(&mut self) -> Option<Self::Item>;
// Provided method
fn size_hint(&self) -> (usize, Option<usize>);
}
And, using an idea from Haskell, the trait implementer can define the trait either using poll_next
or next
; if one is missing, it is automatically defined in terms of the other (in the trait definition, they are mutually recursive, but one of them is required, in order to tie the knot).
This idea doesn't require maybe async at all, but,
Even if Rust ends up having effects or "maybe async", extending the already existing Iterator
trait, having both methods is this is still possible: just define that while the next
method is maybe async (as expected), the poll_next
method exists only if the trait is async (but it isn't itself async).
Something like this (made up syntax)
#[required(or(poll_next, next))]
pub trait async<A> Iterator {
type Item;
// required methods: either poll_next or next
#[if_async<A>] // poll_next exists only when the trait is async
fn poll_next(
self: Pin<&mut Self>,
cx: &mut Context<'_>
) -> Poll<Option<Self::Item>>;
async<A> fn next(&mut self) -> Option<Self::Item>;
// Provided method
fn size_hint(&self) -> (usize, Option<usize>);
// many other provided methods
}
In this case, one can either impl a type for Iterator
using next
and async Iterator
using poll_next
(which is the most low level way, which also enables using async-only constructs in the async implementation), or they can impl a type for both sync and async iterators at the same time (which requires implementing maybe async next
and not using async-only constructs)
Something like this
struct S;
// separate implementations for both `Iterator` and `async Iterator`
impl Iterator for S {
fn next(..) ..
}
impl async Iterator for S {
fn poll_next(..) ..
// or async fn next(...) ..
}
or
// a single implementation for both sync and async iterators
impl async<A> Iterator for S {
async<A> fn next(...) ...
}