Closed
Description
I'm trying to implement trait with async fn
for all async fn
s. Simplified example:
#[async_trait]
trait Trait {
async fn run(&self);
}
#[async_trait]
impl<F, Fut> Trait for F
where
F: Fn() -> Fut + Sync,
Fut: Future<Output = ()> + Send,
{
async fn run(&self) {
self().await
}
}
simplified `cargo expand`
trait Trait {
fn run<'s, 'async_trait>(&'s self) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
's: 'async_trait,
Self: 'async_trait;
}
impl<F, Fut> Trait for F
where
F: Fn() -> Fut + Sync,
Fut: Future<Output = ()> + Send,
{
fn run<'s, 'async_trait>(&'s self) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
's: 'async_trait,
Self: 'async_trait,
{
#[allow(clippy::used_underscore_binding)]
async fn __run<F, Fut>(_self: &F)
where
F: Fn() -> Fut + Sync,
Fut: Future<Output = ()> + Send,
{
_self().await
}
Box::pin(__run::<F, Fut>(self))
}
}
But sadly, this doesn't work:
error[E0309]: the parameter type `Fut` may not live long enough
--> src/lib.rs:16:1
|
16 | #[async_trait]
| ^^^^^^^^^^^^^^
17 | impl<F, Fut> Trait for F
| --- help: consider adding an explicit lifetime bound `Fut: 'async_trait`...
|
note: ...so that the type `impl std::future::Future` will meet its required lifetime bounds
--> src/lib.rs:16:1
|
16 | #[async_trait]
| ^^^^^^^^^^^^^^
error: aborting due to previous error
(adding Fut: 'async_trait
is impossible because it leads to impl has stricter requirements than trait
errors)
But with by-hand desugaring this implementation is possible:
impl<F, Fut> Trait for F
where
F: Fn() -> Fut + Sync,
Fut: Future<Output = ()> + Send,
{
fn run<'s, 'async_trait>(&'s self) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where
's: 'async_trait,
Self: 'async_trait,
{
Box::pin(async move { self().await })
}
}
#[test]
fn test() {
let closure = || async { () };
Trait::run(&closure);
}
So, my questions are:
- Why the first implementation doesn't work, but the second does?
- Is it possible to remove
async move {}
from the last example? (Box::pin(self())
leads to the same errorthe parameter type
Futmay not live long enough
) - Is it possible to write implementation like this, but without so much boilerplate?
- Can
async_trait
to accept implementations like in the first example? (after some changes in how macro works)