想在闭包参数里传可变借用,需要如何解决生命周期问题?
rustc 1.65.0
296 | do_demo(|demo| async move {
| ______________-----_^
| | | |
| | | return type of closure `impl Future<Output = String>` contains a lifetime `'2`
| | has type `&'1 mut Demo`
297 | | println!("demo: {:?}", demo);
298 | | demo.print_mut();
299 | | format!("test demo, id: {}", demo.id)
300 | | })
| |_____^ returning this value requires that `'1` must outlive `'2`
use std::future::Future;
#[derive(Debug)]
struct Demo {
id: i32,
name: String,
}
impl Demo {
fn print(self) {
println!("id:{}, name:{:?}", self.id, self.name);
}
fn print_mut(&mut self) {
println!("id:{}, name:{:?}", self.id, self.name);
}
}
async fn do_demo<F, U>(mut f: F) -> Result<(), String>
where
F: for<'a> FnMut(&'a Demo) -> U,
U: Future<Output = String>,
{
let demo = Demo {
id: 1,
name: "test".to_string(),
};
let ret = f(&demo).await;
demo.print();
println!("f() ret: {:?}", ret);
Ok(())
}
#[tokio::test]
async fn demo() {
do_demo(|demo| async move {
println!("demo: {:?}", demo);
demo.print_mut();
format!("test demo, id: {}", demo.id)
})
.await
.unwrap();
}
在rust playground中你的代码并不会报错的;感觉是tokio::test 并不会被rust playground 识别, 然后我添加了 tokio::mian.......
其实我也郁闷为什么会有这样的错误,
因为在de_demo 中 f(&demo).await 完成后demo 并没有drop
当看到这样的提示:returning this value requires that
'1
must outlive'2
;又看到demo和f(&demo)都在de_demo里面; 我的想法是把 demo 放到do_demo函数的外面试试当然也可以这样,就是把demo移到闭包中:
其他失败的尝试: 给demo 添加static 生命周期; 因为让static告诉编译器demo这个参数的生命周期你要有多长就有多长请放心使用,可是失败了
有时候遇到问题就采用迂回战术(换一种写法)满足功能的同时也能通过编译;可有时候怎么能甘心尼。。。。
其他
对 F:for<'a> FnMut(&'a Demo) -> U 这种生命周期标注很好奇;删除for<'a> 得到的下面的提示就释然了
unsafe block