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 /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate 50 /// the pin projections within the initializers. 51 /// 52 /// # Safety 53 /// 54 /// Only the `init` module is allowed to use this trait. 55 pub unsafe trait HasPinData { 56 type PinData: PinData; 57 58 #[expect(clippy::missing_safety_doc)] 59 unsafe fn __pin_data() -> Self::PinData; 60 } 61 62 /// Marker trait for pinning data of structs. 63 /// 64 /// # Safety 65 /// 66 /// Only the `init` module is allowed to use this trait. 67 pub unsafe trait PinData: Copy { 68 type Datee: ?Sized + HasPinData; 69 70 /// Type inference helper function. 71 fn make_closure<F, O, E>(self, f: F) -> F 72 where 73 F: FnOnce(*mut Self::Datee) -> Result<O, E>, 74 { 75 f 76 } 77 } 78 79 /// This trait is automatically implemented for every type. It aims to provide the same type 80 /// inference help as `HasPinData`. 81 /// 82 /// # Safety 83 /// 84 /// Only the `init` module is allowed to use this trait. 85 pub unsafe trait HasInitData { 86 type InitData: InitData; 87 88 #[expect(clippy::missing_safety_doc)] 89 unsafe fn __init_data() -> Self::InitData; 90 } 91 92 /// Same function as `PinData`, but for arbitrary data. 93 /// 94 /// # Safety 95 /// 96 /// Only the `init` module is allowed to use this trait. 97 pub unsafe trait InitData: Copy { 98 type Datee: ?Sized + HasInitData; 99 100 /// Type inference helper function. 101 fn make_closure<F, O, E>(self, f: F) -> F 102 where 103 F: FnOnce(*mut Self::Datee) -> Result<O, E>, 104 { 105 f 106 } 107 } 108 109 pub struct AllData<T: ?Sized>(Invariant<T>); 110 111 impl<T: ?Sized> Clone for AllData<T> { 112 fn clone(&self) -> Self { 113 *self 114 } 115 } 116 117 impl<T: ?Sized> Copy for AllData<T> {} 118 119 // SAFETY: TODO. 120 unsafe impl<T: ?Sized> InitData for AllData<T> { 121 type Datee = T; 122 } 123 124 // SAFETY: TODO. 125 unsafe impl<T: ?Sized> HasInitData for T { 126 type InitData = AllData<T>; 127 128 unsafe fn __init_data() -> Self::InitData { 129 AllData(PhantomData) 130 } 131 } 132 133 /// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. 134 /// 135 /// # Invariants 136 /// 137 /// If `self.is_init` is true, then `self.value` is initialized. 138 /// 139 /// [`stack_pin_init`]: crate::stack_pin_init 140 pub struct StackInit<T> { 141 value: MaybeUninit<T>, 142 is_init: bool, 143 } 144 145 impl<T> Drop for StackInit<T> { 146 #[inline] 147 fn drop(&mut self) { 148 if self.is_init { 149 // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is 150 // true, `self.value` is initialized. 151 unsafe { self.value.assume_init_drop() }; 152 } 153 } 154 } 155 156 impl<T> StackInit<T> { 157 /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this 158 /// primitive. 159 /// 160 /// [`stack_pin_init`]: crate::stack_pin_init 161 #[inline] 162 pub fn uninit() -> Self { 163 Self { 164 value: MaybeUninit::uninit(), 165 is_init: false, 166 } 167 } 168 169 /// Initializes the contents and returns the result. 170 #[inline] 171 pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> { 172 // SAFETY: We never move out of `this`. 173 let this = unsafe { Pin::into_inner_unchecked(self) }; 174 // The value is currently initialized, so it needs to be dropped before we can reuse 175 // the memory (this is a safety guarantee of `Pin`). 176 if this.is_init { 177 this.is_init = false; 178 // SAFETY: `this.is_init` was true and therefore `this.value` is initialized. 179 unsafe { this.value.assume_init_drop() }; 180 } 181 // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. 182 unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; 183 // INVARIANT: `this.value` is initialized above. 184 this.is_init = true; 185 // SAFETY: The slot is now pinned, since we will never give access to `&mut T`. 186 Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) }) 187 } 188 } 189 190 #[test] 191 fn stack_init_reuse() { 192 use ::std::{borrow::ToOwned, println, string::String}; 193 use core::pin::pin; 194 195 #[derive(Debug)] 196 struct Foo { 197 a: usize, 198 b: String, 199 } 200 let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit()); 201 let value: Result<Pin<&mut Foo>, core::convert::Infallible> = 202 slot.as_mut().init(crate::init!(Foo { 203 a: 42, 204 b: "Hello".to_owned(), 205 })); 206 let value = value.unwrap(); 207 println!("{value:?}"); 208 let value: Result<Pin<&mut Foo>, core::convert::Infallible> = 209 slot.as_mut().init(crate::init!(Foo { 210 a: 24, 211 b: "world!".to_owned(), 212 })); 213 let value = value.unwrap(); 214 println!("{value:?}"); 215 } 216 217 /// When a value of this type is dropped, it drops a `T`. 218 /// 219 /// Can be forgotten to prevent the drop. 220 pub struct DropGuard<T: ?Sized> { 221 ptr: *mut T, 222 } 223 224 impl<T: ?Sized> DropGuard<T> { 225 /// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped. 226 /// 227 /// # Safety 228 /// 229 /// `ptr` must be a valid pointer. 230 /// 231 /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`: 232 /// - has not been dropped, 233 /// - is not accessible by any other means, 234 /// - will not be dropped by any other means. 235 #[inline] 236 pub unsafe fn new(ptr: *mut T) -> Self { 237 Self { ptr } 238 } 239 } 240 241 impl<T: ?Sized> Drop for DropGuard<T> { 242 #[inline] 243 fn drop(&mut self) { 244 // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function 245 // ensuring that this operation is safe. 246 unsafe { ptr::drop_in_place(self.ptr) } 247 } 248 } 249 250 /// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely 251 /// created struct. This is needed, because the `drop` function is safe, but should not be called 252 /// manually. 253 pub struct OnlyCallFromDrop(()); 254 255 impl OnlyCallFromDrop { 256 /// # Safety 257 /// 258 /// This function should only be called from the [`Drop::drop`] function and only be used to 259 /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type. 260 pub unsafe fn new() -> Self { 261 Self(()) 262 } 263 } 264 265 /// Initializer that always fails. 266 /// 267 /// Used by [`assert_pinned!`]. 268 /// 269 /// [`assert_pinned!`]: crate::assert_pinned 270 pub struct AlwaysFail<T: ?Sized> { 271 _t: PhantomData<T>, 272 } 273 274 impl<T: ?Sized> AlwaysFail<T> { 275 /// Creates a new initializer that always fails. 276 pub fn new() -> Self { 277 Self { _t: PhantomData } 278 } 279 } 280 281 impl<T: ?Sized> Default for AlwaysFail<T> { 282 fn default() -> Self { 283 Self::new() 284 } 285 } 286 287 // SAFETY: `__pinned_init` always fails, which is always okay. 288 unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> { 289 unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> { 290 Err(()) 291 } 292 } 293