This is a fork of the widely acclaimed async-trait crate. This crate adds two experimental attributes to async-trait that can be applied to asynchronous trait methods and associated functions to avoid heap memory allocation.
unboxed
or unboxed_simple
attribute is of impl Future<..>
instead of Box<dyn Future<..>>
.Note that, the main author of async-trait did not want to add such options, therefore this fork will not be merged into the upstream.
See async-trait for more details about async-trait.
unboxed
turns an asynchronous trait method or associated function into a synchronous one returning an impl Future<..>
by adding a generic associated type for the method or associated function.
```rust use asynctraitfn::{asynctrait, unboxedsimple};
pub trait SelfToUsize { #[unboxed] async fn get(&self) -> usize; }
impl SelfToUsize for u32 { #[unboxed] async fn get(&self) -> usize { *self as usize } } ```
The compiler generates the following code.
rust
pub trait SelfToUsize {
fn get<'life0, 'async_trait>(&'life0 self) -> Self::RetTypeOfGet<'life0, 'async_trait>
where
'life0: 'async_trait,
Self: 'async_trait;
type RetTypeOfGet<'life0, 'async_trait>: ::core::future::Future<Output = usize>
+ ::core::marker::Send
+ 'async_trait
where
'life0: 'async_trait,
Self: 'async_trait,
Self: 'life0;
}
impl SelfToUsize for u32 {
fn get<'life0, 'async_trait>(&'life0 self) -> Self::RetTypeOfGet<'life0, 'async_trait>
where
'life0: 'async_trait,
Self: 'async_trait,
{
async move {
if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<usize> {
return __ret;
}
let __self = self;
let __ret: usize = { *__self as usize };
#[allow(unreachable_code)]
__ret
}
}
type RetTypeOfGet<'life0, 'async_trait> = impl ::core::future::Future<Output = usize>
+ ::core::marker::Send
+ 'async_trait
where
'life0: 'async_trait,
Self: 'async_trait,
Self: 'life0 ;
}
unboxed_simple
is identical to unboxed
except that it substitutes all the lifetime bounds and parameters with a single, fixed lifetime: 'async_trait
. When code around an unboxed
attribute does not compile, unboxed_simple
might help.
```rust use asynctraitfn::{asynctrait, unboxedsimple};
pub trait AddOther { #[unboxed_simple] async fn add<'s, 'o>(&'a self, other: &'o usize) -> usize; }
impl AddOther for u32 { #[unboxed_simple] async fn add<'s, 'o>(&'a self, other: &'o usize) -> usize { (*self as usize) + *other } }
```
The above code expands to the following code; all the lifetime parameters are replaced with 'async_trait
.
```rust pub trait AddOther { fn add<'asynctrait>( &'asynctrait self, other: &'asynctrait usize, ) -> Self::RetTypeOfAdd<'asynctrait> where Self: 'asynctrait; type RetTypeOfAdd<'asynctrait>: ::core::future::Future
impl AddOther for u32 {
fn add<'asynctrait>(
&'asynctrait self,
other: &'asynctrait usize,
) -> Self::RetTypeOfAdd<'asynctrait>
where
Self: 'asynctrait,
{
async move {
if let ::core::option::Option::Some(ret) = ::core::option::Option::None::