mavix
mavix

Reputation: 2552

"cannot move out of borrowed content" for Vec but not u64

The following code throws an error:

struct Foo {
    a: Vec<u64>,
}

impl Foo {
    fn change_a(&mut self, new_a: Vec<u64>) {
        self.a = *choose(&self.a, &new_a);
    }
}

fn choose<'a>(x: &'a Vec<u64>, y: &'a Vec<u64>) -> &'a Vec<u64> {
    return if x > y { x } else { y };
}

fn main() {
    let mut foo = Foo { a: vec![1] };
    foo.change_a(vec![3]);
    println!("{:?}", foo.a);
}

The error is:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:7:18
  |
7 |         self.a = *choose(&self.a, &new_a);
  |                  ^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

This code works fine if I replace the Vec<u64>s with just u64s.

What is the difference?

Upvotes: 0

Views: 338

Answers (2)

Francis Gagn&#233;
Francis Gagn&#233;

Reputation: 65692

The difference is that u64 implements Copy while Vec<u64> does not. When you try to move a value of a type that implements Copy but the value being moved from cannot be moved, the compiler will not actually move it, but will copy it instead, which is why the version with u64 compiles fine.

Upvotes: 2

Emilgardis
Emilgardis

Reputation: 500

The primitive type u64 implements Copy. This means that u64 has "copy semantics": if the compiler finds that we are trying to take ownership of T: Copy but the value being moved from is still used, T will be copied.

Vec is not Copy, but it is Clone, meaning that we can do

self.a = choose(& self.a, & new_a).clone();

To fix this problem.

Here is another example of copy semantics using your example

Upvotes: 2

Related Questions