Skip to content

Commit 986959b

Browse files
committed
Add a copy of cfg_if to core's internal_macros.rs
core can't depend on external crates the way std can. Rather than revert usage of cfg_if, add a copy of it to core. This does not export our copy, even unstably; such a change could occur in a later commit.
1 parent f701e0d commit 986959b

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

core/src/internal_macros.rs

+93
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,96 @@ macro_rules! impl_fn_for_zst {
187187
)+
188188
}
189189
}
190+
191+
/// A macro for defining `#[cfg]` if-else statements.
192+
///
193+
/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade
194+
/// of `#[cfg]` cases, emitting the implementation which matches first.
195+
///
196+
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code without having to
197+
/// rewrite each clause multiple times.
198+
///
199+
/// # Example
200+
///
201+
/// ```
202+
/// cfg_if! {
203+
/// if #[cfg(unix)] {
204+
/// fn foo() { /* unix specific functionality */ }
205+
/// } else if #[cfg(target_pointer_width = "32")] {
206+
/// fn foo() { /* non-unix, 32-bit functionality */ }
207+
/// } else {
208+
/// fn foo() { /* fallback implementation */ }
209+
/// }
210+
/// }
211+
///
212+
/// # fn main() {}
213+
/// ```
214+
// This is a copy of `cfg_if!` from the `cfg_if` crate.
215+
// The recursive invocations should use $crate if this is ever exported.
216+
macro_rules! cfg_if {
217+
// match if/else chains with a final `else`
218+
(
219+
$(
220+
if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
221+
) else+
222+
else { $( $e_tokens:tt )* }
223+
) => {
224+
cfg_if! {
225+
@__items () ;
226+
$(
227+
(( $i_meta ) ( $( $i_tokens )* )) ,
228+
)+
229+
(() ( $( $e_tokens )* )) ,
230+
}
231+
};
232+
233+
// match if/else chains lacking a final `else`
234+
(
235+
if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
236+
$(
237+
else if #[cfg( $e_meta:meta )] { $( $e_tokens:tt )* }
238+
)*
239+
) => {
240+
cfg_if! {
241+
@__items () ;
242+
(( $i_meta ) ( $( $i_tokens )* )) ,
243+
$(
244+
(( $e_meta ) ( $( $e_tokens )* )) ,
245+
)*
246+
}
247+
};
248+
249+
// Internal and recursive macro to emit all the items
250+
//
251+
// Collects all the previous cfgs in a list at the beginning, so they can be
252+
// negated. After the semicolon is all the remaining items.
253+
(@__items ( $( $_:meta , )* ) ; ) => {};
254+
(
255+
@__items ( $( $no:meta , )* ) ;
256+
(( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
257+
$( $rest:tt , )*
258+
) => {
259+
// Emit all items within one block, applying an appropriate #[cfg]. The
260+
// #[cfg] will require all `$yes` matchers specified and must also negate
261+
// all previous matchers.
262+
#[cfg(all(
263+
$( $yes , )?
264+
not(any( $( $no ),* ))
265+
))]
266+
cfg_if! { @__identity $( $tokens )* }
267+
268+
// Recurse to emit all other items in `$rest`, and when we do so add all
269+
// our `$yes` matchers to the list of `$no` matchers as future emissions
270+
// will have to negate everything we just matched as well.
271+
cfg_if! {
272+
@__items ( $( $no , )* $( $yes , )? ) ;
273+
$( $rest , )*
274+
}
275+
};
276+
277+
// Internal macro to make __apply work out right for different match types,
278+
// because of how macros match/expand stuff.
279+
(@__identity $( $tokens:tt )* ) => {
280+
$( $tokens )*
281+
};
282+
}

0 commit comments

Comments
 (0)