#async-trait #async #nightly

macro async_trait_proto

Async traits using nightly features

4 releases

0.1.0 Jul 25, 2022
0.0.3 Jul 24, 2022
0.0.2 Jul 23, 2022
0.0.1 Jul 23, 2022

#1618 in Procedural macros

Unlicense

15KB
203 lines

async_trait_proto

Crates.io docs.rs Benchmark Rust

Async trait prototype using the desugarization described in RFC 3185 Static Async Fn in Traits.

It should be faster than async-trait because it doesn't use allocations on every invocation and type erasure.

Benchmark

Requires these feature flags and a nightly compiler:

  • #![feature(generic_associated_types)]
  • #![feature(type_alias_impl_trait)]

Example

#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]
use async_trait_proto::async_trait_proto;
struct Foo;

#[async_trait_proto]
trait Bar {
    async fn wait(&self);
}

#[async_trait_proto]
impl Bar for Foo {
    async fn wait(&self) {
        sleep(Duration::from_secs(10)).await;
    }
}
Send + Sync

The trait definition can include attributes that indicate, that the resulting Future has to be Send and/or Sync. This is important when using the traits with work stealing schedulers like tokio.

#![feature(generic_associated_types)]
#![feature(type_alias_impl_trait)]
use async_trait_proto::async_trait_proto;
struct Foo;

#[async_trait_proto]
trait Bar {
    #[send]
    async fn wait(&self);
}

#[async_trait_proto]
impl Bar for Foo {
    async fn wait(&self) {
        todo!()
    }
}

// this trait can now be used with tokio::spawn
async fn spawn_trait<T: Bar + Sync + Send + 'static>(foo: T) {
    let handle = tokio::spawn(async move {
        foo.wait().await;
    });
    handle.await;
}

On the other hand this will not compile:

# #![feature(generic_associated_types)]
# #![feature(type_alias_impl_trait)]
# use async_trait_proto::async_trait_proto;
# struct Foo;

#[async_trait_proto]
trait Bar {
    async fn wait(&self);
}

# #[async_trait_proto]
# impl Bar for Foo {
#     async fn wait(&self) {
#         todo!()
#     }
# }
// this trait can not now be used with tokio::spawn
async fn spawn_trait<T: Bar + Sync + Send + 'static>(foo: T) {
    let handle = tokio::spawn(async move {
        foo.wait().await;
    });
    handle.await;
}

License: Unlicense

Dependencies

~1.5MB
~35K SLoC