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

#
core/mem/
drop_guard.rs

    1use crate::fmt::{self, Debug};
    2use crate::marker::Destruct;
    3use crate::mem::ManuallyDrop;
    4use crate::ops::{Deref, DerefMut};
    5
    6/// Wrap a value and run a closure when dropped.
    7///
    8/// This is useful for quickly creating destructors inline.
    9///
    10/// # Examples
    11///
    12/// ```rust
    13/// # #![allow(unused)]
    14/// #![feature(drop_guard)]
    15///
    16/// use std::mem::DropGuard;
    17///
    18/// {
    19///     // Create a new guard around a string that will
    20///     // print its value when dropped.
    21///     let s = String::from("Chashu likes tuna");
    22///     let mut s = DropGuard::new(s, |s| println!("{s}"));
    23///
    24///     // Modify the string contained in the guard.
    25///     s.push_str("!!!");
    26///
    27///     // The guard will be dropped here, printing:
    28///     // "Chashu likes tuna!!!"
    29/// }
    30/// ```
    31#[unstable(feature = "drop_guard", issue = "144426")]
    32#[doc(alias = "ScopeGuard")]
    33#[doc(alias = "defer")]
    34pub struct DropGuard<T, F>
    35where
    36    F: FnOnce(T),
    37{
    38    inner: ManuallyDrop<T>,
    39    f: ManuallyDrop<F>,
    40}
    41
    42impl<T, F> DropGuard<T, F>
    43where
    44    F: FnOnce(T),
    45{
    46    /// Create a new instance of `DropGuard`.
    47    ///
    48    /// # Example
    49    ///
    50    /// ```rust
    51    /// # #![allow(unused)]
    52    /// #![feature(drop_guard)]
    53    ///
    54    /// use std::mem::DropGuard;
    55    ///
    56    /// let value = String::from("Chashu likes tuna");
    57    /// let guard = DropGuard::new(value, |s| println!("{s}"));
    58    /// ```
    59    #[unstable(feature = "drop_guard", issue = "144426")]
    60    #[must_use]
    61    pub const fn new(inner: T, f: F) -> Self {
    62        Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) }
    63    }
    64
    65    /// Consumes the `DropGuard`, returning the wrapped value.
    66    ///
    67    /// This will not execute the closure. It is typically preferred to call
    68    /// this function instead of `mem::forget` because it will return the stored
    69    /// value and drop variables captured by the closure instead of leaking their
    70    /// owned resources.
    71    ///
    72    /// # Example
    73    ///
    74    /// ```rust
    75    /// # #![allow(unused)]
    76    /// #![feature(drop_guard)]
    77    ///
    78    /// use std::mem::DropGuard;
    79    ///
    80    /// let value = String::from("Nori likes chicken");
    81    /// let guard = DropGuard::new(value, |s| println!("{s}"));
    82    /// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken");
    83    /// ```
    84    #[unstable(feature = "drop_guard", issue = "144426")]
    85    #[rustc_const_unstable(feature = "const_drop_guard", issue = "none")]
    86    #[inline]
    87    pub const fn dismiss(guard: Self) -> T
    88    where
    89        F: [const] Destruct,
    90    {
    91        // First we ensure that dropping the guard will not trigger
    92        // its destructor
    93        let mut guard = ManuallyDrop::new(guard);
    94
    95        // Next we manually read the stored value from the guard.
    96        //
    97        // SAFETY: this is safe because we've taken ownership of the guard.
    98        let value = unsafe { ManuallyDrop::take(&mut guard.inner) };
    99
    100        // Finally we drop the stored closure. We do this *after* having read
    101        // the value, so that even if the closure's `drop` function panics,
    102        // unwinding still tries to drop the value.
    103        //
    104        // SAFETY: this is safe because we've taken ownership of the guard.
    105        unsafe { ManuallyDrop::drop(&mut guard.f) };
    106        value
    107    }
    108}
    109
    110#[unstable(feature = "drop_guard", issue = "144426")]
    111#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    112impl<T, F> const Deref for DropGuard<T, F>
    113where
    114    F: FnOnce(T),
    115{
    116    type Target = T;
    117
    118    fn deref(&self) -> &T {
    119        &*self.inner
    120    }
    121}
    122
    123#[unstable(feature = "drop_guard", issue = "144426")]
    124#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    125impl<T, F> const DerefMut for DropGuard<T, F>
    126where
    127    F: FnOnce(T),
    128{
    129    fn deref_mut(&mut self) -> &mut T {
    130        &mut *self.inner
    131    }
    132}
    133
    134#[unstable(feature = "drop_guard", issue = "144426")]
    135#[rustc_const_unstable(feature = "const_drop_guard", issue = "none")]
    136impl<T, F> const Drop for DropGuard<T, F>
    137where
    138    F: [const] FnOnce(T),
    139{
    140    fn drop(&mut self) {
    141        // SAFETY: `DropGuard` is in the process of being dropped.
    142        let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
    143
    144        // SAFETY: `DropGuard` is in the process of being dropped.
    145        let f = unsafe { ManuallyDrop::take(&mut self.f) };
    146
    147        f(inner);
    148    }
    149}
    150
    151#[unstable(feature = "drop_guard", issue = "144426")]
    152impl<T, F> Debug for DropGuard<T, F>
    153where
    154    T: Debug,
    155    F: FnOnce(T),
    156{
    157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    158        fmt::Debug::fmt(&**self, f)
    159    }
    160}