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 : $anonymous_spec:ident,
27 crate_path = $crate_path:tt : $crate_path_spec:ident,
28 ctor_export_name_prefix = $ctor_export_name_prefix:tt : $ctor_export_name_prefix_spec:ident,
29 ctor_link_section = $ctor_link_section:tt : $ctor_link_section_spec:ident,
30 default_term_method = $default_term_method:tt : $default_term_method_spec:ident,
31 default_unload_method = $default_unload_method:tt : $default_unload_method_spec:ident,
32 export_name_prefix = $export_name_prefix:tt : $export_name_prefix_spec:ident,
33 link_section = $link_section:tt : $link_section_spec:ident,
34 method = $method:tt : $method_spec:ident,
35 proc_macro = $proc_macro:tt : $proc_macro_spec:ident,
36 std = $std:tt : $std_spec:ident,
37 r#unsafe = $no_warn_on_missing_unsafe:tt : $no_warn_on_missing_unsafe_spec:ident,
38 used_linker = $used_linker:tt : $used_linker_spec:ident,
39 ),
40 self = $self:tt,
41 meta = $meta:tt,
42 unsafe = ($($unsafe:tt)*),
43 item = ($vis:vis $(unsafe)? $( extern $abi:literal )? fn $name:ident () $( -> () )? {
44 $($body:tt)*
45 })
46 ) ) => {
47 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
48 features = (
49 anonymous = $anonymous,
50 ctor_export_name_prefix = $ctor_export_name_prefix,
51 ctor_link_section = $ctor_link_section,
52 default_term_method = $default_term_method,
53 default_unload_method = $default_unload_method,
54 export_name_prefix = $export_name_prefix,
55 link_section = $link_section,
56 method = $method,
57 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
58 used_linker = $used_linker,
59 ),
60 meta = $meta,
61 unsafe = ($($unsafe)*),
62 item = ($vis $($unsafe)* $( extern $abi )? fn $name () {
63 $($body)*
64 })
65 ));
66 };
67
68 ( @entry next=$next:path[$next_args:tt], input=(
69 features = (
70 anonymous = $anonymous:tt : $anonymous_spec:ident,
71 $($rest:tt)*
72 ),
73 self = $self:tt,
74 meta = $meta:tt,
75 unsafe = $unsafe:tt,
76 item = ($item:item)
77 ) ) => {
78 compile_error!("Invalid dtor function. \
79 Expected a function with no args, \
80 return value, or type parameters.\n\
81 Valid forms are: [pub] [unsafe] [extern $abi] fn $name() { ... }");
82 };
83
84 ( @entry next=$next:path[$next_args:tt], input=(
85 features = (
86 anonymous = $anonymous:tt : $anonymous_spec:ident,
87 $($rest:tt)*
88 ),
89 self = $self:tt,
90 meta = $meta:tt,
91 unsafe = $unsafe:tt,
92 item = ($($item:tt)*)
93 ) ) => {
94 compile_error!(concat!("Invalid dtor, didn't get an item: ", stringify!($($item)*)));
95 };
96
97 ( @entry next=$next:path[$next_args:tt], input=(
101 features = (
102 anonymous = $anonymous:tt,
103 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
104 ctor_link_section = $ctor_link_section:tt,
105 default_term_method = $default_term_method:tt,
106 default_unload_method = $default_unload_method:tt,
107 export_name_prefix = $export_name_prefix:tt,
108 link_section = $link_section:tt,
109 method = term,
110 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
111 used_linker = $used_linker:tt,
112 ),
113 meta = $meta:tt,
114 unsafe = $unsafe:tt,
115 item = $item:tt
116 ) ) => {
117 $crate::__dtor_parse_impl(@entry next=$next[$next_args], input=(
119 features = (
120 anonymous = $anonymous,
121 method = ($default_term_method $ctor_export_name_prefix $ctor_link_section $export_name_prefix $link_section),
122 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
123 used_linker = $used_linker,
124 ),
125 meta = $meta,
126 unsafe = $unsafe,
127 item = $item
128 ));
129 };
130
131 ( @entry next=$next:path[$next_args:tt], input=(
133 features = (
134 anonymous = $anonymous:tt,
135 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
136 ctor_link_section = $ctor_link_section:tt,
137 default_term_method = $default_term_method:tt,
138 default_unload_method = $default_unload_method:tt,
139 export_name_prefix = $export_name_prefix:tt,
140 link_section = $link_section:tt,
141 method = unload,
142 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
143 used_linker = $used_linker:tt,
144 ),
145 meta = $meta:tt,
146 unsafe = $unsafe:tt,
147 item = $item:tt
148 ) ) => {
149 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
151 features = (
152 anonymous = $anonymous,
153 method = ($default_unload_method $ctor_export_name_prefix $ctor_link_section $export_name_prefix $link_section),
154 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
155 used_linker = $used_linker,
156 ),
157 meta = $meta,
158 unsafe = $unsafe,
159 item = $item
160 ));
161 };
162
163 ( @entry next=$next:path[$next_args:tt], input=(
165 features = (
166 anonymous = $anonymous:tt,
167 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
168 ctor_link_section = $ctor_link_section:tt,
169 default_term_method = $default_term_method:tt,
170 default_unload_method = $default_unload_method:tt,
171 export_name_prefix = $export_name_prefix:tt,
172 link_section = $link_section:tt,
173 method = $method:tt,
174 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
175 used_linker = $used_linker:tt,
176 ),
177 meta = $meta:tt,
178 unsafe = $unsafe:tt,
179 item = $item:tt
180 ) ) => {
181 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
183 features = (
184 anonymous = $anonymous,
185 method = ($method $ctor_export_name_prefix $ctor_link_section $export_name_prefix $link_section),
186 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe,
187 used_linker = $used_linker,
188 ),
189 meta = $meta,
190 unsafe = $unsafe,
191 item = $item
192 ));
193 };
194
195 ( @entry next=$next:path[$next_args:tt], input=(
199 features = (
200 anonymous = $anonymous:tt,
201 method = $method:tt,
202 no_warn_on_missing_unsafe = (),
203 used_linker = $used_linker:tt,
204 ),
205 meta = $meta:tt,
206 unsafe = (),
207 item = $item:tt
208 ) ) => {
209 const _: () = {
210 #[deprecated="dtor deprecation note:\n\n\
211 Use of #[dtor] without `#[dtor(unsafe)]` or `unsafe fn` is deprecated. As code execution\n\
212 before main is unsupported by most Rust runtime functions, these functions must be marked\n\
213 `unsafe`."]
214 const fn dtor_without_unsafe_is_deprecated() {}
215 #[allow(unused)]
216 static UNSAFE_WARNING: () = {
217 dtor_without_unsafe_is_deprecated()
218 };
219 };
220
221 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
222 features = (
223 anonymous = $anonymous,
224 method = $method,
225 used_linker = $used_linker,
226 ),
227 meta = $meta,
228 unsafe = (),
229 item = $item
230 ));
231 };
232
233 ( @entry next=$next:path[$next_args:tt], input=(
235 features = (
236 anonymous = $anonymous:tt,
237 method = $method:tt,
238 no_warn_on_missing_unsafe = $no_warn_on_missing_unsafe:tt,
239 used_linker = $used_linker:tt,
240 ),
241 meta = $meta:tt,
242 unsafe = $unsafe:tt,
243 item = $item:tt
244 ) ) => {
245 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
246 features = (
247 anonymous = $anonymous,
248 method = $method,
249 used_linker = $used_linker,
250 ),
251 meta = $meta,
252 unsafe = $unsafe,
253 item = $item
254 ));
255 };
256
257 ( @entry next=$next:path[$next_args:tt], input=(
259 features = (
260 anonymous = anonymous,
261 method = $method:tt,
262 used_linker = $used_linker:tt,
263 ),
264 meta = $meta:tt,
265 unsafe = $unsafe:tt,
266 item = $item:tt
267 ) ) => {
268 const _: () = {
270 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
271 features = (
272 method = $method,
273 used_linker = $used_linker,
274 ),
275 meta = $meta,
276 unsafe = $unsafe,
277 item = $item
278 ));
279 };
280 };
281
282 ( @entry next=$next:path[$next_args:tt], input=(
283 features = (
284 anonymous = (),
285 method = $method:tt,
286 used_linker = $used_linker:tt,
287 ),
288 meta = $meta:tt,
289 unsafe = $unsafe:tt,
290 item = $item:tt
291 ) ) => {
292 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
293 features = (
294 method = $method,
295 used_linker = $used_linker,
296 ),
297 meta = $meta,
298 unsafe = $unsafe,
299 item = $item
300 ));
301 };
302
303 ( @entry next=$next:path[$next_args:tt], input=(
305 features = (
306 method = $method:tt,
307 used_linker = (),
308 ),
309 meta = $meta:tt,
310 unsafe = $unsafe:tt,
311 item = $item:tt
312 ) ) => {
313 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
314 features = (
315 method = $method,
316 used_linker_meta = (#[used]),
317 ),
318 meta = $meta,
319 unsafe = $unsafe,
320 item = $item
321 ));
322 };
323
324 ( @entry next=$next:path[$next_args:tt], input=(
325 features = (
326 method = $method:tt,
327 used_linker = used_linker,
328 ),
329 meta = $meta:tt,
330 unsafe = $unsafe:tt,
331 item = $item:tt
332 ) ) => {
333 $crate::__dtor_parse_impl!(@entry next=$next[$next_args], input=(
334 features = (
335 method = $method,
336 used_linker_meta = (#[used(linker)]),
337 ),
338 meta = $meta,
339 unsafe = $unsafe,
340 item = $item
341 ));
342 };
343
344 ( @entry next=$next:path[$next_args:tt], input=(
346 features = (
347 method = ($method:tt $ctor_export_name_prefix:tt $ctor_link_section:tt $export_name_prefix:tt $link_section:tt),
348 used_linker_meta = (#$used_linker_meta:tt),
349 ),
350 meta = ($($meta:tt)*),
351 unsafe = ($($unsafe:tt)*),
352 item = ($vis:vis $(unsafe)? $( extern $abi:literal )? fn $name:ident $args:tt $( -> () )? {
353 $($body:tt)*
354 })
355 ) ) => {
356 $($meta)*
357 #[allow(dead_code)]
358 $vis $($unsafe)* $( extern $abi )? fn $name $args {
359 $($unsafe)* $( extern $abi )? fn __dtor_private_inner $args {
362 $($body)*
363 }
364
365 $crate::__dtor_parse_impl!(@dtor next=$next[$next_args], input=(
366 features = (
367 ctor_export_name_prefix = $ctor_export_name_prefix,
368 ctor_link_section = $ctor_link_section,
369 export_name_prefix = $export_name_prefix,
370 link_section = $link_section,
371 method = $method,
372 used_linker_meta = (#$used_linker_meta),
373 ),
374 item = ($($unsafe)* { __dtor_private_inner() })
375 ));
376
377 $($unsafe)* { __dtor_private_inner() }
378 }
379 };
380
381 ( @dtor next=$next:path[$next_args:tt], input=(
384 features = (
385 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
386 ctor_link_section = $ctor_link_section:tt,
387 export_name_prefix = (),
388 link_section = $link_section:tt,
389 method = linker,
390 used_linker_meta = (#$used_linker_meta:tt),
391 ),
392 item = ($($item:tt)*)
393 ) ) => {
394 const _: () = {
395 #[link_section = $link_section]
396 #$used_linker_meta
397 static __DTOR_PRIVATE_REF: extern "C" fn() = {
398 extern "C" fn __dtor_private() {
399 $($item)*
400 }
401 __dtor_private
402 };
403 };
404 };
405
406 ( @dtor next=$next:path[$next_args:tt], input=(
407 features = (
408 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
409 ctor_link_section = $ctor_link_section:tt,
410 export_name_prefix = $export_name_prefix:tt,
411 link_section = $link_section:tt,
412 method = linker,
413 used_linker_meta = (#$used_linker_meta:tt),
414 ),
415 item = ($($item:tt)*)
416 ) ) => {
417 const _: () = {
418 #[no_mangle]
419 #[export_name = concat!($export_name_prefix, "_",
420 env!("CARGO_PKG_NAME"),
421 "_",
422 module_path!(),
423 "_",
424 stringify!($name),
425 "_L",
426 line!(),
427 "C",
428 column!())]
429 extern "C" fn __dtor_private() {
430 $($item)*
431 }
432 };
433 };
434
435 ( @dtor next=$next:path[$next_args:tt], input=(
436 features = (
437 ctor_export_name_prefix = (),
438 ctor_link_section = $ctor_link_section:tt,
439 export_name_prefix = $export_name_prefix:tt,
440 link_section = $link_section:tt,
441 method = $method:ident,
442 used_linker_meta = (#$used_linker_meta:tt),
443 ),
444 item = ($($item:tt)*)
445 ) ) => {
446 const _: () = {
447 #[link_section = $ctor_link_section]
448 #$used_linker_meta
449 static __CTOR_PRIVATE_REF: unsafe extern "C" fn() = {
450 unsafe extern "C" fn __ctor_private() {
451 #[cfg(all(target_family = "wasm", target_os = "unknown"))]
452 {
453 static DISARMED: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false);
454 if DISARMED.swap(true, ::core::sync::atomic::Ordering::Relaxed) {
455 return;
456 }
457 }
458 $crate::__support::$method(__dtor_private);
459 }
460 extern "C" fn __dtor_private() {
461 $($item)*
462 }
463 __ctor_private
464 };
465 };
466 };
467
468 ( @dtor next=$next:path[$next_args:tt], input=(
469 features = (
470 ctor_export_name_prefix = $ctor_export_name_prefix:tt,
471 ctor_link_section = $ctor_link_section:tt,
472 export_name_prefix = $export_name_prefix:tt,
473 link_section = $link_section:tt,
474 method = $method:ident,
475 used_linker_meta = (#$used_linker_meta:tt),
476 ),
477 item = ($($item: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 $($item)*
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}