use core::intrinsics; use core::mem; use core::ptr; /// This replaces the value behind the `v` unique reference by calling the /// relevant function. /// /// If a panic occurs in the `change` closure, the entire process will be aborted. #[allow(dead_code)] // keep as illustration and for future use #[inline] pub fn take_mut(v: &mut T, change: impl FnOnce(T) -> T) { replace(v, |value| (change(value), ())) } /// This replaces the value behind the `v` unique reference by calling the /// relevant function, and returns a result obtained along the way. /// /// If a panic occurs in the `change` closure, the entire process will be aborted. #[inline] pub fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { struct PanicGuard; impl Drop for PanicGuard { fn drop(&mut self) { intrinsics::abort() } } let guard = PanicGuard; let value = unsafe { ptr::read(v) }; let (new_value, ret) = change(value); unsafe { ptr::write(v, new_value); } mem::forget(guard); ret }