dtolnay / async-trait

Type erasure for async trait methods
Apache License 2.0
1.81k stars 84 forks source link

Possibly optimize simple function body? #240

Open novacrazy opened 1 year ago

novacrazy commented 1 year ago

I'm working on an autogenerated EventHandler trait with many async fn on_some_event() methods. There is also one async fn fallback() method for which all default implementations of on_some_event call, giving:

#[async_trait::async_trait]
trait EventHandler {
    async fn fallback(self, args: SomeType) -> U;

    // This 30 times or so for default implementations
    async fn on_some_event(self, args: SomeType) -> U {
        self.fallback(args).await
    }
}

This leads to double-boxing the fallback future, which is likely executing more often than not if the library users don't handle all events.

Would it be possible to flag an async method as "transparent" perhaps? Strip the .await and return the result directly.

// ...
#[async_trait(transparent)]
async fn on_some_event(self, args: SomeType) -> U {
    self.fallback(args).await
}
// would desugar to
fn on_some_event<'async_trait>(self, args: SomeType) 
    -> std::pin::Pin<Box<dyn std::future::Future<Output = U> + Send + 'async_trait>> 
where
    Self: Send + 'async_trait
{
    self.fallback(args)
}

However, if the async_trait codegen is stable enough, I could also just desugar it manually for default implementations.