I want to do something like
impl Widget {
fn foo(self, rhs: Widget) -> Self {
// Some stuff
}
fn update(&mut self, rhs: Widget) {
*self = (*self).foo(rhs)
}
}
but the compiler complains "cannot move out of borrowed context." What's the right way to do this?
One option is to use the take_mut
crate, which offers the take
functions that do exactly what you want:
take
allows for takingT
out of a&mut T
, doing anything with it including consuming it, and producing anotherT
to put back in the&mut T
.
As pointed by Francis Gagné, the problem of doing this is that the &mut
reference will be in a invalid state if a panic happens, and this can lead to undefined behavior. The take_mut
approach is:
During
take
, if a panic occurs, the entire process will be exited, as there's no validT
to put back into the&mut T
.
Here is the code using take
:
extern crate take_mut;
struct Widget;
impl Widget {
fn foo(self, rhs: Widget) -> Self {
self
}
fn update(&mut self, rhs: Widget) {
take_mut::take(self, |s| s.foo(rhs));
}
}