1#![warn(rust_2018_idioms, single_use_lifetimes)]
2
3use std::pin::Pin;
4
5use pin_project::{pin_project, pinned_drop};
6
7#[test]
8fn 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]
29fn 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]
57fn 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]
128fn 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]
154fn 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]
173fn 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]
188fn 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]
247fn 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
265pub 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