From 4e62decff5f07f1a458bbd253a0270c78f080f07 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Wed, 17 Jun 2026 11:57:13 +0100 Subject: [PATCH] internal: fix `cfg_select` polyfill short circuit --- src/internal/macros.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/internal/macros.rs b/src/internal/macros.rs index 59804720476..0a781f1db19 100644 --- a/src/internal/macros.rs +++ b/src/internal/macros.rs @@ -1,4 +1,7 @@ /// Polyfill of `cfg_select` for MSRV < 1.95 +/// +/// Note that this polyfill does not work in type position, so it is not as powerful as the +/// real `cfg_select` macro. That is a limitation that PyO3 can live with for now. #[doc(hidden)] #[cfg(not(cfg_select))] macro_rules! cfg_select { @@ -19,7 +22,7 @@ macro_rules! cfg_select { @parsed($($clauses:meta),*) $cfg:meta => $final_arm:expr $(,)? ) => { - #[cfg($cfg)] + #[cfg(all($cfg, not(any($($clauses),*))))] { $final_arm } @@ -30,30 +33,30 @@ macro_rules! cfg_select { ); }; + // Non-terminating expression arm requires trailing comma ( @parsed($($clauses:meta),*) $cfg:meta => $arm:expr, $($rest:tt)* ) => { - #[cfg($cfg)] + #[cfg(all($cfg, not(any($($clauses),*))))] { $arm } - cfg_select! { @parsed($($clauses,)* $cfg) $($rest)* } }; + // Non-terminating block doesn't require trailing comma ( @parsed($($clauses:meta),*) $cfg:meta => $arm:block $($rest:tt)* ) => { - #[cfg($cfg)] + #[cfg(all($cfg, not(any($($clauses),*))))] $arm - cfg_select! { @parsed($($clauses,)* $cfg) $($rest)* @@ -71,3 +74,17 @@ macro_rules! cfg_select { } }; } + +#[cfg(test)] +mod tests { + #[test] + #[cfg(not(cfg_select))] + fn test_cfg_select_polyfill_short_circuit() { + cfg_select! { + all() => {}, + all() => { + unreachable!("the first arm should be selected, so this arm should not be evaluated"); + } + } + } +}