0

I have a enum, which may contains a vector. And I implement a method for the enum, which can generator a new enum which reuse the same vector in previous enum (I don't want to copy the vector). After generated the new enum, I won't use the previous enum anymore, so I implement this method as fn (self) which would get enum's ownership.

Then I put enum in a structure, I want to replace the enum in the structure by using the enum's method I just implemented. But I got this error:

error[E0507]: cannot move out of borrowed content
  --> src/lib.rs:22:18
   |
22 |         self.0 = self.0.get_a_new_foo();
   |                  ^^^^^^ cannot move out of borrowed content

Is there any way to fix my code?

enum Foo {
    A,
    B(Vec<u32>),
}

impl Foo {
    fn get_a_new_foo(self) -> Foo {
        match self {
            Foo::A => Foo::B(vec![]),
            Foo::B(mut v) => {
                let len = v.len() as u32;
                v.push(len - 1);
                Foo::B(v)
            }
        }
    }
}

struct Bar(Foo);
impl Bar {
    fn replace_foo(&mut self) -> () {
        self.0 = self.0.get_a_new_foo();
    }
}
hellow
  • 12,430
  • 7
  • 56
  • 79
hronro
  • 1,157
  • 1
  • 8
  • 11
  • 1
    Please always include the **full** error message, because as you can see, the problem is not in the `get_a_new_foo` function, but in your `replace_foo` function. – hellow Jul 04 '19 at 08:02

1 Answers1

2

You can use the take_mut crate to do that elegantly:

struct Bar(Foo);
impl Bar {
    fn replace_foo(&mut self) -> () {
        take_mut::take(&mut self.0, |foo| foo.get_a_new_foo());
    }
}

Alternatively without additional dependencies you can do this:

struct Bar(Foo);
impl Bar {
    fn replace_foo(&mut self) -> () {
        let mut tmp = Foo::A;
        std::mem::swap(&mut tmp, &mut self.0);
        tmp = tmp.get_a_new_foo();
        std::mem::swap(&mut tmp, &mut self.0);
    }
}

But it works only if you can cheaply build some "placeholder" variant of Foo, like Foo::A in this case.

michalsrb
  • 4,703
  • 1
  • 18
  • 35