在解构一对盒子时附带移动错误

时间:2015-02-11 23:47:11

标签: rust

以下两行:

let x = Box::new(("slefj".to_string(), "a".to_string()));
let (a, b) = *x;

产生错误:

error[E0382]: use of moved value: `x`
 --> src/main.rs:3:13
  |
3 |     let (a, b) = *x;
  |          -  ^ value used here after move
  |          |
  |          value moved here
  |
  = note: move occurs because `x.0` has type `std::string::String`, which does not implement the `Copy` trait

有趣的是,如果我使用包含多个部分的枚举类型执行此操作,我会得到一个稍微不同的错误:

enum Tree {
    Nil,
    Pair(Box<Tree>, Box<Tree>),
}

fn main() {
    let x = Box::new(Tree::Nil);

    match *x {
        Tree::Pair(a, b) => Tree::Pair(a, b),
        _ => Tree::Nil,
    };
}

我收到错误:

error[E0382]: use of collaterally moved value: `(x:Tree::Pair).1`
  --> src/main.rs:10:23
   |
10 |         Tree::Pair(a, b) => Tree::Pair(a, b),
   |                    -  ^ value used here after move
   |                    |
   |                    value moved here
   |
   = note: move occurs because `(x:Tree::Pair).0` has type `std::boxed::Box<Tree>`, which does not implement the `Copy` trait

为什么会发生这种情况,如何使用let / match轻松破坏结构并获得内部部分的所有权?我知道我可以取消引用并首先命名结构,但如果我将模式匹配深入到结构中,那就会变得非常冗长。

2 个答案:

答案 0 :(得分:6)

你偶然发现limitation on destructuring and boxes。幸运的是,解决这些问题很容易。您需要做的就是引入一个包含整个结构的新中间变量,并从中进行解构:

let x = Box::new(("slefj".to_string(), "a".to_string()));
let pair = *x;
let (a, b) = pair;

第二个例子:

let pair = *x;
match pair {
    Tree::Pair(a, b) => Tree::Pair(a, b),
    _ => Tree::Nil,
};

答案 1 :(得分:0)

好消息是,一旦默认启用non-lexical lifetimes,您的原始代码将照常工作:

#![feature(nll)]

fn main() {
    let x = Box::new(("slefj".to_string(), "a".to_string()));
    let (a, b) = *x;
}

借用检查器跟踪开箱即用功能的功能得到增强,从而可以编译代码。