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 /// Zero-sized type used to mark a type as invariant. 11 /// 12 /// This is a polyfill for the [unstable type] in the standard library of the same name. 13 /// 14 /// See the [nomicon] for what subtyping is. See also [this table]. 15 /// 16 /// [unstable type]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomInvariant.html 17 /// [nomicon]: https://doc.rust-lang.org/nomicon/subtyping.html 18 /// [this table]: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns 19 #[repr(transparent)] 20 pub struct PhantomInvariant<T: ?Sized>(PhantomData<fn(T) -> T>); 21 22 impl<T: ?Sized> Clone for PhantomInvariant<T> { 23 #[inline(always)] 24 fn clone(&self) -> Self { 25 *self 26 } 27 } 28 29 impl<T: ?Sized> Copy for PhantomInvariant<T> {} 30 31 impl<T: ?Sized> Default for PhantomInvariant<T> { 32 #[inline(always)] 33 fn default() -> Self { 34 Self::new() 35 } 36 } 37 38 impl<T: ?Sized> PhantomInvariant<T> { 39 #[inline(always)] 40 pub const fn new() -> Self { 41 Self(PhantomData) 42 } 43 } 44 45 /// Zero-sized type used to mark a lifetime as invariant. 46 /// 47 /// This is a polyfill for the [unstable type] in the standard library of the same name. 48 /// 49 /// [unstable type]: https://doc.rust-lang.org/nightly/std/marker/struct.PhantomInvariantLifetime.html 50 #[repr(transparent)] 51 #[derive(Clone, Copy, Default)] 52 pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>); 53 54 impl PhantomInvariantLifetime<'_> { 55 #[inline(always)] 56 pub const fn new() -> Self { 57 Self(PhantomInvariant::new()) 58 } 59 } 60 61 /// Module-internal type implementing `PinInit` and `Init`. 62 /// 63 /// It is unsafe to create this type, since the closure needs to fulfill the same safety 64 /// requirement as the `__pinned_init`/`__init` functions. 65 pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) PhantomInvariant<(E, T)>); 66 67 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 68 // `__init` invariants. 69 unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E> 70 where 71 F: FnOnce(*mut T) -> Result<(), E>, 72 { 73 #[inline] 74 unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 75 (self.0)(slot) 76 } 77 } 78 79 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 80 // `__pinned_init` invariants. 81 unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E> 82 where 83 F: FnOnce(*mut T) -> Result<(), E>, 84 { 85 #[inline] 86 unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { 87 (self.0)(slot) 88 } 89 } 90 91 /// Token type to signify successful initialization. 92 /// 93 /// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this 94 /// token type to prevent returning `Ok` from an initializer without initializing all fields. 95 pub struct InitOk(()); 96 97 impl InitOk { 98 /// Creates a new token. 99 /// 100 /// # Safety 101 /// 102 /// This function may only be called from the `init!` macro in `../internal/src/init.rs`. 103 #[inline(always)] 104 pub unsafe fn new() -> Self { 105 Self(()) 106 } 107 } 108 109 /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate 110 /// the pin projections within the initializers. 111 /// 112 /// # Safety 113 /// 114 /// Only the `init` module is allowed to use this trait. 115 pub unsafe trait HasPinData { 116 type PinData; 117 118 #[expect(clippy::missing_safety_doc)] 119 unsafe fn __pin_data() -> Self::PinData; 120 } 121 122 /// This trait is automatically implemented for every type. It aims to provide the same type 123 /// inference help as `HasPinData`. 124 /// 125 /// # Safety 126 /// 127 /// Only the `init` module is allowed to use this trait. 128 pub unsafe trait HasInitData { 129 type InitData; 130 131 #[expect(clippy::missing_safety_doc)] 132 unsafe fn __init_data() -> Self::InitData; 133 } 134 135 pub struct AllData<T: ?Sized>(PhantomInvariant<T>); 136 137 impl<T: ?Sized> Clone for AllData<T> { 138 fn clone(&self) -> Self { 139 *self 140 } 141 } 142 143 impl<T: ?Sized> Copy for AllData<T> {} 144 145 impl<T: ?Sized> AllData<T> { 146 /// Type inference helper function. 147 #[inline(always)] 148 pub fn __make_closure<F, E>(self, f: F) -> F 149 where 150 F: FnOnce(*mut T) -> Result<InitOk, E>, 151 { 152 f 153 } 154 } 155 156 // SAFETY: TODO. 157 unsafe impl<T: ?Sized> HasInitData for T { 158 type InitData = AllData<T>; 159 160 unsafe fn __init_data() -> Self::InitData { 161 AllData(PhantomInvariant::new()) 162 } 163 } 164 165 /// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. 166 /// 167 /// # Invariants 168 /// 169 /// If `self.is_init` is true, then `self.value` is initialized. 170 /// 171 /// [`stack_pin_init`]: crate::stack_pin_init 172 pub struct StackInit<T> { 173 value: MaybeUninit<T>, 174 is_init: bool, 175 } 176 177 impl<T> Drop for StackInit<T> { 178 #[inline] 179 fn drop(&mut self) { 180 if self.is_init { 181 // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is 182 // true, `self.value` is initialized. 183 unsafe { self.value.assume_init_drop() }; 184 } 185 } 186 } 187 188 impl<T> StackInit<T> { 189 /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this 190 /// primitive. 191 /// 192 /// [`stack_pin_init`]: crate::stack_pin_init 193 #[inline] 194 pub fn uninit() -> Self { 195 Self { 196 value: MaybeUninit::uninit(), 197 is_init: false, 198 } 199 } 200 201 /// Initializes the contents and returns the result. 202 #[inline] 203 pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> { 204 // SAFETY: We never move out of `this`. 205 let this = unsafe { Pin::into_inner_unchecked(self) }; 206 // The value is currently initialized, so it needs to be dropped before we can reuse 207 // the memory (this is a safety guarantee of `Pin`). 208 if this.is_init { 209 this.is_init = false; 210 // SAFETY: `this.is_init` was true and therefore `this.value` is initialized. 211 unsafe { this.value.assume_init_drop() }; 212 } 213 // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. 214 unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; 215 // INVARIANT: `this.value` is initialized above. 216 this.is_init = true; 217 // SAFETY: The slot is now pinned, since we will never give access to `&mut T`. 218 Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) }) 219 } 220 } 221 222 #[test] 223 #[cfg(feature = "std")] 224 fn stack_init_reuse() { 225 use ::std::{borrow::ToOwned, println, string::String}; 226 use core::pin::pin; 227 228 #[derive(Debug)] 229 struct Foo { 230 a: usize, 231 b: String, 232 } 233 let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit()); 234 let value: Result<Pin<&mut Foo>, core::convert::Infallible> = 235 slot.as_mut().init(crate::init!(Foo { 236 a: 42, 237 b: "Hello".to_owned(), 238 })); 239 let value = value.unwrap(); 240 println!("{value:?}"); 241 let value: Result<Pin<&mut Foo>, core::convert::Infallible> = 242 slot.as_mut().init(crate::init!(Foo { 243 a: 24, 244 b: "world!".to_owned(), 245 })); 246 let value = value.unwrap(); 247 println!("{value:?}"); 248 } 249 250 // Marker types that determines type of `DropGuard`'s let bindings. 251 pub struct Pinned; 252 pub struct Unpinned; 253 254 /// Represent an uninitialized field. 255 /// 256 /// # Invariants 257 /// 258 /// - `ptr` is valid, properly aligned and points to uninitialized and exclusively accessed memory. 259 /// - If `P` is `Pinned`, then `ptr` is structurally pinned. 260 pub struct Slot<P, T: ?Sized> { 261 ptr: *mut T, 262 _phantom: PhantomData<P>, 263 } 264 265 impl<P, T: ?Sized> Slot<P, T> { 266 /// # Safety 267 /// 268 /// - `ptr` is valid, properly aligned and points to uninitialized and exclusively accessed 269 /// memory. 270 /// - If `P` is `Pinned`, then `ptr` is structurally pinned. 271 #[inline(always)] 272 pub unsafe fn new(ptr: *mut T) -> Self { 273 // INVARIANT: Per safety requirement. 274 Self { 275 ptr, 276 _phantom: PhantomData, 277 } 278 } 279 280 /// Initialize the field by value. 281 #[inline(always)] 282 pub fn write(self, value: T) -> DropGuard<P, T> 283 where 284 T: Sized, 285 { 286 // SAFETY: `self.ptr` is a valid and aligned pointer for write. 287 unsafe { self.ptr.write(value) } 288 // SAFETY: 289 // - `self.ptr` is valid and properly aligned per type invariant. 290 // - `*self.ptr` is initialized above and the ownership is transferred to the guard. 291 // - If `P` is `Pinned`, `self.ptr` is pinned. 292 unsafe { DropGuard::new(self.ptr) } 293 } 294 } 295 296 impl<T: ?Sized> Slot<Unpinned, T> { 297 /// Initialize the field. 298 #[inline(always)] 299 pub fn init<E>(self, init: impl Init<T, E>) -> Result<DropGuard<Unpinned, T>, E> { 300 // SAFETY: 301 // - `self.ptr` is valid and properly aligned. 302 // - when `Err` is returned, we also propagate the error without touching `slot`; 303 // also `self` is consumed so it cannot be touched further. 304 unsafe { init.__init(self.ptr)? }; 305 306 // SAFETY: 307 // - `self.ptr` is valid and properly aligned per type invariant. 308 // - `*self.ptr` is initialized above and the ownership is transferred to the guard. 309 Ok(unsafe { DropGuard::new(self.ptr) }) 310 } 311 } 312 313 impl<T: ?Sized> Slot<Pinned, T> { 314 /// Initialize the field. 315 #[inline(always)] 316 pub fn init<E>(self, init: impl PinInit<T, E>) -> Result<DropGuard<Pinned, T>, E> { 317 // SAFETY: 318 // - `self.ptr` is valid and properly aligned. 319 // - when `Err` is returned, we also propagate the error without touching `ptr`; 320 // also `self` is consumed so it cannot be touched further. 321 // - the drop guard will not hand out `&mut` (only `Pin<&mut T>`). 322 unsafe { init.__pinned_init(self.ptr)? }; 323 324 // SAFETY: 325 // - `self.ptr` is valid, properly aligned and pinned per type invariant. 326 // - `*self.ptr` is initialized above and the ownership is transferred to the guard. 327 Ok(unsafe { DropGuard::new(self.ptr) }) 328 } 329 } 330 331 /// When a value of this type is dropped, it drops a `T`. 332 /// 333 /// Can be forgotten to prevent the drop. 334 /// 335 /// # Invariants 336 /// 337 /// - `ptr` is valid and properly aligned. 338 /// - `*ptr` is initialized and owned by this guard. 339 /// - if `P` is `Pinned`, `ptr` is pinned. 340 pub struct DropGuard<P, T: ?Sized> { 341 ptr: *mut T, 342 phantom: PhantomData<P>, 343 } 344 345 impl<P, T: ?Sized> DropGuard<P, T> { 346 /// Creates a drop guard and transfer the ownership of the pointer content. 347 /// 348 /// The ownership is only relinguished if the guard is forgotten via [`core::mem::forget`]. 349 /// 350 /// # Safety 351 /// 352 /// - `ptr` is valid and properly aligned. 353 /// - `*ptr` is initialized, and the ownership is transferred to this guard. 354 /// - if `P` is `Pinned`, `ptr` is pinned. 355 #[inline] 356 pub unsafe fn new(ptr: *mut T) -> Self { 357 // INVARIANT: By safety requirement. 358 Self { 359 ptr, 360 phantom: PhantomData, 361 } 362 } 363 } 364 365 impl<T: ?Sized> DropGuard<Unpinned, T> { 366 /// Create a let binding for accessor use. 367 #[inline] 368 pub fn let_binding(&mut self) -> &mut T { 369 // SAFETY: Per type invariant. 370 unsafe { &mut *self.ptr } 371 } 372 } 373 374 impl<T: ?Sized> DropGuard<Pinned, T> { 375 /// Create a let binding for accessor use. 376 #[inline] 377 pub fn let_binding(&mut self) -> Pin<&mut T> { 378 // SAFETY: `self.ptr` is valid, properly aligned, initialized, exclusively accessible and 379 // pinned per type invariant. 380 unsafe { Pin::new_unchecked(&mut *self.ptr) } 381 } 382 } 383 384 impl<P, T: ?Sized> Drop for DropGuard<P, T> { 385 #[inline] 386 fn drop(&mut self) { 387 // SAFETY: `self.ptr` is valid, properly aligned and `*self.ptr` is owned by this guard. 388 unsafe { ptr::drop_in_place(self.ptr) } 389 } 390 } 391 392 /// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely 393 /// created struct. This is needed, because the `drop` function is safe, but should not be called 394 /// manually. 395 pub struct OnlyCallFromDrop(()); 396 397 impl OnlyCallFromDrop { 398 /// # Safety 399 /// 400 /// This function should only be called from the [`Drop::drop`] function and only be used to 401 /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type. 402 pub unsafe fn new() -> Self { 403 Self(()) 404 } 405 } 406 407 /// Initializer that always fails. 408 /// 409 /// Used by [`assert_pinned!`]. 410 /// 411 /// [`assert_pinned!`]: crate::assert_pinned 412 pub struct AlwaysFail<T: ?Sized> { 413 _t: PhantomData<T>, 414 } 415 416 impl<T: ?Sized> AlwaysFail<T> { 417 /// Creates a new initializer that always fails. 418 pub fn new() -> Self { 419 Self { _t: PhantomData } 420 } 421 } 422 423 impl<T: ?Sized> Default for AlwaysFail<T> { 424 fn default() -> Self { 425 Self::new() 426 } 427 } 428 429 // SAFETY: `__pinned_init` always fails, which is always okay. 430 unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> { 431 unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> { 432 Err(()) 433 } 434 } 435