place/
lib.rs

1//! Placement new in Rust
2#![cfg_attr(not(test), no_std)]
3
4/// Initialize a struct in-place at `buf`, and return a mutable reference
5///
6/// `buf` is a MaybeUninit of your type
7///
8/// It is your responsibility to drop your type if needed when you're done with
9/// it.
10///
11/// It is your responsibility to correctly produce the MaybeUninit
12///
13/// This macro will ensure that all fields are initialized, and is thus
14/// safe to call.
15///
16/// # Examples
17///
18/// ```rust
19/// # use place::place;
20/// # use std::mem::MaybeUninit;
21///
22/// struct MyCoolStruct {
23///     b: bool,
24///     s: String,
25/// }
26///
27/// let mut buf = MaybeUninit::uninit();
28///
29/// let x: &mut MyCoolStruct = place!(
30///     buf,
31///     MyCoolStruct {
32///         b: true,
33///         s: String::from("works"),
34///     }
35/// );
36///
37/// # // SAFETY: buf has been initialized above
38/// # unsafe { buf.assume_init_drop() };
39/// ```
40#[macro_export]
41macro_rules! place {
42    (
43        $buf:expr,
44        $typ:ident {
45            $(
46                $f:ident: $f_val:expr
47            ),*
48            $(,)?
49        }
50    ) => {{
51        use core::{mem::MaybeUninit, ptr::addr_of_mut};
52        const _: () = {
53            // Ignore useless warnings
54            #[allow(unreachable_code, clippy::diverging_sub_expression)]
55            fn _check_types() {
56                // This check means Rust will validate that all struct fields were passed in,
57                // meaning that all fields will be initialized below
58                //
59                // This check is the key to making this macro safe.
60                $typ {
61                    $(
62                        $f: loop {}
63                    ),*
64                };
65            }
66        };
67        // Ensures types are correct
68        let buf: &mut MaybeUninit<$typ> = &mut $buf;
69        let ptr = buf.as_mut_ptr();
70        $(
71            // SAFETY: Only pointers are used, and the above compile check
72            // ensures all fields were specified
73            unsafe { addr_of_mut!((*ptr).$f).write($f_val); }
74        )*
75        // SAFETY: All fields have been initialized above
76        // The compiler ensures that all fields were used, all types were correct,
77        // and that size and alignment are correct.
78        unsafe { buf.assume_init_mut() }
79    }};
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use core::mem::MaybeUninit;
86
87    #[derive(Debug)]
88    struct MyCoolStruct {
89        b: bool,
90        s: String,
91        v: Vec<String>,
92    }
93
94    #[test]
95    fn miri() {
96        let mut buf = MaybeUninit::uninit();
97
98        let x: &mut MyCoolStruct = place!(
99            buf,
100            MyCoolStruct {
101                b: true,
102                s: String::from("works"),
103                v: vec![String::from("works")],
104            }
105        );
106        dbg!(x);
107
108        // SAFETY: buf has been initialized above
109        unsafe { buf.assume_init_drop() };
110    }
111}