Generic trait polymorphism and async send bounds

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:

2 Likes

Actually, the mentioned "Generic trait polymorphism" can also be used to implement the real Functor trait in Rust...

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.