Skip to content

Commit 6f03732

Browse files
committed
reimpl
Signed-off-by: tison <wander4096@gmail.com>
1 parent 31a625c commit 6f03732

File tree

3 files changed

+79
-18
lines changed

3 files changed

+79
-18
lines changed

library/core/src/mem/drop_guard.rs

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,16 @@ use crate::ops::{Deref, DerefMut};
1919
/// {
2020
/// // Create a new guard that will do something
2121
/// // when dropped.
22-
/// let _guard = defer! { println!("Goodbye, world!") };
22+
/// defer! { println!("Goodbye, world!") };
23+
///
24+
/// // The guard will be dropped here, printing:
25+
/// // "Goodbye, world!"
26+
/// }
27+
///
28+
/// {
29+
/// // Create a new guard that will do something
30+
/// // when dropped.
31+
/// let _guard = DropGuard::new(|| println!("Goodbye, world!"));
2332
///
2433
/// // The guard will be dropped here, printing:
2534
/// // "Goodbye, world!"
@@ -29,7 +38,7 @@ use crate::ops::{Deref, DerefMut};
2938
/// // Create a new guard around a string that will
3039
/// // print its value when dropped.
3140
/// let s = String::from("Chashu likes tuna");
32-
/// let mut s = DropGuard::new(s, |s| println!("{s}"));
41+
/// let mut s = DropGuard::with_value(s, |s| println!("{s}"));
3342
///
3443
/// // Modify the string contained in the guard.
3544
/// s.push_str("!!!");
@@ -41,15 +50,18 @@ use crate::ops::{Deref, DerefMut};
4150
#[unstable(feature = "drop_guard", issue = "144426")]
4251
#[doc(alias = "ScopeGuard")]
4352
#[doc(alias = "defer")]
44-
pub struct DropGuard<T, F>
53+
pub struct DropGuard<T = (), F = UnitFn<fn()>>
4554
where
4655
F: FnOnce(T),
4756
{
4857
inner: ManuallyDrop<T>,
4958
f: ManuallyDrop<F>,
5059
}
5160

52-
/// Create a new instance of `DropGuard` with a cleanup closure.
61+
/// Create an anonymous `DropGuard` with a cleanup closure.
62+
///
63+
/// The macro takes statements, which are the body of a closure
64+
/// that will run when the scope is exited.
5365
///
5466
/// # Example
5567
///
@@ -59,11 +71,34 @@ where
5971
///
6072
/// use std::mem::defer;
6173
///
62-
/// let _guard = defer! { println!("Goodbye, world!") };
74+
/// defer! { println!("Goodbye, world!") };
6375
/// ```
6476
#[unstable(feature = "drop_guard", issue = "144426")]
6577
pub macro defer($($t:tt)*) {
66-
$crate::mem::DropGuard::new((), |()| { $($t)* })
78+
let _guard = $crate::mem::DropGuard::new(|| { $($t)* });
79+
}
80+
81+
impl<F> DropGuard<(), UnitFn<F>>
82+
where
83+
F: FnOnce(),
84+
{
85+
/// Create a new instance of `DropGuard` with a cleanup closure.
86+
///
87+
/// # Example
88+
///
89+
/// ```rust
90+
/// # #![allow(unused)]
91+
/// #![feature(drop_guard)]
92+
///
93+
/// use std::mem::DropGuard;
94+
///
95+
/// let guard = DropGuard::new(|| println!("Goodbye, world!"));
96+
/// ```
97+
#[unstable(feature = "drop_guard", issue = "144426")]
98+
#[must_use]
99+
pub const fn new(f: F) -> Self {
100+
Self { inner: ManuallyDrop::new(()), f: ManuallyDrop::new(UnitFn(f)) }
101+
}
67102
}
68103

69104
impl<T, F> DropGuard<T, F>
@@ -81,11 +116,11 @@ where
81116
/// use std::mem::DropGuard;
82117
///
83118
/// let value = String::from("Chashu likes tuna");
84-
/// let guard = DropGuard::new(value, |s| println!("{s}"));
119+
/// let guard = DropGuard::with_value(value, |s| println!("{s}"));
85120
/// ```
86121
#[unstable(feature = "drop_guard", issue = "144426")]
87122
#[must_use]
88-
pub const fn new(inner: T, f: F) -> Self {
123+
pub const fn with_value(inner: T, f: F) -> Self {
89124
Self { inner: ManuallyDrop::new(inner), f: ManuallyDrop::new(f) }
90125
}
91126

@@ -105,7 +140,7 @@ where
105140
/// use std::mem::DropGuard;
106141
///
107142
/// let value = String::from("Nori likes chicken");
108-
/// let guard = DropGuard::new(value, |s| println!("{s}"));
143+
/// let guard = DropGuard::with_value(value, |s| println!("{s}"));
109144
/// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken");
110145
/// ```
111146
#[unstable(feature = "drop_guard", issue = "144426")]
@@ -185,3 +220,28 @@ where
185220
fmt::Debug::fmt(&**self, f)
186221
}
187222
}
223+
224+
#[unstable(feature = "drop_guard", issue = "144426")]
225+
pub struct UnitFn<F>(F);
226+
227+
#[unstable(feature = "drop_guard", issue = "144426")]
228+
impl<F> FnOnce<((),)> for UnitFn<F>
229+
where
230+
F: FnOnce(),
231+
{
232+
type Output = ();
233+
234+
extern "rust-call" fn call_once(self, _args: ((),)) -> Self::Output {
235+
(self.0)()
236+
}
237+
}
238+
239+
#[unstable(feature = "drop_guard", issue = "144426")]
240+
impl<F> Debug for UnitFn<F>
241+
where
242+
F: FnOnce(),
243+
{
244+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245+
write!(f, "UnitFn")
246+
}
247+
}

library/coretests/tests/mem.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -800,9 +800,9 @@ fn const_maybe_uninit_zeroed() {
800800
#[test]
801801
fn drop_guards_only_dropped_by_closure_when_run() {
802802
let value_drops = Cell::new(0);
803-
let value = defer! { value_drops.set(1 + value_drops.get()) };
803+
let value = DropGuard::new(|| value_drops.set(1 + value_drops.get()));
804804
let closure_drops = Cell::new(0);
805-
let guard = DropGuard::new(value, |_| closure_drops.set(1 + closure_drops.get()));
805+
let guard = DropGuard::with_value(value, |_| closure_drops.set(1 + closure_drops.get()));
806806
assert_eq!(value_drops.get(), 0);
807807
assert_eq!(closure_drops.get(), 0);
808808
drop(guard);
@@ -813,8 +813,8 @@ fn drop_guards_only_dropped_by_closure_when_run() {
813813
#[test]
814814
fn drop_guard_into_inner() {
815815
let dropped = Cell::new(false);
816-
let value = DropGuard::new(42, |_| dropped.set(true));
817-
let guard = DropGuard::new(value, |_| dropped.set(true));
816+
let value = DropGuard::with_value(42, |_| dropped.set(true));
817+
let guard = DropGuard::with_value(value, |_| dropped.set(true));
818818
let inner = DropGuard::dismiss(guard);
819819
assert_eq!(dropped.get(), false);
820820
assert_eq!(*inner, 42);
@@ -825,18 +825,19 @@ fn drop_guard_into_inner() {
825825
fn drop_guard_always_drops_value_if_closure_drop_unwinds() {
826826
// Create a value with a destructor, which we will validate ran successfully.
827827
let mut value_was_dropped = false;
828-
let value_with_tracked_destruction = defer! { value_was_dropped = true };
828+
let value_with_tracked_destruction = DropGuard::new(|| value_was_dropped = true);
829829

830830
// Create a closure that will begin unwinding when dropped.
831-
let drop_bomb = defer! { panic!() };
831+
let drop_bomb = DropGuard::new(|| panic!());
832832
let closure_that_panics_on_drop = move |_| {
833833
let _drop_bomb = drop_bomb;
834834
};
835835

836836
// This will run the closure, which will panic when dropped. This should
837837
// run the destructor of the value we passed, which we validate.
838838
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
839-
let guard = DropGuard::new(value_with_tracked_destruction, closure_that_panics_on_drop);
839+
let guard =
840+
DropGuard::with_value(value_with_tracked_destruction, closure_that_panics_on_drop);
840841
DropGuard::dismiss(guard);
841842
}));
842843
assert!(value_was_dropped);
@@ -845,7 +846,7 @@ fn drop_guard_always_drops_value_if_closure_drop_unwinds() {
845846
#[test]
846847
fn defer_moved_value() {
847848
let data = "owned data".to_string();
848-
let _guard = defer! {
849+
defer! {
849850
std::thread::spawn(move || { assert_eq!(data.as_str(), "owned data") }).join().ok();
850851
};
851852
}

library/std/src/sys/thread/unix.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl Thread {
4848
let data = init;
4949
let mut attr: mem::MaybeUninit<libc::pthread_attr_t> = mem::MaybeUninit::uninit();
5050
assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
51-
let mut attr = DropGuard::new(&mut attr, |attr| {
51+
let mut attr = DropGuard::with_value(&mut attr, |attr| {
5252
assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0)
5353
});
5454

0 commit comments

Comments
 (0)