如何保存一个捕获变量的盒装异步函数?



我想从闭包中获得一个可以捕获变量的盒装异步函数:

use std::future::Future;
use std::pin::Pin;
fn constrain<Fun>(fun: Fun) -> Fun
where
Fun: for<'arg> Fn(&'arg usize, &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'arg>>,
{
fun
}
struct Test {}
impl Test {
pub async fn fun<'test, 'arg>(&'test self, val0: &'arg usize, val1: &'arg usize) -> usize
where
'arg: 'test,
{
*val0 + *val1
}
}
pub async fn fun<'arg>(val0: &'arg usize, val1: &'arg usize) -> usize {
val0 + val1
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let test = Test {};
let boxed = Box::new(constrain(move |v0, v1| {
let ret = Box::pin(async {
test.fun(v0, v1).await
//fun(v0, v1).await
});
ret
}));
let v0 = 10;
let v1 = 20;
let ret = boxed(&v0, &v1).await;
println!("{ret}");
}

当我调用"fun"时,它可以工作,因为它没有捕获"test"。当我调用'test.fun(…)'时,它失败了:

error: lifetime may not live long enough
--> src/main.rs:46:9
|
38 |     let boxed = Box::new(constrain(move |v0, v1|
|                                    -------------
|                                    |     |
|                                    |     has type `&'2 usize`
|                                    lifetime `'1` represents this closure's body
...
46 |         ret
|         ^^^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
= note: closure implements `Fn`, so references to captured variables can't escape the closure
error: could not compile `playground` due to previous error

我不知道如何将闭包的生命周期限制在参数上。

这里有一些很接近的东西:

use std::pin::Pin;
use std::future::Future;
#[macro_use]
extern crate derive_new;
#[derive(new)]
struct Test
{
}
impl Test
{
pub async fn fun<'test, 'arg>(&'test self, val0: &'arg usize, val1: &'arg usize) -> usize
where 'arg: 'test
{
*val0 + *val1
}
}
trait ClosureFn
{
fn call<'myself, 'arg>(&'myself self, v0: &'arg usize, v1: &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'myself>>
where 'arg: 'myself;
}
#[derive(new)]
struct Closure
{
test: Test
}
impl ClosureFn for Closure
{
fn call<'myself, 'arg>(&'myself self, v0: &'arg usize, v1: &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'myself>>
where 'arg: 'myself
{
Box::pin(async
{
self.test.fun(v0, v1).await
})
}
}
#[tokio::main(flavor = "current_thread")]
async fn main()
{
let test = Test::new();
let boxed: Box<dyn ClosureFn> = Box::new(Closure::new(test));
let v0 = 10;
let v1 = 20;
let ret = boxed.call(&v0, &v1).await;
println!("{ret}");
}

不幸的是,你需要创建一个'Closure'结构,并通过'call'调用这个函数。

我错过了async函数的移动,我被编译器的错误信息弄糊涂了:

use std::future::Future;
use std::pin::Pin;
fn constrain<Fun>(fun: Fun) -> Fun
where
Fun: for<'arg> Fn(&'arg usize, &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'arg>>,
{
fun
}
#[derive(Clone)]
struct Test {}
impl Test
{
pub async fn fun<'test, 'arg>(&'test self, val0: &'arg usize, val1: &'arg usize) -> usize
where
'arg: 'test,
{
*val0 + *val1
}
}
pub async fn fun<'arg>(val0: &'arg usize, val1: &'arg usize) -> usize {
val0 + val1
}
#[tokio::main(flavor = "current_thread")]
async fn main()
{
let test = Test{};
let boxed = Box::new(constrain(move |v0, v1|
{
let test = test.clone();
let ret = Box::pin(async move
{
test.fun(v0, v1).await
//fun(v0, v1).await
});
ret
}));
let v0 = 10;
let v1 = 20;
let ret = boxed(&v0, &v1).await;
println!("{ret}");
}

我在这里找到了解决方案,它也发生在别人身上:https://users.rust-lang.org/t/lifetimes-issue-while-storing-rust-async-closure-functions-for-later-invocation/52232/2

最新更新