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
28use std::pin::Pin;
29
30use pin_project::{pin_project, pinned_drop};
31
32// #[pin_project(PinnedDrop)]
33pub struct Struct<'a, T> {
34 was_dropped: &'a mut bool,
35 // #[pin]
36 field: T,
37}
38
39const _: () = {
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)]
139impl<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
154fn main() {}
155