1 // SPDX-License-Identifier: Apache-2.0 OR MIT
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 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 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 struct Struct {
60 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 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 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: () } | Self::Tuple(()) | Self::Unit => {}
117 }
118 if let Self::Struct { f: () } = *self {}
119 if let Self::Tuple(()) = *self {}
120 if let Self::Unit = *self {}
121 }
122 }
123 }
124
125 #[test]
self_inside_macro_containing_fn()126 fn self_inside_macro_containing_fn() {
127 macro_rules! mac {
128 ($($tt:tt)*) => {
129 $($tt)*
130 };
131 }
132
133 #[pin_project(PinnedDrop)]
134 struct S(());
135
136 #[pinned_drop]
137 impl PinnedDrop for S {
138 fn drop(self: Pin<&mut Self>) {
139 mac!({
140 #[allow(dead_code)]
141 struct S(());
142 impl S {
143 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 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 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 mod self_path {
266 use super::*;
267
268 #[pin_project(PinnedDrop)]
269 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