我有以下 Rust 代码
use std::error::Error;
#[derive(Debug)]
enum MyEnum {
First,
Second,
}
fn do_something(index: usize, m: &MyEnum) {
eprintln!("do_something: {} {:?}", index, m);
}
async fn test() -> Result<(), Box<dyn Error>> {
let myvec = vec![MyEnum::First, MyEnum::Second];
let c = String::from("cap");
let futures = myvec.iter().enumerate().map(|(index, el)| async {
eprintln!("Element: {}", &c);
do_something(index, el);
});
futures::future::join_all(futures).await;
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
test().await?;
Ok(())
}
编译器抱怨:
error[E0373]: async block may outlive the current function, but it borrows `index`, which is owned by the current function
--> src/main.rs:17:62
|
17 | let futures = myvec.iter().enumerate().map(|(index, el)| async {
| ^^^^^ may outlive borrowed value `index`
18 | eprintln!("Element: {}", &c);
19 | do_something(index, el);
| ----- `index` is borrowed here
|
为什么它没有抱怨变量el
?
如何修复此代码?我想继续使用迭代器而不是for
循环。我可以更改代码的其他部分,例如do_something()
可以有不同的原型。
我把c
变量放在这里是为了禁止使用 的简单解决方案async move {...}
。字符串c
不应该被移动。
没有enumerate()
(和没有index
) 也可以工作。我期望index
(具有usize
类型) 可以轻松复制。
这正是问题所在,因为
usize
是复制,所以要移动,编译器只需要捕获共享引用,当需要值时,它只需&
复制字节即可。首先,它会使用最弱的捕获类型,&mut
然后,只有当这些都不起作用时,它才会移动。问题在于,它是闭包
index
的一个局部,当它返回未来时,它就消失了。el
不存在同样的问题,因为它是对myvec
所拥有的外部的引用test
,它确实存在足够长的时间,因此对它的任何引用也可以存在足够长的时间。要修复它你只需要应用你自己发现的“简单解决方案”,任何你不想移动的捕获你可以简单地用所需的绑定类型(或)遮蔽1 :
&
&mut
1当然您不必对其进行隐藏,但隐藏可以让您不必担心新名称,并且在这里非常符合惯用做法。