1 | // Original code (./pinned_drop.rs): |
2 | // |
3 | // ```rust |
4 | // #![allow(dead_code)] |
5 | // |
6 | // use std::pin::Pin; |
7 | // |
8 | // use pin_project::{pin_project, pinned_drop}; |
9 | // |
10 | // #[pin_project(PinnedDrop)] |
11 | // pub struct Struct<'a, T> { |
12 | // was_dropped: &'a mut bool, |
13 | // #[pin] |
14 | // field: T, |
15 | // } |
16 | // |
17 | // #[pinned_drop] |
18 | // fn drop_Struct<T>(mut this: Pin<&mut Struct<'_, T>>) { |
19 | // **this.project().was_dropped = true; |
20 | // } |
21 | // |
22 | // fn main() {} |
23 | // ``` |
24 | |
25 | #![allow (dead_code, unused_imports, unused_parens, unknown_lints, renamed_and_removed_lints)] |
26 | #![allow (clippy::needless_lifetimes, clippy::mut_mut)] |
27 | |
28 | use std::pin::Pin; |
29 | |
30 | use pin_project::{pin_project , pinned_drop }; |
31 | |
32 | // #[pin_project(PinnedDrop)] |
33 | pub struct Struct<'a, T> { |
34 | was_dropped: &'a mut bool, |
35 | // #[pin] |
36 | field: T, |
37 | } |
38 | |
39 | const _: () = { |
40 | pub(crate) struct __StructProjection<'pin, 'a, T> |
41 | where |
42 | Struct<'a, T>: 'pin, |
43 | { |
44 | was_dropped: &'pin mut (&'a mut bool), |
45 | field: ::pin_project::__private::Pin<&'pin mut (T)>, |
46 | } |
47 | pub(crate) struct __StructProjectionRef<'pin, 'a, T> |
48 | where |
49 | Struct<'a, T>: 'pin, |
50 | { |
51 | was_dropped: &'pin (&'a mut bool), |
52 | field: ::pin_project::__private::Pin<&'pin (T)>, |
53 | } |
54 | |
55 | impl<'a, T> Struct<'a, T> { |
56 | pub(crate) fn project<'pin>( |
57 | self: ::pin_project::__private::Pin<&'pin mut Self>, |
58 | ) -> __StructProjection<'pin, 'a, T> { |
59 | unsafe { |
60 | let Self { was_dropped, field } = self.get_unchecked_mut(); |
61 | __StructProjection { |
62 | was_dropped, |
63 | field: ::pin_project::__private::Pin::new_unchecked(field), |
64 | } |
65 | } |
66 | } |
67 | pub(crate) fn project_ref<'pin>( |
68 | self: ::pin_project::__private::Pin<&'pin Self>, |
69 | ) -> __StructProjectionRef<'pin, 'a, T> { |
70 | unsafe { |
71 | let Self { was_dropped, field } = self.get_ref(); |
72 | __StructProjectionRef { |
73 | was_dropped, |
74 | field: ::pin_project::__private::Pin::new_unchecked(field), |
75 | } |
76 | } |
77 | } |
78 | } |
79 | |
80 | // Ensure that it's impossible to use pin projections on a #[repr(packed)] |
81 | // struct. |
82 | // |
83 | // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34 |
84 | // for details. |
85 | #[forbid (unaligned_references, safe_packed_borrows)] |
86 | fn __assert_not_repr_packed<'a, T>(this: &Struct<'a, T>) { |
87 | let _ = &this.was_dropped; |
88 | let _ = &this.field; |
89 | } |
90 | |
91 | impl<'a, T> ::pin_project::__private::Drop for Struct<'a, T> { |
92 | fn drop(&mut self) { |
93 | // Safety - we're in 'drop', so we know that 'self' will |
94 | // never move again. |
95 | let pinned_self = unsafe { ::pin_project::__private::Pin::new_unchecked(self) }; |
96 | // We call `pinned_drop` only once. Since `PinnedDrop::drop` |
97 | // is an unsafe method and a private API, it is never called again in safe |
98 | // code *unless the user uses a maliciously crafted macro*. |
99 | unsafe { |
100 | ::pin_project::__private::PinnedDrop::drop(pinned_self); |
101 | } |
102 | } |
103 | } |
104 | |
105 | // Automatically create the appropriate conditional `Unpin` implementation. |
106 | // |
107 | // See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53. |
108 | // for details. |
109 | pub struct __Struct<'pin, 'a, T> { |
110 | __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T)>, |
111 | __field0: T, |
112 | __lifetime0: &'a (), |
113 | } |
114 | impl<'pin, 'a, T> ::pin_project::__private::Unpin for Struct<'a, T> where |
115 | __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin |
116 | { |
117 | } |
118 | // A dummy impl of `UnsafeUnpin`, to ensure that the user cannot implement it. |
119 | #[doc (hidden)] |
120 | unsafe impl<'pin, 'a, T> ::pin_project::UnsafeUnpin for Struct<'a, T> where |
121 | __Struct<'pin, 'a, T>: ::pin_project::__private::Unpin |
122 | { |
123 | } |
124 | }; |
125 | |
126 | // Implementing `PinnedDrop::drop` is safe, but calling it is not safe. |
127 | // This is because destructors can be called multiple times in safe code and |
128 | // [double dropping is unsound](https://github.com/rust-lang/rust/pull/62360). |
129 | // |
130 | // Ideally, it would be desirable to be able to forbid manual calls in |
131 | // the same way as `Drop::drop`, but the library cannot do it. So, by using |
132 | // macros and replacing them with private traits, we prevent users from |
133 | // calling `PinnedDrop::drop`. |
134 | // |
135 | // Users can implement [`Drop`] safely using `#[pinned_drop]` and can drop a |
136 | // type that implements `PinnedDrop` using the [`drop`] function safely. |
137 | // **Do not call or implement this trait directly.** |
138 | #[doc (hidden)] |
139 | impl<T> ::pin_project::__private::PinnedDrop for Struct<'_, T> { |
140 | // Since calling it twice on the same object would be UB, |
141 | // this method is unsafe. |
142 | unsafe fn drop(self: Pin<&mut Self>) { |
143 | #[allow (clippy::needless_pass_by_value)] |
144 | fn __drop_inner<T>(__self: Pin<&mut Struct<'_, T>>) { |
145 | // A dummy `__drop_inner` function to prevent users call outer `__drop_inner`. |
146 | fn __drop_inner() {} |
147 | |
148 | **__self.project().was_dropped = true; |
149 | } |
150 | __drop_inner(self); |
151 | } |
152 | } |
153 | |
154 | fn main() {} |
155 | |