Skip to main content

libc/
macros.rs

1/// A macro for defining #[cfg] if-else statements.
2///
3/// This is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
4/// `#[cfg]` cases, emitting the implementation which matches first.
5///
6/// This allows you to conveniently provide a long list #[cfg]'d blocks of code without having to
7/// rewrite each clause multiple times.
8macro_rules! cfg_if {
9    // match if/else chains with a final `else`
10    ($(
11        if #[cfg($($meta:meta),*)] { $($it:item)* }
12    ) else * else {
13        $($it2:item)*
14    }) => {
15        cfg_if! {
16            @__items
17            () ;
18            $( ( ($($meta),*) ($($it)*) ), )*
19            ( () ($($it2)*) ),
20        }
21    };
22
23    // match if/else chains lacking a final `else`
24    (
25        if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
26        $(
27            else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
28        )*
29    ) => {
30        cfg_if! {
31            @__items
32            () ;
33            ( ($($i_met),*) ($($i_it)*) ),
34            $( ( ($($e_met),*) ($($e_it)*) ), )*
35            ( () () ),
36        }
37    };
38
39    // Internal and recursive macro to emit all the items
40    //
41    // Collects all the negated `cfg`s in a list at the beginning and after the
42    // semicolon is all the remaining items
43    (@__items ($($not:meta,)*) ; ) => {};
44    (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ),
45     $($rest:tt)*) => {
46        // Emit all items within one block, applying an appropriate #[cfg]. The
47        // #[cfg] will require all `$m` matchers specified and must also negate
48        // all previous matchers.
49        cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
50
51        // Recurse to emit all other items in `$rest`, and when we do so add all
52        // our `$m` matchers to the list of `$not` matchers as future emissions
53        // will have to negate everything we just matched as well.
54        cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* }
55    };
56
57    // Internal macro to Apply a cfg attribute to a list of items
58    (@__apply $m:meta, $($it:item)*) => {
59        $(#[$m] $it)*
60    };
61}
62
63/// Create an internal crate prelude with `core` reexports and common types.
64macro_rules! prelude {
65    () => {
66        mod types;
67
68        /// Frequently-used types that are available on all platforms
69        ///
70        /// We need to reexport the core types so this works with `rust-dep-of-std`.
71        mod prelude {
72            // Exports from `core`
73            #[allow(unused_imports)]
74            pub(crate) use core::clone::Clone;
75            #[allow(unused_imports)]
76            pub(crate) use core::cmp::{
77                Eq,
78                PartialEq,
79            };
80            #[allow(unused_imports)]
81            pub(crate) use core::default::Default;
82            #[allow(unused_imports)]
83            pub(crate) use core::iter::Iterator;
84            #[allow(unused_imports)]
85            pub(crate) use core::marker::{
86                Copy,
87                Send,
88                Sync,
89            };
90            #[allow(unused_imports)]
91            pub(crate) use core::option::Option::{
92                self,
93                None,
94                Some,
95            };
96            #[allow(unused_imports)]
97            pub(crate) use core::prelude::v1::derive;
98            #[allow(unused_imports)]
99            pub(crate) use core::{
100                assert,
101                cfg,
102                compile_error,
103                debug_assert,
104                fmt,
105                hash,
106                iter,
107                mem,
108                panic,
109                ptr,
110                unimplemented,
111            };
112
113            #[allow(unused_imports)]
114            pub(crate) use fmt::Debug;
115            #[allow(unused_imports)]
116            pub(crate) use mem::{
117                align_of,
118                align_of_val,
119                size_of,
120                size_of_val,
121            };
122
123            #[allow(unused_imports)]
124            #[cfg(any(target_os = "linux", target_os = "android", target_os = "l4re"))]
125            pub(crate) use crate::types::u32_cast_ioctl;
126            #[allow(unused_imports)]
127            pub(crate) use crate::types::{
128                cstr,
129                replace_array_items,
130                u16_cast_short,
131                u32_cast_int,
132                u32_cast_long,
133                u8_slice_cast_char_slice,
134                ulong_cast_int,
135                ulong_cast_uint,
136                CEnumRepr,
137                Padding,
138            };
139            // Commonly used types defined in this crate
140            #[allow(unused_imports)]
141            pub(crate) use crate::{
142                c_char,
143                c_double,
144                c_float,
145                c_int,
146                c_long,
147                c_longlong,
148                c_short,
149                c_uchar,
150                c_uint,
151                c_ulong,
152                c_ulonglong,
153                c_ushort,
154                c_void,
155                intptr_t,
156                size_t,
157                ssize_t,
158                uintptr_t,
159            };
160        }
161    };
162}
163
164/// Implement `Clone`, `Copy`, and `Debug` for one or more structs, as well as `PartialEq`, `Eq`,
165/// and `Hash` if the `extra_traits` feature is enabled.
166///
167/// Also mark the type with `repr(C)`.
168///
169/// Use [`s_no_extra_traits`] for structs where the `extra_traits` feature does not make sense, and
170/// for unions.
171macro_rules! s {
172    ($(
173        $(#[$attr:meta])*
174        $pub:vis $t:ident $i:ident { $($field:tt)* }
175    )*) => ($(
176        s!(it: $(#[$attr])* $pub $t $i { $($field)* });
177    )*);
178
179    (it: $(#[$attr:meta])* $pub:vis union $i:ident { $($field:tt)* }) => (
180        compile_error!("unions cannot derive extra traits, use s_no_extra_traits instead");
181    );
182
183    (it: $(#[$attr:meta])* $pub:vis struct $i:ident { $($field:tt)* }) => (
184        #[repr(C)]
185        #[::core::prelude::v1::derive(
186            ::core::clone::Clone,
187            ::core::marker::Copy,
188            ::core::fmt::Debug,
189        )]
190        #[cfg_attr(
191            feature = "extra_traits",
192            ::core::prelude::v1::derive(
193                ::core::cmp::PartialEq,
194                ::core::cmp::Eq,
195                ::core::hash::Hash,
196            )
197        )]
198        #[allow(deprecated)]
199        $(#[$attr])*
200        $pub struct $i { $($field)* }
201    );
202}
203
204/// Implement `Clone`, `Copy`, and `Debug` for a tuple struct, as well as `PartialEq`, `Eq`, and
205/// `Hash` if the `extra_traits` feature is enabled.
206///
207/// Unlike `s!`, this does *not* mark the type with `repr(C)`. Users should provide their own
208/// `repr` attribute via `$attr` as necessary.
209macro_rules! s_paren {
210    ($(
211        $(#[$attr:meta])*
212        $pub:vis struct $i:ident ( $($field:tt)* );
213    )*) => ($(
214        #[::core::prelude::v1::derive(
215            ::core::clone::Clone,
216            ::core::marker::Copy,
217            ::core::fmt::Debug,
218        )]
219        #[cfg_attr(
220            feature = "extra_traits",
221            ::core::prelude::v1::derive(
222                ::core::cmp::PartialEq,
223                ::core::cmp::Eq,
224                ::core::hash::Hash,
225            )
226        )]
227        $(#[$attr])*
228        $pub struct $i ( $($field)* );
229    )*);
230}
231
232/// Implement `Clone`, `Copy`, and `Debug` for one or more structs/unions, but exclude `PartialEq`,
233/// `Eq`, and `Hash`.
234///
235/// Also mark the type with `repr(C)`.
236///
237/// Most structs will prefer to use [`s`].
238macro_rules! s_no_extra_traits {
239    ($(
240        $(#$attr:tt)*
241        $pub:vis $t:ident $i:ident { $($field:tt)* }
242    )*) => ($(
243        s_no_extra_traits!(it: $(#$attr)* $pub $t $i { $($field)* });
244    )*);
245
246    (it: $(#$attr:tt)* $pub:vis union $i:ident { $($field:tt)* }) => (
247        union_with_debug! {
248            $(#$attr)* $pub union $i { $($field)* }
249        }
250    );
251
252    (it: $(#$attr:tt)* $pub:vis struct $i:ident { $($field:tt)* }) => (
253        #[repr(C)]
254        #[::core::prelude::v1::derive(
255            ::core::clone::Clone,
256            ::core::marker::Copy,
257            ::core::fmt::Debug,
258        )]
259        $(#$attr)*
260        $pub struct $i { $($field)* }
261    );
262}
263
264/// Like [`s`], but (1) generates a `Default` impl for every struct in the block, and (2) adds a
265/// private field to the struct to replicate the effects of the `non_exhaustive` attribute while
266/// rust-lang/rust#132699 gets sorted out.
267///
268/// To opt out of having the private field added, annotate the struct with an `exhaustive`
269/// attribute, as in:
270///
271/// ```ignore
272/// s2! {
273///     #[exhaustive]
274///     struct Something {
275///         ...
276///     }
277/// }
278/// ```
279///
280/// See [`custom_struct`] for details.
281macro_rules! s2 {
282    ($(
283        $(#$attr:tt)*
284        $pub:vis $t:ident $i:ident { $($field:tt)* }
285    )*) => ($(
286        s2!(it: $(#$attr)* $pub $t $i { $($field)* });
287    )*);
288
289    (it: $(#$attr:tt)* $pub:vis union $i:ident { $($field:tt)* }) => (
290        compile_error!(
291            "unions cannot derive extra traits, use `s_no_extra_traits2` \
292             instead"
293        );
294    );
295
296    (it: $(#$attr:tt)* $pub:vis struct $i:ident { $($field:tt)* }) => (
297        custom_struct! {
298            attrs: {
299                #[repr(C)]
300                #[::core::prelude::v1::derive(
301                    ::core::clone::Clone,
302                    ::core::marker::Copy,
303                    ::core::fmt::Debug,
304                )]
305                #[cfg_attr(
306                    feature = "extra_traits",
307                    ::core::prelude::v1::derive(
308                        ::core::cmp::PartialEq,
309                        ::core::cmp::Eq,
310                        ::core::hash::Hash,
311                    )
312                )]
313                #[allow(deprecated)]
314            }
315            $(#$attr)* $pub struct $i { $($field)* }
316        }
317    );
318}
319
320/// Like [`s_no_extra_traits`], but (1) generates a `Default` impl for every struct in the block,
321/// and (2) adds a private field to replicate the effects of the built-in `non_exhaustive` attribute
322/// while rust-lang/rust#132699 gets sorted out.
323///
324/// Unions are emitted just like `s_no_extra_traits!` does, with no `Default`.  A struct field of
325/// union type supplies its own default via `#[custom_default(...)]`.
326///
327/// To opt out of having the private field added, annotate the struct with an `exhaustive`
328/// attribute, as in:
329///
330/// ```ignore
331/// s_no_extra_traits2! {
332///     #[exhaustive]
333///     struct Something {
334///         ...
335///     }
336/// }
337/// ```
338macro_rules! s_no_extra_traits2 {
339    ($(
340        $(#$attr:tt)*
341        $pub:vis $t:ident $i:ident { $($field:tt)* }
342    )*) => ($(
343        s_no_extra_traits2!(it: $(#$attr)* $pub $t $i { $($field)* });
344    )*);
345
346    (it: $(#$attr:tt)* $pub:vis union $i:ident { $($field:tt)* }) => (
347        union_with_debug! {
348            $(#$attr)* $pub union $i { $($field)* }
349        }
350    );
351
352    (it: $(#$attr:tt)* $pub:vis struct $i:ident { $($field:tt)* }) => (
353        custom_struct! {
354            attrs: {
355                #[repr(C)]
356                #[::core::prelude::v1::derive(
357                    ::core::clone::Clone,
358                    ::core::marker::Copy,
359                    ::core::fmt::Debug,
360                )]
361            }
362            $(#$attr)* $pub struct $i { $($field)* }
363        }
364    );
365}
366
367/// Emit a union plus its `Debug` impl.
368///
369/// Unions can't derive `Debug`, so it is written out here. Attributes are split like
370/// [`custom_struct`] does. Everything goes on the union, but only the `cfg`s are repeated on the
371/// impl, otherwise a union that is configured out leaves an impl behind.
372macro_rules! union_with_debug {
373    (
374        $(#$attr:tt)*
375        $vis:vis union $name:ident { $($body:tt)* }
376    ) => {
377        union_with_debug! {
378            @split_attrs,
379            cfg_attrs: { },
380            other_attrs: { },
381            remaining_attrs: { $(#$attr)* },
382            found_default_via_unsafe_zeroed: false,
383            vis: $vis,
384            name: $name,
385            body: { $($body)* },
386        }
387    };
388
389    // a `cfg` also has to gate the impl
390    (
391        @split_attrs,
392        cfg_attrs: { $($cfg_attrs:tt)* },
393        other_attrs: { $($other_attrs:tt)* },
394        remaining_attrs: {
395            #[cfg($($cfg:tt)*)]
396            $($tail:tt)*
397        },
398        found_default_via_unsafe_zeroed: $found_default:tt,
399        vis: $vis:vis,
400        name: $name:ident,
401        body: { $($body:tt)* },
402    ) => {
403        union_with_debug! {
404            @split_attrs,
405            cfg_attrs: { $($cfg_attrs)* #[cfg($($cfg)*)] },
406            other_attrs: { $($other_attrs)* },
407            remaining_attrs: { $($tail)* },
408            found_default_via_unsafe_zeroed: $found_default,
409            vis: $vis,
410            name: $name,
411            body: { $($body)* },
412        }
413    };
414
415    // a `cfg` also has to gate the impl
416    (
417        @split_attrs,
418        cfg_attrs: { $($cfg_attrs:tt)* },
419        other_attrs: { $($other_attrs:tt)* },
420        remaining_attrs: {
421            #[unsafe(union_default_via_zeroed)]
422            $($tail:tt)*
423        },
424        found_default_via_unsafe_zeroed: $found_default:tt,
425        vis: $vis:vis,
426        name: $name:ident,
427        body: { $($body:tt)* },
428    ) => {
429        union_with_debug! {
430            @split_attrs,
431            cfg_attrs: { $($cfg_attrs)* },
432            other_attrs: { $($other_attrs)* },
433            remaining_attrs: { $($tail)* },
434            found_default_via_unsafe_zeroed: true,
435            vis: $vis,
436            name: $name,
437            body: { $($body)* },
438        }
439    };
440
441    // anything else belongs to the union only
442    (
443        @split_attrs,
444        cfg_attrs: { $($cfg_attrs:tt)* },
445        other_attrs: { $($other_attrs:tt)* },
446        remaining_attrs: {
447            #$other:tt
448            $($tail:tt)*
449        },
450        found_default_via_unsafe_zeroed: $found_default:tt,
451        vis: $vis:vis,
452        name: $name:ident,
453        body: { $($body:tt)* },
454    ) => {
455        union_with_debug! {
456            @split_attrs,
457            cfg_attrs: { $($cfg_attrs)* },
458            other_attrs: { $($other_attrs)* #$other },
459            remaining_attrs: { $($tail)* },
460            found_default_via_unsafe_zeroed: $found_default,
461            vis: $vis,
462            name: $name,
463            body: { $($body)* },
464        }
465    };
466
467    // done
468    (
469        @split_attrs,
470        cfg_attrs: { $($cfg_attrs:tt)* },
471        other_attrs: { $($other_attrs:tt)* },
472        remaining_attrs: { },
473        found_default_via_unsafe_zeroed: $found_default:tt,
474        vis: $vis:vis,
475        name: $name:ident,
476        body: { $($body:tt)* },
477    ) => {
478        #[repr(C)]
479        #[::core::prelude::v1::derive(
480            ::core::clone::Clone,
481            ::core::marker::Copy,
482        )]
483        $($other_attrs)*
484        $($cfg_attrs)*
485        $vis union $name { $($body)* }
486
487        $($cfg_attrs)*
488        #[allow(deprecated)]
489        impl ::core::fmt::Debug for $name {
490            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
491                f.debug_struct(::core::stringify!($name)).finish_non_exhaustive()
492            }
493        }
494
495        emit_union_default_via_unsafe_zeroed! {
496            found_default_via_unsafe_zeroed: $found_default,
497            cfg_attrs: { $($cfg_attrs)* },
498            name: $name,
499        }
500    };
501}
502
503/// Add a `Default` impl that is just `mem::zeroed`.
504macro_rules! emit_union_default_via_unsafe_zeroed {
505    (
506        found_default_via_unsafe_zeroed: false,
507        cfg_attrs: { $($cfg_attrs:tt)* },
508        name: $name:ident,
509    ) => {
510    };
511
512    (
513        found_default_via_unsafe_zeroed: true,
514        cfg_attrs: { $($cfg_attrs:tt)* },
515        name: $name:ident,
516    ) => {
517        $($cfg_attrs)*
518        impl ::core::default::Default for $name {
519            fn default() -> Self {
520                unsafe { ::core::mem::zeroed() }
521            }
522        }
523    };
524}
525
526/// Emit a struct with the given derive attributes plus a generated `Default` impl. Ensure that the
527/// record has an additional private field added to replicate `#[non_exhaustive]`, unless it is
528/// annotated with `#[exhaustive]`.
529///
530/// Fields default to `Default::default()`. A field whose default can't be derived must carry
531/// `#[custom_default(EXPR)]` as its *first* attribute, and `EXPR` is used instead.
532///
533/// This works by scanning each field for `#[custom_default]` attributes. If one exists, the
534/// attribute's contents are added to `processed_field_defaults` and will be used in the expansion
535/// for `Default`. If it does not exist, `Default::default()` is used instead. In either case, the
536/// field is added to `processed_fields` with `#[custom_default]` stripped if necessary, and
537/// `custom_struct` is invoked again with the remaining fields.
538///
539/// Attributes are split into `cfg_attrs` and `other_attrs` before the fields are scanned. Both go
540/// on the struct, but only the `cfg`s are repeated on the `Default` impl. A `cfg` decides whether
541/// the type exists at all, so without it a configured-out struct leaves an impl behind referring to
542/// a type that isn't there.
543///
544/// Out of `other_attrs`, we scan for `#[exhaustive]`. If found, we remove it but take into account
545/// that the record should be expanded _without_ an additional private field. The scan for both
546/// `cfg` attributes and the (non-existent) `exhaustive` attribute is done in one linear pass.
547macro_rules! custom_struct {
548    // entry; `attrs` is the attribute block the caller wants on the struct
549    // (repr, derives, etc.), which is merged with the struct's own attributes.
550    (
551        attrs: { $($attrs:tt)* }
552        $(#$attr:tt)*
553        $vis:vis struct $name:ident { $($body:tt)* }
554    ) => {
555        custom_struct! {
556            @split_attrs,
557            cfg_attrs: { },
558            other_attrs: { },
559            remaining_attrs: { $($attrs)* $(#$attr)* },
560            found_exhaustive_attr: false,
561            vis: $vis,
562            name: $name,
563            body: { $($body)* },
564        }
565    };
566
567    // a `cfg` also has to gate the impl
568    (
569        @split_attrs,
570        cfg_attrs: { $($cfg_attrs:tt)* },
571        other_attrs: { $($other_attrs:tt)* },
572        remaining_attrs: {
573            #[cfg($($cfg:tt)*)]
574            $($tail:tt)*
575        },
576        found_exhaustive_attr: $found_exhaustive:tt,
577        vis: $vis:vis,
578        name: $name:ident,
579        body: { $($body:tt)* },
580    ) => {
581        custom_struct! {
582            @split_attrs,
583            cfg_attrs: { $($cfg_attrs)* #[cfg($($cfg)*)] },
584            other_attrs: { $($other_attrs)* },
585            remaining_attrs: { $($tail)* },
586            found_exhaustive_attr: $found_exhaustive,
587            vis: $vis,
588            name: $name,
589            body: { $($body)* },
590        }
591    };
592
593    // `exhaustive` must be taken into account as many times as it appears,
594    // though the effect is the same with a single annotation.
595    (
596        @split_attrs,
597        cfg_attrs: { $($cfg_attrs:tt)* },
598        other_attrs: { $($other_attrs:tt)* },
599        remaining_attrs: {
600            #[exhaustive]
601            $($tail:tt)*
602        },
603        found_exhaustive_attr: $_:tt,
604        vis: $vis:vis,
605        name: $name:ident,
606        body: { $($body:tt)* },
607    ) => {
608        custom_struct! {
609            @split_attrs,
610            cfg_attrs: { $($cfg_attrs)* },
611            other_attrs: { $($other_attrs)* },
612            remaining_attrs: { $($tail)* },
613            found_exhaustive_attr: true,
614            vis: $vis,
615            name: $name,
616            body: { $($body)* },
617        }
618    };
619
620    // anything else belongs to the struct only
621    (
622        @split_attrs,
623        cfg_attrs: { $($cfg_attrs:tt)* },
624        other_attrs: { $($other_attrs:tt)* },
625        remaining_attrs: {
626            #$other:tt
627            $($tail:tt)*
628        },
629        found_exhaustive_attr: $found_exhaustive:tt,
630        vis: $vis:vis,
631        name: $name:ident,
632        body: { $($body:tt)* },
633    ) => {
634        custom_struct! {
635            @split_attrs,
636            cfg_attrs: { $($cfg_attrs)* },
637            other_attrs: { $($other_attrs)* #$other },
638            remaining_attrs: { $($tail)* },
639            found_exhaustive_attr: $found_exhaustive,
640            vis: $vis,
641            name: $name,
642            body: { $($body)* },
643        }
644    };
645
646    // attributes are split, move on to the fields
647    (
648        @split_attrs,
649        cfg_attrs: { $($cfg_attrs:tt)* },
650        other_attrs: { $($other_attrs:tt)* },
651        remaining_attrs: { },
652        found_exhaustive_attr: $found_exhaustive:tt,
653        vis: $vis:vis,
654        name: $name:ident,
655        body: { $($body:tt)* },
656    ) => {
657        custom_struct! {
658            @struct,
659            cfg_attrs: { $($cfg_attrs)* },
660            other_attrs: { $($other_attrs)* },
661            found_exhaustive_attr: $found_exhaustive,
662            vis: $vis,
663            name: $name,
664            processed_fields: { },
665            processed_field_defaults: { },
666            remaining_fields: { $($body)* },
667        }
668    };
669
670    // field led by #[custom_default(...)]
671    (
672        @struct,
673        cfg_attrs: { $($cfg_attrs:tt)* },
674        other_attrs: { $($other_attrs:tt)* },
675        found_exhaustive_attr: $found_exhaustive:tt,
676        vis: $vis:vis,
677        name: $name:ident,
678        processed_fields: { $($processed_fields:tt)* },
679        processed_field_defaults: { $($processed_field_defaults:tt)* },
680        remaining_fields: {
681            #[custom_default($default:expr)]
682            $(#[$fattr:meta])*
683            $fvis:vis $fname:ident: $fty:ty,
684            $($tail:tt)*
685        },
686    ) => {
687        custom_struct! {
688            @struct,
689            cfg_attrs: { $($cfg_attrs)* },
690            other_attrs: { $($other_attrs)* },
691            found_exhaustive_attr: $found_exhaustive,
692            vis: $vis,
693            name: $name,
694            processed_fields: { $($processed_fields)* $(#[$fattr])* $fvis $fname: $fty, },
695            processed_field_defaults: {
696                $($processed_field_defaults)*
697                $(#[$fattr])* $fname: $default,
698            },
699            remaining_fields: { $($tail)* },
700        }
701    };
702
703    // plain field
704    (
705        @struct,
706        cfg_attrs: { $($cfg_attrs:tt)* },
707        other_attrs: { $($other_attrs:tt)* },
708        found_exhaustive_attr: $found_exhaustive:tt,
709        vis: $vis:vis,
710        name: $name:ident,
711        processed_fields: { $($processed_fields:tt)* },
712        processed_field_defaults: { $($processed_field_defaults:tt)* },
713        remaining_fields: {
714            $(#[$fattr:meta])*
715            $fvis:vis $fname:ident: $fty:ty,
716            $($tail:tt)*
717        },
718    ) => {
719        custom_struct! {
720            @struct,
721            cfg_attrs: { $($cfg_attrs)* },
722            other_attrs: { $($other_attrs)* },
723            found_exhaustive_attr: $found_exhaustive,
724            vis: $vis,
725            name: $name,
726            processed_fields: { $($processed_fields)* $(#[$fattr])* $fvis $fname: $fty, },
727            processed_field_defaults: {
728                $($processed_field_defaults)*
729                $(#[$fattr])* $fname: ::core::default::Default::default(),
730            },
731            remaining_fields: { $($tail)* },
732        }
733    };
734
735    // done
736    (
737        @struct,
738        cfg_attrs: { $($cfg_attrs:tt)* },
739        other_attrs: { $($other_attrs:tt)* },
740        found_exhaustive_attr: $found_exhaustive:tt,
741        vis: $vis:vis,
742        name: $name:ident,
743        processed_fields: { $($processed_fields:tt)* },
744        processed_field_defaults: { $($processed_field_defaults:tt)* },
745        remaining_fields: { },
746    ) => {
747        emit_struct_definition! {
748            found_exhaustive_attr: $found_exhaustive,
749            body: {
750                $($other_attrs)*
751                $($cfg_attrs)*
752                $vis $name { $($processed_fields)* }
753            }
754        }
755
756        $($cfg_attrs)*
757        // The impl names the type and its fields, which warns if either is
758        // deprecated.
759        #[allow(deprecated)]
760        impl ::core::default::Default for $name {
761            // Field attributes (`#[cfg]`, doc comments) get forwarded to the
762            // initializer too. Docs are harmless there but trip the lint, so
763            // silence it.
764            #[allow(unused_doc_comments)]
765            fn default() -> Self {
766                emit_struct_default_body! {
767                    found_exhaustive_attr: $found_exhaustive,
768                    body: { $($processed_field_defaults)* }
769                }
770            }
771        }
772    };
773}
774
775/// Expands the definition of the record defined at [`custom_struct`], with either one of an
776/// additional private field or with its verbatim fields.
777macro_rules! emit_struct_definition {
778    (
779        found_exhaustive_attr: false,
780        body: { $(#[$attr:meta])* $vis:vis $name:ident { $($field:tt)* } }
781    ) => {
782        #[allow(clippy::manual_non_exhaustive)]
783        $(#[$attr])*
784        $vis struct $name { $($field)* __non_exhaustive: () }
785    };
786
787    (
788        found_exhaustive_attr: true,
789        body: { $(#[$attr:meta])* $vis:vis $name:ident { $($field:tt)* } }
790    ) => {
791        $(#[$attr])*
792        $vis struct $name { $($field)* }
793    };
794}
795
796/// Expands the `Default` implementation of the record defined at [`custom_struct`], with either one
797/// of an additional private field initialized to the unit value, or the record's fields verbatim.
798macro_rules! emit_struct_default_body {
799    (
800        found_exhaustive_attr: false,
801        body: { $($field_default:tt)* }
802    ) => {
803        Self { $($field_default)* __non_exhaustive: () }
804    };
805
806    (
807        found_exhaustive_attr: true,
808        body: { $($field_default:tt)* }
809    ) => {
810        Self { $($field_default)* }
811    };
812}
813
814/// Create an uninhabited type that can't be constructed. It implements `Debug`, `Clone`, and
815/// `Copy`, but these aren't meaningful for extern types so they should eventually be removed.
816///
817/// Really what we want here is something that also can't be named without indirection (in ADTs or
818/// function signatures), but this doesn't exist.
819macro_rules! extern_ty {
820    ($(
821        $(#[$attr:meta])*
822        $vis:vis type $i:ident;
823    )*) => ($(
824        $(#[$attr])*
825        /// This is an extern type ("opaque" or "incomplete" type in C).
826        ///
827        /// <div class="warning">
828        /// This type's current representation allows inspecting some properties, such as via
829        /// <code>size_of</code>, and it is technically possible to construct the type within
830        /// <code>MaybeUninit</code>, However, this <strong>MUST NOT</strong> be relied upon
831        /// because a future version of <code>libc</code> may switch to a proper
832        /// <a href="https://rust-lang.github.io/rfcs/1861-extern-types.html">extern type</a>
833        /// representation when available.
834        /// </div>
835        // ^ unfortunately warning blocks currently don't render markdown so we need to
836        // use raw HTML.
837        //
838        // Representation based on the Nomicon:
839        // <https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs>.
840        //
841        // FIXME(1.0): These traits are unreachable and should be removed.
842        #[::core::prelude::v1::derive(
843            ::core::clone::Clone,
844            ::core::marker::Copy,
845            ::core::fmt::Debug,
846        )]
847        #[repr(C)]
848        $vis struct $i {
849            _data: (),
850            _marker: ::core::marker::PhantomData<(*mut u8, ::core::marker::PhantomPinned)>,
851        }
852    )*);
853}
854
855/// Implement `Clone` and `Copy` for an enum, as well as `Debug`, `Eq`, `Hash`, and
856/// `PartialEq` if the `extra_traits` feature is enabled.
857// FIXME(#4419): Replace all uses of `e!` with `c_enum!`
858macro_rules! e {
859    ($(
860        $(#[$attr:meta])*
861        pub enum $i:ident { $($field:tt)* }
862    )*) => ($(
863        #[cfg_attr(
864            feature = "extra_traits",
865            ::core::prelude::v1::derive(Eq, Hash, PartialEq)
866        )]
867        #[::core::prelude::v1::derive(
868            ::core::clone::Clone,
869            ::core::marker::Copy,
870            ::core::fmt::Debug,
871        )]
872        $(#[$attr])*
873        pub enum $i { $($field)* }
874    )*);
875}
876
877/// Represent a C enum as Rust constants and a type.
878///
879/// C enums can't soundly be mapped to Rust enums since C enums are allowed to have duplicates or
880/// unlisted values, but this is UB in Rust. This enum doesn't implement any traits, its main
881/// purpose is to calculate the correct enum values.
882///
883/// Use the magic name `#anon` if the C enum doesn't create a type.
884///
885/// See <https://github.com/rust-lang/libc/issues/4419> for more.
886macro_rules! c_enum {
887    // Matcher for multiple enums
888    ($(
889        $(#[repr($repr:ty)])?
890        $vis:vis enum $($ty_name:ident)? $(#$anon:ident)? {
891            $(
892                $(#[$meta:meta])*
893                $field_vis:vis $variant:ident $(= $value:expr)?,
894            )+
895        }
896    )+) => {
897        $(c_enum!(@single;
898            $(#[repr($repr)])?
899            $vis enum $($ty_name)? $(#$anon)? {
900                $(
901                    $(#[$meta])*
902                    $field_vis $variant $(= $value)?,
903                )+
904            }
905        );)+
906    };
907
908    // Matcher for a single enum
909    (@single;
910        $(#[repr($repr:ty)])?
911        $vis:vis enum $ty_name:ident {
912            $(
913                $(#[$meta:meta])*
914                $field_vis:vis $variant:ident $(= $value:expr)?,
915            )+
916        }
917    ) => {
918        $vis type $ty_name = c_enum!(@ty $($repr)?);
919        c_enum! {
920            @variant;
921            ty: $ty_name;
922            default: 0;
923            variants: [$(
924                $(#[$meta])*
925                $field_vis $variant $(= $value)?,
926            )+]
927        }
928    };
929
930    // Matcher for a single anonymous enum
931    (@single;
932        $(#[repr($repr:ty)])?
933        $vis:vis enum #anon {
934            $(
935                $(#[$meta:meta])*
936                $field_vis:vis $variant:ident $(= $value:expr)?,
937            )+
938        }
939    ) => {
940        c_enum! {
941            @variant;
942            ty: c_enum!(@ty $($repr)?);
943            default: 0;
944            variants: [$(
945                $(#[$meta])*
946                $field_vis $variant $(= $value)?,
947            )+]
948        }
949    };
950
951    // Matcher for variants: eats a single variant then recurses with the rest
952    (@variant;
953        ty: $_ty_name:ty;
954        default: $_idx:expr;
955        variants: []
956    ) => { /* end of the chain */ };
957    (
958        @variant;
959        ty: $ty_name:ty;
960        default: $default_val:expr;
961        variants: [
962            $(#[$meta:meta])*
963            $field_vis:vis $variant:ident $(= $value:expr)?,
964            $($tail:tt)*
965        ]
966    ) => {
967        $(#[$meta])*
968        #[allow(deprecated)]
969        $field_vis const $variant: $ty_name = {
970            #[allow(unused_variables)]
971            let r = $default_val;
972            $(let r = $value;)?
973            r
974        };
975
976        // The next value is always one more than the previous value, unless
977        // set explicitly.
978        c_enum! {
979            @variant;
980            ty: $ty_name;
981            default: $variant + 1;
982            variants: [$($tail)*]
983        }
984    };
985
986    // Use a specific type if provided, otherwise default to `CEnumRepr`
987    (@ty $repr:ty) => { $repr };
988    (@ty) => { $crate::prelude::CEnumRepr };
989}
990
991/// Define a function that can be either `safe` or `unsafe` and optionally `const`. This always
992/// marks the function inline and adds `extern "C"`.
993macro_rules! f {
994    ($(
995        $(#[$attr:meta])*
996        pub $(const $($const_dummy:literal)?)?
997        $(unsafe $($unsafe_dummy:literal)?)? $(safe $($safe_dummy:literal)?)?
998        fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty
999            $body:block
1000    )+) => {$(
1001        f! {
1002            @single
1003            $(#[$attr])*
1004            pub $(const $($const_dummy)?)?
1005            $(unsafe $($unsafe_dummy)?)? $(safe $($safe_dummy)?)?
1006            fn $i ($($arg: $argty),*) -> $ret
1007                $body
1008        }
1009    )+};
1010
1011    (@single
1012        $(#[$attr:meta])*
1013        pub $(const $($const_dummy:literal)?)? unsafe
1014        fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty
1015            $body:block
1016    ) => {
1017        #[inline]
1018        $(#[$attr])*
1019        pub $(const $($const_dummy)?)? unsafe extern "C"
1020        fn $i ($($arg: $argty),*) -> $ret
1021            $body
1022    };
1023
1024    (@single
1025        $(#[$attr:meta])*
1026        pub $(const $($const_dummy:literal)?)? safe
1027        fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty
1028            $body:block
1029    ) => {
1030        #[inline]
1031        $(#[$attr])*
1032        pub $(const $($const_dummy)?)? extern "C"
1033        fn $i ($($arg: $argty),*) -> $ret
1034            $body
1035    };
1036
1037    (@single
1038        pub $(const $($const_dummy:literal)?)?
1039        fn $i:ident ($($arg:ident: $argty:ty),* $(,)?) -> $ret:ty
1040            $body:block
1041    ) => {
1042        compile_error!("either `safe` or `unsafe` must be specified");
1043    };
1044}
1045
1046// This macro is used to deprecate items that should be accessed via the mach2 crate
1047macro_rules! deprecated_mach {
1048    (pub const $id:ident: $ty:ty = $expr:expr;) => {
1049        #[deprecated(
1050            since = "0.2.55",
1051            note = "Use the `mach2` crate instead",
1052        )]
1053        #[allow(deprecated)]
1054        pub const $id: $ty = $expr;
1055    };
1056    ($(pub const $id:ident: $ty:ty = $expr:expr;)*) => {
1057        $(
1058            deprecated_mach!(
1059                pub const $id: $ty = $expr;
1060            );
1061        )*
1062    };
1063    (pub type $id:ident = $ty:ty;) => {
1064        #[deprecated(
1065            since = "0.2.55",
1066            note = "Use the `mach2` crate instead",
1067        )]
1068        #[allow(deprecated)]
1069        pub type $id = $ty;
1070    };
1071    ($(pub type $id:ident = $ty:ty;)*) => {
1072        $(
1073            deprecated_mach!(
1074                pub type $id = $ty;
1075            );
1076        )*
1077    }
1078}
1079
1080/// Polyfill for std's `offset_of`.
1081// FIXME(msrv): stabilized in std in 1.77
1082macro_rules! offset_of {
1083    ($Ty:path, $field:ident) => {{
1084        // Taken from bytemuck, avoids accidentally calling on deref
1085        #[allow(clippy::unneeded_wildcard_pattern)]
1086        let $Ty { $field: _, .. };
1087        let data = core::mem::MaybeUninit::<$Ty>::uninit();
1088        let ptr = data.as_ptr();
1089        // nested unsafe, see f!
1090        #[allow(unused_unsafe)]
1091        // SAFETY: computed address is inbounds since we have a stack alloc for
1092        // T
1093        let fptr = unsafe { core::ptr::addr_of!((*ptr).$field) };
1094        let off = (fptr as usize).checked_sub(ptr as usize).unwrap();
1095        core::assert!(off <= core::mem::size_of::<$Ty>());
1096        off
1097    }};
1098}
1099
1100#[cfg(test)]
1101mod tests {
1102    use core::any::TypeId;
1103    use core::prelude::v1::*;
1104
1105    use crate::types::CEnumRepr;
1106
1107    #[test]
1108    fn c_enum_basic() {
1109        // By default, variants get sequential values.
1110        c_enum! {
1111            pub enum e {
1112                VAR0,
1113                VAR1,
1114                VAR2,
1115            }
1116
1117            // Also check enums that don't create a type.
1118            pub enum #anon {
1119                ANON0,
1120                ANON1,
1121                ANON2,
1122            }
1123
1124            // No visibility required.
1125            enum #anon {
1126                ANON3,
1127                ANON4,
1128                ANON5,
1129            }
1130        }
1131
1132        assert_eq!(TypeId::of::<e>(), TypeId::of::<CEnumRepr>());
1133        assert_eq!(VAR0, 0 as CEnumRepr);
1134        assert_eq!(VAR1, 1 as CEnumRepr);
1135        assert_eq!(VAR2, 2 as CEnumRepr);
1136
1137        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<CEnumRepr>());
1138        assert_eq!(ANON0, 0 as CEnumRepr);
1139        assert_eq!(ANON1, 1 as CEnumRepr);
1140        assert_eq!(ANON2, 2 as CEnumRepr);
1141
1142        assert_eq!(type_id_of_val(&ANON3), TypeId::of::<CEnumRepr>());
1143        assert_eq!(ANON3, 0 as CEnumRepr);
1144        assert_eq!(ANON4, 1 as CEnumRepr);
1145        assert_eq!(ANON5, 2 as CEnumRepr);
1146    }
1147
1148    #[test]
1149    fn c_enum_repr() {
1150        // Check specifying the integer representation
1151        c_enum! {
1152            #[repr(u16)]
1153            pub enum e {
1154                VAR0,
1155            }
1156
1157            #[repr(u16)]
1158            pub enum #anon {
1159                ANON0,
1160            }
1161        }
1162
1163        assert_eq!(TypeId::of::<e>(), TypeId::of::<u16>());
1164        assert_eq!(VAR0, 0_u16);
1165
1166        assert_eq!(type_id_of_val(&ANON0), TypeId::of::<u16>());
1167        assert_eq!(ANON0, 0_u16);
1168    }
1169
1170    #[test]
1171    fn c_enum_set_value() {
1172        // Setting an explicit value resets the count.
1173        c_enum! {
1174            pub enum e {
1175                VAR2 = 2,
1176                VAR3,
1177                VAR4,
1178            }
1179        }
1180
1181        assert_eq!(VAR2, 2 as CEnumRepr);
1182        assert_eq!(VAR3, 3 as CEnumRepr);
1183        assert_eq!(VAR4, 4 as CEnumRepr);
1184    }
1185
1186    #[test]
1187    fn c_enum_multiple_set_value() {
1188        // C enums always take one more than the previous value, unless set to a
1189        // specific value. Duplicates are allowed.
1190        c_enum! {
1191            pub enum e {
1192                VAR0,
1193                VAR2_0 = 2,
1194                VAR3_0,
1195                VAR4_0,
1196                VAR2_1 = 2,
1197                VAR3_1,
1198                VAR4_1,
1199            }
1200        }
1201
1202        assert_eq!(VAR0, 0 as CEnumRepr);
1203        assert_eq!(VAR2_0, 2 as CEnumRepr);
1204        assert_eq!(VAR3_0, 3 as CEnumRepr);
1205        assert_eq!(VAR4_0, 4 as CEnumRepr);
1206        assert_eq!(VAR2_1, 2 as CEnumRepr);
1207        assert_eq!(VAR3_1, 3 as CEnumRepr);
1208        assert_eq!(VAR4_1, 4 as CEnumRepr);
1209    }
1210
1211    #[test]
1212    fn c_enum_vis() {
1213        mod priv1 {
1214            c_enum! {
1215                #[repr(u8)]
1216                pub enum e1 {
1217                    PRIV_ON_1 = 10,
1218                    // Variant should still be usable within its visibility
1219                    pub PUB1 = PRIV_ON_1 * 2,
1220                }
1221            }
1222        }
1223        mod priv2 {
1224            c_enum! {
1225                #[repr(u16)]
1226                pub enum e2 {
1227                    pub PRIV_ON_1 = 42,
1228                    pub PUB2 = PRIV_ON_1 * 2,
1229                }
1230            }
1231        }
1232
1233        use priv1::*;
1234        use priv2::*;
1235
1236        assert_eq!(TypeId::of::<e1>(), TypeId::of::<u8>());
1237        assert_eq!(TypeId::of::<e2>(), TypeId::of::<u16>());
1238        assert_eq!(PUB1, 10u8 * 2);
1239        assert_eq!(PUB2, 42u16 * 2);
1240        // Verify that the default is private. If `PRIV_ON_1` was actually
1241        // public in `priv1`, this would be an ambiguous import and/or type
1242        // mismatch error.
1243        assert_eq!(PRIV_ON_1, 42u16);
1244    }
1245
1246    #[test]
1247    fn c_enum_attrs() {
1248        // Note this can't work with `#[cfg]` currently because our expansion uses `previous + 1`
1249        c_enum! {
1250            pub enum e {
1251                VAR0,
1252                WITH_CFG = if cfg!(target_arch = "x86_64") { 86 } else { 1234 },
1253                #[deprecated]
1254                DEPRECATED,
1255                NOT_DEPRECATED,
1256            }
1257        }
1258
1259        if cfg!(target_arch = "x86_64") {
1260            assert_eq!(WITH_CFG, 86);
1261        } else {
1262            assert_eq!(WITH_CFG, 1234);
1263        }
1264
1265        #[expect(deprecated)]
1266        let _ = DEPRECATED;
1267        #[deny(deprecated)]
1268        let _ = NOT_DEPRECATED;
1269    }
1270
1271    #[test]
1272    #[deny(unused_unsafe)]
1273    fn f_safety() {
1274        // Enusure the created functions are safe / unsafe / const as expected
1275        f! {
1276            pub unsafe fn unsafe_foo() -> u32 { 100 }
1277            pub const unsafe fn const_unsafe_foo() -> u32 { 101 }
1278            pub safe fn safe_foo() -> u32 { 200 }
1279            pub const safe fn const_safe_foo() -> u32 { 201 }
1280        }
1281
1282        assert_eq!(unsafe { unsafe_foo() }, 100u32);
1283        assert_eq!(const { unsafe { const_unsafe_foo() } }, 101u32);
1284        assert_eq!(safe_foo(), 200u32);
1285        assert_eq!(const { const_safe_foo() }, 201u32);
1286
1287        // Check the ABI
1288        let _: unsafe extern "C" fn() -> u32 = unsafe_foo;
1289        let _: unsafe extern "C" fn() -> u32 = const_unsafe_foo;
1290        let _: extern "C" fn() -> u32 = safe_foo;
1291        let _: extern "C" fn() -> u32 = const_safe_foo;
1292    }
1293
1294    fn type_id_of_val<T: 'static>(_: &T) -> TypeId {
1295        TypeId::of::<T>()
1296    }
1297
1298    #[test]
1299    fn test_offset_of() {
1300        #[repr(C)]
1301        struct Off1 {
1302            a: u8,
1303            b: u32,
1304            c: Off2,
1305            d: u64,
1306        }
1307
1308        #[repr(C)]
1309        #[repr(align(128))]
1310        struct Off2 {}
1311
1312        assert_eq!(core::mem::offset_of!(Off1, a), offset_of!(Off1, a));
1313        assert_eq!(core::mem::offset_of!(Off1, b), offset_of!(Off1, b));
1314        assert_eq!(core::mem::offset_of!(Off1, c), offset_of!(Off1, c));
1315        assert_eq!(core::mem::offset_of!(Off1, d), offset_of!(Off1, d));
1316    }
1317
1318    #[test]
1319    fn s2_is_non_exhaustive() {
1320        // Without `#[exhaustive]`, the record should have an additional field
1321        // added at the end. If this test compiles, it has it.
1322        s2! {
1323            struct Something {
1324                a: u32,
1325            }
1326        }
1327
1328        let s = Something::default();
1329        assert_eq!(s.__non_exhaustive, ());
1330    }
1331
1332    #[test]
1333    fn s2_uses_exhaustive() {
1334        // With `#[exhaustive]`, the record should be regurgitated as-is. If
1335        // this test compiles, then it works.
1336        s2! {
1337            #[exhaustive]
1338            struct Something {
1339                a: u32,
1340            }
1341        }
1342
1343        #[allow(unused)]
1344        let s = Something {
1345            a: Default::default(),
1346        };
1347    }
1348
1349    #[test]
1350    fn s2_uses_mixed_exhaustive() {
1351        // `#[exhaustive]` should work when sandwiched between attributes. If
1352        // the test compiles, then it works.
1353        s2! {
1354            #[repr(align(8))]
1355            #[exhaustive]
1356            #[repr(align(2))]
1357            struct Something {
1358                a: u32,
1359            }
1360        }
1361
1362        #[allow(unused)]
1363        let s = Something {
1364            a: Default::default(),
1365        };
1366    }
1367
1368    #[test]
1369    fn s2_uses_custom_default() {
1370        // A non-default value proves `custom_default` is used rather than a
1371        // derived default.
1372        s2! {
1373            struct CustomDefault {
1374                a: u32,
1375                #[custom_default([1; 64])]
1376                buf: [u8; 64],
1377            }
1378        }
1379
1380        let s = CustomDefault::default();
1381        assert_eq!(s.a, 0);
1382        assert_eq!(s.buf, [1u8; 64]);
1383    }
1384
1385    #[test]
1386    fn s2_keeps_field_attrs() {
1387        // If `custom_default` stripping ate the other field attributes, the two
1388        // `a` fields would collide.
1389        s2! {
1390            struct FieldAttrs {
1391                #[cfg(target_arch = "x86_64")]
1392                a: u8,
1393                #[cfg(not(target_arch = "x86_64"))]
1394                a: u64,
1395            }
1396        }
1397
1398        let s = FieldAttrs::default();
1399        #[cfg(target_arch = "x86_64")]
1400        assert_eq!(s.a, 0u8);
1401        #[cfg(not(target_arch = "x86_64"))]
1402        assert_eq!(s.a, 0u64);
1403    }
1404
1405    #[test]
1406    fn s2_single_cfg_field() {
1407        // This field only exists on x86_64, so its default init needs the same
1408        // `cfg` or `Default` won't build on other arches.
1409        s2! {
1410            struct SingleCfg {
1411                common: u32,
1412                #[cfg(target_arch = "x86_64")]
1413                x86_only: u64,
1414            }
1415        }
1416
1417        let s = SingleCfg::default();
1418        assert_eq!(s.common, 0);
1419        #[cfg(target_arch = "x86_64")]
1420        assert_eq!(s.x86_only, 0);
1421    }
1422
1423    #[test]
1424    fn s_no_extra_traits2_zeroes_union() {
1425        // A union field's default is supplied by
1426        // `custom_default(unsafe { mem::zeroed })`.
1427        s_no_extra_traits2! {
1428            union U {
1429                a: u32,
1430                b: f32,
1431            }
1432
1433            struct HasUnion {
1434                x: u16,
1435                #[custom_default(unsafe { ::core::mem::zeroed::<U>() })]
1436                u: U,
1437            }
1438        }
1439
1440        let s = HasUnion::default();
1441        assert_eq!(s.x, 0);
1442        assert_eq!(unsafe { s.u.a }, 0);
1443    }
1444
1445    #[test]
1446    fn s2_keeps_struct_cfg() {
1447        // The opposite of the configured-out types in `macro_checks`. With the
1448        // `cfg` true the type and its `Default` both exist, and the other
1449        // attributes still apply.
1450        s2! {
1451            #[cfg(true)]
1452            #[repr(align(8))]
1453            /// a doc comment
1454            struct EnabledCfg {
1455                a: u32,
1456                #[cfg(target_arch = "x86_64")]
1457                x86_only: u8,
1458                #[custom_default([1; 40])]
1459                buf: [u8; 40],
1460            }
1461        }
1462
1463        let s = EnabledCfg::default();
1464        assert_eq!(s.a, 0);
1465        assert_eq!(s.buf, [1u8; 40]);
1466        assert_eq!(align_of::<EnabledCfg>(), 8);
1467        #[cfg(target_arch = "x86_64")]
1468        assert_eq!(s.x86_only, 0);
1469    }
1470
1471    #[test]
1472    fn s2_union_default() {
1473        s_no_extra_traits2! {
1474            #[unsafe(union_default_via_zeroed)]
1475            union Foo {
1476                a: u32,
1477                b: u64
1478            }
1479
1480            #[expect(unused)]
1481            union Bar {
1482                a: u32,
1483                b: u64
1484            }
1485        }
1486
1487        let f: Foo = Foo::default();
1488        assert_eq!(unsafe { f.b }, 0);
1489
1490        // Ensure it isn't always implemented, otherwise we would get a conflict.
1491        impl Default for Bar {
1492            fn default() -> Self {
1493                unimplemented!()
1494            }
1495        }
1496    }
1497}
1498
1499#[cfg(test)]
1500#[allow(unused)]
1501mod macro_checks {
1502    use core::prelude::v1::*;
1503
1504    s! {
1505        pub struct S1 {
1506            pub a: u32,
1507            b: u32,
1508        }
1509
1510        struct S1Priv {
1511            pub a: u32,
1512            b: u32,
1513        }
1514    }
1515
1516    s_no_extra_traits! {
1517        pub struct S2 {
1518            pub a: u32,
1519            b: u32,
1520        }
1521
1522        struct S2Priv {
1523            pub a: u32,
1524            b: u32,
1525        }
1526
1527        pub union U2 {
1528            pub a: u32,
1529            b: f32,
1530        }
1531
1532        union U2Priv {
1533            pub a: u32,
1534            b: f32,
1535        }
1536    }
1537
1538    extern_ty! {
1539        type Foo;
1540        pub type Bar;
1541    }
1542
1543    s2! {
1544        pub struct S3 {
1545            pub a: u32,
1546            #[custom_default([1; 64])]
1547            pub buf: [u8; 64],
1548        }
1549
1550        struct S3Priv {
1551            pub a: u32,
1552            b: u32,
1553        }
1554    }
1555
1556    s_no_extra_traits2! {
1557        pub union U3 {
1558            pub a: u32,
1559            b: f32,
1560        }
1561
1562        pub struct S4 {
1563            pub a: u32,
1564            #[custom_default(unsafe { ::core::mem::zeroed::<U3>() })]
1565            pub u: U3,
1566        }
1567    }
1568
1569    fn assert_impls_default<T: Default>() {}
1570
1571    fn check_default() {
1572        assert_impls_default::<S3>();
1573        assert_impls_default::<S4>();
1574    }
1575
1576    // Types configured out entirely, checking that the generated impls carry
1577    // the same `cfg` as the type. Without it they fail to compile with "cannot
1578    // find type".
1579    s2! {
1580        #[cfg(false)]
1581        pub struct S5 {
1582            pub a: u32,
1583            #[custom_default([1; 64])]
1584            pub buf: [u8; 64],
1585        }
1586    }
1587
1588    s_no_extra_traits! {
1589        #[cfg(false)]
1590        pub union U4 {
1591            pub a: u32,
1592            b: f32,
1593        }
1594    }
1595
1596    s_no_extra_traits2! {
1597        #[cfg(false)]
1598        pub union U5 {
1599            pub a: u32,
1600            b: f32,
1601        }
1602
1603        #[cfg(false)]
1604        pub struct S6 {
1605            pub a: u32,
1606        }
1607    }
1608
1609    // The generated impls name the type and its fields, so they need to allow
1610    // deprecation.  `deny` turns the warning into an error if that ever stops
1611    // being the case.
1612    mod deprecated_checks {
1613        #![deny(deprecated)]
1614
1615        s2! {
1616            #[deprecated(since = "0.0.0", note = "check that generated impls don't warn")]
1617            pub struct S7 {
1618                pub a: u32,
1619            }
1620        }
1621
1622        s_no_extra_traits! {
1623            #[deprecated(since = "0.0.0", note = "check that generated impls don't warn")]
1624            pub union U6 {
1625                pub a: u32,
1626                b: f32,
1627            }
1628        }
1629
1630        s_no_extra_traits2! {
1631            #[deprecated(since = "0.0.0", note = "check that generated impls don't warn")]
1632            pub union U7 {
1633                pub a: u32,
1634                b: f32,
1635            }
1636        }
1637    }
1638}