Currently it's hard to specific Send bounds in async trait, and solutions like Return type notation or Inferred async send bounds are not quite consistent and extensible.
If we have generic trait parameters(similar to ,generic type/lifetime/const parameters), the Send
bounds can be represent like:
trait AsyncIterator<trait R = Unbound> {
type Item;
fn next(&mut self) -> impl Future<Output = Option<Self::Item>> + R + '_;
}
/// or with symbol like ' in lifetime notation.
trait AsyncIterator<`R = Unbound> {
type Item;
fn next(&mut self) -> impl Future<Output = Option<Self::Item>> + R + '_;
}
// or with async syntax sugar
trait AsyncIterator<`R = Unbound> {
type Item;
async fn next(&mut self) -> Option<Self::Item> + R;
}
async fn traverse_no_send<I: AsyncIterator>(mut iter: I) { /* ... */ }
async fn traverse_send<I: AsyncIterator<Send>>(mut iter: I) { /* ... */ }
Where trait parameters can be contravariant, i.e. AsyncIterator<Send + Sync>
is AsyncIterator<Send>
.
The existential quantification way(associated trait) may be written as:
trait AsyncIterator {
trait R = Unbound;
type Item;
async fn next(&mut self) -> Option<Self::Item> + Self::R;
}
Refers: