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