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!

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.