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             let _ = 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 #[rustversion::since(1.40)] // https://github.com/rust-lang/rust/pull/64690
154 #[test]
self_inside_macro_def()155 fn self_inside_macro_def() {
156     #[pin_project(PinnedDrop)]
157     pub struct S(());
158 
159     #[pinned_drop]
160     impl PinnedDrop for S {
161         fn drop(self: Pin<&mut Self>) {
162             macro_rules! mac {
163                 () => {{
164                     let _ = self;
165                     let _ = Self(());
166                 }};
167             }
168             mac!();
169         }
170     }
171 }
172 
173 #[test]
self_arg_inside_macro_call()174 fn self_arg_inside_macro_call() {
175     #[pin_project(PinnedDrop)]
176     struct Struct {
177         f: (),
178     }
179 
180     #[pinned_drop]
181     impl PinnedDrop for Struct {
182         fn drop(self: Pin<&mut Self>) {
183             let _: Vec<_> = vec![self.f];
184         }
185     }
186 }
187 
188 #[test]
self_ty_inside_macro_call()189 fn self_ty_inside_macro_call() {
190     macro_rules! mac {
191         ($($tt:tt)*) => {
192             $($tt)*
193         };
194     }
195 
196     #[pin_project(PinnedDrop)]
197     pub struct Struct<T: Send>
198     where
199         mac!(Self): Send,
200     {
201         _f: T,
202     }
203 
204     impl<T: Send> Struct<T> {
205         const ASSOC1: usize = 1;
206         fn assoc1() {}
207     }
208 
209     trait Trait {
210         type Assoc2;
211         const ASSOC2: usize;
212         fn assoc2();
213     }
214 
215     impl<T: Send> Trait for Struct<T> {
216         type Assoc2 = ();
217         const ASSOC2: usize = 2;
218         fn assoc2() {}
219     }
220 
221     #[pinned_drop]
222     impl<T: Send> PinnedDrop for Struct<T>
223     where
224         mac!(Self): Send,
225     {
226         #[allow(path_statements)]
227         #[allow(clippy::no_effect)]
228         fn drop(self: Pin<&mut Self>) {
229             // inherent items
230             mac!(Self::ASSOC1;);
231             mac!(<Self>::ASSOC1;);
232             mac!(Self::assoc1(););
233             mac!(<Self>::assoc1(););
234 
235             // trait items
236             mac!(let _: <Self as Trait>::Assoc2;);
237             mac!(Self::ASSOC2;);
238             mac!(<Self>::ASSOC2;);
239             mac!(<Self as Trait>::ASSOC2;);
240             mac!(Self::assoc2(););
241             mac!(<Self>::assoc2(););
242             mac!(<Self as Trait>::assoc2(););
243         }
244     }
245 }
246 
247 #[test]
inside_macro()248 fn inside_macro() {
249     #[pin_project(PinnedDrop)]
250     struct S(());
251 
252     macro_rules! mac {
253         ($expr:expr) => {
254             #[pinned_drop]
255             impl PinnedDrop for S {
256                 fn drop(self: Pin<&mut Self>) {
257                     let _ = $expr;
258                 }
259             }
260         };
261     }
262 
263     mac!(1);
264 }
265