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] |
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] |
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] |
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] |
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] |
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] |
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] |
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] |
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 | |
271 | fn f() {} |
272 | |
273 | #[pinned_drop ] |
274 | impl<T: Unpin> PinnedDrop for self::S<T> { |
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 | |