@@ -127,6 +127,7 @@ register_builtin! {
127127 ( asm, Asm ) => asm_expand,
128128 ( global_asm, GlobalAsm ) => global_asm_expand,
129129 ( naked_asm, NakedAsm ) => naked_asm_expand,
130+ ( cfg_select, CfgSelect ) => cfg_select_expand,
130131 ( cfg, Cfg ) => cfg_expand,
131132 ( core_panic, CorePanic ) => panic_expand,
132133 ( std_panic, StdPanic ) => panic_expand,
@@ -355,6 +356,71 @@ fn naked_asm_expand(
355356 ExpandResult :: ok ( expanded)
356357}
357358
359+ fn cfg_select_expand (
360+ db : & dyn ExpandDatabase ,
361+ id : MacroCallId ,
362+ tt : & tt:: TopSubtree ,
363+ span : Span ,
364+ ) -> ExpandResult < tt:: TopSubtree > {
365+ let loc = db. lookup_intern_macro_call ( id) ;
366+ let cfg_options = loc. krate . cfg_options ( db) ;
367+
368+ let mut iter = tt. iter ( ) ;
369+ let mut expand_to = None ;
370+ while let Some ( next) = iter. peek ( ) {
371+ let active = if let tt:: TtElement :: Leaf ( tt:: Leaf :: Ident ( ident) ) = next
372+ && ident. sym == sym:: underscore
373+ {
374+ iter. next ( ) ;
375+ true
376+ } else {
377+ cfg_options. check ( & CfgExpr :: parse_from_iter ( & mut iter) ) != Some ( false )
378+ } ;
379+ match iter. expect_glued_punct ( ) {
380+ Ok ( it) if it. len ( ) == 2 && it[ 0 ] . char == '=' && it[ 1 ] . char == '>' => { }
381+ _ => {
382+ let err_span = iter. peek ( ) . map ( |it| it. first_span ( ) ) . unwrap_or ( span) ;
383+ return ExpandResult :: new (
384+ tt:: TopSubtree :: empty ( tt:: DelimSpan :: from_single ( span) ) ,
385+ ExpandError :: other ( err_span, "expected `=>` after cfg expression" ) ,
386+ ) ;
387+ }
388+ }
389+ let expand_to_if_active = match iter. next ( ) {
390+ Some ( tt:: TtElement :: Subtree ( _, tt) ) => tt. remaining ( ) ,
391+ _ => {
392+ let err_span = iter. peek ( ) . map ( |it| it. first_span ( ) ) . unwrap_or ( span) ;
393+ return ExpandResult :: new (
394+ tt:: TopSubtree :: empty ( tt:: DelimSpan :: from_single ( span) ) ,
395+ ExpandError :: other ( err_span, "expected a token tree after `=>`" ) ,
396+ ) ;
397+ }
398+ } ;
399+
400+ if expand_to. is_none ( ) && active {
401+ expand_to = Some ( expand_to_if_active) ;
402+ }
403+ }
404+ match expand_to {
405+ Some ( expand_to) => {
406+ let mut builder = tt:: TopSubtreeBuilder :: new ( tt:: Delimiter {
407+ kind : tt:: DelimiterKind :: Invisible ,
408+ open : span,
409+ close : span,
410+ } ) ;
411+ builder. extend_with_tt ( expand_to) ;
412+ ExpandResult :: ok ( builder. build ( ) )
413+ }
414+ None => ExpandResult :: new (
415+ tt:: TopSubtree :: empty ( tt:: DelimSpan :: from_single ( span) ) ,
416+ ExpandError :: other (
417+ span,
418+ "none of the predicates in this `cfg_select` evaluated to true" ,
419+ ) ,
420+ ) ,
421+ }
422+ }
423+
358424fn cfg_expand (
359425 db : & dyn ExpandDatabase ,
360426 id : MacroCallId ,
0 commit comments