1 /// A macro for defining #[cfg] if-else statements.
3 /// This is similar to the `if/elif` C preprocessor macro by allowing definition
4 /// of a cascade of `#[cfg]` cases, emitting the implementation which matches
7 /// This allows you to conveniently provide a long list #[cfg]'d blocks of code
8 /// without having to rewrite each clause multiple times.
9 #[allow(unused_macros)]
11 // match if/else chains with a final `else`
13 if #[cfg($($meta:meta),*)] { $($it:item)* }
20 $
( ( ($
($meta
),*) ($
($it
)*) ), )*
25 // match if/else chains lacking a final `else`
27 if #[cfg($($i_met:meta),*)] { $($i_it:item)* }
29 else if #[cfg($($e_met:meta),*)] { $($e_it:item)* }
35 ( ($
($i_met
),*) ($
($i_it
)*) ),
36 $
( ( ($
($e_met
),*) ($
($e_it
)*) ), )*
41 // Internal and recursive macro to emit all the items
43 // Collects all the negated `cfg`s in a list at the beginning and after the
44 // semicolon is all the remaining items
45 (@
__items ($
($not
:meta
,)*) ; ) => {}
;
46 (@
__items ($
($not
:meta
,)*) ; ( ($
($m
:meta
),*) ($
($it
:item
)*) ),
48 // Emit all items within one block, applying an appropriate #[cfg]. The
49 // #[cfg] will require all `$m` matchers specified and must also negate
50 // all previous matchers.
51 cfg_if
! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* }
53 // Recurse to emit all other items in `$rest`, and when we do so add all
54 // our `$m` matchers to the list of `$not` matchers as future emissions
55 // will have to negate everything we just matched as well.
56 cfg_if
! { @__items ($($not,)* $($m,)*) ; $($rest)* }
59 // Internal macro to Apply a cfg attribute to a list of items
60 (@__apply $m
:meta
, $
($it
:item
)*) => {
65 #[allow(unused_macros)]
67 ($
($
(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
68 s
!(it
: $
(#[$attr])* pub $t $i { $($field)* });
70 (it
: $
(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
71 compile_error
!("unions cannot derive extra traits, use s_no_extra_traits instead");
73 (it
: $
(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
76 #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
79 pub struct $i { $($field)* }
85 fn clone(&self) -> $i { *self }
90 #[allow(unused_macros)]
91 macro_rules
! s_no_extra_traits
{
92 ($
($
(#[$attr:meta])* pub $t:ident $i:ident { $($field:tt)* })*) => ($(
93 s_no_extra_traits
!(it
: $
(#[$attr])* pub $t $i { $($field)* });
95 (it
: $
(#[$attr:meta])* pub union $i:ident { $($field:tt)* }) => (
97 if #[cfg(libc_union)] {
101 pub union $i { $($field)* }
104 impl ::Copy
for $i {}
105 impl ::Clone
for $i
{
106 fn clone(&self) -> $i { *self }
111 (it
: $
(#[$attr:meta])* pub struct $i:ident { $($field:tt)* }) => (
115 pub struct $i { $($field)* }
118 impl ::Copy
for $i {}
120 impl ::Clone
for $i
{
121 fn clone(&self) -> $i { *self }
126 #[allow(unused_macros)]
128 ($
($
(#[$attr:meta])* pub enum $i:ident { $($field:tt)* })*) => ($(
130 #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
132 pub enum $i { $($field)* }
134 impl ::Copy
for $i {}
135 impl ::Clone
for $i
{
136 fn clone(&self) -> $i { *self }
141 #[allow(unused_macros)]
142 macro_rules
! s_paren
{
143 ($
($
(#[$attr:meta])* pub struct $i:ident ( $($field:tt)* ); )* ) => ($(
145 #[cfg_attr(feature = "extra_traits", derive(Debug, Eq, Hash, PartialEq))]
147 pub struct $
i ( $
($field
)* );
149 impl ::Copy
for $i {}
150 impl ::Clone
for $i
{
151 fn clone(&self) -> $i { *self }
156 // This is a pretty horrible hack to allow us to conditionally mark
157 // some functions as 'const', without requiring users of this macro
158 // to care about the "const-extern-fn" feature.
160 // When 'const-extern-fn' is enabled, we emit the captured 'const' keyword
161 // in the expanded function.
163 // When 'const-extern-fn' is disabled, we always emit a plain 'pub unsafe extern fn'.
164 // Note that the expression matched by the macro is exactly the same - this allows
165 // users of this macro to work whether or not 'const-extern-fn' is enabled
167 // Unfortunately, we need to duplicate most of this macro between the 'cfg_if' blocks.
168 // This is because 'const unsafe extern fn' won't even parse on older compilers,
169 // so we need to avoid emitting it at all of 'const-extern-fn'.
171 // Specifically, moving the 'cfg_if' into the macro body will *not* work.
172 // Doing so would cause the '#[cfg(feature = "const-extern-fn")]' to be emitted
173 // into user code. The 'cfg' gate will not stop Rust from trying to parse the
174 // 'pub const unsafe extern fn', so users would get a compiler error even when
175 // the 'const-extern-fn' feature is disabled
177 // Note that users of this macro need to place 'const' in a weird position
178 // (after the closing ')' for the arguments, but before the return type).
179 // This was the only way I could satisfy the following two requirements:
180 // 1. Avoid ambiguity errors from 'macro_rules!' (which happen when writing '$foo:ident fn'
181 // 2. Allow users of this macro to mix 'pub fn foo' and 'pub const fn bar' within the same
184 if #[cfg(libc_const_extern_fn)] {
185 #[allow(unused_macros)]
187 ($
($
(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
188 $
($arg
:ident
: $argty
:ty
),*
194 pub $
($constness
)* unsafe extern fn $
i($
($arg
: $argty
),*
201 #[allow(unused_macros)]
202 macro_rules
! safe_f
{
203 ($
($
(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
204 $
($arg
:ident
: $argty
:ty
),*
210 pub $
($constness
)* extern fn $
i($
($arg
: $argty
),*
217 #[allow(unused_macros)]
218 macro_rules
! const_fn
{
219 ($
($
(#[$attr:meta])* $({$constness:ident})* fn $i:ident(
220 $
($arg
:ident
: $argty
:ty
),*
226 $
($constness
)* fn $
i($
($arg
: $argty
),*
234 #[allow(unused_macros)]
236 ($
($
(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
237 $
($arg
:ident
: $argty
:ty
),*
243 pub unsafe extern fn $
i($
($arg
: $argty
),*
250 #[allow(unused_macros)]
251 macro_rules
! safe_f
{
252 ($
($
(#[$attr:meta])* pub $({$constness:ident})* fn $i:ident(
253 $
($arg
:ident
: $argty
:ty
),*
259 pub extern fn $
i($
($arg
: $argty
),*
266 #[allow(unused_macros)]
267 macro_rules
! const_fn
{
268 ($
($
(#[$attr:meta])* $({$constness:ident})* fn $i:ident(
269 $
($arg
:ident
: $argty
:ty
),*
275 fn $
i($
($arg
: $argty
),*
284 #[allow(unused_macros)]
285 macro_rules
! __item
{
291 #[allow(unused_macros)]
292 macro_rules
! align_const
{
294 pub const $name
:ident
: $t1
:ty
295 = $t2
:ident { $($field:tt)* }
;)*) => ($
(
298 pub const $name
: $t1
= $t2
{
301 #[cfg(not(libc_align))]
303 pub const $name
: $t1
= $t2
{
310 // This macro is used to deprecate items that should be accessed via the mach crate
311 #[allow(unused_macros)]
312 macro_rules
! deprecated_mach
{
313 (pub const $id
:ident
: $ty
:ty
= $expr
:expr
;) => {
316 note
= "Use the `mach` crate instead",
319 pub const $id
: $ty
= $expr
;
321 ($
(pub const $id
:ident
: $ty
:ty
= $expr
:expr
;)*) => {
324 pub const $id
: $ty
= $expr
;
328 (pub type $id
:ident
= $ty
:ty
;) => {
331 note
= "Use the `mach` crate instead",
336 ($
(pub type $id
:ident
= $ty
:ty
;)*) => {