#How do you temporary move out a value?

11 messages · Page 1 of 1 (latest)

terse mantle
#

Consider the following code:

struct NonCloneCopyableStruct; // Just a placeholder example.


pub struct TestStruct{
    a_new: NonCloneCopyableStruct,
    a_old: Option<NonCloneCopyableStruct>
}

impl TestStruct {
    pub fn new(a_new: NonCloneCopyableStruct) -> Self {
        Self { a_new , a_old: None }
    }
    
    fn update(&mut self, new: NonCloneCopyableStruct) {
        self.a_old = Some(self.a_new);
        self.a_new = new;
    }
}

fn main() {
    let mut test_struct = TestStruct::new(NonCloneCopyableStruct);
    test_struct.update(NonCloneCopyableStruct);
}

It is technically valid, even if it it temporarily invalid as seen by the borrow checker.

error[E0507]: cannot move out of `self.a_new` which is behind a mutable reference

Am I required to use unsafe here to allow for this technicality?
And if so, how?

#

I am aware I could make a_new a Option<NonCloneCopyableStruct>, and then simply use swap/take.
But that's bypassing the problem, and not a solution I am aiming for.

gilded veldt
dim hull
#

&mut references have to always be valid, so you can't temporarily move something out of them. The code above can use replace:

let old = std::mem::replace(&mut self.a_new, new);
self.a_old = Some(old);
```You can also use `unsafe` and raw pointers if this doesn't work for what you have.
gilded veldt
#

you can also assign it to old first and then mem::swap the fields

terse mantle
dim hull
#

You have to Option::insert it to get a mut ref.

#
let new = self.a_old.insert(new);
std::mem::swap(&mut self.a_new, new);
gilded veldt
#

?play ```rust
struct NonCloneCopyableStruct;

pub struct TestStruct {
a_new: NonCloneCopyableStruct,
a_old: Option<NonCloneCopyableStruct>,
}
fn main() {
let mut x = TestStruct {
a_new: NonCloneCopyableStruct,
a_old: Some(NonCloneCopyableStruct),
};
if let TestStruct {
a_new,
a_old: Some(b),
} = &mut x
{
std::mem::swap(a_new, b);
}
}

hardy sandalBOT
terse mantle
#

Got it, thanks!