Why doesn't the compiler allow this?

use std::rc::Rc;

struct A {
    a: Rc<Vec<u8>>,
    b: B
}

impl A {
    fn new() -> Self {
        let a = Rc::new(vec![1,2,3]);
        Self {
            a,
            b: B::new(a.clone())
        }
    }
}

struct B {
    a: Rc<Vec<u8>>
}

impl B {
    fn new(a: Rc<Vec<u8>>) -> Self {
        Self {
            a
        }
    }
}

/* This would work 

impl A {
    fn new() -> Self {
        let a = Rc::new(vec![1,2,3]);
        let b = a.clone();
        Self {
            a,
            b: B::new(b)
        }
    }
}
*/

fn main() {
    let _a = A::new();
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of moved value: `a`
  --> src/main.rs:13:23
   |
10 |         let a = Rc::new(vec![1,2,3]);
   |             - move occurs because `a` has type `std::rc::Rc<std::vec::Vec<u8>>`, which does not implement the `Copy` trait
11 |         Self {
12 |             a,
   |             - value moved here
13 |             b: B::new(a.clone())
   |                       ^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

The fields are initialized in the order in which they appear in your code. That is, first the variable a is moved to initialized the field a and then the initialization code for b can no longer refer to that value as the variable a has been moved from (and you can't refer to the just initialized field). However, you can simply swap the order of initialization so that the move occurs after it has been cloned.

impl A {
    fn new() -> Self {
        let a = Rc::new(vec![1,2,3]);
        Self {
            b: B::new(a.clone()),
            a,
        }
    }
}
2 Likes

Thank you ! I feel so dumb for asking, I just thought something was wrong with a.clone() passed as argument, but you are right in reality the value "a" get moved and then cloning is impossible!!!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.