1#[macro_export]
2#[doc(hidden)]
3macro_rules! __dtor_parse {
4 ( $($input:tt)* ) => {
5 $crate::__perform!(
6 ($($input)*),
7 $crate::__chain[
8 $crate::__parse_item[$crate::__dtor_features],
9 $crate::__extract_unsafe,
10 $crate::__dtor_parse_impl,
11 ]
12 );
13 };
14}
15
16#[macro_export]
19#[doc(hidden)]
20macro_rules! __dtor_parse_impl {
21 ( @entry next=$next:path[$next_args:tt], input=(
25 features = (
26 anonymous = $anonymous:tt,
27 crate_path = $crate_path:tt,
28 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
29 ctor_link_section = $ctor_link_section:tt,
30 default_term_method = $default_term_method:tt,
31 default_unload_method = $default_unload_method:tt,
32 export_name_prefix = $export_name_prefix:tt,
33 link_section = $link_section:tt,
34 method = $method:tt,
35 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
36 proc_macro = $proc_macro:tt,
37 std = $std:tt,
38 used_linker = $used_linker:tt,
39 ),
40 meta = $meta:tt,
41 unsafe = ($($unsafe:tt)*),
42 item = ($vis:vis $(unsafe)? $( extern $abi:literal )? fn $name:ident () $( -> () )? {
43 $($body:tt)*
44 })
45 ) ) => {
46 $crate::__dtor_parse_impl!(@checkfail method=$method);
47
48 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
49 features = (
50 anonymous = $anonymous,
51 ctor_export_name_prefix = $ctor_export_name_prefix,
52 ctor_link_section = $ctor_link_section,
53 default_term_method = $default_term_method,
54 default_unload_method = $default_unload_method,
55 export_name_prefix = $export_name_prefix,
56 link_section = $link_section,
57 method = $method,
58 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
59 used_linker = $used_linker,
60 ),
61 meta = $meta,
62 unsafe = ($($unsafe)*),
63 item = ($vis $($unsafe)* $( extern $abi )? fn $name () {
64 $($body)*
65 })
66 ));
67 };
68
69 ( @checkfail method=term ) => {};
70 ( @checkfail method=unload ) => {};
71 ( @checkfail method=at_module_exit ) => {};
72 ( @checkfail method=at_binary_exit ) => {};
73 ( @checkfail method=linker ) => {};
74 ( @checkfail method=$any:tt ) => {
75 compile_error!(concat!("Invalid dtor method: ", stringify!($any)));
76 };
77
78 ( @checkfail $($rest:tt)* ) => {};
79
80 ( @entry next=$next:path[$next_args:tt], input=(
81 features = (
82 anonymous = $anonymous:tt,
83 crate_path = $crate_path:tt,
84 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
85 ctor_link_section = $ctor_link_section:tt,
86 default_term_method = $default_term_method:tt,
87 default_unload_method = $default_unload_method:tt,
88 export_name_prefix = $export_name_prefix:tt,
89 link_section = $link_section:tt,
90 method = $method:tt,
91 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
92 proc_macro = $proc_macro:tt,
93 std = $std:tt,
94 used_linker = $used_linker:tt,
95 ),
96 meta = $meta:tt,
97 unsafe = $unsafe:tt,
98 item = ($item:item)
99 ) ) => {
100 compile_error!("Invalid dtor function. \
101 Expected a function with no args, \
102 return value, or type parameters.\n\
103 Valid forms are: [pub] [unsafe] [extern $abi] fn $name() { ... }");
104 };
105
106 ( @entry next=$next:path[$next_args:tt], input=(
110 features = (
111 anonymous = $anonymous:tt,
112 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
113 ctor_link_section = $ctor_link_section:tt,
114 default_term_method = $default_term_method:tt,
115 default_unload_method = $default_unload_method:tt,
116 export_name_prefix = $export_name_prefix:tt,
117 link_section = $link_section:tt,
118 method = term,
119 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
120 used_linker = $used_linker:tt,
121 ),
122 meta = $meta:tt,
123 unsafe = $unsafe:tt,
124 item = $item:tt
125 ) ) => {
126 $crate::__dtor_parse_impl(@entry next=$next[$next_args], input=(
128 features = (
129 anonymous = $anonymous,
130 method = ($default_term_method $ctor_export_name_prefix $ctor_link_section $export_name_prefix $link_section),
131 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
132 used_linker = $used_linker,
133 ),
134 meta = $meta,
135 unsafe = $unsafe,
136 item = $item
137 ));
138 };
139
140 ( @entry next=$next:path[$next_args:tt], input=(
142 features = (
143 anonymous = $anonymous:tt,
144 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
145 ctor_link_section = $ctor_link_section:tt,
146 default_term_method = $default_term_method:tt,
147 default_unload_method = $default_unload_method:tt,
148 export_name_prefix = $export_name_prefix:tt,
149 link_section = $link_section:tt,
150 method = unload,
151 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
152 used_linker = $used_linker:tt,
153 ),
154 meta = $meta:tt,
155 unsafe = $unsafe:tt,
156 item = $item:tt
157 ) ) => {
158 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
160 features = (
161 anonymous = $anonymous,
162 method = ($default_unload_method $ctor_export_name_prefix $ctor_link_section $export_name_prefix $link_section),
163 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
164 used_linker = $used_linker,
165 ),
166 meta = $meta,
167 unsafe = $unsafe,
168 item = $item
169 ));
170 };
171
172 ( @entry next=$next:path[$next_args:tt], input=(
174 features = (
175 anonymous = $anonymous:tt,
176 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
177 ctor_link_section = $ctor_link_section:tt,
178 default_term_method = $default_term_method:tt,
179 default_unload_method = $default_unload_method:tt,
180 export_name_prefix = $export_name_prefix:tt,
181 link_section = $link_section:tt,
182 method = $method:tt,
183 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
184 used_linker = $used_linker:tt,
185 ),
186 meta = $meta:tt,
187 unsafe = $unsafe:tt,
188 item = $item:tt
189 ) ) => {
190 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
192 features = (
193 anonymous = $anonymous,
194 method = ($method $ctor_export_name_prefix $ctor_link_section $export_name_prefix $link_section),
195 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
196 used_linker = $used_linker,
197 ),
198 meta = $meta,
199 unsafe = $unsafe,
200 item = $item
201 ));
202 };
203
204 ( @entry next=$next:path[$next_args:tt], input=(
208 features = (
209 anonymous = $anonymous:tt,
210 method = $method:tt,
211 no_warn_on_missing_unsafe = (),
212 used_linker = $used_linker:tt,
213 ),
214 meta = $meta:tt,
215 unsafe = (),
216 item = $item:tt
217 ) ) => {
218 const _: () = {
219 #[deprecated="dtor deprecation note:\n\n\
220 Use of #[dtor] without `#[dtor(unsafe)]` or `unsafe fn` is deprecated. As code execution\n\
221 before main is unsupported by most Rust runtime functions, these functions must be marked\n\
222 `unsafe`."]
223 const fn dtor_without_unsafe_is_deprecated() {}
224 #[allow(unused)]
225 static UNSAFE_WARNING: () = {
226 dtor_without_unsafe_is_deprecated()
227 };
228 };
229
230 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
231 features = (
232 anonymous = $anonymous,
233 method = $method,
234 used_linker = $used_linker,
235 ),
236 meta = $meta,
237 unsafe = (),
238 item = $item
239 ));
240 };
241
242 ( @entry next=$next:path[$next_args:tt], input=(
244 features = (
245 anonymous = $anonymous:tt,
246 method = $method:tt,
247 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
248 used_linker = $used_linker:tt,
249 ),
250 meta = $meta:tt,
251 unsafe = $unsafe:tt,
252 item = $item:tt
253 ) ) => {
254 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
255 features = (
256 anonymous = $anonymous,
257 method = $method,
258 used_linker = $used_linker,
259 ),
260 meta = $meta,
261 unsafe = $unsafe,
262 item = $item
263 ));
264 };
265
266 ( @entry next=$next:path[$next_args:tt], input=(
268 features = (
269 anonymous = anonymous,
270 method = $method:tt,
271 used_linker = $used_linker:tt,
272 ),
273 meta = $meta:tt,
274 unsafe = $unsafe:tt,
275 item = $item:tt
276 ) ) => {
277 const _: () = {
279 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
280 features = (
281 method = $method,
282 used_linker = $used_linker,
283 ),
284 meta = $meta,
285 unsafe = $unsafe,
286 item = $item
287 ));
288 };
289 };
290
291 ( @entry next=$next:path[$next_args:tt], input=(
292 features = (
293 anonymous = (),
294 method = $method:tt,
295 used_linker = $used_linker:tt,
296 ),
297 meta = $meta:tt,
298 unsafe = $unsafe:tt,
299 item = $item:tt
300 ) ) => {
301 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
302 features = (
303 method = $method,
304 used_linker = $used_linker,
305 ),
306 meta = $meta,
307 unsafe = $unsafe,
308 item = $item
309 ));
310 };
311
312 ( @entry next=$next:path[$next_args:tt], input=(
314 features = (
315 method = $method:tt,
316 used_linker = (),
317 ),
318 meta = $meta:tt,
319 unsafe = $unsafe:tt,
320 item = $item:tt
321 ) ) => {
322 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
323 features = (
324 method = $method,
325 used_linker_meta = (#[used]),
326 ),
327 meta = $meta,
328 unsafe = $unsafe,
329 item = $item
330 ));
331 };
332
333 ( @entry next=$next:path[$next_args:tt], input=(
334 features = (
335 method = $method:tt,
336 used_linker = used_linker,
337 ),
338 meta = $meta:tt,
339 unsafe = $unsafe:tt,
340 item = $item:tt
341 ) ) => {
342 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
343 features = (
344 method = $method,
345 used_linker_meta = (#[used(linker)]),
346 ),
347 meta = $meta,
348 unsafe = $unsafe,
349 item = $item
350 ));
351 };
352
353 ( @entry next=$next:path[$next_args:tt], input=(
355 features = (
356 method = ($method:tt $ctor_export_name_prefix:tt $ctor_link_section:tt $export_name_prefix:tt $link_section:tt),
357 used_linker_meta = (#$used_linker_meta:tt),
358 ),
359 meta = ($($meta:tt)*),
360 unsafe = ($($unsafe:tt)*),
361 item = ($vis:vis $(unsafe)? $( extern $abi:literal )? fn $name:ident $args:tt $( -> () )? {
362 $($body:tt)*
363 })
364 ) ) => {
365 $($meta)*
366 $vis $($unsafe)* $( extern $abi )? fn $name $args {
367 $crate::__dtor_parse_impl!(@dtor next=$next[$next_args], input=(
368 features = (
369 ctor_export_name_prefix = $ctor_export_name_prefix,
370 ctor_link_section = $ctor_link_section,
371 export_name_prefix = $export_name_prefix,
372 link_section = $link_section,
373 method = $method,
374 used_linker_meta = (#$used_linker_meta),
375 ),
376 item = $name,
377 unsafe = ($($unsafe)*)
378 ));
379
380 $($body)*
381 }
382 };
383
384 ( @dtor next=$next:path[$next_args:tt], input=(
387 features = (
388 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
389 ctor_link_section = $ctor_link_section:tt,
390 export_name_prefix = (),
391 link_section = $link_section:tt,
392 method = linker,
393 used_linker_meta = (#$used_linker_meta:tt),
394 ),
395 item = $name:ident,
396 unsafe = ($($unsafe:tt)*)
397 ) ) => {
398 const _: () = {
399 #[link_section = $link_section]
400 #$used_linker_meta
401 static __DTOR_PRIVATE_REF: extern "C" fn() = {
402 extern "C" fn __dtor_private() {
403 $($unsafe)* { $name() }
404 }
405 __dtor_private
406 };
407 };
408 };
409
410 ( @dtor next=$next:path[$next_args:tt], input=(
411 features = (
412 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
413 ctor_link_section = $ctor_link_section:tt,
414 export_name_prefix = $export_name_prefix:tt,
415 link_section = $link_section:tt,
416 method = linker,
417 used_linker_meta = (#$used_linker_meta:tt),
418 ),
419 item = $name:ident,
420 unsafe = ($($unsafe:tt)*)
421 ) ) => {
422 const _: () = {
423 #[no_mangle]
424 #[export_name = concat!($export_name_prefix, "_",
425 env!("CARGO_PKG_NAME"),
426 "_",
427 module_path!(),
428 "_",
429 stringify!($name),
430 "_L",
431 line!(),
432 "C",
433 column!())]
434 extern "C" fn __dtor_private() {
435 $($unsafe)* { $name() }
436 }
437 };
438 };
439
440 ( @dtor next=$next:path[$next_args:tt], input=(
441 features = (
442 ctor_export_name_prefix = (),
443 ctor_link_section = $ctor_link_section:tt,
444 export_name_prefix = $export_name_prefix:tt,
445 link_section = $link_section:tt,
446 method = $method:ident,
447 used_linker_meta = (#$used_linker_meta:tt),
448 ),
449 item = $name:ident,
450 unsafe = ($($unsafe:tt)*)
451 ) ) => {
452 const _: () = {
453 #[link_section = $ctor_link_section]
454 #$used_linker_meta
455 static __CTOR_PRIVATE_REF: unsafe extern "C" fn() = {
456 unsafe extern "C" fn __ctor_private() {
457 $crate::__support::$method(__dtor_private);
458 }
459 extern "C" fn __dtor_private() {
460 $($unsafe)* { $name() }
461 }
462 __ctor_private
463 };
464 };
465 };
466
467 ( @dtor next=$next:path[$next_args:tt], input=(
468 features = (
469 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
470 ctor_link_section = $ctor_link_section:tt,
471 export_name_prefix = $export_name_prefix:tt,
472 link_section = $link_section:tt,
473 method = $method:ident,
474 used_linker_meta = (#$used_linker_meta:tt),
475 ),
476 item = $name:ident,
477 unsafe = ($($unsafe:tt)*)
478 ) ) => {
479 const _: () = {
480 #[no_mangle]
481 #[export_name = concat!($ctor_export_name_prefix, "_",
482 env!("CARGO_PKG_NAME"),
483 "_",
484 module_path!(),
485 "_",
486 stringify!($name),
487 "_L",
488 line!(),
489 "C",
490 column!())]
491 unsafe extern "C" fn __ctor_private() {
492 $crate::__support::$method(__dtor_private);
493 }
494
495 extern "C" fn __dtor_private() {
496 $($unsafe)* { $name() }
497 }
498 };
499 };
500
501 ( @entry next=$next:path[$next_args:tt], input=$input:tt ) => {
502 compile_error!(concat!("Invalid dtor input: ", stringify!($input)));
503 };
504}