diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 1301dedf1241a..74bf353907455 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -1,4 +1,5 @@ use crate::fmt::{self, Debug}; +use crate::marker::Destruct; use crate::mem::ManuallyDrop; use crate::ops::{Deref, DerefMut}; @@ -78,32 +79,37 @@ where /// /// let value = String::from("Nori likes chicken"); /// let guard = DropGuard::new(value, |s| println!("{s}")); - /// assert_eq!(guard.dismiss(), "Nori likes chicken"); + /// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken"); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] + #[rustc_const_unstable(feature = "const_drop_guard", issue = "none")] #[inline] - pub fn dismiss(self) -> T { + pub const fn dismiss(guard: Self) -> T + where + F: [const] Destruct, + { // First we ensure that dropping the guard will not trigger // its destructor - let mut this = ManuallyDrop::new(self); + 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 this.inner) }; + 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 this.f) }; + unsafe { ManuallyDrop::drop(&mut guard.f) }; value } } #[unstable(feature = "drop_guard", issue = "144426")] -impl Deref for DropGuard +#[rustc_const_unstable(feature = "const_convert", issue = "143773")] +impl const Deref for DropGuard where F: FnOnce(T), { @@ -115,7 +121,8 @@ where } #[unstable(feature = "drop_guard", issue = "144426")] -impl DerefMut for DropGuard +#[rustc_const_unstable(feature = "const_convert", issue = "143773")] +impl const DerefMut for DropGuard where F: FnOnce(T), { @@ -125,9 +132,10 @@ where } #[unstable(feature = "drop_guard", issue = "144426")] -impl Drop for DropGuard +#[rustc_const_unstable(feature = "const_drop_guard", issue = "none")] +impl const Drop for DropGuard where - F: FnOnce(T), + F: [const] FnOnce(T), { fn drop(&mut self) { // SAFETY: `DropGuard` is in the process of being dropped. diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 00582109aa2c5..5247e01fba01b 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -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 = guard.dismiss(); + let inner = DropGuard::dismiss(guard); assert_eq!(dropped.get(), false); assert_eq!(*inner, 42); } @@ -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); - guard.dismiss(); + DropGuard::dismiss(guard); })); assert!(value_was_dropped); }