1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 //! This module contains library internal items. 4 //! 5 //! These items must not be used outside of this crate and the pin-init-internal crate located at 6 //! `../internal`. 7 8 use super::*; 9 10 /// See the [nomicon] for what subtyping is. See also [this table]. 11 /// 12 /// The reason for not using `PhantomData<*mut T>` is that that type never implements [`Send`] and 13 /// [`Sync`]. Hence `fn(*mut T) -> *mut T` is used, as that type always implements them. 14 /// 15 /// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html 16 /// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns 17 pub(crate) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>; 18 19 /// Module-internal type implementing `PinInit` and `Init`. 20 /// 21 /// It is unsafe to create this type, since the closure needs to fulfill the same safety 22 /// requirement as the `__pinned_init`/`__init` functions. 23 pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) Invariant<(E, T)>); 24 25 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 26 // `__init` invariants. 27 unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E> 28 where 29 F: FnOnce(*mut T) -> Result<(), E>, 30 { 31 #[inline] 32 unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 33 (self.0)(slot) 34 } 35 } 36 37 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 38 // `__pinned_init` invariants. 39 unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E> 40 where 41 F: FnOnce(*mut T) -> Result<(), E>, 42 { 43 #[inline] 44 unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { 45 (self.0)(slot) 46 } 47 } 48 49 /// Token type to signify successful initialization. 50 /// 51 /// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this 52 /// token type to prevent returning `Ok` from an initializer without initializing all fields. 53 pub struct InitOk(()); 54 55 impl InitOk { 56 /// Creates a new token. 57 /// 58 /// # Safety 59 /// 60 /// This function may only be called from the `init!` macro in `../internal/src/init.rs`. 61 #[inline(always)] 62 pub unsafe fn new() -> Self { 63 Self(()) 64 } 65 } 66 67 /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate 68 /// the pin projections within the initializers. 69 /// 70 /// # Safety 71 /// 72 /// Only the `init` module is allowed to use this trait. 73 pub unsafe trait HasPinData { 74 type PinData: PinData; 75 76 #[expect(clippy::missing_safety_doc)] 77 unsafe fn __pin_data() -> Self::PinData; 78 } 79 80 /// Marker trait for pinning data of structs. 81 /// 82 /// # Safety 83 /// 84 /// Only the `init` module is allowed to use this trait. 85 pub unsafe trait PinData: Copy { 86 type Datee: ?Sized + HasPinData; 87 88 /// Type inference helper function. 89 #[inline(always)] 90 fn make_closure<F, E>(self, f: F) -> F 91 where 92 F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>, 93 { 94 f 95 } 96 } 97 98 /// This trait is automatically implemented for every type. It aims to provide the same type 99 /// inference help as `HasPinData`. 100 /// 101 /// # Safety 102 /// 103 /// Only the `init` module is allowed to use this trait. 104 pub unsafe trait HasInitData { 105 type InitData: InitData; 106 107 #[expect(clippy::missing_safety_doc)] 108 unsafe fn __init_data() -> Self::InitData; 109 } 110 111 /// Same function as `PinData`, but for arbitrary data. 112 /// 113 /// # Safety 114 /// 115 /// Only the `init` module is allowed to use this trait. 116 pub unsafe trait InitData: Copy { 117 type Datee: ?Sized + HasInitData; 118 119 /// Type inference helper function. 120 #[inline(always)] 121 fn make_closure<F, E>(self, f: F) -> F 122 where 123 F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>, 124 { 125 f 126 } 127 } 128 129 pub struct AllData<T: ?Sized>(Invariant<T>); 130 131 impl<T: ?Sized> Clone for AllData<T> { 132 fn clone(&self) -> Self { 133 *self 134 } 135 } 136 137 impl<T: ?Sized> Copy for AllData<T> {} 138 139 // SAFETY: TODO. 140 unsafe impl<T: ?Sized> InitData for AllData<T> { 141 type Datee = T; 142 } 143 144 // SAFETY: TODO. 145 unsafe impl<T: ?Sized> HasInitData for T { 146 type InitData = AllData<T>; 147 148 unsafe fn __init_data() -> Self::InitData { 149 AllData(PhantomData) 150 } 151 } 152 153 /// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. 154 /// 155 /// # Invariants 156 /// 157 /// If `self.is_init` is true, then `self.value` is initialized. 158 /// 159 /// [`stack_pin_init`]: crate::stack_pin_init 160 pub struct StackInit<T> { 161 value: MaybeUninit<T>, 162 is_init: bool, 163 } 164 165 impl<T> Drop for StackInit<T> { 166 #[inline] 167 fn drop(&mut self) { 168 if self.is_init { 169 // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is 170 // true, `self.value` is initialized. 171 unsafe { self.value.assume_init_drop() }; 172 } 173 } 174 } 175 176 impl<T> StackInit<T> { 177 /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this 178 /// primitive. 179 /// 180 /// [`stack_pin_init`]: crate::stack_pin_init 181 #[inline] 182 pub fn uninit() -> Self { 183 Self { 184 value: MaybeUninit::uninit(), 185 is_init: false, 186 } 187 } 188 189 /// Initializes the contents and returns the result. 190 #[inline] 191 pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> { 192 // SAFETY: We never move out of `this`. 193 let this = unsafe { Pin::into_inner_unchecked(self) }; 194 // The value is currently initialized, so it needs to be dropped before we can reuse 195 // the memory (this is a safety guarantee of `Pin`). 196 if this.is_init { 197 this.is_init = false; 198 // SAFETY: `this.is_init` was true and therefore `this.value` is initialized. 199 unsafe { this.value.assume_init_drop() }; 200 } 201 // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. 202 unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; 203 // INVARIANT: `this.value` is initialized above. 204 this.is_init = true; 205 // SAFETY: The slot is now pinned, since we will never give access to `&mut T`. 206 Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) }) 207 } 208 } 209 210 #[test] 211 #[cfg(feature = "std")] 212 fn stack_init_reuse() { 213 use ::std::{borrow::ToOwned, println, string::String}; 214 use core::pin::pin; 215 216 #[derive(Debug)] 217 struct Foo { 218 a: usize, 219 b: String, 220 } 221 let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit()); 222 let value: Result<Pin<&mut Foo>, core::convert::Infallible> = 223 slot.as_mut().init(crate::init!(Foo { 224 a: 42, 225 b: "Hello".to_owned(), 226 })); 227 let value = value.unwrap(); 228 println!("{value:?}"); 229 let value: Result<Pin<&mut Foo>, core::convert::Infallible> = 230 slot.as_mut().init(crate::init!(Foo { 231 a: 24, 232 b: "world!".to_owned(), 233 })); 234 let value = value.unwrap(); 235 println!("{value:?}"); 236 } 237 238 /// When a value of this type is dropped, it drops a `T`. 239 /// 240 /// Can be forgotten to prevent the drop. 241 /// 242 /// # Invariants 243 /// 244 /// - `ptr` is valid and properly aligned. 245 /// - `*ptr` is initialized and owned by this guard. 246 pub struct DropGuard<T: ?Sized> { 247 ptr: *mut T, 248 } 249 250 impl<T: ?Sized> DropGuard<T> { 251 /// Creates a drop guard and transfer the ownership of the pointer content. 252 /// 253 /// The ownership is only relinguished if the guard is forgotten via [`core::mem::forget`]. 254 /// 255 /// # Safety 256 /// 257 /// - `ptr` is valid and properly aligned. 258 /// - `*ptr` is initialized, and the ownership is transferred to this guard. 259 #[inline] 260 pub unsafe fn new(ptr: *mut T) -> Self { 261 // INVARIANT: By safety requirement. 262 Self { ptr } 263 } 264 265 /// Create a let binding for accessor use. 266 #[inline] 267 pub fn let_binding(&mut self) -> &mut T { 268 // SAFETY: Per type invariant. 269 unsafe { &mut *self.ptr } 270 } 271 } 272 273 impl<T: ?Sized> Drop for DropGuard<T> { 274 #[inline] 275 fn drop(&mut self) { 276 // SAFETY: `self.ptr` is valid, properly aligned and `*self.ptr` is owned by this guard. 277 unsafe { ptr::drop_in_place(self.ptr) } 278 } 279 } 280 281 /// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely 282 /// created struct. This is needed, because the `drop` function is safe, but should not be called 283 /// manually. 284 pub struct OnlyCallFromDrop(()); 285 286 impl OnlyCallFromDrop { 287 /// # Safety 288 /// 289 /// This function should only be called from the [`Drop::drop`] function and only be used to 290 /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type. 291 pub unsafe fn new() -> Self { 292 Self(()) 293 } 294 } 295 296 /// Initializer that always fails. 297 /// 298 /// Used by [`assert_pinned!`]. 299 /// 300 /// [`assert_pinned!`]: crate::assert_pinned 301 pub struct AlwaysFail<T: ?Sized> { 302 _t: PhantomData<T>, 303 } 304 305 impl<T: ?Sized> AlwaysFail<T> { 306 /// Creates a new initializer that always fails. 307 pub fn new() -> Self { 308 Self { _t: PhantomData } 309 } 310 } 311 312 impl<T: ?Sized> Default for AlwaysFail<T> { 313 fn default() -> Self { 314 Self::new() 315 } 316 } 317 318 // SAFETY: `__pinned_init` always fails, which is always okay. 319 unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> { 320 unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> { 321 Err(()) 322 } 323 } 324