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