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