在递归枚举上使用附带移动的值错误
Use of collaterally moved value error on a recursive enum
我有一个用于实现列表的递归 Item
结构:
#[derive(Debug)]
pub enum Item<T> {
Cons(T, Box<Item<T>>),
Nil,
}
在实现一个元素接一个元素插入的函数时,我发现 Rust 编译器对我的代码不太满意:
pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
match *it {
Item::Nil => return it,
Item::Cons(a, b) => {
let itm = Box::new(Item::Cons(val, b));
return Box::new(Item::Cons(a, itm));
}
}
}
我得到的错误对于新手来说是相当模糊的:
error[E0382]: use of collaterally moved value: `(it as Item::Cons).1`
--> src/main.rs:12:23
|
12 | Item::Cons(a, b) => {
| - ^ value used here after move
| |
| value moved here
|
= note: move occurs because the value has type `T`, which does not implement the `Copy` trait
Another similar question 建议分两步进行解包阶段,但不能在这里使用,因为我们需要直接解包一个双字段 Cons(..)
项目而不是像 [=17= 这样的嵌套项目] 可以应用两阶段技巧的地方。我尝试过的例子:
pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
match *it {
Item::Nil => return it,
Item::Cons(..) => {
let Item::Cons(a, b) = *it;
let itm = Box::new(Item::Cons(val, b));
return Box::new(Item::Cons(a, itm));
}
}
}
但是我得到另一个错误:
error[E0005]: refutable pattern in local binding: `Nil` not covered
--> src/main.rs:13:17
|
13 | let Item::Cons(a, b) = *it;
| ^^^^^^^^^^^^^^^^ pattern `Nil` not covered
虽然我很确定这在这一点上是详尽无遗的,因为我们之前匹配了一个Cons
。
您可能正在遭受 issue 16223 (see also 22205 的困扰,它具有更接近的再现),尽管今天的非词汇生命周期并没有解决这个问题。这似乎排除了通过 Box
解构多个事物。
这是一种解决它的方法,虽然它不是最有效的方法,因为它会不必要地解除分配和重新分配:
#[derive(Debug)]
pub enum Item<T> {
Cons(T, Box<Item<T>>),
Nil,
}
pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
match { *it } {
Item::Nil => Box::new(Item::Nil),
Item::Cons(a, b) => {
let itm = Box::new(Item::Cons(val, b));
Box::new(Item::Cons(a, itm))
}
}
}
fn main() {}
更详细的方法是从 Box
中提取值,操纵 that,然后将操纵的值放回 Box
。这应该减少分配量:
use std::mem;
pub fn add_after<T>(mut item: Box<Item<T>>, val: T) -> Box<Item<T>> {
let unboxed_value = mem::replace(&mut *item, Item::Nil);
match unboxed_value {
Item::Nil => item,
Item::Cons(a, b) => {
let itm = Box::new(Item::Cons(val, b));
*item = Item::Cons(a, itm);
item
}
}
}
另请参阅:
- Collaterally moved error when deconstructing a Box of pairs
我有一个用于实现列表的递归 Item
结构:
#[derive(Debug)]
pub enum Item<T> {
Cons(T, Box<Item<T>>),
Nil,
}
在实现一个元素接一个元素插入的函数时,我发现 Rust 编译器对我的代码不太满意:
pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
match *it {
Item::Nil => return it,
Item::Cons(a, b) => {
let itm = Box::new(Item::Cons(val, b));
return Box::new(Item::Cons(a, itm));
}
}
}
我得到的错误对于新手来说是相当模糊的:
error[E0382]: use of collaterally moved value: `(it as Item::Cons).1`
--> src/main.rs:12:23
|
12 | Item::Cons(a, b) => {
| - ^ value used here after move
| |
| value moved here
|
= note: move occurs because the value has type `T`, which does not implement the `Copy` trait
Another similar question 建议分两步进行解包阶段,但不能在这里使用,因为我们需要直接解包一个双字段 Cons(..)
项目而不是像 [=17= 这样的嵌套项目] 可以应用两阶段技巧的地方。我尝试过的例子:
pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
match *it {
Item::Nil => return it,
Item::Cons(..) => {
let Item::Cons(a, b) = *it;
let itm = Box::new(Item::Cons(val, b));
return Box::new(Item::Cons(a, itm));
}
}
}
但是我得到另一个错误:
error[E0005]: refutable pattern in local binding: `Nil` not covered
--> src/main.rs:13:17
|
13 | let Item::Cons(a, b) = *it;
| ^^^^^^^^^^^^^^^^ pattern `Nil` not covered
虽然我很确定这在这一点上是详尽无遗的,因为我们之前匹配了一个Cons
。
您可能正在遭受 issue 16223 (see also 22205 的困扰,它具有更接近的再现),尽管今天的非词汇生命周期并没有解决这个问题。这似乎排除了通过 Box
解构多个事物。
这是一种解决它的方法,虽然它不是最有效的方法,因为它会不必要地解除分配和重新分配:
#[derive(Debug)]
pub enum Item<T> {
Cons(T, Box<Item<T>>),
Nil,
}
pub fn add_after<T>(it: Box<Item<T>>, val: T) -> Box<Item<T>> {
match { *it } {
Item::Nil => Box::new(Item::Nil),
Item::Cons(a, b) => {
let itm = Box::new(Item::Cons(val, b));
Box::new(Item::Cons(a, itm))
}
}
}
fn main() {}
更详细的方法是从 Box
中提取值,操纵 that,然后将操纵的值放回 Box
。这应该减少分配量:
use std::mem;
pub fn add_after<T>(mut item: Box<Item<T>>, val: T) -> Box<Item<T>> {
let unboxed_value = mem::replace(&mut *item, Item::Nil);
match unboxed_value {
Item::Nil => item,
Item::Cons(a, b) => {
let itm = Box::new(Item::Cons(val, b));
*item = Item::Cons(a, itm);
item
}
}
}
另请参阅:
- Collaterally moved error when deconstructing a Box of pairs