1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | |
3 | /*! |
4 | <!-- Note: Document from sync-markdown-to-rustdoc:start through sync-markdown-to-rustdoc:end |
5 | is synchronized from README.md. Any changes to that range are not preserved. --> |
6 | <!-- tidy:sync-markdown-to-rustdoc:start --> |
7 | |
8 | A crate for safe and ergonomic [pin-projection]. |
9 | |
10 | ## Usage |
11 | |
12 | Add this to your `Cargo.toml`: |
13 | |
14 | ```toml |
15 | [dependencies] |
16 | pin-project = "1" |
17 | ``` |
18 | |
19 | ## Examples |
20 | |
21 | [`#[pin_project]`][`pin_project`] attribute creates projection types |
22 | covering all the fields of struct or enum. |
23 | |
24 | ``` |
25 | use std::pin::Pin; |
26 | |
27 | use pin_project::pin_project; |
28 | |
29 | #[pin_project] |
30 | struct Struct<T, U> { |
31 | #[pin] |
32 | pinned: T, |
33 | unpinned: U, |
34 | } |
35 | |
36 | impl<T, U> Struct<T, U> { |
37 | fn method(self: Pin<&mut Self>) { |
38 | let this = self.project(); |
39 | let _: Pin<&mut T> = this.pinned; // Pinned reference to the field |
40 | let _: &mut U = this.unpinned; // Normal reference to the field |
41 | } |
42 | } |
43 | ``` |
44 | |
45 | [*code like this will be generated*][struct-default-expanded] |
46 | |
47 | To use `#[pin_project]` on enums, you need to name the projection type |
48 | returned from the method. |
49 | |
50 | ``` |
51 | use std::pin::Pin; |
52 | |
53 | use pin_project::pin_project; |
54 | |
55 | #[pin_project(project = EnumProj)] |
56 | enum Enum<T, U> { |
57 | Pinned(#[pin] T), |
58 | Unpinned(U), |
59 | } |
60 | |
61 | impl<T, U> Enum<T, U> { |
62 | fn method(self: Pin<&mut Self>) { |
63 | match self.project() { |
64 | EnumProj::Pinned(x) => { |
65 | let _: Pin<&mut T> = x; |
66 | } |
67 | EnumProj::Unpinned(y) => { |
68 | let _: &mut U = y; |
69 | } |
70 | } |
71 | } |
72 | } |
73 | ``` |
74 | |
75 | [*code like this will be generated*][enum-default-expanded] |
76 | |
77 | See [`#[pin_project]`][`pin_project`] attribute for more details, and |
78 | see [examples] directory for more examples and generated code. |
79 | |
80 | ## Related Projects |
81 | |
82 | - [pin-project-lite]: A lightweight version of pin-project written with declarative macros. |
83 | |
84 | [enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs |
85 | [examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md |
86 | [pin-project-lite]: https://github.com/taiki-e/pin-project-lite |
87 | [pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning |
88 | [struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs |
89 | |
90 | <!-- tidy:sync-markdown-to-rustdoc:end --> |
91 | */ |
92 | |
93 | #![no_std ] |
94 | #![doc (test( |
95 | no_crate_inject, |
96 | attr( |
97 | deny(warnings, rust_2018_idioms, single_use_lifetimes), |
98 | allow(dead_code, unused_variables) |
99 | ) |
100 | ))] |
101 | #![warn (unsafe_op_in_unsafe_fn)] |
102 | #![warn ( |
103 | // Lints that may help when writing public library. |
104 | missing_debug_implementations, |
105 | missing_docs, |
106 | clippy::alloc_instead_of_core, |
107 | clippy::exhaustive_enums, |
108 | clippy::exhaustive_structs, |
109 | clippy::impl_trait_in_params, |
110 | // clippy::missing_inline_in_public_items, |
111 | clippy::std_instead_of_alloc, |
112 | clippy::std_instead_of_core, |
113 | )] |
114 | #![allow (clippy::needless_doctest_main)] |
115 | |
116 | #[doc (inline)] |
117 | pub use pin_project_internal::pin_project; |
118 | #[doc (inline)] |
119 | pub use pin_project_internal::pinned_drop; |
120 | |
121 | /// A trait used for custom implementations of [`Unpin`]. |
122 | /// |
123 | /// This trait is used in conjunction with the `UnsafeUnpin` argument to |
124 | /// the [`#[pin_project]`][macro@pin_project] attribute. |
125 | /// |
126 | /// # Safety |
127 | /// |
128 | /// The Rust [`Unpin`] trait is safe to implement - by itself, |
129 | /// implementing it cannot lead to [undefined behavior][undefined-behavior]. |
130 | /// Undefined behavior can only occur when other unsafe code is used. |
131 | /// |
132 | /// It turns out that using pin projections, which requires unsafe code, |
133 | /// imposes additional requirements on an [`Unpin`] impl. Normally, all of this |
134 | /// unsafety is contained within this crate, ensuring that it's impossible for |
135 | /// you to violate any of the guarantees required by pin projection. |
136 | /// |
137 | /// However, things change if you want to provide a custom [`Unpin`] impl |
138 | /// for your `#[pin_project]` type. As stated in [the Rust |
139 | /// documentation][pin-projection], you must be sure to only implement [`Unpin`] |
140 | /// when all of your `#[pin]` fields (i.e. structurally pinned fields) are also |
141 | /// [`Unpin`]. |
142 | /// |
143 | /// To help highlight this unsafety, the `UnsafeUnpin` trait is provided. |
144 | /// Implementing this trait is logically equivalent to implementing [`Unpin`] - |
145 | /// this crate will generate an [`Unpin`] impl for your type that 'forwards' to |
146 | /// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type |
147 | /// uses structural pinning (otherwise, you wouldn't be using this crate!), |
148 | /// you must be sure that your `UnsafeUnpin` impls follows all of |
149 | /// the requirements for an [`Unpin`] impl of a structurally-pinned type. |
150 | /// |
151 | /// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not* |
152 | /// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`]. |
153 | /// This is effectively the same thing as adding a [`PhantomPinned`] to your |
154 | /// type. |
155 | /// |
156 | /// Since this trait is `unsafe`, impls of it will be detected by the |
157 | /// `unsafe_code` lint, and by tools like [`cargo geiger`][cargo-geiger]. |
158 | /// |
159 | /// # Examples |
160 | /// |
161 | /// An `UnsafeUnpin` impl which, in addition to requiring that structurally |
162 | /// pinned fields be [`Unpin`], imposes an additional requirement: |
163 | /// |
164 | /// ``` |
165 | /// use pin_project::{UnsafeUnpin, pin_project}; |
166 | /// |
167 | /// #[pin_project(UnsafeUnpin)] |
168 | /// struct Struct<K, V> { |
169 | /// #[pin] |
170 | /// field_1: K, |
171 | /// field_2: V, |
172 | /// } |
173 | /// |
174 | /// unsafe impl<K, V> UnsafeUnpin for Struct<K, V> where K: Unpin + Clone {} |
175 | /// ``` |
176 | /// |
177 | /// [`PhantomPinned`]: core::marker::PhantomPinned |
178 | /// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger |
179 | /// [pin-projection]: core::pin#projections-and-structural-pinning |
180 | /// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html |
181 | pub unsafe trait UnsafeUnpin {} |
182 | |
183 | // Not public API. |
184 | #[doc (hidden)] |
185 | #[allow (missing_debug_implementations)] |
186 | pub mod __private { |
187 | use core::mem::ManuallyDrop; |
188 | #[doc (hidden)] |
189 | pub use core::{ |
190 | marker::{PhantomData, PhantomPinned, Unpin}, |
191 | ops::Drop, |
192 | pin::Pin, |
193 | ptr, |
194 | }; |
195 | |
196 | #[doc (hidden)] |
197 | pub use pin_project_internal::__PinProjectInternalDerive; |
198 | |
199 | use super::UnsafeUnpin; |
200 | |
201 | // An internal trait used for custom implementations of [`Drop`]. |
202 | // |
203 | // **Do not call or implement this trait directly.** |
204 | // |
205 | // # Why this trait is private and `#[pinned_drop]` attribute is needed? |
206 | // |
207 | // Implementing `PinnedDrop::drop` is safe, but calling it is not safe. |
208 | // This is because destructors can be called multiple times in safe code and |
209 | // [double dropping is unsound][rust-lang/rust#62360]. |
210 | // |
211 | // Ideally, it would be desirable to be able to forbid manual calls in |
212 | // the same way as [`Drop::drop`], but the library cannot do it. So, by using |
213 | // macros and replacing them with private traits, |
214 | // this crate prevent users from calling `PinnedDrop::drop` in safe code. |
215 | // |
216 | // This allows implementing [`Drop`] safely using `#[pinned_drop]`. |
217 | // Also by using the [`drop`] function just like dropping a type that directly |
218 | // implements [`Drop`], can drop safely a type that implements `PinnedDrop`. |
219 | // |
220 | // [rust-lang/rust#62360]: https://github.com/rust-lang/rust/pull/62360 |
221 | #[doc (hidden)] |
222 | pub trait PinnedDrop { |
223 | #[doc (hidden)] |
224 | unsafe fn drop(self: Pin<&mut Self>); |
225 | } |
226 | |
227 | // This is an internal helper struct used by `pin-project-internal`. |
228 | // This allows us to force an error if the user tries to provide |
229 | // a regular `Unpin` impl when they specify the `UnsafeUnpin` argument. |
230 | // This is why we need Wrapper: |
231 | // |
232 | // Supposed we have the following code: |
233 | // |
234 | // ``` |
235 | // #[pin_project(UnsafeUnpin)] |
236 | // struct MyStruct<T> { |
237 | // #[pin] field: T |
238 | // } |
239 | // |
240 | // impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpin {} // generated by pin-project-internal |
241 | // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user |
242 | // ``` |
243 | // |
244 | // We want this code to be rejected - the user is completely bypassing |
245 | // `UnsafeUnpin`, and providing an unsound Unpin impl in safe code! |
246 | // |
247 | // Unfortunately, the Rust compiler will accept the above code. |
248 | // Because MyStruct is declared in the same crate as the user-provided impl, |
249 | // the compiler will notice that `MyStruct<T>: UnsafeUnpin` never holds. |
250 | // |
251 | // The solution is to introduce the `Wrapper` struct, which is defined |
252 | // in the `pin-project` crate. |
253 | // |
254 | // We now have code that looks like this: |
255 | // |
256 | // ``` |
257 | // impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpin {} // generated by pin-project-internal |
258 | // impl<T> Unpin for MyStruct<T> where T: Copy // written by the user |
259 | // ``` |
260 | // |
261 | // We also have `unsafe impl<T> UnsafeUnpin for Wrapper<T> where T: UnsafeUnpin {}` |
262 | // in the `pin-project` crate. |
263 | // |
264 | // Now, our generated impl has a bound involving a type defined in another |
265 | // crate - Wrapper. This will cause rust to conservatively assume that |
266 | // `Wrapper<MyStruct<T>>: UnsafeUnpin` holds, in the interest of preserving |
267 | // forwards compatibility (in case such an impl is added for Wrapper<T> in |
268 | // a new version of the crate). |
269 | // |
270 | // This will cause rust to reject any other `Unpin` impls for MyStruct<T>, |
271 | // since it will assume that our generated impl could potentially apply in |
272 | // any situation. |
273 | // |
274 | // This achieves the desired effect - when the user writes |
275 | // `#[pin_project(UnsafeUnpin)]`, the user must either provide no impl of |
276 | // `UnsafeUnpin` (which is equivalent to making the type never implement |
277 | // Unpin), or provide an impl of `UnsafeUnpin`. It is impossible for them to |
278 | // provide an impl of `Unpin` |
279 | #[doc (hidden)] |
280 | #[allow (dead_code)] |
281 | pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T); |
282 | // SAFETY: `T` implements UnsafeUnpin. |
283 | unsafe impl<T: ?Sized + UnsafeUnpin> UnsafeUnpin for Wrapper<'_, T> {} |
284 | |
285 | // Workaround for issue on unstable negative_impls feature that allows unsound overlapping Unpin |
286 | // implementations and rustc bug that leaks unstable negative_impls into stable. |
287 | // See https://github.com/taiki-e/pin-project/issues/340#issuecomment-2432146009 for details. |
288 | #[doc (hidden)] |
289 | pub type PinnedFieldsOf<T> = |
290 | <PinnedFieldsOfHelperStruct<T> as PinnedFieldsOfHelperTrait>::Actual; |
291 | // We cannot use <Option<T> as IntoIterator>::Item or similar since we should allow ?Sized in T. |
292 | #[doc (hidden)] |
293 | pub trait PinnedFieldsOfHelperTrait { |
294 | type Actual: ?Sized; |
295 | } |
296 | #[doc (hidden)] |
297 | pub struct PinnedFieldsOfHelperStruct<T: ?Sized>(T); |
298 | impl<T: ?Sized> PinnedFieldsOfHelperTrait for PinnedFieldsOfHelperStruct<T> { |
299 | type Actual = T; |
300 | } |
301 | |
302 | // This is an internal helper struct used by `pin-project-internal`. |
303 | // |
304 | // See https://github.com/taiki-e/pin-project/pull/53 for more details. |
305 | #[doc (hidden)] |
306 | pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData<T>); |
307 | impl<T> Unpin for AlwaysUnpin<'_, T> {} |
308 | |
309 | // This is an internal helper used to ensure a value is dropped. |
310 | #[doc (hidden)] |
311 | pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T); |
312 | impl<T: ?Sized> UnsafeDropInPlaceGuard<T> { |
313 | #[doc (hidden)] |
314 | pub unsafe fn new(ptr: *mut T) -> Self { |
315 | Self(ptr) |
316 | } |
317 | } |
318 | impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> { |
319 | fn drop(&mut self) { |
320 | // SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee |
321 | // that `ptr` is valid for drop when this guard is destructed. |
322 | unsafe { |
323 | ptr::drop_in_place(self.0); |
324 | } |
325 | } |
326 | } |
327 | |
328 | // This is an internal helper used to ensure a value is overwritten without |
329 | // its destructor being called. |
330 | #[doc (hidden)] |
331 | pub struct UnsafeOverwriteGuard<T> { |
332 | target: *mut T, |
333 | value: ManuallyDrop<T>, |
334 | } |
335 | impl<T> UnsafeOverwriteGuard<T> { |
336 | #[doc (hidden)] |
337 | pub unsafe fn new(target: *mut T, value: T) -> Self { |
338 | Self { target, value: ManuallyDrop::new(value) } |
339 | } |
340 | } |
341 | impl<T> Drop for UnsafeOverwriteGuard<T> { |
342 | fn drop(&mut self) { |
343 | // SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee |
344 | // that `target` is valid for writes when this guard is destructed. |
345 | unsafe { |
346 | ptr::write(self.target, ptr::read(&*self.value)); |
347 | } |
348 | } |
349 | } |
350 | } |
351 | |