Replace field of borrowed struct using its old value

Hello,

If I have a borrowed struct, how can I replace a field with a new value that is created while consuming the old one? For example:

struct A {}

struct B {
    a: A
}

impl A {
    fn updated(self) -> A { self }
}

impl B {
    fn update(&mut self) {
        self.a = self.a.updated();
    }
}

This complains:

   |
13 |         self.a = self.a.updated();
   |                  ^^^^^^ --------- `self.a` moved due to this method call
   |                  |
   |                  move occurs because `self.a` has type `experiment::A`, which does not implement the `Copy` trait
   |
note: this function takes ownership of the receiver `self`, which moves `self.a`
  --> src/experiment.rs:8:16
   |
8  |     fn updated(self) -> A { self }
   |                ^^^^

How can I implement this? Thanks!

Best, Oliver

The problem is that a is left in a de-initialized state for the duration of the call to updated, and this could be observed if updated panics.

You have a few options:

  • Replace a with some temporary, e.g. default, value
  • Use Option<A> or some other type that has an explicit "uninitialized" state
  • Use replace_with or similar to abort should a panic happen in A::updated

Thanks for the detailed explanation! I was hoping there is something in the standard library. I restructured my code to avoid the issue, but I'll keep the option in mind for the future. Thanks!