1#![no_std]
2
3use core::mem::ManuallyDrop;
4
5pub fn defer<F>(f: F) -> impl Drop
7where
8 F: FnOnce(),
9{
10 struct Defer<F: FnOnce()>(ManuallyDrop<F>);
11
12 impl<F: FnOnce()> Drop for Defer<F> {
13 fn drop(&mut self) {
14 let f: F = unsafe { ManuallyDrop::take(&mut self.0) };
15 f();
16 }
17 }
18
19 Defer(ManuallyDrop::new(f))
20}
21
22#[macro_export]
24macro_rules! defer {
25 ($e:expr) => {
26 let _defer = $crate::defer(|| $e);
27 };
28}
29
30#[test]
31fn test() {
32 use core::cell::RefCell;
33
34 let i = RefCell::new(0);
35
36 {
37 let _d = defer(|| *i.borrow_mut() += 1);
38 assert_eq!(*i.borrow(), 0);
39 }
40
41 assert_eq!(*i.borrow(), 1);
42}
43
44#[test]
45fn test_macro() {
46 use core::cell::RefCell;
47
48 let i = RefCell::new(0);
49 let k = RefCell::new(0);
50
51 {
52 defer!(*i.borrow_mut() += 1);
53 defer!(*k.borrow_mut() += 1);
54 assert_eq!(*i.borrow(), 0);
55 assert_eq!(*k.borrow(), 0);
56 }
57
58 assert_eq!(*i.borrow(), 1);
59 assert_eq!(*k.borrow(), 1);
60}