Recently, I wrote the following:
use std::ptr;
fn modify_mut_ret<T,R,F> (ptr: &mut T, f: F) -> R
where F: FnOnce(T) -> (T,R)
{
unsafe {
let (t,r) = f(ptr::read(ptr));
ptr::write(ptr,t);
r
}
}
This is a simple utility, so I expected it was in the standard library, but I couldn't find it (at least in std::mem). If we assume, for example, T: Default, we can safely implement this with an extra drop overhead:
use std::mem;
#[inline]
fn modify_mut_ret<T,R,F>(ptr: &mut T, f: F) -> R
where F: FnOnce(T) -> (T,R),
T: Default
{
let mut t = T::default();
mem::swap(ptr, &mut t);
let (t,r) = f(t);
*ptr = t;
r
}
I don't think the first implementation contains any undefined behavior: we have no alignment issue, and we, with ptr::write, eliminate one of the two ownerships duplicated with ptr::read. However I'm anxious about the fact that std seemingly doesn't contain a function with this behavior. Have I got anything wrong or have I forgot something? Does the unsafe code above contain any UB?