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