use crate::fmt::{self, Debug}; use crate::mem::ManuallyDrop; use crate::ops::{Deref, DerefMut}; /// Wrap a value and run a closure when dropped. /// /// This is useful for quickly creating destructors inline. /// /// # Examples /// /// ```rust /// # #![allow(unused)] /// #![feature(drop_guard)] /// /// use std::mem::DropGuard; /// /// { /// // Create a new guard around a string that will /// // print its value when dropped. /// let s = String::from("Chashu likes tuna"); /// let mut s = DropGuard::new(s, |s| println!("{s}")); /// /// // Modify the string contained in the guard. /// s.push_str("!!!"); /// /// // The guard will be dropped here, printing: /// // "Chashu likes tuna!!!" /// } /// ``` #[unstable(feature = "drop_guard", issue = "144426")] #[doc(alias = "ScopeGuard")] #[doc(alias = "defer")] pub struct DropGuard where F: FnOnce(T), { inner: ManuallyDrop, f: ManuallyDrop, } impl DropGuard where F: FnOnce(T), { /// Create a new instance of `DropGuard`. /// /// # Example /// /// ```rust /// # #![allow(unused)] /// #![feature(drop_guard)] /// /// use std::mem::DropGuard; /// /// let value = String::from("Chashu likes tuna"); /// let guard = DropGuard::new(value, |s| println!("{s}")); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] #[must_use] pub const fn new(inner: T, f: F) -> Self { Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) } } /// Consumes the `DropGuard`, returning the wrapped value. /// /// This will not execute the closure. This is implemented as an associated /// function to prevent any potential conflicts with any other methods called /// `into_inner` from the `Deref` and `DerefMut` impls. /// /// It is typically preferred to call this function instead of `mem::forget` /// because it will return the stored value and drop variables captured /// by the closure instead of leaking their owned resources. /// /// # Example /// /// ```rust /// # #![allow(unused)] /// #![feature(drop_guard)] /// /// use std::mem::DropGuard; /// /// let value = String::from("Nori likes chicken"); /// let guard = DropGuard::new(value, |s| println!("{s}")); /// assert_eq!(DropGuard::into_inner(guard), "Nori likes chicken"); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] #[inline] pub fn into_inner(guard: Self) -> T { // First we ensure that dropping the guard will not trigger // its destructor let mut guard = ManuallyDrop::new(guard); // Next we manually read the stored value from the guard. // // SAFETY: this is safe because we've taken ownership of the guard. let value = unsafe { ManuallyDrop::take(&mut guard.inner) }; // Finally we drop the stored closure. We do this *after* having read // the value, so that even if the closure's `drop` function panics, // unwinding still tries to drop the value. // // SAFETY: this is safe because we've taken ownership of the guard. unsafe { ManuallyDrop::drop(&mut guard.f) }; value } } #[unstable(feature = "drop_guard", issue = "144426")] impl Deref for DropGuard where F: FnOnce(T), { type Target = T; fn deref(&self) -> &T { &*self.inner } } #[unstable(feature = "drop_guard", issue = "144426")] impl DerefMut for DropGuard where F: FnOnce(T), { fn deref_mut(&mut self) -> &mut T { &mut *self.inner } } #[unstable(feature = "drop_guard", issue = "144426")] impl Drop for DropGuard where F: FnOnce(T), { fn drop(&mut self) { // SAFETY: `DropGuard` is in the process of being dropped. let inner = unsafe { ManuallyDrop::take(&mut self.inner) }; // SAFETY: `DropGuard` is in the process of being dropped. let f = unsafe { ManuallyDrop::take(&mut self.f) }; f(inner); } } #[unstable(feature = "drop_guard", issue = "144426")] impl Debug for DropGuard where T: Debug, F: FnOnce(T), { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } }