Sound inplace owned update function

Problem

// this code is not allowed
self.data = self.data;

// case where an owned value is required, because data is not clone (or copy)
self.data = match self.data {
    Data::One(v) => v.transform_into_two(),
    Data::Two(v) => v.transform_into_one(),
}; 

Solution?

fn update_value<T>(value: &mut T, update: impl FnOnce(T) -> T) {
    unsafe {
        let v = std::ptr::read(value);
        let v = update(v);
        std::ptr::write(value, v);
    }
}

update_value(&mut self.data ,|data| match data {
    Data::One(v) => v.transform_into_two(),
    Data::Two(v) => v.transform_into_one(),
});

Questions

  1. Is this sound?
  2. Is there a standard library function to solve the problem?

It is sound only if update never panics, since Rust type system can't constraint that, the function as-is is not sound.

No. But you can look into replace_with.

2 Likes

Thanks for the quick answer.

There is a safe version of your ptr::read/write solution:

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.