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> {
project<'pin>( self: ::pin_project::__private::Pin<&'pin mut Self>, ) -> __StructProjection<'pin, '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 }
project_ref<'pin>( self: ::pin_project::__private::Pin<&'pin Self>, ) -> __StructProjectionRef<'pin, 'a, T>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)]
__assert_not_repr_packed<'a, T>(this: &Struct<'a, T>)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> {
drop(&mut self)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.
drop(self: Pin<&mut Self>)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
main()154 fn main() {}
155