manually_drop.rs - source
Description: Source of the Rust file `library/core/src/mem/manually_drop.rs`.

#
core/mem/
manually_drop.rs

    1use crate::cmp::Ordering;
    2use crate::hash::{Hash, Hasher};
    3use crate::marker::{Destruct, StructuralPartialEq};
    4use crate::mem::MaybeDangling;
    5use crate::ops::{Deref, DerefMut, DerefPure};
    6use crate::ptr;
    7
    8/// A wrapper to inhibit the compiler from automatically calling `T`’s
    9/// destructor. This wrapper is 0-cost.
    10///
    11/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
    12/// `T`, and is subject to the same layout optimizations as `T`. As a
    13/// consequence, it has *no effect* on the assumptions that the compiler makes
    14/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` with
    15/// [`mem::zeroed`] is undefined behavior. If you need to handle uninitialized
    16/// data, use [`MaybeUninit<T>`] instead.
    17///
    18/// Note that accessing the value inside a `ManuallyDrop<T>` is safe. This means
    19/// that a `ManuallyDrop<T>` whose content has been dropped must not be exposed
    20/// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe.
    21///
    22/// # `ManuallyDrop` and drop order
    23///
    24/// Rust has a well-defined [drop order] of values. To make sure that fields or
    25/// locals are dropped in a specific order, reorder the declarations such that
    26/// the implicit drop order is the correct one.
    27///
    28/// It is possible to use `ManuallyDrop` to control the drop order, but this
    29/// requires unsafe code and is hard to do correctly in the presence of
    30/// unwinding.
    31///
    32/// For example, if you want to make sure that a specific field is dropped after
    33/// the others, make it the last field of a struct:
    34///
    35/// ```
    36/// struct Context;
    37///
    38/// struct Widget {
    39///     children: Vec<Widget>,
    40///     // `context` will be dropped after `children`.
    41///     // Rust guarantees that fields are dropped in the order of declaration.
    42///     context: Context,
    43/// }
    44/// ```
    45///
    46/// # Interaction with `Box`
    47///
    48/// Currently, if you have a `ManuallyDrop<T>`, where the type `T` is a `Box` or
    49/// contains a `Box` inside, then dropping the `T` followed by moving the
    50/// `ManuallyDrop<T>` is [considered to be undefined
    51/// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245).
    52/// That is, the following code causes undefined behavior:
    53///
    54/// ```no_run
    55/// use std::mem::ManuallyDrop;
    56///
    57/// let mut x = ManuallyDrop::new(Box::new(42));
    58/// unsafe {
    59///     ManuallyDrop::drop(&mut x);
    60/// }
    61/// let y = x; // Undefined behavior!
    62/// ```
    63///
    64/// This is [likely to change in the
    65/// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the
    66/// meantime, consider using [`MaybeUninit`] instead.
    67///
    68/// # Safety hazards when storing `ManuallyDrop` in a struct or an enum.
    69///
    70/// Special care is needed when all of the conditions below are met:
    71/// * A struct or enum contains a `ManuallyDrop`.
    72/// * The `ManuallyDrop` is not inside a `union`.
    73/// * The struct or enum is part of public API, or is stored in a struct or an
    74///   enum that is part of public API.
    75/// * There is code that drops the contents of the `ManuallyDrop` field, and
    76///   this code is outside the struct or enum's `Drop` implementation.
    77///
    78/// In particular, the following hazards may occur:
    79///
    80/// #### Storing generic types
    81///
    82/// If the `ManuallyDrop` contains a client-supplied generic type, the client
    83/// might provide a `Box` as that type. This would cause undefined behavior when
    84/// the struct or enum is later moved, as mentioned in the previous section. For
    85/// example, the following code causes undefined behavior:
    86///
    87/// ```no_run
    88/// use std::mem::ManuallyDrop;
    89///
    90/// pub struct BadOption<T> {
    91///     // Invariant: Has been dropped if `is_some` is false.
    92///     value: ManuallyDrop<T>,
    93///     is_some: bool,
    94/// }
    95/// impl<T> BadOption<T> {
    96///     pub fn new(value: T) -> Self {
    97///         Self { value: ManuallyDrop::new(value), is_some: true }
    98///     }
    99///     pub fn change_to_none(&mut self) {
    100///         if self.is_some {
    101///             self.is_some = false;
    102///             unsafe {
    103///                 // SAFETY: `value` hasn't been dropped yet, as per the invariant
    104///                 // (This is actually unsound!)
    105///                 ManuallyDrop::drop(&mut self.value);
    106///             }
    107///         }
    108///     }
    109/// }
    110///
    111/// // In another crate:
    112///
    113/// let mut option = BadOption::new(Box::new(42));
    114/// option.change_to_none();
    115/// let option2 = option; // Undefined behavior!
    116/// ```
    117///
    118/// #### Deriving traits
    119///
    120/// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on
    121/// the struct or enum could be unsound, since the derived implementations of
    122/// these traits would access the `ManuallyDrop` field. For example, the
    123/// following code causes undefined behavior:
    124///
    125/// ```no_run
    126/// use std::mem::ManuallyDrop;
    127///
    128/// // This derive is unsound in combination with the `ManuallyDrop::drop` call.
    129/// #[derive(Debug)]
    130/// pub struct Foo {
    131///     value: ManuallyDrop<String>,
    132/// }
    133/// impl Foo {
    134///     pub fn new() -> Self {
    135///         let mut temp = Self {
    136///             value: ManuallyDrop::new(String::from("Unsafe rust is hard."))
    137///         };
    138///         unsafe {
    139///             // SAFETY: `value` hasn't been dropped yet.
    140///             ManuallyDrop::drop(&mut temp.value);
    141///         }
    142///         temp
    143///     }
    144/// }
    145///
    146/// // In another crate:
    147///
    148/// let foo = Foo::new();
    149/// println!("{:?}", foo); // Undefined behavior!
    150/// ```
    151///
    152/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
    153/// [`mem::zeroed`]: crate::mem::zeroed
    154/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
    155/// [`MaybeUninit`]: crate::mem::MaybeUninit
    156#[stable(feature = "manually_drop", since = "1.20.0")]
    157#[lang = "manually_drop"]
    158#[derive(Copy, Clone, Debug, Default)]
    159#[repr(transparent)]
    160#[rustc_pub_transparent]
    161pub struct ManuallyDrop<T: ?Sized> {
    162    value: MaybeDangling<T>,
    163}
    164
    165impl<T> ManuallyDrop<T> {
    166    /// Wrap a value to be manually dropped.
    167    ///
    168    /// # Examples
    169    ///
    170    /// ```rust
    171    /// use std::mem::ManuallyDrop;
    172    /// let mut x = ManuallyDrop::new(String::from("Hello World!"));
    173    /// x.truncate(5); // You can still safely operate on the value
    174    /// assert_eq!(*x, "Hello");
    175    /// // But `Drop` will not be run here
    176    /// # // FIXME(https://github.com/rust-lang/miri/issues/3670):
    177    /// # // use -Zmiri-disable-leak-check instead of unleaking in tests meant to leak.
    178    /// # let _ = ManuallyDrop::into_inner(x);
    179    /// ```
    180    #[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
    181    #[stable(feature = "manually_drop", since = "1.20.0")]
    182    #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
    183    #[inline(always)]
    184    pub const fn new(value: T) -> ManuallyDrop<T> {
    185        ManuallyDrop { value: MaybeDangling::new(value) }
    186    }
    187
    188    /// Extracts the value from the `ManuallyDrop` container.
    189    ///
    190    /// This allows the value to be dropped again.
    191    ///
    192    /// # Examples
    193    ///
    194    /// ```rust
    195    /// use std::mem::ManuallyDrop;
    196    /// let x = ManuallyDrop::new(Box::new(()));
    197    /// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
    198    /// ```
    199    #[stable(feature = "manually_drop", since = "1.20.0")]
    200    #[rustc_const_stable(feature = "const_manually_drop", since = "1.32.0")]
    201    #[inline(always)]
    202    pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
    203        // Cannot use `MaybeDangling::into_inner` as that does not yet have the desired semantics.
    204        // SAFETY: We know this is a valid `T`. `slot` will not be dropped.
    205        unsafe { (&raw const slot).cast::<T>().read() }
    206    }
    207
    208    /// Takes the value from the `ManuallyDrop<T>` container out.
    209    ///
    210    /// This method is primarily intended for moving out values in drop.
    211    /// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
    212    /// you can use this method to take the value and use it however desired.
    213    ///
    214    /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
    215    /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
    216    ///
    217    /// # Safety
    218    ///
    219    /// This function semantically moves out the contained value without preventing further usage,
    220    /// leaving the state of this container unchanged.
    221    /// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
    222    ///
    223    #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
    224    #[stable(feature = "manually_drop_take", since = "1.42.0")]
    225    #[rustc_const_unstable(feature = "const_manually_drop_take", issue = "148773")]
    226    #[inline]
    227    pub const unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
    228        // SAFETY: we are reading from a reference, which is guaranteed
    229        // to be valid for reads.
    230        unsafe { ptr::read(slot.value.as_ref()) }
    231    }
    232}
    233
    234impl<T: ?Sized> ManuallyDrop<T> {
    235    /// Manually drops the contained value.
    236    ///
    237    /// This is exactly equivalent to calling [`ptr::drop_in_place`] with a
    238    /// pointer to the contained value. As such, unless the contained value is a
    239    /// packed struct, the destructor will be called in-place without moving the
    240    /// value, and thus can be used to safely drop [pinned] data.
    241    ///
    242    /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
    243    ///
    244    /// # Safety
    245    ///
    246    /// This function runs the destructor of the contained value. Other than changes made by
    247    /// the destructor itself, the memory is left unchanged, and so as far as the compiler is
    248    /// concerned still holds a bit-pattern which is valid for the type `T`.
    249    ///
    250    /// However, this "zombie" value should not be exposed to safe code, and this function
    251    /// should not be called more than once. To use a value after it's been dropped, or drop
    252    /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does).
    253    /// This is normally prevented by the type system, but users of `ManuallyDrop` must
    254    /// uphold those guarantees without assistance from the compiler.
    255    ///
    256    /// [pinned]: crate::pin
    257    #[stable(feature = "manually_drop", since = "1.20.0")]
    258    #[inline]
    259    #[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
    260    pub const unsafe fn drop(slot: &mut ManuallyDrop<T>)
    261    where
    262        T: [const] Destruct,
    263    {
    264        // SAFETY: we are dropping the value pointed to by a mutable reference
    265        // which is guaranteed to be valid for writes.
    266        // It is up to the caller to make sure that `slot` isn't dropped again.
    267        unsafe { ptr::drop_in_place(slot.value.as_mut()) }
    268    }
    269}
    270
    271#[stable(feature = "manually_drop", since = "1.20.0")]
    272#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    273impl<T: ?Sized> const Deref for ManuallyDrop<T> {
    274    type Target = T;
    275    #[inline(always)]
    276    fn deref(&self) -> &T {
    277        self.value.as_ref()
    278    }
    279}
    280
    281#[stable(feature = "manually_drop", since = "1.20.0")]
    282#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    283impl<T: ?Sized> const DerefMut for ManuallyDrop<T> {
    284    #[inline(always)]
    285    fn deref_mut(&mut self) -> &mut T {
    286        self.value.as_mut()
    287    }
    288}
    289
    290#[unstable(feature = "deref_pure_trait", issue = "87121")]
    291unsafe impl<T: ?Sized> DerefPure for ManuallyDrop<T> {}
    292
    293#[stable(feature = "manually_drop", since = "1.20.0")]
    294impl<T: ?Sized + Eq> Eq for ManuallyDrop<T> {}
    295
    296#[stable(feature = "manually_drop", since = "1.20.0")]
    297impl<T: ?Sized + PartialEq> PartialEq for ManuallyDrop<T> {
    298    fn eq(&self, other: &Self) -> bool {
    299        self.value.as_ref().eq(other.value.as_ref())
    300    }
    301}
    302
    303#[stable(feature = "manually_drop", since = "1.20.0")]
    304impl<T: ?Sized> StructuralPartialEq for ManuallyDrop<T> {}
    305
    306#[stable(feature = "manually_drop", since = "1.20.0")]
    307impl<T: ?Sized + Ord> Ord for ManuallyDrop<T> {
    308    fn cmp(&self, other: &Self) -> Ordering {
    309        self.value.as_ref().cmp(other.value.as_ref())
    310    }
    311}
    312
    313#[stable(feature = "manually_drop", since = "1.20.0")]
    314impl<T: ?Sized + PartialOrd> PartialOrd for ManuallyDrop<T> {
    315    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    316        self.value.as_ref().partial_cmp(other.value.as_ref())
    317    }
    318}
    319
    320#[stable(feature = "manually_drop", since = "1.20.0")]
    321impl<T: ?Sized + Hash> Hash for ManuallyDrop<T> {
    322    fn hash<H: Hasher>(&self, state: &mut H) {
    323        self.value.as_ref().hash(state);
    324    }
    325}