External Publication
Visit Post

Another Experiment To Make Unsafe Rust Safer: Preventing UB In MaybeUninit With Compile Time Error

Rust Internals [Unofficial] May 22, 2026
Source

Hello, I'm doing this experiment. What do you guys think? :]

use std::mem::MaybeUninit;
use std::marker::PhantomData;

pub struct Uninit;
pub struct Init;

pub struct UninitStorage<T>(MaybeUninit<T>);

pub struct InitStorage<T>(MaybeUninit<T>);

impl<T> Drop for InitStorage<T> {
    fn drop(&mut self) {
        unsafe {
            self.0.assume_init_drop();
        }
    }
}

pub struct UninitGuard<T, State> {
    storage: State,
    _marker: PhantomData<T>,
}

#[diagnostic::on_unimplemented(
    message = "Illegal access: Memory is not initialized yet!",
    label = "Attempted to operate on data here, but the status is still `Uninit`",
    note = "Call `.write(val)` on the UninitGuard first before accessing its references or pointers."
)]
pub trait IsInitialized<State> {}

#[diagnostic::do_not_recommend]
impl<T> IsInitialized<InitStorage<T>> for UninitGuard<T, InitStorage<T>> {}

impl<T> UninitGuard<T, UninitStorage<T>> {
    pub fn new() -> Self {
        Self {
            storage: UninitStorage(MaybeUninit::uninit()),
            _marker: PhantomData,
        }
    }

    pub fn zeroed() -> Self {
        Self {
            storage: UninitStorage(MaybeUninit::zeroed()),
            _marker: PhantomData,
        }
    }

    pub const fn uninit() -> Self {
        Self {
            storage: UninitStorage(MaybeUninit::uninit()),
            _marker: PhantomData,
        }
    }

    pub fn write(self, val: T) -> UninitGuard<T, InitStorage<T>> {
        let mut storage = MaybeUninit::uninit();
        storage.write(val);
        UninitGuard {
            storage: InitStorage(storage),
            _marker: PhantomData,
        }
    }
}

impl<T, State> UninitGuard<T, State>
where
    Self: IsInitialized<State>,
{
    pub fn as_ptr(&self) -> *const T {
        let storage = unsafe { &*( &self.storage as *const State as *const MaybeUninit<T> ) };
        storage.as_ptr()
    }

    pub fn as_mut_ptr(&mut self) -> *mut T {
        let storage = unsafe { &mut *( &mut self.storage as *mut State as *mut MaybeUninit<T> ) };
        storage.as_mut_ptr()
    }

    pub fn get_ref(&self) -> &T {
        let storage = unsafe { &*( &self.storage as *const State as *const MaybeUninit<T> ) };
        unsafe { storage.assume_init_ref() }
    }

    pub fn get_mut(&mut self) -> &mut T {
        let storage = unsafe { &mut *( &mut self.storage as *mut State as *mut MaybeUninit<T> ) };
        unsafe { storage.assume_init_mut() }
    }

    pub fn assume_init(self) -> T {
        let mut this = std::mem::ManuallyDrop::new(self);
        let storage = unsafe { &mut *( &mut this.storage as *mut State as *mut MaybeUninit<T> ) };
        unsafe { storage.assume_init_read() }
    }

    pub fn replace(&mut self, val: T) -> T {
        let storage = unsafe { &mut *( &mut self.storage as *mut State as *mut MaybeUninit<T> ) };
        let old = unsafe { storage.assume_init_read() };
        storage.write(val);
        old
    }
}

impl<T> UninitGuard<T, InitStorage<T>> {
    pub const fn new_init(val: T) -> Self {
        Self {
            storage: InitStorage(MaybeUninit::new(val)),
            _marker: PhantomData,
        }
    }
}

fn a() {
    let guard = UninitGuard::<String, _>::new();
    let tes = guard.assume_init();
}

fn main() {

}

It will cause compile time error if we call assume_init, get reference, get pointer when the memory is uninitialized yet

   Compiling playground v0.0.1 (/playground)
error[E0599]: Illegal access: Memory is not initialized yet!
   --> src/main.rs:115:21
    |
 19 | pub struct UninitGuard<T, State> {
    | -------------------------------- method `assume_init` not found for this struct because it doesn't satisfy `_: IsInitialized<UninitStorage<String>>`
...
115 |     let tes = guard.assume_init();
    |                     ^^^^^^^^^^^ Attempted to operate on data here, but the status is still `Uninit`
    |
note: trait bound `UninitGuard<String, UninitStorage<String>>: IsInitialized<UninitStorage<String>>` was not satisfied
   --> src/main.rs:68:11
    |
 66 | impl<T, State> UninitGuard<T, State>
    |                ---------------------
 67 | where
 68 |     Self: IsInitialized<State>,
    |           ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
    = note: Call `.write(val)` on the UninitGuard first before accessing its references or pointers.
note: the trait `IsInitialized` must be implemented
   --> src/main.rs:29:1
    |
 29 | pub trait IsInitialized<State> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0599`.
error: could not compile `playground` (bin "playground") due to 1 previous error
Standard Output

What is the escape hatch that you guys spot in this code?

If this experiment is successful, it would be a valuable addition to the standard library. Because it prevents many UBs that are related to uninitialized memory

Discussion in the ATmosphere

Loading comments...