11use crate :: util:: check_builtin_macro_attribute;
22
3+ use rustc_ast:: mut_visit:: { self , MutVisitor } ;
4+ use rustc_ast:: ptr:: P ;
35use rustc_ast:: { self as ast, AstLike } ;
6+ use rustc_data_structures:: map_in_place:: MapInPlace ;
47use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
58use rustc_expand:: config:: StripUnconfigured ;
9+ use rustc_expand:: configure;
610use rustc_span:: symbol:: sym;
711use rustc_span:: Span ;
12+ use smallvec:: SmallVec ;
813
9- pub fn expand (
14+ crate fn expand (
1015 ecx : & mut ExtCtxt < ' _ > ,
1116 _span : Span ,
1217 meta_item : & ast:: MetaItem ,
1318 item : Annotatable ,
1419) -> Vec < Annotatable > {
1520 check_builtin_macro_attribute ( ecx, meta_item, sym:: cfg_eval) ;
1621
17- let mut visitor =
18- StripUnconfigured { sess : ecx. sess , features : ecx. ecfg . features , modified : false } ;
22+ let mut visitor = CfgEval {
23+ cfg : StripUnconfigured { sess : ecx. sess , features : ecx. ecfg . features , modified : false } ,
24+ } ;
1925 let mut item = visitor. fully_configure ( item) ;
20- if visitor. modified {
26+ if visitor. cfg . modified {
2127 // Erase the tokens if cfg-stripping modified the item
2228 // This will cause us to synthesize fake tokens
2329 // when `nt_to_tokenstream` is called on this item.
@@ -27,3 +33,165 @@ pub fn expand(
2733 }
2834 vec ! [ item]
2935}
36+
37+ crate struct CfgEval < ' a > {
38+ pub cfg : StripUnconfigured < ' a > ,
39+ }
40+
41+ impl CfgEval < ' _ > {
42+ fn configure < T : AstLike > ( & mut self , node : T ) -> Option < T > {
43+ self . cfg . configure ( node)
44+ }
45+
46+ fn configure_foreign_mod ( & mut self , foreign_mod : & mut ast:: ForeignMod ) {
47+ let ast:: ForeignMod { unsafety : _, abi : _, items } = foreign_mod;
48+ items. flat_map_in_place ( |item| self . configure ( item) ) ;
49+ }
50+
51+ fn configure_variant_data ( & mut self , vdata : & mut ast:: VariantData ) {
52+ match vdata {
53+ ast:: VariantData :: Struct ( fields, ..) | ast:: VariantData :: Tuple ( fields, _) => {
54+ fields. flat_map_in_place ( |field| self . configure ( field) )
55+ }
56+ ast:: VariantData :: Unit ( _) => { }
57+ }
58+ }
59+
60+ fn configure_item_kind ( & mut self , item : & mut ast:: ItemKind ) {
61+ match item {
62+ ast:: ItemKind :: Struct ( def, _generics) | ast:: ItemKind :: Union ( def, _generics) => {
63+ self . configure_variant_data ( def)
64+ }
65+ ast:: ItemKind :: Enum ( ast:: EnumDef { variants } , _generics) => {
66+ variants. flat_map_in_place ( |variant| self . configure ( variant) ) ;
67+ for variant in variants {
68+ self . configure_variant_data ( & mut variant. data ) ;
69+ }
70+ }
71+ _ => { }
72+ }
73+ }
74+
75+ fn configure_expr_kind ( & mut self , expr_kind : & mut ast:: ExprKind ) {
76+ match expr_kind {
77+ ast:: ExprKind :: Match ( _m, arms) => {
78+ arms. flat_map_in_place ( |arm| self . configure ( arm) ) ;
79+ }
80+ ast:: ExprKind :: Struct ( _path, fields, _base) => {
81+ fields. flat_map_in_place ( |field| self . configure ( field) ) ;
82+ }
83+ _ => { }
84+ }
85+ }
86+
87+ fn configure_pat ( & mut self , pat : & mut P < ast:: Pat > ) {
88+ if let ast:: PatKind :: Struct ( _path, fields, _etc) = & mut pat. kind {
89+ fields. flat_map_in_place ( |field| self . configure ( field) ) ;
90+ }
91+ }
92+
93+ fn configure_fn_decl ( & mut self , fn_decl : & mut ast:: FnDecl ) {
94+ fn_decl. inputs . flat_map_in_place ( |arg| self . configure ( arg) ) ;
95+ }
96+
97+ crate fn fully_configure ( & mut self , item : Annotatable ) -> Annotatable {
98+ // Since the item itself has already been configured by the InvocationCollector,
99+ // we know that fold result vector will contain exactly one element
100+ match item {
101+ Annotatable :: Item ( item) => Annotatable :: Item ( self . flat_map_item ( item) . pop ( ) . unwrap ( ) ) ,
102+ Annotatable :: TraitItem ( item) => {
103+ Annotatable :: TraitItem ( self . flat_map_trait_item ( item) . pop ( ) . unwrap ( ) )
104+ }
105+ Annotatable :: ImplItem ( item) => {
106+ Annotatable :: ImplItem ( self . flat_map_impl_item ( item) . pop ( ) . unwrap ( ) )
107+ }
108+ Annotatable :: ForeignItem ( item) => {
109+ Annotatable :: ForeignItem ( self . flat_map_foreign_item ( item) . pop ( ) . unwrap ( ) )
110+ }
111+ Annotatable :: Stmt ( stmt) => {
112+ Annotatable :: Stmt ( stmt. map ( |stmt| self . flat_map_stmt ( stmt) . pop ( ) . unwrap ( ) ) )
113+ }
114+ Annotatable :: Expr ( mut expr) => Annotatable :: Expr ( {
115+ self . visit_expr ( & mut expr) ;
116+ expr
117+ } ) ,
118+ Annotatable :: Arm ( arm) => Annotatable :: Arm ( self . flat_map_arm ( arm) . pop ( ) . unwrap ( ) ) ,
119+ Annotatable :: Field ( field) => {
120+ Annotatable :: Field ( self . flat_map_field ( field) . pop ( ) . unwrap ( ) )
121+ }
122+ Annotatable :: FieldPat ( fp) => {
123+ Annotatable :: FieldPat ( self . flat_map_field_pattern ( fp) . pop ( ) . unwrap ( ) )
124+ }
125+ Annotatable :: GenericParam ( param) => {
126+ Annotatable :: GenericParam ( self . flat_map_generic_param ( param) . pop ( ) . unwrap ( ) )
127+ }
128+ Annotatable :: Param ( param) => {
129+ Annotatable :: Param ( self . flat_map_param ( param) . pop ( ) . unwrap ( ) )
130+ }
131+ Annotatable :: StructField ( sf) => {
132+ Annotatable :: StructField ( self . flat_map_struct_field ( sf) . pop ( ) . unwrap ( ) )
133+ }
134+ Annotatable :: Variant ( v) => {
135+ Annotatable :: Variant ( self . flat_map_variant ( v) . pop ( ) . unwrap ( ) )
136+ }
137+ }
138+ }
139+ }
140+
141+ impl MutVisitor for CfgEval < ' _ > {
142+ fn visit_foreign_mod ( & mut self , foreign_mod : & mut ast:: ForeignMod ) {
143+ self . configure_foreign_mod ( foreign_mod) ;
144+ mut_visit:: noop_visit_foreign_mod ( foreign_mod, self ) ;
145+ }
146+
147+ fn visit_item_kind ( & mut self , item : & mut ast:: ItemKind ) {
148+ self . configure_item_kind ( item) ;
149+ mut_visit:: noop_visit_item_kind ( item, self ) ;
150+ }
151+
152+ fn visit_expr ( & mut self , expr : & mut P < ast:: Expr > ) {
153+ self . cfg . configure_expr ( expr) ;
154+ self . configure_expr_kind ( & mut expr. kind ) ;
155+ mut_visit:: noop_visit_expr ( expr, self ) ;
156+ }
157+
158+ fn filter_map_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
159+ let mut expr = configure ! ( self , expr) ;
160+ self . configure_expr_kind ( & mut expr. kind ) ;
161+ mut_visit:: noop_visit_expr ( & mut expr, self ) ;
162+ Some ( expr)
163+ }
164+
165+ fn flat_map_generic_param (
166+ & mut self ,
167+ param : ast:: GenericParam ,
168+ ) -> SmallVec < [ ast:: GenericParam ; 1 ] > {
169+ mut_visit:: noop_flat_map_generic_param ( configure ! ( self , param) , self )
170+ }
171+
172+ fn flat_map_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVec < [ ast:: Stmt ; 1 ] > {
173+ mut_visit:: noop_flat_map_stmt ( configure ! ( self , stmt) , self )
174+ }
175+
176+ fn flat_map_item ( & mut self , item : P < ast:: Item > ) -> SmallVec < [ P < ast:: Item > ; 1 ] > {
177+ mut_visit:: noop_flat_map_item ( configure ! ( self , item) , self )
178+ }
179+
180+ fn flat_map_impl_item ( & mut self , item : P < ast:: AssocItem > ) -> SmallVec < [ P < ast:: AssocItem > ; 1 ] > {
181+ mut_visit:: noop_flat_map_assoc_item ( configure ! ( self , item) , self )
182+ }
183+
184+ fn flat_map_trait_item ( & mut self , item : P < ast:: AssocItem > ) -> SmallVec < [ P < ast:: AssocItem > ; 1 ] > {
185+ mut_visit:: noop_flat_map_assoc_item ( configure ! ( self , item) , self )
186+ }
187+
188+ fn visit_pat ( & mut self , pat : & mut P < ast:: Pat > ) {
189+ self . configure_pat ( pat) ;
190+ mut_visit:: noop_visit_pat ( pat, self )
191+ }
192+
193+ fn visit_fn_decl ( & mut self , mut fn_decl : & mut P < ast:: FnDecl > ) {
194+ self . configure_fn_decl ( & mut fn_decl) ;
195+ mut_visit:: noop_visit_fn_decl ( fn_decl, self ) ;
196+ }
197+ }
0 commit comments