Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
827 views
in Technique[技术] by (71.8m points)

rust - Collaterally moved error when deconstructing a Box of pairs

The following two lines:

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

produce the error:

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

Interestingly, if I do this with an enumeration type with multiple parts, I get a slightly different error:

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,
    };
}

I get the error:

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

Why does this happen, and how can I easily destruct structures with let/match and get ownership of the inner parts? I know I can dereference and name the structure first, but that gets horribly verbose if I'm pattern matching deep into a structure.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have stumbled on a limitation on destructuring and boxes. Luckily, it's easy to work around these. All you need to do is introduce a new intermediary variable that contains the whole structure, and destructure from that:

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

The second example:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...