From 363715946dda3204b75e30bdb58852f5175b2527 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 15 Dec 2025 23:42:35 +0800 Subject: [PATCH 1/5] Add common case for DropGuard that takes no inner value Signed-off-by: tison --- library/core/src/mem/drop_guard.rs | 42 ++++++++++++++++++++++++++---- library/coretests/tests/mem.rs | 15 ++++++----- library/std/src/sys/thread/unix.rs | 2 +- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 74bf353907455..2ff74a28df253 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -16,10 +16,19 @@ use crate::ops::{Deref, DerefMut}; /// use std::mem::DropGuard; /// /// { +/// // Create a new guard that will do something +/// // when dropped. +/// let _guard = DropGuard::new(|()| println!("Goodbye, world!")); +/// +/// // The guard will be dropped here, printing: +/// // "Goodbye, world!" +/// } +/// +/// { /// // 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}")); +/// let mut s = DropGuard::new_with(s, |s| println!("{s}")); /// /// // Modify the string contained in the guard. /// s.push_str("!!!"); @@ -39,11 +48,34 @@ where f: ManuallyDrop, } +impl DropGuard<(), F> +where + F: FnOnce(()), +{ + /// Create a new instance of `DropGuard` with a cleanup closure. + /// + /// # Example + /// + /// ```rust + /// # #![allow(unused)] + /// #![feature(drop_guard)] + /// + /// use std::mem::DropGuard; + /// + /// let guard = DropGuard::new(|()| println!("Goodbye, world!")); + /// ``` + #[unstable(feature = "drop_guard", issue = "144426")] + #[must_use] + pub const fn new(f: F) -> Self { + Self { inner: ManuallyDrop::new(()), f: ManuallyDrop::new(f) } + } +} + impl DropGuard where F: FnOnce(T), { - /// Create a new instance of `DropGuard`. + /// Create a new instance of `DropGuard` with a value and a cleanup closure. /// /// # Example /// @@ -54,11 +86,11 @@ where /// use std::mem::DropGuard; /// /// let value = String::from("Chashu likes tuna"); - /// let guard = DropGuard::new(value, |s| println!("{s}")); + /// let guard = DropGuard::new_with(value, |s| println!("{s}")); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] #[must_use] - pub const fn new(inner: T, f: F) -> Self { + pub const fn new_with(inner: T, f: F) -> Self { Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) } } @@ -78,7 +110,7 @@ where /// use std::mem::DropGuard; /// /// let value = String::from("Nori likes chicken"); - /// let guard = DropGuard::new(value, |s| println!("{s}")); + /// let guard = DropGuard::new_with(value, |s| println!("{s}")); /// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken"); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 5247e01fba01b..61117e3372749 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -800,9 +800,9 @@ fn const_maybe_uninit_zeroed() { #[test] fn drop_guards_only_dropped_by_closure_when_run() { let value_drops = Cell::new(0); - let value = DropGuard::new((), |()| value_drops.set(1 + value_drops.get())); + let value = DropGuard::new(|()| value_drops.set(1 + value_drops.get())); let closure_drops = Cell::new(0); - let guard = DropGuard::new(value, |_| closure_drops.set(1 + closure_drops.get())); + let guard = DropGuard::new_with(value, |_| closure_drops.set(1 + closure_drops.get())); assert_eq!(value_drops.get(), 0); assert_eq!(closure_drops.get(), 0); drop(guard); @@ -813,8 +813,8 @@ fn drop_guards_only_dropped_by_closure_when_run() { #[test] 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 value = DropGuard::new_with(42, |_| dropped.set(true)); + let guard = DropGuard::new_with(value, |_| dropped.set(true)); let inner = DropGuard::dismiss(guard); assert_eq!(dropped.get(), false); assert_eq!(*inner, 42); @@ -825,10 +825,10 @@ fn drop_guard_into_inner() { fn drop_guard_always_drops_value_if_closure_drop_unwinds() { // Create a value with a destructor, which we will validate ran successfully. let mut value_was_dropped = false; - let value_with_tracked_destruction = DropGuard::new((), |_| value_was_dropped = true); + let value_with_tracked_destruction = DropGuard::new(|()| value_was_dropped = true); // Create a closure that will begin unwinding when dropped. - let drop_bomb = DropGuard::new((), |_| panic!()); + let drop_bomb = DropGuard::new(|()| panic!()); let closure_that_panics_on_drop = move |_| { let _drop_bomb = drop_bomb; }; @@ -836,7 +836,8 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() { // This will run the closure, which will panic when dropped. This should // 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); + let guard = + DropGuard::new_with(value_with_tracked_destruction, closure_that_panics_on_drop); DropGuard::dismiss(guard); })); assert!(value_was_dropped); diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index 18cdea0e1b1b3..a6e874004bce1 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -48,7 +48,7 @@ impl Thread { let data = init; let mut attr: mem::MaybeUninit = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); - let mut attr = DropGuard::new(&mut attr, |attr| { + let mut attr = DropGuard::new_with(&mut attr, |attr| { assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0) }); From 50bff8376cb174780ab1ac91109493ccdb6ed256 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 16 Dec 2025 10:21:36 +0800 Subject: [PATCH 2/5] Use top-level function constructor Signed-off-by: tison --- library/core/src/mem/drop_guard.rs | 84 +++++++++++++++--------------- library/core/src/mem/mod.rs | 2 +- library/coretests/tests/mem.rs | 15 +++--- library/std/src/sys/thread/unix.rs | 7 ++- 4 files changed, 53 insertions(+), 55 deletions(-) diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 2ff74a28df253..0056ea5184ab1 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -13,12 +13,13 @@ use crate::ops::{Deref, DerefMut}; /// # #![allow(unused)] /// #![feature(drop_guard)] /// -/// use std::mem::DropGuard; +/// use std::mem::defer; +/// use std::mem::guard; /// /// { /// // Create a new guard that will do something /// // when dropped. -/// let _guard = DropGuard::new(|()| println!("Goodbye, world!")); +/// let _guard = defer(|| println!("Goodbye, world!")); /// /// // The guard will be dropped here, printing: /// // "Goodbye, world!" @@ -28,7 +29,7 @@ use crate::ops::{Deref, DerefMut}; /// // 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_with(s, |s| println!("{s}")); +/// let mut s = guard(s, |s| println!("{s}")); /// /// // Modify the string contained in the guard. /// s.push_str("!!!"); @@ -48,52 +49,50 @@ where f: ManuallyDrop, } -impl DropGuard<(), F> +/// Create a new instance of `DropGuard` with a value and a cleanup closure. +/// +/// # Example +/// +/// ```rust +/// # #![allow(unused)] +/// #![feature(drop_guard)] +/// +/// use std::mem::guard; +/// +/// let value = String::from("Chashu likes tuna"); +/// let guard = guard(value, |s| println!("{s}")); +/// ``` +#[unstable(feature = "drop_guard", issue = "144426")] +#[must_use] +pub const fn guard(value: T, f: F) -> DropGuard where - F: FnOnce(()), + F: FnOnce(T), { - /// Create a new instance of `DropGuard` with a cleanup closure. - /// - /// # Example - /// - /// ```rust - /// # #![allow(unused)] - /// #![feature(drop_guard)] - /// - /// use std::mem::DropGuard; - /// - /// let guard = DropGuard::new(|()| println!("Goodbye, world!")); - /// ``` - #[unstable(feature = "drop_guard", issue = "144426")] - #[must_use] - pub const fn new(f: F) -> Self { - Self { inner: ManuallyDrop::new(()), f: ManuallyDrop::new(f) } - } + DropGuard { inner: ManuallyDrop::new(value), f: ManuallyDrop::new(f) } +} + +/// Create a new instance of `DropGuard` with a cleanup closure. +/// +/// # Example +/// +/// ```rust +/// # #![allow(unused)] +/// #![feature(drop_guard)] +/// +/// use std::mem::defer; +/// +/// let guard = defer(|| println!("Goodbye, world!")); +/// ``` +#[unstable(feature = "drop_guard", issue = "144426")] +#[must_use] +pub const fn defer(f: impl FnOnce()) -> DropGuard<(), impl FnOnce(())> { + guard((), move |_| f()) } impl DropGuard where F: FnOnce(T), { - /// Create a new instance of `DropGuard` with a value and a cleanup closure. - /// - /// # Example - /// - /// ```rust - /// # #![allow(unused)] - /// #![feature(drop_guard)] - /// - /// use std::mem::DropGuard; - /// - /// let value = String::from("Chashu likes tuna"); - /// let guard = DropGuard::new_with(value, |s| println!("{s}")); - /// ``` - #[unstable(feature = "drop_guard", issue = "144426")] - #[must_use] - pub const fn new_with(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. It is typically preferred to call @@ -108,9 +107,10 @@ where /// #![feature(drop_guard)] /// /// use std::mem::DropGuard; + /// use std::mem::guard; /// /// let value = String::from("Nori likes chicken"); - /// let guard = DropGuard::new_with(value, |s| println!("{s}")); + /// let guard = guard(value, |s| println!("{s}")); /// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken"); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index ad5fda0cfe4db..26fef9aa3ac4a 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -25,7 +25,7 @@ pub use transmutability::{Assume, TransmuteFrom}; mod drop_guard; #[unstable(feature = "drop_guard", issue = "144426")] -pub use drop_guard::DropGuard; +pub use drop_guard::{DropGuard, defer, guard}; // This one has to be a re-export (rather than wrapping the underlying intrinsic) so that we can do // the special magic "types have equal size" check at the call site. diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 61117e3372749..b63cccd83f9b7 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -800,9 +800,9 @@ fn const_maybe_uninit_zeroed() { #[test] fn drop_guards_only_dropped_by_closure_when_run() { let value_drops = Cell::new(0); - let value = DropGuard::new(|()| value_drops.set(1 + value_drops.get())); + let value = defer(|| value_drops.set(1 + value_drops.get())); let closure_drops = Cell::new(0); - let guard = DropGuard::new_with(value, |_| closure_drops.set(1 + closure_drops.get())); + let guard = guard(value, |_| closure_drops.set(1 + closure_drops.get())); assert_eq!(value_drops.get(), 0); assert_eq!(closure_drops.get(), 0); drop(guard); @@ -813,8 +813,8 @@ fn drop_guards_only_dropped_by_closure_when_run() { #[test] fn drop_guard_into_inner() { let dropped = Cell::new(false); - let value = DropGuard::new_with(42, |_| dropped.set(true)); - let guard = DropGuard::new_with(value, |_| dropped.set(true)); + let value = guard(42, |_| dropped.set(true)); + let guard = guard(value, |_| dropped.set(true)); let inner = DropGuard::dismiss(guard); assert_eq!(dropped.get(), false); assert_eq!(*inner, 42); @@ -825,10 +825,10 @@ fn drop_guard_into_inner() { fn drop_guard_always_drops_value_if_closure_drop_unwinds() { // Create a value with a destructor, which we will validate ran successfully. let mut value_was_dropped = false; - let value_with_tracked_destruction = DropGuard::new(|()| value_was_dropped = true); + let value_with_tracked_destruction = defer(|| value_was_dropped = true); // Create a closure that will begin unwinding when dropped. - let drop_bomb = DropGuard::new(|()| panic!()); + let drop_bomb = defer(|| panic!()); let closure_that_panics_on_drop = move |_| { let _drop_bomb = drop_bomb; }; @@ -836,8 +836,7 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() { // This will run the closure, which will panic when dropped. This should // run the destructor of the value we passed, which we validate. let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - let guard = - DropGuard::new_with(value_with_tracked_destruction, closure_that_panics_on_drop); + let guard = guard(value_with_tracked_destruction, closure_that_panics_on_drop); DropGuard::dismiss(guard); })); assert!(value_was_dropped); diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index a6e874004bce1..2d3b2824a63f5 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -8,7 +8,7 @@ target_os = "wasi", )))] use crate::ffi::CStr; -use crate::mem::{self, DropGuard, ManuallyDrop}; +use crate::mem::{self, ManuallyDrop, guard}; use crate::num::NonZero; #[cfg(all(target_os = "linux", target_env = "gnu"))] use crate::sys::weak::dlsym; @@ -48,9 +48,8 @@ impl Thread { let data = init; let mut attr: mem::MaybeUninit = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); - let mut attr = DropGuard::new_with(&mut attr, |attr| { - assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0) - }); + let mut attr = + guard(&mut attr, |attr| assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0)); #[cfg(any(target_os = "espidf", target_os = "nuttx"))] if stack > 0 { From 50fb573c6892ca79357b500a7242cf8de81b6212 Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 16 Dec 2025 20:17:03 +0800 Subject: [PATCH 3/5] Move back DropGuard::new Signed-off-by: tison --- library/core/src/mem/drop_guard.rs | 51 +++++++++++++++--------------- library/core/src/mem/mod.rs | 2 +- library/coretests/tests/mem.rs | 8 ++--- library/std/src/sys/thread/unix.rs | 7 ++-- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 0056ea5184ab1..f118c17dbc8bc 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -13,8 +13,8 @@ use crate::ops::{Deref, DerefMut}; /// # #![allow(unused)] /// #![feature(drop_guard)] /// +/// use std::mem::DropGuard; /// use std::mem::defer; -/// use std::mem::guard; /// /// { /// // Create a new guard that will do something @@ -29,7 +29,7 @@ use crate::ops::{Deref, DerefMut}; /// // Create a new guard around a string that will /// // print its value when dropped. /// let s = String::from("Chashu likes tuna"); -/// let mut s = guard(s, |s| println!("{s}")); +/// let mut s = DropGuard::new(s, |s| println!("{s}")); /// /// // Modify the string contained in the guard. /// s.push_str("!!!"); @@ -49,28 +49,6 @@ where f: ManuallyDrop, } -/// Create a new instance of `DropGuard` with a value and a cleanup closure. -/// -/// # Example -/// -/// ```rust -/// # #![allow(unused)] -/// #![feature(drop_guard)] -/// -/// use std::mem::guard; -/// -/// let value = String::from("Chashu likes tuna"); -/// let guard = guard(value, |s| println!("{s}")); -/// ``` -#[unstable(feature = "drop_guard", issue = "144426")] -#[must_use] -pub const fn guard(value: T, f: F) -> DropGuard -where - F: FnOnce(T), -{ - DropGuard { inner: ManuallyDrop::new(value), f: ManuallyDrop::new(f) } -} - /// Create a new instance of `DropGuard` with a cleanup closure. /// /// # Example @@ -93,6 +71,28 @@ impl DropGuard where F: FnOnce(T), { + /// Create a new instance of `DropGuard` with a value and a cleanup closure. + /// + /// # 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(value: T, f: F) -> DropGuard + where + F: FnOnce(T), + { + DropGuard { inner: ManuallyDrop::new(value), f: ManuallyDrop::new(f) } + } + /// Consumes the `DropGuard`, returning the wrapped value. /// /// This will not execute the closure. It is typically preferred to call @@ -107,10 +107,9 @@ where /// #![feature(drop_guard)] /// /// use std::mem::DropGuard; - /// use std::mem::guard; /// /// let value = String::from("Nori likes chicken"); - /// let guard = guard(value, |s| println!("{s}")); + /// let guard = DropGuard::new(value, |s| println!("{s}")); /// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken"); /// ``` #[unstable(feature = "drop_guard", issue = "144426")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 26fef9aa3ac4a..1fd9d9e8ec37e 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -25,7 +25,7 @@ pub use transmutability::{Assume, TransmuteFrom}; mod drop_guard; #[unstable(feature = "drop_guard", issue = "144426")] -pub use drop_guard::{DropGuard, defer, guard}; +pub use drop_guard::{DropGuard, defer}; // This one has to be a re-export (rather than wrapping the underlying intrinsic) so that we can do // the special magic "types have equal size" check at the call site. diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index b63cccd83f9b7..b48c0ea5aa789 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -802,7 +802,7 @@ fn drop_guards_only_dropped_by_closure_when_run() { let value_drops = Cell::new(0); let value = defer(|| value_drops.set(1 + value_drops.get())); let closure_drops = Cell::new(0); - let guard = guard(value, |_| closure_drops.set(1 + closure_drops.get())); + let guard = DropGuard::new(value, |_| closure_drops.set(1 + closure_drops.get())); assert_eq!(value_drops.get(), 0); assert_eq!(closure_drops.get(), 0); drop(guard); @@ -813,8 +813,8 @@ fn drop_guards_only_dropped_by_closure_when_run() { #[test] fn drop_guard_into_inner() { let dropped = Cell::new(false); - let value = guard(42, |_| dropped.set(true)); - let guard = guard(value, |_| dropped.set(true)); + let value = DropGuard::new(42, |_| dropped.set(true)); + let guard = DropGuard::new(value, |_| dropped.set(true)); let inner = DropGuard::dismiss(guard); assert_eq!(dropped.get(), false); assert_eq!(*inner, 42); @@ -836,7 +836,7 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() { // This will run the closure, which will panic when dropped. This should // run the destructor of the value we passed, which we validate. let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - let guard = guard(value_with_tracked_destruction, closure_that_panics_on_drop); + let guard = DropGuard::new(value_with_tracked_destruction, closure_that_panics_on_drop); DropGuard::dismiss(guard); })); assert!(value_was_dropped); diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index 2d3b2824a63f5..18cdea0e1b1b3 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -8,7 +8,7 @@ target_os = "wasi", )))] use crate::ffi::CStr; -use crate::mem::{self, ManuallyDrop, guard}; +use crate::mem::{self, DropGuard, ManuallyDrop}; use crate::num::NonZero; #[cfg(all(target_os = "linux", target_env = "gnu"))] use crate::sys::weak::dlsym; @@ -48,8 +48,9 @@ impl Thread { let data = init; let mut attr: mem::MaybeUninit = mem::MaybeUninit::uninit(); assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0); - let mut attr = - guard(&mut attr, |attr| assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0)); + let mut attr = DropGuard::new(&mut attr, |attr| { + assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0) + }); #[cfg(any(target_os = "espidf", target_os = "nuttx"))] if stack > 0 { From 16509f90d7f8eae50a06630c3fbe4f99ccada8ea Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 16 Dec 2025 20:29:37 +0800 Subject: [PATCH 4/5] try defer as macro Signed-off-by: tison --- library/core/src/mem/drop_guard.rs | 11 +++++------ library/coretests/tests/mem.rs | 14 +++++++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index f118c17dbc8bc..53d46ddc40659 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -19,7 +19,7 @@ use crate::ops::{Deref, DerefMut}; /// { /// // Create a new guard that will do something /// // when dropped. -/// let _guard = defer(|| println!("Goodbye, world!")); +/// let _guard = defer! { println!("Goodbye, world!") }; /// /// // The guard will be dropped here, printing: /// // "Goodbye, world!" @@ -59,12 +59,11 @@ where /// /// use std::mem::defer; /// -/// let guard = defer(|| println!("Goodbye, world!")); +/// let _guard = defer! { println!("Goodbye, world!") }; /// ``` #[unstable(feature = "drop_guard", issue = "144426")] -#[must_use] -pub const fn defer(f: impl FnOnce()) -> DropGuard<(), impl FnOnce(())> { - guard((), move |_| f()) +pub macro defer($($t:tt)*) { + $crate::mem::DropGuard::new((), |()| { $($t)* }) } impl DropGuard @@ -86,7 +85,7 @@ where /// ``` #[unstable(feature = "drop_guard", issue = "144426")] #[must_use] - pub const fn new(value: T, f: F) -> DropGuard + pub const fn new(value: T, f: F) -> DropGuard where F: FnOnce(T), { diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index b48c0ea5aa789..91fe625de9728 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -800,7 +800,7 @@ fn const_maybe_uninit_zeroed() { #[test] fn drop_guards_only_dropped_by_closure_when_run() { let value_drops = Cell::new(0); - let value = defer(|| value_drops.set(1 + value_drops.get())); + let value = defer! { value_drops.set(1 + value_drops.get()) }; let closure_drops = Cell::new(0); let guard = DropGuard::new(value, |_| closure_drops.set(1 + closure_drops.get())); assert_eq!(value_drops.get(), 0); @@ -825,10 +825,10 @@ fn drop_guard_into_inner() { fn drop_guard_always_drops_value_if_closure_drop_unwinds() { // Create a value with a destructor, which we will validate ran successfully. let mut value_was_dropped = false; - let value_with_tracked_destruction = defer(|| value_was_dropped = true); + let value_with_tracked_destruction = defer! { value_was_dropped = true }; // Create a closure that will begin unwinding when dropped. - let drop_bomb = defer(|| panic!()); + let drop_bomb = defer! { panic!() }; let closure_that_panics_on_drop = move |_| { let _drop_bomb = drop_bomb; }; @@ -841,3 +841,11 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() { })); assert!(value_was_dropped); } + +#[test] +fn defer_moved_value() { + let data = "owned data".to_string(); + let _guard = defer! { + std::thread::spawn(move || { assert_eq!(data.as_str(), "owned data") }).join().ok(); + }; +} From 31a625cf6e0ad66222e06a0c9447a9866ea654d6 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 17 Dec 2025 13:31:29 +0800 Subject: [PATCH 5/5] revert back and forth changes Signed-off-by: tison --- library/core/src/mem/drop_guard.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 53d46ddc40659..ca193a14f565a 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -85,11 +85,8 @@ where /// ``` #[unstable(feature = "drop_guard", issue = "144426")] #[must_use] - pub const fn new(value: T, f: F) -> DropGuard - where - F: FnOnce(T), - { - DropGuard { inner: ManuallyDrop::new(value), f: ManuallyDrop::new(f) } + 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.