use std::future::Future;
use tokio; // 0.3.1
struct Foo {}
async fn worker(foo: &mut Foo) {}
trait AsyncSingleArgFnOnce<Arg>: FnOnce(Arg) -> <Self as AsyncSingleArgFnOnce<Arg>>::Fut {
type Fut: Future<Output=<Self as AsyncSingleArgFnOnce<Arg>>::Output>;
type Output;
}
impl<Arg, F, Fut> AsyncSingleArgFnOnce<Arg> for F
where
F: FnOnce(Arg) -> Fut,
Fut: Future,
{
type Fut = Fut;
type Output = Fut::Output;
}
async fn applier<F>(f: F)
where
for<'a> F: AsyncSingleArgFnOnce<&'a mut Foo, Output=()>,
{
let mut foo = Foo {};
f(&mut foo).await
}
#[tokio::main]
async fn main() {
applier(worker).await;
}
this works. I’m not sure if the extra trait can be avoided.
Edit: added FnOnce supertrait
Edit2: refactored into more general trait and removed methods
Edit3: further generalization