• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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