@@ -168,6 +168,94 @@ pub macro assert_matches {
168168 } ,
169169}
170170
171+ /// A macro for defining `#[cfg]` match-like statements.
172+ ///
173+ /// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
174+ /// `#[ cfg] ` cases, emitting the implementation which matches first.
175+ ///
176+ /// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
177+ /// without having to rewrite each clause multiple times.
178+ ///
179+ /// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
180+ /// all previous declarations do not evaluate to true.
181+ ///
182+ /// # Example
183+ ///
184+ /// ```
185+ /// #![feature(cfg_match)]
186+ ///
187+ /// cfg_match! {
188+ /// cfg(unix) => {
189+ /// fn foo() { /* unix specific functionality */ }
190+ /// }
191+ /// cfg(target_pointer_width = "32") => {
192+ /// fn foo() { /* non-unix, 32-bit functionality */ }
193+ /// }
194+ /// _ => {
195+ /// fn foo() { /* fallback implementation */ }
196+ /// }
197+ /// }
198+ /// ```
199+ #[ unstable ( feature = "cfg_match" , issue = "115585" ) ]
200+ #[ rustc_diagnostic_item = "cfg_match" ]
201+ pub macro cfg_match {
202+ // with a final wildcard
203+ (
204+ $( cfg ( $initial_meta: meta) => { $( $initial_tokens: item) * } ) +
205+ _ => { $( $extra_tokens: item) * }
206+ ) => {
207+ cfg_match ! {
208+ @__items ( ) ;
209+ $( ( ( $initial_meta) ( $( $initial_tokens) * ) ) , ) +
210+ ( ( ) ( $( $extra_tokens) * ) ) ,
211+ }
212+ } ,
213+
214+ // without a final wildcard
215+ (
216+ $( cfg ( $extra_meta: meta) => { $( $extra_tokens: item) * } ) *
217+ ) => {
218+ cfg_match ! {
219+ @__items ( ) ;
220+ $( ( ( $extra_meta) ( $( $extra_tokens) * ) ) , ) *
221+ }
222+ } ,
223+
224+ // Internal and recursive macro to emit all the items
225+ //
226+ // Collects all the previous cfgs in a list at the beginning, so they can be
227+ // negated. After the semicolon is all the remaining items.
228+ ( @__items ( $( $_: meta, ) * ) ; ) => { } ,
229+ (
230+ @__items ( $( $no: meta, ) * ) ;
231+ ( ( $( $yes: meta) ?) ( $( $tokens: item) * ) ) ,
232+ $( $rest: tt, ) *
233+ ) => {
234+ // Emit all items within one block, applying an appropriate #[cfg]. The
235+ // #[cfg] will require all `$yes` matchers specified and must also negate
236+ // all previous matchers.
237+ #[ cfg( all(
238+ $( $yes, ) ?
239+ not( any( $( $no) , * ) )
240+ ) ) ]
241+ cfg_match ! { @__identity $( $tokens) * }
242+
243+ // Recurse to emit all other items in `$rest`, and when we do so add all
244+ // our `$yes` matchers to the list of `$no` matchers as future emissions
245+ // will have to negate everything we just matched as well.
246+ cfg_match ! {
247+ @__items ( $( $no, ) * $( $yes, ) ?) ;
248+ $( $rest, ) *
249+ }
250+ } ,
251+
252+ // Internal macro to make __apply work out right for different match types,
253+ // because of how macros match/expand stuff.
254+ ( @__identity $( $tokens: item) * ) => {
255+ $( $tokens) *
256+ }
257+ }
258+
171259/// Asserts that a boolean expression is `true` at runtime.
172260///
173261/// This will invoke the [`panic!`] macro if the provided expression cannot be
@@ -321,95 +409,6 @@ pub macro debug_assert_matches($($arg:tt)*) {
321409 }
322410}
323411
324- /// A macro for defining `#[cfg]` match-like statements.
325- ///
326- /// It is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade of
327- /// `#[cfg]` cases, emitting the implementation which matches first.
328- ///
329- /// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
330- /// without having to rewrite each clause multiple times.
331- ///
332- /// Trailing `_` wildcard match arms are **optional** and they indicate a fallback branch when
333- /// all previous declarations do not evaluate to true.
334- ///
335- /// # Example
336- ///
337- /// ```
338- /// #![feature(cfg_match)]
339- ///
340- /// cfg_match! {
341- /// cfg(unix) => {
342- /// fn foo() { /* unix specific functionality */ }
343- /// }
344- /// cfg(target_pointer_width = "32") => {
345- /// fn foo() { /* non-unix, 32-bit functionality */ }
346- /// }
347- /// _ => {
348- /// fn foo() { /* fallback implementation */ }
349- /// }
350- /// }
351- /// ```
352- #[ macro_export]
353- #[ unstable( feature = "cfg_match" , issue = "115585" ) ]
354- #[ rustc_diagnostic_item = "cfg_match" ]
355- macro_rules! cfg_match {
356- // with a final wildcard
357- (
358- $( cfg( $initial_meta: meta) => { $( $initial_tokens: item) * } ) +
359- _ => { $( $extra_tokens: item) * }
360- ) => {
361- cfg_match! {
362- @__items ( ) ;
363- $( ( ( $initial_meta) ( $( $initial_tokens) * ) ) , ) +
364- ( ( ) ( $( $extra_tokens) * ) ) ,
365- }
366- } ;
367-
368- // without a final wildcard
369- (
370- $( cfg( $extra_meta: meta) => { $( $extra_tokens: item) * } ) *
371- ) => {
372- cfg_match! {
373- @__items ( ) ;
374- $( ( ( $extra_meta) ( $( $extra_tokens) * ) ) , ) *
375- }
376- } ;
377-
378- // Internal and recursive macro to emit all the items
379- //
380- // Collects all the previous cfgs in a list at the beginning, so they can be
381- // negated. After the semicolon is all the remaining items.
382- ( @__items ( $( $_: meta, ) * ) ; ) => { } ;
383- (
384- @__items ( $( $no: meta, ) * ) ;
385- ( ( $( $yes: meta) ?) ( $( $tokens: item) * ) ) ,
386- $( $rest: tt, ) *
387- ) => {
388- // Emit all items within one block, applying an appropriate #[cfg]. The
389- // #[cfg] will require all `$yes` matchers specified and must also negate
390- // all previous matchers.
391- #[ cfg( all(
392- $( $yes, ) ?
393- not( any( $( $no) ,* ) )
394- ) ) ]
395- cfg_match! { @__identity $( $tokens) * }
396-
397- // Recurse to emit all other items in `$rest`, and when we do so add all
398- // our `$yes` matchers to the list of `$no` matchers as future emissions
399- // will have to negate everything we just matched as well.
400- cfg_match! {
401- @__items ( $( $no, ) * $( $yes, ) ?) ;
402- $( $rest, ) *
403- }
404- } ;
405-
406- // Internal macro to make __apply work out right for different match types,
407- // because of how macros match/expand stuff.
408- ( @__identity $( $tokens: item) * ) => {
409- $( $tokens) *
410- } ;
411- }
412-
413412/// Returns whether the given expression matches any of the given patterns.
414413///
415414/// Like in a `match` expression, the pattern can be optionally followed by `if`
0 commit comments