owned this note changed 2 years ago
Published Linked with GitHub

Deep dive: AFIT Send bounds and keyword generics

Background (outdated)

tags: deep-dive

Leave questions, observations, discussion topics below.


trait ?async Iterator {
    type Item;
    ?async fn next(&mut self) -> Option<Self::Item>;
    fn size_hint(&self) -> (usize, Option<usize>) {..}
}

struct AsyncFile;

// always async impl!
impl async Iterator for AsyncFile { .. }
trait Foo {
    async fn bar() {}
    async fn baz() {}
    async fn bin() {}
}

// ... and how do we mark all methods in `Foo` as `Send`

trait async Foo {
    async fn bar() {}
}

progression!

// say we start with this
trait async HealthCheck { .. }
async fn foo(check: impl async HealthCheck) { .. }

// .. but later on we realize `HealthCheck` may also
// be useful in !async contexts, so we change it to this:
trait ?async HealthCheck { .. }

// .. usage remains exactly as it was before!:
async fn foo(check: impl async HealthCheck) { .. }

// .. but maybe we want `foo` to also become `?async`, so we then can
// opt into instead changing it to:
?async fn foo(check: impl ?async HealthCheck) { .. }
trait async HealthCheck { .. }
async fn foo(check: impl async(Send) HealthCheck) { .. }

Open Questions

What is the default?

Are methods Send by default and we opt out? Or do we opt in to Send?


// Do we write this?
async fn foo(check: impl async(Send) HealthCheck) { .. }

// Or this?
async fn foo(check: impl async(?Send) HealthCheck) { .. }

Does async show up in imports?

use my_crate::HealthCheck;

// Could you do...
use my_crate::async(Send) HealthCheck as async HealthCheck;


// What about aliases

type UsizeOption = Option<usize>;

trait AsyncHealthCheck = async HealthCheck;

fn foo(x: impl async(Send) AsyncHealthCheck) { .. }

If we can hide async behind a trait alias, we shouldn't require it on the trait definition.

trait async HealthCheck {
    async fn check(...);    
}

trait async SendHealthCheck = async(Send) HealthCheck;

fn foo(check: impl async HealthCheck) { .. }

fn bar(check: impl async SendHealthCheck) { .. }

trait SendHealthCheck = async(Send) HealthCheck;

trait async HealthCheck {
    async fn check(...);    
}

trait async SendHealthCheck = async(Send) HealthCheck;

fn foo(check: impl HealthCheck + Send) { .. }

fn bar(check: impl SendHealthCheck) { .. }

Supertraits

// Trait today!
trait FixedLengthIterator: Iterator { .. }

// Maybe-async variant
trait ?async FixedLengthIterator: ?async Iterator { .. }

// Always async variant
trait async FixedLengthIterator: async Iterator { .. }

Are async Trait and Trait different names?

Can I do this?


trait Bar {
    fn foo();
}

trait async Bar {
    async fn baz();
}

Yosh: probably not; they live in the same namespace. But you could imagine an async and !async impl of the same ?async trait on a single type.

struct ?async File { .. }

// either..
impl ?async Read
Select a repo