1 #![warn(rust_2018_idioms, single_use_lifetimes)]
2 
3 use std::pin::Pin;
4 
5 use pin_project::{pin_project, pinned_drop};
6 
7 #[test]
safe_project()8 fn safe_project() {
9     #[pin_project(PinnedDrop)]
10     pub struct Struct<'a> {
11         was_dropped: &'a mut bool,
12         #[pin]
13         field: u8,
14     }
15 
16     #[pinned_drop]
17     impl PinnedDrop for Struct<'_> {
18         fn drop(self: Pin<&mut Self>) {
19             **self.project().was_dropped = true;
20         }
21     }
22 
23     let mut was_dropped = false;
24     drop(Struct { was_dropped: &mut was_dropped, field: 42 });
25     assert!(was_dropped);
26 }
27 
28 #[test]
self_call()29 fn self_call() {
30     #[pin_project(PinnedDrop)]
31     pub struct S<T>(T);
32 
33     trait Trait {
34         fn self_ref(&self) {}
35         fn self_pin_ref(self: Pin<&Self>) {}
36         fn self_mut(&mut self) {}
37         fn self_pin_mut(self: Pin<&mut Self>) {}
38         fn assoc_fn(_this: Pin<&mut Self>) {}
39     }
40 
41     impl<T> Trait for S<T> {}
42 
43     #[pinned_drop]
44     impl<T> PinnedDrop for S<T> {
45         fn drop(mut self: Pin<&mut Self>) {
46             self.self_ref();
47             self.as_ref().self_pin_ref();
48             self.self_mut();
49             self.as_mut().self_pin_mut();
50             Self::assoc_fn(self.as_mut());
51             <Self>::assoc_fn(self.as_mut());
52         }
53     }
54 }
55 
56 #[test]
self_ty()57 fn self_ty() {
58     #[pin_project(PinnedDrop)]
59     pub struct Struct {
60         pub f: (),
61     }
62 
63     #[pinned_drop]
64     impl PinnedDrop for Struct {
65         #[allow(irrefutable_let_patterns)]
66         #[allow(clippy::match_single_binding)]
67         fn drop(mut self: Pin<&mut Self>) {
68             // expr
69             let _: Self = Self { f: () };
70 
71             // pat
72             match *self {
73                 Self { f: () } => {}
74             }
75             if let Self { f: () } = *self {}
76             let Self { f: () } = *self;
77         }
78     }
79 
80     #[pin_project(PinnedDrop)]
81     pub struct TupleStruct(());
82 
83     #[pinned_drop]
84     impl PinnedDrop for TupleStruct {
85         #[allow(irrefutable_let_patterns)]
86         fn drop(mut self: Pin<&mut Self>) {
87             // expr
88             let _: Self = Self(());
89 
90             // pat
91             match *self {
92                 Self(_) => {}
93             }
94             if let Self(_) = *self {}
95             let Self(_) = *self;
96         }
97     }
98 
99     #[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)]
100     pub enum Enum {
101         Struct { f: () },
102         Tuple(()),
103         Unit,
104     }
105 
106     #[pinned_drop]
107     impl PinnedDrop for Enum {
108         fn drop(mut self: Pin<&mut Self>) {
109             // expr
110             let _: Self = Self::Struct { f: () };
111             let _: Self = Self::Tuple(());
112             let _: Self = Self::Unit;
113 
114             // pat
115             match *self {
116                 Self::Struct { f: () } => {}
117                 Self::Tuple(_) => {}
118                 Self::Unit => {}
119             }
120             if let Self::Struct { f: () } = *self {}
121             if let Self::Tuple(_) = *self {}
122             if let Self::Unit = *self {}
123         }
124     }
125 }
126 
127 #[test]
self_inside_macro_containing_fn()128 fn self_inside_macro_containing_fn() {
129     macro_rules! mac {
130         ($($tt:tt)*) => {
131             $($tt)*
132         };
133     }
134 
135     #[pin_project(PinnedDrop)]
136     pub struct S(());
137 
138     #[pinned_drop]
139     impl PinnedDrop for S {
140         fn drop(self: Pin<&mut Self>) {
141             mac!({
142                 impl S {
143                     pub fn _f(self) -> Self {
144                         self
145                     }
146                 }
147             });
148         }
149     }
150 }
151 
152 // See also `ui/pinned_drop/self.rs`.
153 #[test]
self_inside_macro_def()154 fn self_inside_macro_def() {
155     #[pin_project(PinnedDrop)]
156     pub struct S(());
157 
158     #[pinned_drop]
159     impl PinnedDrop for S {
160         fn drop(self: Pin<&mut Self>) {
161             macro_rules! mac {
162                 () => {{
163                     let _ = self;
164                     let _ = Self(());
165                 }};
166             }
167             mac!();
168         }
169     }
170 }
171 
172 #[test]
self_arg_inside_macro_call()173 fn self_arg_inside_macro_call() {
174     #[pin_project(PinnedDrop)]
175     struct Struct {
176         f: (),
177     }
178 
179     #[pinned_drop]
180     impl PinnedDrop for Struct {
181         fn drop(self: Pin<&mut Self>) {
182             let _: Vec<_> = vec![self.f];
183         }
184     }
185 }
186 
187 #[test]
self_ty_inside_macro_call()188 fn self_ty_inside_macro_call() {
189     macro_rules! mac {
190         ($($tt:tt)*) => {
191             $($tt)*
192         };
193     }
194 
195     #[pin_project(PinnedDrop)]
196     pub struct Struct<T: Send>
197     where
198         mac!(Self): Send,
199     {
200         _f: T,
201     }
202 
203     impl<T: Send> Struct<T> {
204         const ASSOC1: usize = 1;
205         fn assoc1() {}
206     }
207 
208     trait Trait {
209         type Assoc2;
210         const ASSOC2: usize;
211         fn assoc2();
212     }
213 
214     impl<T: Send> Trait for Struct<T> {
215         type Assoc2 = u8;
216         const ASSOC2: usize = 2;
217         fn assoc2() {}
218     }
219 
220     #[pinned_drop]
221     impl<T: Send> PinnedDrop for Struct<T>
222     where
223         mac!(Self): Send,
224     {
225         #[allow(path_statements)]
226         #[allow(clippy::no_effect)]
227         fn drop(self: Pin<&mut Self>) {
228             // inherent items
229             mac!(Self::ASSOC1;);
230             mac!(<Self>::ASSOC1;);
231             mac!(Self::assoc1(););
232             mac!(<Self>::assoc1(););
233 
234             // trait items
235             mac!(let _: <Self as Trait>::Assoc2;);
236             mac!(Self::ASSOC2;);
237             mac!(<Self>::ASSOC2;);
238             mac!(<Self as Trait>::ASSOC2;);
239             mac!(Self::assoc2(););
240             mac!(<Self>::assoc2(););
241             mac!(<Self as Trait>::assoc2(););
242         }
243     }
244 }
245 
246 #[test]
inside_macro()247 fn inside_macro() {
248     #[pin_project(PinnedDrop)]
249     struct S(());
250 
251     macro_rules! mac {
252         ($expr:expr) => {
253             #[pinned_drop]
254             impl PinnedDrop for S {
255                 fn drop(self: Pin<&mut Self>) {
256                     let _ = $expr;
257                 }
258             }
259         };
260     }
261 
262     mac!(1);
263 }
264 
265 pub mod self_path {
266     use super::*;
267 
268     #[pin_project(PinnedDrop)]
269     pub struct S<T: Unpin>(T);
270 
f()271     fn f() {}
272 
273     #[pinned_drop]
274     impl<T: Unpin> PinnedDrop for self::S<T> {
drop(mut self: Pin<&mut Self>)275         fn drop(mut self: Pin<&mut Self>) {
276             self::f();
277             let _: self::S<()> = self::S(());
278             let _: self::S<Pin<&mut Self>> = self::S(self.as_mut());
279             let self::S(()) = self::S(());
280             let self::S(&mut Self(_)) = self::S(&mut *self);
281         }
282     }
283 }
284