1010
1111use attr:: HasAttrs ;
1212use feature_gate:: { emit_feature_err, EXPLAIN_STMT_ATTR_SYNTAX , Features , get_features, GateIssue } ;
13- use fold:: Folder ;
1413use { fold, attr} ;
1514use ast;
1615use codemap:: { Spanned , respan} ;
17- use parse:: { ParseSess , token } ;
16+ use parse:: ParseSess ;
1817use ptr:: P ;
1918
2019use util:: small_vector:: SmallVector ;
@@ -27,8 +26,51 @@ pub struct StripUnconfigured<'a> {
2726 pub features : Option < & ' a Features > ,
2827}
2928
29+ // `cfg_attr`-process the crate's attributes and compute the crate's features.
30+ pub fn features ( mut krate : ast:: Crate , sess : & ParseSess , should_test : bool )
31+ -> ( ast:: Crate , Features ) {
32+ let features;
33+ {
34+ let mut strip_unconfigured = StripUnconfigured {
35+ config : & krate. config . clone ( ) ,
36+ should_test : should_test,
37+ sess : sess,
38+ features : None ,
39+ } ;
40+
41+ let unconfigured_attrs = krate. attrs . clone ( ) ;
42+ let err_count = sess. span_diagnostic . err_count ( ) ;
43+ if let Some ( attrs) = strip_unconfigured. configure ( krate. attrs ) {
44+ krate. attrs = attrs;
45+ } else { // the entire crate is unconfigured
46+ krate. attrs = Vec :: new ( ) ;
47+ krate. module . items = Vec :: new ( ) ;
48+ return ( krate, Features :: new ( ) ) ;
49+ }
50+
51+ features = get_features ( & sess. span_diagnostic , & krate. attrs ) ;
52+
53+ // Avoid reconfiguring malformed `cfg_attr`s
54+ if err_count == sess. span_diagnostic . err_count ( ) {
55+ strip_unconfigured. features = Some ( & features) ;
56+ strip_unconfigured. configure ( unconfigured_attrs) ;
57+ }
58+ }
59+
60+ ( krate, features)
61+ }
62+
63+ macro_rules! configure {
64+ ( $this: ident, $node: ident) => {
65+ match $this. configure( $node) {
66+ Some ( node) => node,
67+ None => return Default :: default ( ) ,
68+ }
69+ }
70+ }
71+
3072impl < ' a > StripUnconfigured < ' a > {
31- fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
73+ pub fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
3274 let node = self . process_cfg_attrs ( node) ;
3375 if self . in_cfg ( node. attrs ( ) ) { Some ( node) } else { None }
3476 }
@@ -123,65 +165,35 @@ impl<'a> StripUnconfigured<'a> {
123165 }
124166 }
125167 }
126- }
127-
128- // Support conditional compilation by transforming the AST, stripping out
129- // any items that do not belong in the current configuration
130- pub fn strip_unconfigured_items ( mut krate : ast:: Crate , sess : & ParseSess , should_test : bool )
131- -> ( ast:: Crate , Features ) {
132- let features;
133- {
134- let mut strip_unconfigured = StripUnconfigured {
135- config : & krate. config . clone ( ) ,
136- should_test : should_test,
137- sess : sess,
138- features : None ,
139- } ;
140-
141- let err_count = sess. span_diagnostic . err_count ( ) ;
142- let krate_attrs = strip_unconfigured. configure ( krate. attrs . clone ( ) ) . unwrap_or_default ( ) ;
143- features = get_features ( & sess. span_diagnostic , & krate_attrs) ;
144- if err_count < sess. span_diagnostic . err_count ( ) {
145- krate. attrs = krate_attrs. clone ( ) ; // Avoid reconfiguring malformed `cfg_attr`s
146- }
147-
148- strip_unconfigured. features = Some ( & features) ;
149- krate = strip_unconfigured. fold_crate ( krate) ;
150- krate. attrs = krate_attrs;
151- }
152168
153- ( krate, features)
154- }
155-
156- impl < ' a > fold:: Folder for StripUnconfigured < ' a > {
157- fn fold_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
169+ pub fn configure_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
158170 ast:: ForeignMod {
159171 abi : foreign_mod. abi ,
160- items : foreign_mod. items . into_iter ( ) . filter_map ( |item| {
161- self . configure ( item) . map ( |item| fold:: noop_fold_foreign_item ( item, self ) )
162- } ) . collect ( ) ,
172+ items : foreign_mod. items . into_iter ( ) . filter_map ( |item| self . configure ( item) ) . collect ( ) ,
163173 }
164174 }
165175
166- fn fold_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
167- let fold_struct = | this : & mut Self , vdata| match vdata {
176+ fn configure_variant_data ( & mut self , vdata : ast:: VariantData ) -> ast:: VariantData {
177+ match vdata {
168178 ast:: VariantData :: Struct ( fields, id) => {
169- let fields = fields. into_iter ( ) . filter_map ( |field| this . configure ( field) ) ;
179+ let fields = fields. into_iter ( ) . filter_map ( |field| self . configure ( field) ) ;
170180 ast:: VariantData :: Struct ( fields. collect ( ) , id)
171181 }
172182 ast:: VariantData :: Tuple ( fields, id) => {
173- let fields = fields. into_iter ( ) . filter_map ( |field| this . configure ( field) ) ;
183+ let fields = fields. into_iter ( ) . filter_map ( |field| self . configure ( field) ) ;
174184 ast:: VariantData :: Tuple ( fields. collect ( ) , id)
175185 }
176186 ast:: VariantData :: Unit ( id) => ast:: VariantData :: Unit ( id)
177- } ;
187+ }
188+ }
178189
179- let item = match item {
190+ pub fn configure_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
191+ match item {
180192 ast:: ItemKind :: Struct ( def, generics) => {
181- ast:: ItemKind :: Struct ( fold_struct ( self , def) , generics)
193+ ast:: ItemKind :: Struct ( self . configure_variant_data ( def) , generics)
182194 }
183195 ast:: ItemKind :: Union ( def, generics) => {
184- ast:: ItemKind :: Union ( fold_struct ( self , def) , generics)
196+ ast:: ItemKind :: Union ( self . configure_variant_data ( def) , generics)
185197 }
186198 ast:: ItemKind :: Enum ( def, generics) => {
187199 let variants = def. variants . into_iter ( ) . filter_map ( |v| {
@@ -190,7 +202,7 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
190202 node : ast:: Variant_ {
191203 name : v. node . name ,
192204 attrs : v. node . attrs ,
193- data : fold_struct ( self , v. node . data ) ,
205+ data : self . configure_variant_data ( v. node . data ) ,
194206 disr_expr : v. node . disr_expr ,
195207 } ,
196208 span : v. span
@@ -202,12 +214,19 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
202214 } , generics)
203215 }
204216 item => item,
205- } ;
217+ }
218+ }
206219
207- fold:: noop_fold_item_kind ( item, self )
220+ pub fn configure_expr_kind ( & mut self , expr_kind : ast:: ExprKind ) -> ast:: ExprKind {
221+ if let ast:: ExprKind :: Match ( m, arms) = expr_kind {
222+ let arms = arms. into_iter ( ) . filter_map ( |a| self . configure ( a) ) . collect ( ) ;
223+ ast:: ExprKind :: Match ( m, arms)
224+ } else {
225+ expr_kind
226+ }
208227 }
209228
210- fn fold_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
229+ pub fn configure_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
211230 self . visit_stmt_or_expr_attrs ( expr. attrs ( ) ) ;
212231
213232 // If an expr is valid to cfg away it will have been removed by the
@@ -222,64 +241,64 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
222241 self . sess . span_diagnostic . span_err ( attr. span , msg) ;
223242 }
224243
225- let expr = self . process_cfg_attrs ( expr) ;
226- fold_expr ( self , expr)
244+ self . process_cfg_attrs ( expr)
227245 }
228246
229- fn fold_opt_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
230- self . configure ( expr) . map ( |expr| fold_expr ( self , expr) )
247+ pub fn configure_stmt ( & mut self , stmt : ast:: Stmt ) -> Option < ast:: Stmt > {
248+ self . visit_stmt_or_expr_attrs ( stmt. attrs ( ) ) ;
249+ self . configure ( stmt)
231250 }
251+ }
232252
233- fn fold_stmt ( & mut self , stmt : ast :: Stmt ) -> SmallVector < ast :: Stmt > {
234- self . visit_stmt_or_expr_attrs ( stmt . attrs ( ) ) ;
235- self . configure ( stmt ) . map ( |stmt| fold :: noop_fold_stmt ( stmt , self ) )
236- . unwrap_or ( SmallVector :: zero ( ) )
253+ impl < ' a > fold :: Folder for StripUnconfigured < ' a > {
254+ fn fold_foreign_mod ( & mut self , foreign_mod : ast :: ForeignMod ) -> ast :: ForeignMod {
255+ let foreign_mod = self . configure_foreign_mod ( foreign_mod ) ;
256+ fold :: noop_fold_foreign_mod ( foreign_mod , self )
237257 }
238258
239- fn fold_mac ( & mut self , mac : ast:: Mac ) -> ast:: Mac {
240- fold:: noop_fold_mac ( mac, self )
259+ fn fold_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
260+ let item = self . configure_item_kind ( item) ;
261+ fold:: noop_fold_item_kind ( item, self )
262+ }
263+
264+ fn fold_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
265+ let mut expr = self . configure_expr ( expr) . unwrap ( ) ;
266+ expr. node = self . configure_expr_kind ( expr. node ) ;
267+ P ( fold:: noop_fold_expr ( expr, self ) )
268+ }
269+
270+ fn fold_opt_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
271+ let mut expr = configure ! ( self , expr) . unwrap ( ) ;
272+ expr. node = self . configure_expr_kind ( expr. node ) ;
273+ Some ( P ( fold:: noop_fold_expr ( expr, self ) ) )
274+ }
275+
276+ fn fold_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVector < ast:: Stmt > {
277+ match self . configure_stmt ( stmt) {
278+ Some ( stmt) => fold:: noop_fold_stmt ( stmt, self ) ,
279+ None => return SmallVector :: zero ( ) ,
280+ }
241281 }
242282
243283 fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
244- self . configure ( item) . map ( |item| fold:: noop_fold_item ( item, self ) )
245- . unwrap_or ( SmallVector :: zero ( ) )
284+ fold:: noop_fold_item ( configure ! ( self , item) , self )
246285 }
247286
248287 fn fold_impl_item ( & mut self , item : ast:: ImplItem ) -> SmallVector < ast:: ImplItem > {
249- self . configure ( item) . map ( |item| fold:: noop_fold_impl_item ( item, self ) )
250- . unwrap_or ( SmallVector :: zero ( ) )
288+ fold:: noop_fold_impl_item ( configure ! ( self , item) , self )
251289 }
252290
253291 fn fold_trait_item ( & mut self , item : ast:: TraitItem ) -> SmallVector < ast:: TraitItem > {
254- self . configure ( item) . map ( |item| fold:: noop_fold_trait_item ( item, self ) )
255- . unwrap_or ( SmallVector :: zero ( ) )
292+ fold:: noop_fold_trait_item ( configure ! ( self , item) , self )
256293 }
257294
258- fn fold_interpolated ( & mut self , nt : token :: Nonterminal ) -> token :: Nonterminal {
295+ fn fold_mac ( & mut self , mac : ast :: Mac ) -> ast :: Mac {
259296 // Don't configure interpolated AST (c.f. #34171).
260297 // Interpolated AST will get configured once the surrounding tokens are parsed.
261- nt
298+ mac
262299 }
263300}
264301
265- fn fold_expr ( folder : & mut StripUnconfigured , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
266- expr. map ( |ast:: Expr { id, span, node, attrs} | {
267- fold:: noop_fold_expr ( ast:: Expr {
268- id : id,
269- node : match node {
270- ast:: ExprKind :: Match ( m, arms) => {
271- ast:: ExprKind :: Match ( m, arms. into_iter ( )
272- . filter_map ( |a| folder. configure ( a) )
273- . collect ( ) )
274- }
275- _ => node
276- } ,
277- span : span,
278- attrs : attrs,
279- } , folder)
280- } )
281- }
282-
283302fn is_cfg ( attr : & ast:: Attribute ) -> bool {
284303 attr. check_name ( "cfg" )
285304}
0 commit comments