partial_uninit/
lib.rs

1#![feature(maybe_uninit_ref)]
2#![feature(new_uninit)]
3#![feature(specialization)]
4
5use std::mem::MaybeUninit;
6
7/// PartialUninit.
8pub trait PartialUninit: Sized {
9    fn partial_uninit() -> MaybeUninit<Self> {
10        let mut uninit = MaybeUninit::<Self>::uninit();
11        unsafe {
12            uninit.get_mut().partial_init();
13        }
14        uninit
15    }
16
17    fn boxed_partial_uninit() -> Box<MaybeUninit<Self>> {
18        let mut uninit = Box::<Self>::new_uninit();
19        unsafe {
20            uninit.get_mut().partial_init();
21        }
22        uninit
23    }
24
25    fn partial_init(&mut self);
26}
27
28impl<T> PartialUninit for T {
29    default fn partial_init(&mut self) {}
30}
31
32#[cfg(test)]
33mod tests {
34    use super::PartialUninit;
35    use std::mem::MaybeUninit;
36
37    #[test]
38    fn it_works() {
39        struct Struct {
40            a: u8,
41            b: u8,
42        }
43
44        impl PartialUninit for Struct {
45            fn partial_init(&mut self) {
46                self.a = 9;
47            }
48        }
49
50        let mut uninit: MaybeUninit<Struct> = PartialUninit::partial_uninit();
51        unsafe {
52            uninit.get_mut().b = 9;
53        }
54        let init = unsafe { uninit.assume_init() };
55        assert_eq!(init.a, 9);
56        assert_eq!(init.b, 9);
57    }
58}