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