1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | |
3 | /*! |
4 | <!-- tidy:crate-doc:start --> |
5 | A crate for safe and ergonomic [pin-projection]. |
6 | |
7 | ## Usage |
8 | |
9 | Add this to your `Cargo.toml`: |
10 | |
11 | ```toml |
12 | [dependencies] |
13 | pin-project = "1" |
14 | ``` |
15 | |
16 | *Compiler support: requires rustc 1.56+* |
17 | |
18 | ## Examples |
19 | |
20 | [`#[pin_project]`][`pin_project`] attribute creates projection types |
21 | covering all the fields of struct or enum. |
22 | |
23 | ```rust |
24 | use std::pin::Pin; |
25 | |
26 | use pin_project::pin_project; |
27 | |
28 | #[pin_project] |
29 | struct Struct<T, U> { |
30 | #[pin] |
31 | pinned: T, |
32 | unpinned: U, |
33 | } |
34 | |
35 | impl<T, U> Struct<T, U> { |
36 | fn method(self: Pin<&mut Self>) { |
37 | let this = self.project(); |
38 | let _: Pin<&mut T> = this.pinned; // Pinned reference to the field |
39 | let _: &mut U = this.unpinned; // Normal reference to the field |
40 | } |
41 | } |
42 | ``` |
43 | |
44 | [*code like this will be generated*][struct-default-expanded] |
45 | |
46 | To use `#[pin_project]` on enums, you need to name the projection type |
47 | returned from the method. |
48 | |
49 | ```rust |
50 | use std::pin::Pin; |
51 | |
52 | use pin_project::pin_project; |
53 | |
54 | #[pin_project(project = EnumProj)] |
55 | enum Enum<T, U> { |
56 | Pinned(#[pin] T), |
57 | Unpinned(U), |
58 | } |
59 | |
60 | impl<T, U> Enum<T, U> { |
61 | fn method(self: Pin<&mut Self>) { |
62 | match self.project() { |
63 | EnumProj::Pinned(x) => { |
64 | let _: Pin<&mut T> = x; |
65 | } |
66 | EnumProj::Unpinned(y) => { |
67 | let _: &mut U = y; |
68 | } |
69 | } |
70 | } |
71 | } |
72 | ``` |
73 | |
74 | [*code like this will be generated*][enum-default-expanded] |
75 | |
76 | See [`#[pin_project]`][`pin_project`] attribute for more details, and |
77 | see [examples] directory for more examples and generated code. |
78 | |
79 | ## Related Projects |
80 | |
81 | - [pin-project-lite]: A lightweight version of pin-project written with declarative macros. |
82 | |
83 | [enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs |
84 | [examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md |
85 | [pin-project-lite]: https://github.com/taiki-e/pin-project-lite |
86 | [pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning |
87 | [struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs |
88 | |
89 | <!-- tidy:crate-doc:end --> |
90 | */ |
91 | |
92 | #![no_std ] |
93 | #![doc (test( |
94 | no_crate_inject, |
95 | attr( |
96 | deny(warnings, rust_2018_idioms, single_use_lifetimes), |
97 | allow(dead_code, unused_variables) |
98 | ) |
99 | ))] |
100 | #![warn (unsafe_op_in_unsafe_fn)] |
101 | #![warn ( |
102 | // Lints that may help when writing public library. |
103 | missing_debug_implementations, |
104 | missing_docs, |
105 | clippy::alloc_instead_of_core, |
106 | clippy::exhaustive_enums, |
107 | clippy::exhaustive_structs, |
108 | clippy::impl_trait_in_params, |
109 | // clippy::missing_inline_in_public_items, |
110 | clippy::std_instead_of_alloc, |
111 | clippy::std_instead_of_core, |
112 | )] |
113 | #![allow (clippy::needless_doctest_main)] |
114 | |
115 | #[doc (inline)] |
116 | pub use pin_project_internal::pin_project; |
117 | #[doc (inline)] |
118 | pub use pin_project_internal::pinned_drop; |
119 | |
120 | /// A trait used for custom implementations of [`Unpin`]. |
121 | /// |
122 | /// This trait is used in conjunction with the `UnsafeUnpin` argument to |
123 | /// the [`#[pin_project]`][macro@pin_project] attribute. |
124 | /// |
125 | /// # Safety |
126 | /// |
127 | /// The Rust [`Unpin`] trait is safe to implement - by itself, |
128 | /// implementing it cannot lead to [undefined behavior][undefined-behavior]. |
129 | /// Undefined behavior can only occur when other unsafe code is used. |
130 | /// |
131 | /// It turns out that using pin projections, which requires unsafe code, |
132 | /// imposes additional requirements on an [`Unpin`] impl. Normally, all of this |
133 | /// unsafety is contained within this crate, ensuring that it's impossible for |
134 | /// you to violate any of the guarantees required by pin projection. |
135 | /// |
136 | /// However, things change if you want to provide a custom [`Unpin`] impl |
137 | /// for your `#[pin_project]` type. As stated in [the Rust |
138 | /// documentation][pin-projection], you must be sure to only implement [`Unpin`] |
139 | /// when all of your `#[pin]` fields (i.e. structurally pinned fields) are also |
140 | /// [`Unpin`]. |
141 | /// |
142 | /// To help highlight this unsafety, the `UnsafeUnpin` trait is provided. |
143 | /// Implementing this trait is logically equivalent to implementing [`Unpin`] - |
144 | /// this crate will generate an [`Unpin`] impl for your type that 'forwards' to |
145 | /// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type |
146 | /// uses structural pinning (otherwise, you wouldn't be using this crate!), |
147 | /// you must be sure that your `UnsafeUnpin` impls follows all of |
148 | /// the requirements for an [`Unpin`] impl of a structurally-pinned type. |
149 | /// |
150 | /// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not* |
151 | /// provide an impl of `UnsafeUnpin`, your type will never implement [`Unpin`]. |
152 | /// This is effectively the same thing as adding a [`PhantomPinned`] to your |
153 | /// type. |
154 | /// |
155 | /// Since this trait is `unsafe`, impls of it will be detected by the |
156 | /// `unsafe_code` lint, and by tools like [`cargo geiger`][cargo-geiger]. |
157 | /// |
158 | /// # Examples |
159 | /// |
160 | /// An `UnsafeUnpin` impl which, in addition to requiring that structurally |
161 | /// pinned fields be [`Unpin`], imposes an additional requirement: |
162 | /// |
163 | /// ``` |
164 | /// use pin_project::{pin_project, UnsafeUnpin}; |
165 | /// |
166 | /// #[pin_project(UnsafeUnpin)] |
167 | /// struct Struct<K, V> { |
168 | /// #[pin] |
169 | /// field_1: K, |
170 | /// field_2: V, |
171 | /// } |
172 | /// |
173 | /// unsafe impl<K, V> UnsafeUnpin for Struct<K, V> where K: Unpin + Clone {} |
174 | /// ``` |
175 | /// |
176 | /// [`PhantomPinned`]: core::marker::PhantomPinned |
177 | /// [cargo-geiger]: https://github.com/rust-secure-code/cargo-geiger |
178 | /// [pin-projection]: core::pin#projections-and-structural-pinning |
179 | /// [undefined-behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html |
180 | pub unsafe trait UnsafeUnpin {} |
181 | |
182 | // Not public API. |
183 | #[doc (hidden)] |
184 | pub mod __private { |
185 | #![allow (missing_debug_implementations)] |
186 | |
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 | pub struct Wrapper<'a, T: ?Sized>(PhantomData<&'a ()>, T); |
281 | |
282 | // SAFETY: `T` implements UnsafeUnpin. |
283 | unsafe impl<T: ?Sized + UnsafeUnpin> UnsafeUnpin for Wrapper<'_, T> {} |
284 | |
285 | // This is an internal helper struct used by `pin-project-internal`. |
286 | // |
287 | // See https://github.com/taiki-e/pin-project/pull/53 for more details. |
288 | #[doc (hidden)] |
289 | pub struct AlwaysUnpin<'a, T>(PhantomData<&'a ()>, PhantomData<T>); |
290 | |
291 | impl<T> Unpin for AlwaysUnpin<'_, T> {} |
292 | |
293 | // This is an internal helper used to ensure a value is dropped. |
294 | #[doc (hidden)] |
295 | pub struct UnsafeDropInPlaceGuard<T: ?Sized>(*mut T); |
296 | |
297 | impl<T: ?Sized> UnsafeDropInPlaceGuard<T> { |
298 | #[doc (hidden)] |
299 | pub unsafe fn new(ptr: *mut T) -> Self { |
300 | Self(ptr) |
301 | } |
302 | } |
303 | |
304 | impl<T: ?Sized> Drop for UnsafeDropInPlaceGuard<T> { |
305 | fn drop(&mut self) { |
306 | // SAFETY: the caller of `UnsafeDropInPlaceGuard::new` must guarantee |
307 | // that `ptr` is valid for drop when this guard is destructed. |
308 | unsafe { |
309 | ptr::drop_in_place(self.0); |
310 | } |
311 | } |
312 | } |
313 | |
314 | // This is an internal helper used to ensure a value is overwritten without |
315 | // its destructor being called. |
316 | #[doc (hidden)] |
317 | pub struct UnsafeOverwriteGuard<T> { |
318 | target: *mut T, |
319 | value: ManuallyDrop<T>, |
320 | } |
321 | |
322 | impl<T> UnsafeOverwriteGuard<T> { |
323 | #[doc (hidden)] |
324 | pub unsafe fn new(target: *mut T, value: T) -> Self { |
325 | Self { target, value: ManuallyDrop::new(value) } |
326 | } |
327 | } |
328 | |
329 | impl<T> Drop for UnsafeOverwriteGuard<T> { |
330 | fn drop(&mut self) { |
331 | // SAFETY: the caller of `UnsafeOverwriteGuard::new` must guarantee |
332 | // that `target` is valid for writes when this guard is destructed. |
333 | unsafe { |
334 | ptr::write(self.target, ptr::read(&*self.value)); |
335 | } |
336 | } |
337 | } |
338 | } |
339 | |