我有一个简单的(我认为应该是)任务将map
的值包含在一个Vec
中并产生另一个Vec
:
# [derive(Clone)]
struct Value(u32);
# [derive(Clone)]
struct Id(u32);
struct ValuesInfo {
values: Vec<Value>,
name: String,
id: Id
}
struct ValueInfo{
value: Value,
name: String,
id: Id
}
fn extend_values(v: Vec<ValuesInfo>) -> Vec<Vec<ValueInfo>> {
v.into_iter().map(|values_info|{
values_info.values.into_iter().map(|value|{
ValueInfo{
value,
name: values_info.name.clone(),
id: values_info.id.clone()
}
}).collect::<Vec<ValueInfo>>()
}).collect::<Vec<Vec<ValueInfo>>>()
}
Playground permalink
这里有一个部分移动错误,看起来像
Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of moved value: `values_info`
--> src/lib.rs:20:44
|
20 | values_info.values.into_iter().map(|value|{
| ----------- ^^^^^^^ value borrowed here after partial move
| |
| `values_info.values` moved due to this method call
...
23 | name: values_info.name.clone(),
| ----------- borrow occurs due to use in closure
|
note: this function consumes the receiver `self` by taking ownership of it, which moves `values_info.values`
= note: move occurs because `values_info.values` has type `std::vec::Vec<Value>`, which does not implement the `Copy` trait
error: aborting due to previous error
我需要这个部分move
,因为这就是任务的内容。有解决这个错误的方法吗?
3条答案
按热度按时间lb3vh1jj1#
在2018版的Rust中,闭包总是通过变量名来捕获整个变量,所以传递给内部
map
的闭包将引用values_info
,这是无效的,因为values_info
已经被部分移动了(即使闭包不需要访问被移动的部分)。rust 色2021+
自Rust 2021以来,只捕获闭包主体中所需的最小字段集。这使得原始代码能够按预期工作¹,因此您可以通过简单的changing the playground edition to 2021来消除错误。更多信息请参见edition guide。
2015年和2018年生 rust
在以前的版本中,您可以手动执行此操作:首先反构
ValuesInfo
*,只捕获闭包内部的name
和id
。一旦得到ValuesInfo
,就可以在外部闭包的参数列表中反构它:另请参阅
¹除非
ValuesInfo
实现了Drop
,这使得任何解构或部分移动都不健全。tpgth1q72#
在闭包中命名
values_info
将借用它作为一个整体,尽管它已经被部分移动了(正如错误消息所告诉的)。xuo3flqw3#
也就是说,如果你真的不想复制/克隆
Value
,你需要事先输入clone
name和id
。编译器会阻止你使用values_info.name.clone()
,因为函数into_iter
已经使用了values_info
。如果你真的不想复制Value
,代码看起来应该是这样的