Skip to content

Commit

Permalink
Remove cfg_match from the prelude
Browse files Browse the repository at this point in the history
  • Loading branch information
c410-f3r committed Oct 25, 2023
1 parent c2ef351 commit 0b96e47
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 89 deletions.
3 changes: 3 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ pub mod assert_matches {
pub use crate::macros::{assert_matches, debug_assert_matches};
}

#[unstable(feature = "cfg_match", issue = "115585")]
pub use crate::macros::cfg_match;

#[macro_use]
mod internal_macros;

Expand Down
177 changes: 88 additions & 89 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,94 @@ pub macro assert_matches {
},
}

/// A macro for defining `#[cfg]` match-like statements.
///
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
/// `#[cfg]` cases, emitting the implementation which matches first.
///
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
/// without having to rewrite each clause multiple times.
///
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
/// all previous declarations do not evaluate to true.
///
/// # Example
///
/// ```
/// #![feature(cfg_match)]
///
/// cfg_match! {
/// cfg(unix) => {
/// fn foo() { /* unix specific functionality */ }
/// }
/// cfg(target_pointer_width = "32") => {
/// fn foo() { /* non-unix, 32-bit functionality */ }
/// }
/// _ => {
/// fn foo() { /* fallback implementation */ }
/// }
/// }
/// ```
#[unstable(feature = "cfg_match", issue = "115585")]
#[rustc_diagnostic_item = "cfg_match"]
pub macro cfg_match {
// with a final wildcard
(
$(cfg($initial_meta:meta) => { $($initial_tokens:item)* })+
_ => { $($extra_tokens:item)* }
) => {
cfg_match! {
@__items ();
$((($initial_meta) ($($initial_tokens)*)),)+
(() ($($extra_tokens)*)),
}
},

// without a final wildcard
(
$(cfg($extra_meta:meta) => { $($extra_tokens:item)* })*
) => {
cfg_match! {
@__items ();
$((($extra_meta) ($($extra_tokens)*)),)*
}
},

// Internal and recursive macro to emit all the items
//
// Collects all the previous cfgs in a list at the beginning, so they can be
// negated. After the semicolon is all the remaining items.
(@__items ($($_:meta,)*);) => {},
(
@__items ($($no:meta,)*);
(($($yes:meta)?) ($($tokens:item)*)),
$($rest:tt,)*
) => {
// Emit all items within one block, applying an appropriate #[cfg]. The
// #[cfg] will require all `$yes` matchers specified and must also negate
// all previous matchers.
#[cfg(all(
$($yes,)?
not(any($($no),*))
))]
cfg_match! { @__identity $($tokens)* }

// Recurse to emit all other items in `$rest`, and when we do so add all
// our `$yes` matchers to the list of `$no` matchers as future emissions
// will have to negate everything we just matched as well.
cfg_match! {
@__items ($($no,)* $($yes,)?);
$($rest,)*
}
},

// Internal macro to make __apply work out right for different match types,
// because of how macros match/expand stuff.
(@__identity $($tokens:item)*) => {
$($tokens)*
}
}

/// Asserts that a boolean expression is `true` at runtime.
///
/// This will invoke the [`panic!`] macro if the provided expression cannot be
Expand Down Expand Up @@ -321,95 +409,6 @@ pub macro debug_assert_matches($($arg:tt)*) {
}
}

/// A macro for defining `#[cfg]` match-like statements.
///
/// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
/// `#[cfg]` cases, emitting the implementation which matches first.
///
/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
/// without having to rewrite each clause multiple times.
///
/// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
/// all previous declarations do not evaluate to true.
///
/// # Example
///
/// ```
/// #![feature(cfg_match)]
///
/// cfg_match! {
/// cfg(unix) => {
/// fn foo() { /* unix specific functionality */ }
/// }
/// cfg(target_pointer_width = "32") => {
/// fn foo() { /* non-unix, 32-bit functionality */ }
/// }
/// _ => {
/// fn foo() { /* fallback implementation */ }
/// }
/// }
/// ```
#[macro_export]
#[unstable(feature = "cfg_match", issue = "115585")]
#[rustc_diagnostic_item = "cfg_match"]
macro_rules! cfg_match {
// with a final wildcard
(
$(cfg($initial_meta:meta) => { $($initial_tokens:item)* })+
_ => { $($extra_tokens:item)* }
) => {
cfg_match! {
@__items ();
$((($initial_meta) ($($initial_tokens)*)),)+
(() ($($extra_tokens)*)),
}
};

// without a final wildcard
(
$(cfg($extra_meta:meta) => { $($extra_tokens:item)* })*
) => {
cfg_match! {
@__items ();
$((($extra_meta) ($($extra_tokens)*)),)*
}
};

// Internal and recursive macro to emit all the items
//
// Collects all the previous cfgs in a list at the beginning, so they can be
// negated. After the semicolon is all the remaining items.
(@__items ($($_:meta,)*);) => {};
(
@__items ($($no:meta,)*);
(($($yes:meta)?) ($($tokens:item)*)),
$($rest:tt,)*
) => {
// Emit all items within one block, applying an appropriate #[cfg]. The
// #[cfg] will require all `$yes` matchers specified and must also negate
// all previous matchers.
#[cfg(all(
$($yes,)?
not(any($($no),*))
))]
cfg_match! { @__identity $($tokens)* }

// Recurse to emit all other items in `$rest`, and when we do so add all
// our `$yes` matchers to the list of `$no` matchers as future emissions
// will have to negate everything we just matched as well.
cfg_match! {
@__items ($($no,)* $($yes,)?);
$($rest,)*
}
};

// Internal macro to make __apply work out right for different match types,
// because of how macros match/expand stuff.
(@__identity $($tokens:item)*) => {
$($tokens)*
};
}

/// Returns whether the given expression matches any of the given patterns.
///
/// Like in a `match` expression, the pattern can be optionally followed by `if`
Expand Down

0 comments on commit 0b96e47

Please sign in to comment.