1 // SPDX-License-Identifier: Apache-2.0 OR MIT 2 3 //! This module contains API-internal items for pin-init. 4 //! 5 //! These items must not be used outside of 6 //! - `kernel/init.rs` 7 //! - `macros/pin_data.rs` 8 //! - `macros/pinned_drop.rs` 9 10 use super::*; 11 12 /// See the [nomicon] for what subtyping is. See also [this table]. 13 /// 14 /// The reason for not using `PhantomData<*mut T>` is that that type never implements [`Send`] and 15 /// [`Sync`]. Hence `fn(*mut T) -> *mut T` is used, as that type always implements them. 16 /// 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 pub(super) type Invariant<T> = PhantomData<fn(*mut T) -> *mut T>; 20 21 /// Module-internal type implementing `PinInit` and `Init`. 22 /// 23 /// It is unsafe to create this type, since the closure needs to fulfill the same safety 24 /// requirement as the `__pinned_init`/`__init` functions. 25 pub(crate) struct InitClosure<F, T: ?Sized, E>(pub(crate) F, pub(crate) Invariant<(E, T)>); 26 27 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 28 // `__init` invariants. 29 unsafe impl<T: ?Sized, F, E> Init<T, E> for InitClosure<F, T, E> 30 where 31 F: FnOnce(*mut T) -> Result<(), E>, 32 { 33 #[inline] 34 unsafe fn __init(self, slot: *mut T) -> Result<(), E> { 35 (self.0)(slot) 36 } 37 } 38 39 // SAFETY: While constructing the `InitClosure`, the user promised that it upholds the 40 // `__pinned_init` invariants. 41 unsafe impl<T: ?Sized, F, E> PinInit<T, E> for InitClosure<F, T, E> 42 where 43 F: FnOnce(*mut T) -> Result<(), E>, 44 { 45 #[inline] 46 unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> { 47 (self.0)(slot) 48 } 49 } 50 51 /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate 52 /// the pin projections within the initializers. 53 /// 54 /// # Safety 55 /// 56 /// Only the `init` module is allowed to use this trait. 57 pub unsafe trait HasPinData { 58 type PinData: PinData; 59 60 #[expect(clippy::missing_safety_doc)] 61 unsafe fn __pin_data() -> Self::PinData; 62 } 63 64 /// Marker trait for pinning data of structs. 65 /// 66 /// # Safety 67 /// 68 /// Only the `init` module is allowed to use this trait. 69 pub unsafe trait PinData: Copy { 70 type Datee: ?Sized + HasPinData; 71 72 /// Type inference helper function. 73 fn make_closure<F, O, E>(self, f: F) -> F 74 where 75 F: FnOnce(*mut Self::Datee) -> Result<O, E>, 76 { 77 f 78 } 79 } 80 81 /// This trait is automatically implemented for every type. It aims to provide the same type 82 /// inference help as `HasPinData`. 83 /// 84 /// # Safety 85 /// 86 /// Only the `init` module is allowed to use this trait. 87 pub unsafe trait HasInitData { 88 type InitData: InitData; 89 90 #[expect(clippy::missing_safety_doc)] 91 unsafe fn __init_data() -> Self::InitData; 92 } 93 94 /// Same function as `PinData`, but for arbitrary data. 95 /// 96 /// # Safety 97 /// 98 /// Only the `init` module is allowed to use this trait. 99 pub unsafe trait InitData: Copy { 100 type Datee: ?Sized + HasInitData; 101 102 /// Type inference helper function. 103 fn make_closure<F, O, E>(self, f: F) -> F 104 where 105 F: FnOnce(*mut Self::Datee) -> Result<O, E>, 106 { 107 f 108 } 109 } 110 111 pub struct AllData<T: ?Sized>(Invariant<T>); 112 113 impl<T: ?Sized> Clone for AllData<T> { 114 fn clone(&self) -> Self { 115 *self 116 } 117 } 118 119 impl<T: ?Sized> Copy for AllData<T> {} 120 121 // SAFETY: TODO. 122 unsafe impl<T: ?Sized> InitData for AllData<T> { 123 type Datee = T; 124 } 125 126 // SAFETY: TODO. 127 unsafe impl<T: ?Sized> HasInitData for T { 128 type InitData = AllData<T>; 129 130 unsafe fn __init_data() -> Self::InitData { 131 AllData(PhantomData) 132 } 133 } 134 135 /// Stack initializer helper type. Use [`stack_pin_init`] instead of this primitive. 136 /// 137 /// # Invariants 138 /// 139 /// If `self.is_init` is true, then `self.value` is initialized. 140 /// 141 /// [`stack_pin_init`]: crate::stack_pin_init 142 pub struct StackInit<T> { 143 value: MaybeUninit<T>, 144 is_init: bool, 145 } 146 147 impl<T> Drop for StackInit<T> { 148 #[inline] 149 fn drop(&mut self) { 150 if self.is_init { 151 // SAFETY: As we are being dropped, we only call this once. And since `self.is_init` is 152 // true, `self.value` is initialized. 153 unsafe { self.value.assume_init_drop() }; 154 } 155 } 156 } 157 158 impl<T> StackInit<T> { 159 /// Creates a new [`StackInit<T>`] that is uninitialized. Use [`stack_pin_init`] instead of this 160 /// primitive. 161 /// 162 /// [`stack_pin_init`]: crate::stack_pin_init 163 #[inline] 164 pub fn uninit() -> Self { 165 Self { 166 value: MaybeUninit::uninit(), 167 is_init: false, 168 } 169 } 170 171 /// Initializes the contents and returns the result. 172 #[inline] 173 pub fn init<E>(self: Pin<&mut Self>, init: impl PinInit<T, E>) -> Result<Pin<&mut T>, E> { 174 // SAFETY: We never move out of `this`. 175 let this = unsafe { Pin::into_inner_unchecked(self) }; 176 // The value is currently initialized, so it needs to be dropped before we can reuse 177 // the memory (this is a safety guarantee of `Pin`). 178 if this.is_init { 179 this.is_init = false; 180 // SAFETY: `this.is_init` was true and therefore `this.value` is initialized. 181 unsafe { this.value.assume_init_drop() }; 182 } 183 // SAFETY: The memory slot is valid and this type ensures that it will stay pinned. 184 unsafe { init.__pinned_init(this.value.as_mut_ptr())? }; 185 // INVARIANT: `this.value` is initialized above. 186 this.is_init = true; 187 // SAFETY: The slot is now pinned, since we will never give access to `&mut T`. 188 Ok(unsafe { Pin::new_unchecked(this.value.assume_init_mut()) }) 189 } 190 } 191 192 /// When a value of this type is dropped, it drops a `T`. 193 /// 194 /// Can be forgotten to prevent the drop. 195 pub struct DropGuard<T: ?Sized> { 196 ptr: *mut T, 197 } 198 199 impl<T: ?Sized> DropGuard<T> { 200 /// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped. 201 /// 202 /// # Safety 203 /// 204 /// `ptr` must be a valid pointer. 205 /// 206 /// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`: 207 /// - has not been dropped, 208 /// - is not accessible by any other means, 209 /// - will not be dropped by any other means. 210 #[inline] 211 pub unsafe fn new(ptr: *mut T) -> Self { 212 Self { ptr } 213 } 214 } 215 216 impl<T: ?Sized> Drop for DropGuard<T> { 217 #[inline] 218 fn drop(&mut self) { 219 // SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function 220 // ensuring that this operation is safe. 221 unsafe { ptr::drop_in_place(self.ptr) } 222 } 223 } 224 225 /// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely 226 /// created struct. This is needed, because the `drop` function is safe, but should not be called 227 /// manually. 228 pub struct OnlyCallFromDrop(()); 229 230 impl OnlyCallFromDrop { 231 /// # Safety 232 /// 233 /// This function should only be called from the [`Drop::drop`] function and only be used to 234 /// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type. 235 pub unsafe fn new() -> Self { 236 Self(()) 237 } 238 } 239 240 /// Initializer that always fails. 241 /// 242 /// Used by [`assert_pinned!`]. 243 /// 244 /// [`assert_pinned!`]: crate::assert_pinned 245 pub struct AlwaysFail<T: ?Sized> { 246 _t: PhantomData<T>, 247 } 248 249 impl<T: ?Sized> AlwaysFail<T> { 250 /// Creates a new initializer that always fails. 251 pub fn new() -> Self { 252 Self { _t: PhantomData } 253 } 254 } 255 256 impl<T: ?Sized> Default for AlwaysFail<T> { 257 fn default() -> Self { 258 Self::new() 259 } 260 } 261 262 // SAFETY: `__pinned_init` always fails, which is always okay. 263 unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> { 264 unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> { 265 Err(()) 266 } 267 } 268