Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/pin-init/src/__internal.rs
29280 views
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
#[cfg(feature = "std")]
192
fn stack_init_reuse() {
193
use ::std::{borrow::ToOwned, println, string::String};
194
use core::pin::pin;
195
196
#[derive(Debug)]
197
struct Foo {
198
a: usize,
199
b: String,
200
}
201
let mut slot: Pin<&mut StackInit<Foo>> = pin!(StackInit::uninit());
202
let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
203
slot.as_mut().init(crate::init!(Foo {
204
a: 42,
205
b: "Hello".to_owned(),
206
}));
207
let value = value.unwrap();
208
println!("{value:?}");
209
let value: Result<Pin<&mut Foo>, core::convert::Infallible> =
210
slot.as_mut().init(crate::init!(Foo {
211
a: 24,
212
b: "world!".to_owned(),
213
}));
214
let value = value.unwrap();
215
println!("{value:?}");
216
}
217
218
/// When a value of this type is dropped, it drops a `T`.
219
///
220
/// Can be forgotten to prevent the drop.
221
pub struct DropGuard<T: ?Sized> {
222
ptr: *mut T,
223
}
224
225
impl<T: ?Sized> DropGuard<T> {
226
/// Creates a new [`DropGuard<T>`]. It will [`ptr::drop_in_place`] `ptr` when it gets dropped.
227
///
228
/// # Safety
229
///
230
/// `ptr` must be a valid pointer.
231
///
232
/// It is the callers responsibility that `self` will only get dropped if the pointee of `ptr`:
233
/// - has not been dropped,
234
/// - is not accessible by any other means,
235
/// - will not be dropped by any other means.
236
#[inline]
237
pub unsafe fn new(ptr: *mut T) -> Self {
238
Self { ptr }
239
}
240
}
241
242
impl<T: ?Sized> Drop for DropGuard<T> {
243
#[inline]
244
fn drop(&mut self) {
245
// SAFETY: A `DropGuard` can only be constructed using the unsafe `new` function
246
// ensuring that this operation is safe.
247
unsafe { ptr::drop_in_place(self.ptr) }
248
}
249
}
250
251
/// Token used by `PinnedDrop` to prevent calling the function without creating this unsafely
252
/// created struct. This is needed, because the `drop` function is safe, but should not be called
253
/// manually.
254
pub struct OnlyCallFromDrop(());
255
256
impl OnlyCallFromDrop {
257
/// # Safety
258
///
259
/// This function should only be called from the [`Drop::drop`] function and only be used to
260
/// delegate the destruction to the pinned destructor [`PinnedDrop::drop`] of the same type.
261
pub unsafe fn new() -> Self {
262
Self(())
263
}
264
}
265
266
/// Initializer that always fails.
267
///
268
/// Used by [`assert_pinned!`].
269
///
270
/// [`assert_pinned!`]: crate::assert_pinned
271
pub struct AlwaysFail<T: ?Sized> {
272
_t: PhantomData<T>,
273
}
274
275
impl<T: ?Sized> AlwaysFail<T> {
276
/// Creates a new initializer that always fails.
277
pub fn new() -> Self {
278
Self { _t: PhantomData }
279
}
280
}
281
282
impl<T: ?Sized> Default for AlwaysFail<T> {
283
fn default() -> Self {
284
Self::new()
285
}
286
}
287
288
// SAFETY: `__pinned_init` always fails, which is always okay.
289
unsafe impl<T: ?Sized> PinInit<T, ()> for AlwaysFail<T> {
290
unsafe fn __pinned_init(self, _slot: *mut T) -> Result<(), ()> {
291
Err(())
292
}
293
}
294
295