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