mini-RFC: ManuallyDrop::take


#1

Prompted by all of the Drop discussion, and quoting @scottmcm’s implementation.

If there aren’t any objections, suggestions, or corrections, I’ll probably open a PR with this. It seems like a small but useful addition. I’m primarily interested in suggestions for wording of the docs.

impl<T> ManuallyDrop<T> {
    
    /// Take the contained value out.
    ///
    /// This method is primarily intended for moving out values in drop.
    /// Instead of using `ManuallyDrop::drop` to manually drop the value,
    /// you can use this method to take the value and use it however desired.
    /// `Drop` will be invoked normally at end of scope, as with all other owned values.
    ///
    /// If you have ownership of the value, you can use `ManuallyDrop::into_inner` instead.
    ///
    /// # Safety
    ///
    /// This function semantically moves out the contained value without preventing further usage.
    /// It is up to the user of this method to ensure that this container is not used again.
    pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
        ManuallyDrop::into_inner(ptr::read(slot))
    }
}

#2

Is it necessory to add a ManuallyDrop::drop() call?

impl<T> ManuallyDrop<T> {
    
    /// Take the contained value out.
    ///
    /// This method is primarily intended for moving out values in drop.
    /// Instead of using `ManuallyDrop::drop` to manually drop the value,
    /// you can use this method to take the value and use it however desired.
    /// `Drop` will be invoked normally at end of scope, as with all other owned values.
    ///
    /// If you have ownership of the value, you can use `ManuallyDrop::into_inner` instead.
    ///
    /// # Safety
    ///
    /// This function semantically moves out the contained value without preventing further usage.
    /// It is up to the user of this method to ensure that this container is not used again.
    pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
        let r = ManuallyDrop::into_inner(ptr::read(slot))
        ManuallyDrop::drop(slot);
        r
    }
}

#3

No? Why would it be? (It would be unsound to include?)

The whole point is to take the value out of the ManuallyDrop, without dropping it, so that the caller can have the value and do whatever with it (which will (probably) include dropping it at some point in the future). The version left behind in slot is effectively uninitialized memory at this point.


#4

Looks good! One minor idea: add the following to it:

#[must_use = "if you don't need the value, you can `ManuallyDrop::drop` instead"]

#5

PR posted: https://github.com/rust-lang/rust/pull/55421