subst/non_aliasing.rs
1use core::mem::MaybeUninit;
2
3/// Simple wrapper around [`MaybeUninit`] that guarantees the type is initialized.
4///
5/// This may sound odd, but the compiler can not assume that `MaybeUninit` is initialized,
6/// but as far is the compiler is concerned, `MaybeUninit<T>` is not keeping any references around, even if `T` would.
7/// So `NonAliasing<T>` is not aliassing anything untill you call `inner()` to get your `&T` back.
8///
9/// We use this to create a (hopefully) sound self referential struct in `TemplateBuf` and `ByteTemplateBuf`.
10pub struct NonAliasing<T> {
11 inner: MaybeUninit<T>,
12}
13
14impl<T> NonAliasing<T> {
15 pub fn new(inner: T) -> Self {
16 let inner = MaybeUninit::new(inner);
17 Self { inner }
18 }
19
20 pub fn inner(&self) -> &T {
21 // SAFETY: We always initialize `inner` in the constructor.
22 unsafe {
23 self.inner.assume_init_ref()
24 }
25 }
26}
27
28impl<T> Drop for NonAliasing<T> {
29 fn drop(&mut self) {
30 // SAFETY: We always initialize `inner` in the constructor,
31 // the API only exposes `assume_init_ref()`,
32 // and we're in the destructor, so nobody is going to call assume_init_read() again.
33 unsafe {
34 drop(self.inner.assume_init_read())
35 }
36 }
37}