编写一个调用另一个异步函数的异步函数

Phi*_*ost 5 rust

我正在尝试创建一个将函数指针作为参数的异步函数。它会做一些事情,调用函数,等待结果,然后再做一些事情:

use std::future::Future;

async fn run_another_async_fn<F, Fut>(f: F)
where
    Fut: Future<Output = ()>,
    F: FnOnce(&mut i32) -> Fut,
{
    let mut i = 42;
    println!("running function");
    f(&mut i).await;
    println!("ran function");
}

async fn foo(i: &mut i32) {}

async fn bar() {
    run_another_async_fn(foo);
}
Run Code Online (Sandbox Code Playgroud)

[在 Rust Playground 上查看]

不幸的是,这无法编译:

error[E0308]: mismatched types
  --> src/lib.rs:17:5
   |
17 |     run_another_async_fn(foo);
   |     ^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected associated type `<for<'_> fn(&mut i32) -> impl Future {foo} as FnOnce<(&mut i32,)>>::Output`
              found associated type `<for<'_> fn(&mut i32) -> impl Future {foo} as FnOnce<(&mut i32,)>>::Output`
   = note: the required lifetime does not necessarily outlive the empty lifetime
note: the lifetime requirement is introduced here
  --> src/lib.rs:6:28
   |
6  |     F: FnOnce(&mut i32) -> Fut,
   |                            ^^^
Run Code Online (Sandbox Code Playgroud)

首先,编译器似乎完全找到了它的预期,但它仍然在抱怨?

其次,什么是“空人生”?我想它一定意味着'_,这有什么特殊意义吗?

最后,有什么方法可以编译它?

Sve*_*rev 1

问题是无法在子句中为F和指定相同的生命周期。Futwhere

幸运的是(如果您不介意分配未来的堆)有一个简单的解决方法。您可以使用现有的,futures::future::BoxFuture;如下所示:

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
Run Code Online (Sandbox Code Playgroud)

借助它的帮助,您可以为借用指定相同的生命周期参数并作为未来的特征绑定:

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
Run Code Online (Sandbox Code Playgroud)

您还必须添加一个适配器函数,它将具有正确的返回类型 - 即而BoxFuture<'_, T>不是impl Future

 where  for<'a> F: FnOnce(&'a mut i32) -> BoxFuture<'a, ()>,
Run Code Online (Sandbox Code Playgroud)

或使用闭包:

fn asd(i: &mut i32) -> BoxFuture<'_, ()> {
    foo(i).boxed()
}
Run Code Online (Sandbox Code Playgroud)

结果你的代码将如下所示:

run_another_async_fn(|i| foo(i).boxed());
Run Code Online (Sandbox Code Playgroud)