Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions library/core/src/mem/drop_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,10 @@ where

/// 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.
/// This will not execute the closure. 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
///
Expand All @@ -81,26 +78,26 @@ where
///
/// let value = String::from("Nori likes chicken");
/// let guard = DropGuard::new(value, |s| println!("{s}"));
/// assert_eq!(DropGuard::into_inner(guard), "Nori likes chicken");
/// assert_eq!(guard.dismiss(), "Nori likes chicken");
/// ```
#[unstable(feature = "drop_guard", issue = "144426")]
#[inline]
pub fn into_inner(guard: Self) -> T {
pub fn dismiss(self) -> T {
// First we ensure that dropping the guard will not trigger
// its destructor
let mut guard = ManuallyDrop::new(guard);
let mut this = ManuallyDrop::new(self);

// 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) };
let value = unsafe { ManuallyDrop::take(&mut this.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) };
unsafe { ManuallyDrop::drop(&mut this.f) };
value
}
}
Expand Down
4 changes: 2 additions & 2 deletions library/coretests/tests/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ fn drop_guard_into_inner() {
let dropped = Cell::new(false);
let value = DropGuard::new(42, |_| dropped.set(true));
let guard = DropGuard::new(value, |_| dropped.set(true));
let inner = DropGuard::into_inner(guard);
let inner = guard.dismiss();
assert_eq!(dropped.get(), false);
assert_eq!(*inner, 42);
}
Expand All @@ -837,7 +837,7 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() {
// run the destructor of the value we passed, which we validate.
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
let guard = DropGuard::new(value_with_tracked_destruction, closure_that_panics_on_drop);
DropGuard::into_inner(guard);
guard.dismiss();
}));
assert!(value_was_dropped);
}
Loading