From 4165f9a4de97a78a355457eda9613d82f860849a Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 17 Jul 2026 13:30:47 -0400 Subject: [PATCH] Replace cfg_if! macro with cfg_select! fallback --- src/control/group/generic.rs | 9 +++-- src/control/group/mod.rs | 20 +++++---- src/macros.rs | 78 ++++++++++++------------------------ 3 files changed, 42 insertions(+), 65 deletions(-) diff --git a/src/control/group/generic.rs b/src/control/group/generic.rs index 09d5cd8a25..f154307499 100644 --- a/src/control/group/generic.rs +++ b/src/control/group/generic.rs @@ -5,16 +5,17 @@ use core::{mem, ptr}; // a 32-bit architecture will just end up being more expensive because // shifts and multiplies will need to be emulated. -cfg_if! { - if #[cfg(any( +cfg_select! { + any( target_pointer_width = "64", target_arch = "aarch64", target_arch = "x86_64", target_arch = "wasm32", - ))] { + ) => { type GroupWord = u64; type NonZeroGroupWord = core::num::NonZeroU64; - } else { + } + _ => { type GroupWord = u32; type NonZeroGroupWord = core::num::NonZeroU32; } diff --git a/src/control/group/mod.rs b/src/control/group/mod.rs index 7c526d8cca..8bc11bc682 100644 --- a/src/control/group/mod.rs +++ b/src/control/group/mod.rs @@ -5,7 +5,7 @@ // modules. Be sure to edit `ci/tools.sh` to add in the necessary cfgs if you // change these, so that your implementation gets properly linted. -cfg_if! { +cfg_select! { // Use the SSE2 implementation if possible: it allows us to scan 16 buckets // at once instead of 8. We don't bother with AVX since it would require // runtime dispatch and wouldn't gain us much anyways: the probability of @@ -14,32 +14,36 @@ cfg_if! { // I attempted an implementation on ARM using NEON instructions, but it // turns out that most NEON instructions have multi-cycle latency, which in // the end outweighs any gains over the generic implementation. - if #[cfg(all( + all( target_feature = "sse2", any(target_arch = "x86", target_arch = "x86_64"), not(miri), - ))] { + ) => { mod sse2; use sse2 as imp; - } else if #[cfg(all( + } + all( target_arch = "aarch64", target_feature = "neon", // NEON intrinsics are currently broken on big-endian targets. // See https://github.com/rust-lang/stdarch/issues/1484. target_endian = "little", not(miri), - ))] { + ) => { mod neon; use neon as imp; - } else if #[cfg(all( + } + all( feature = "nightly", target_arch = "loongarch64", target_feature = "lsx", not(miri), - ))] { + ) => { mod lsx; use lsx as imp; - } else { + } + + _ => { mod generic; use generic as imp; } diff --git a/src/macros.rs b/src/macros.rs index 7177d22123..2d92112ee3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,70 +1,42 @@ -// See the cfg-if crate. -#[expect(unused_macro_rules)] -macro_rules! cfg_if { - // match if/else chains with a final `else` - ($( - if #[cfg($($meta:meta),*)] { $($it:item)* } - ) else * else { - $($it2:item)* - }) => { - cfg_if! { - @__items - () ; - $( ( ($($meta),*) ($($it)*) ), )* - ( () ($($it2)*) ), - } +// FIXME: remove once we bump MSRV >= 1.95.0 +// Originally by @folkertdev on Zulip: +// https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/compiler-builtins.20msrv.20policy.3F/near/606320965 +/// Fallback `cfg_select!` on older Rust. +/// +/// Requires braces around output, but works for items and expressions. +#[cfg(not(feature = "nightly"))] +#[macro_export] +macro_rules! cfg_select { + ({ $($tt:tt)* }) => {{ + $crate::cfg_select! { $($tt)* } + }}; + (_ => { $($output:tt)* }) => { + $($output)* }; - - // match if/else chains lacking a final `else` ( - if #[cfg($($i_met:meta),*)] { $($i_it:item)* } - $( - else if #[cfg($($e_met:meta),*)] { $($e_it:item)* } - )* + $cfg:meta => $output:tt + $($( $rest:tt )+)? ) => { - cfg_if! { - @__items - () ; - ( ($($i_met),*) ($($i_it)*) ), - $( ( ($($e_met),*) ($($e_it)*) ), )* - ( () () ), - } - }; - - // Internal and recursive macro to emit all the items - // - // Collects all the negated cfgs in a list at the beginning and after the - // semicolon is all the remaining items - (@__items ($($not:meta,)*) ; ) => {}; - (@__items ($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => { - // Emit all items within one block, applying an appropriate #[cfg]. The - // #[cfg] will require all `$m` matchers specified and must also negate - // all previous matchers. - cfg_if! { @__apply cfg(all($($m,)* not(any($($not),*)))), $($it)* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$m` matchers to the list of `$not` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { @__items ($($not,)* $($m,)*) ; $($rest)* } - }; - - // Internal macro to Apply a cfg attribute to a list of items - (@__apply $m:meta, $($it:item)*) => { - $(#[$m] $it)* - }; + #[cfg($cfg)] + $crate::cfg_select! { _ => $output } + $( + #[cfg(not($cfg))] + $crate::cfg_select! { $($rest)+ } + )? + } } // Helper macro for specialization. This also helps avoid parse errors if the // default fn syntax for specialization changes in the future. #[cfg(feature = "nightly")] macro_rules! default_fn { - (#[$($a:tt)*] $($tt:tt)*) => { + (#[$($a:tt)*] $($tt:tt)*) => { #[$($a)*] default $($tt)* } } #[cfg(not(feature = "nightly"))] macro_rules! default_fn { - ($($tt:tt)*) => { + ($($tt:tt)*) => { $($tt)* } }