diff --git a/CHANGELOG.md b/CHANGELOG.md index ab61f6f4..27815798 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `[pin_]init_scope` functions to run arbitrary code inside of an initializer. +- `&'static mut MaybeUninit` now implements `InPlaceWrite`. This enables users to use external + allocation mechanisms such as `static_cell`. ### Changed diff --git a/src/lib.rs b/src/lib.rs index 8dc9dd5a..ea59c86a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1536,6 +1536,33 @@ pub trait InPlaceWrite { fn write_pin_init(self, init: impl PinInit) -> Result, E>; } +impl InPlaceWrite for &'static mut MaybeUninit { + type Initialized = &'static mut T; + + fn write_init(self, init: impl Init) -> Result { + let slot = self.as_mut_ptr(); + + // SAFETY: `slot` is a valid pointer to uninitialized memory. + unsafe { init.__init(slot)? }; + + // SAFETY: The above call initialized the memory. + unsafe { Ok(self.assume_init_mut()) } + } + + fn write_pin_init(self, init: impl PinInit) -> Result, E> { + let slot = self.as_mut_ptr(); + + // SAFETY: `slot` is a valid pointer to uninitialized memory. + // + // The `'static` borrow guarantees the data will not be + // moved/invalidated until it gets dropped (which is never). + unsafe { init.__pinned_init(slot)? }; + + // SAFETY: The above call initialized the memory. + Ok(Pin::static_mut(unsafe { self.assume_init_mut() })) + } +} + /// Trait facilitating pinned destruction. /// /// Use [`pinned_drop`] to implement this trait safely: