1
1
use crate :: util:: check_builtin_macro_attribute;
2
2
3
+ use rustc_ast:: mut_visit:: { self , MutVisitor } ;
4
+ use rustc_ast:: ptr:: P ;
3
5
use rustc_ast:: { self as ast, AstLike } ;
6
+ use rustc_data_structures:: map_in_place:: MapInPlace ;
4
7
use rustc_expand:: base:: { Annotatable , ExtCtxt } ;
5
8
use rustc_expand:: config:: StripUnconfigured ;
9
+ use rustc_expand:: configure;
6
10
use rustc_span:: symbol:: sym;
7
11
use rustc_span:: Span ;
12
+ use smallvec:: SmallVec ;
8
13
9
- pub fn expand (
14
+ crate fn expand (
10
15
ecx : & mut ExtCtxt < ' _ > ,
11
16
_span : Span ,
12
17
meta_item : & ast:: MetaItem ,
13
18
item : Annotatable ,
14
19
) -> Vec < Annotatable > {
15
20
check_builtin_macro_attribute ( ecx, meta_item, sym:: cfg_eval) ;
16
21
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
+ } ;
19
25
let mut item = visitor. fully_configure ( item) ;
20
- if visitor. modified {
26
+ if visitor. cfg . modified {
21
27
// Erase the tokens if cfg-stripping modified the item
22
28
// This will cause us to synthesize fake tokens
23
29
// when `nt_to_tokenstream` is called on this item.
@@ -27,3 +33,165 @@ pub fn expand(
27
33
}
28
34
vec ! [ item]
29
35
}
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