@@ -6,13 +6,14 @@ use feature_gate::{
66 get_features,
77 GateIssue ,
88} ;
9- use { fold , attr} ;
9+ use attr;
1010use ast;
1111use source_map:: Spanned ;
1212use edition:: Edition ;
1313use parse:: { token, ParseSess } ;
1414use smallvec:: SmallVec ;
1515use errors:: Applicability ;
16+ use visit_mut:: { self , Action } ;
1617
1718use ptr:: P ;
1819
@@ -64,8 +65,26 @@ macro_rules! configure {
6465}
6566
6667impl < ' a > StripUnconfigured < ' a > {
67- pub fn configure < T : HasAttrs > ( & mut self , node : T ) -> Option < T > {
68- let node = self . process_cfg_attrs ( node) ;
68+ pub fn keep_then < T : HasAttrs , R > (
69+ & mut self ,
70+ node : & mut T ,
71+ then : impl FnOnce ( & mut Self , & mut T )
72+ ) -> Action < R > {
73+ if likely ! ( self . keep( node) ) {
74+ then ( self , node) ;
75+ Action :: Reuse
76+ } else {
77+ Action :: Remove
78+ }
79+ }
80+
81+ pub fn keep < T : HasAttrs > ( & mut self , node : & mut T ) -> bool {
82+ self . process_cfg_attrs ( node) ;
83+ self . in_cfg ( node. attrs ( ) )
84+ }
85+
86+ pub fn configure < T : HasAttrs > ( & mut self , mut node : T ) -> Option < T > {
87+ self . process_cfg_attrs ( & mut node) ;
6988 if self . in_cfg ( node. attrs ( ) ) { Some ( node) } else { None }
7089 }
7190
@@ -75,10 +94,23 @@ impl<'a> StripUnconfigured<'a> {
7594 /// Gives compiler warnigns if any `cfg_attr` does not contain any
7695 /// attributes and is in the original source code. Gives compiler errors if
7796 /// the syntax of any `cfg_attr` is incorrect.
78- pub fn process_cfg_attrs < T : HasAttrs > ( & mut self , node : T ) -> T {
79- node. map_attrs ( |attrs| {
80- attrs. into_iter ( ) . flat_map ( |attr| self . process_cfg_attr ( attr) ) . collect ( )
81- } )
97+ pub fn process_cfg_attrs < T : HasAttrs > ( & mut self , node : & mut T ) {
98+ let attrs = if let Some ( attrs) = node. attrs_mut ( ) {
99+ attrs
100+ } else {
101+ // No attributes so nothing to do
102+ return ;
103+ } ;
104+ if likely ! ( attrs. is_empty( ) ) {
105+ return ;
106+ }
107+ if likely ! ( !attrs. iter( ) . any( |attr| attr. check_name( "cfg_attr" ) ) ) {
108+ return ;
109+ }
110+ let new_attrs: Vec < _ > = attrs. drain ( ..) . flat_map ( |attr| {
111+ self . process_cfg_attr ( attr)
112+ } ) . collect ( ) ;
113+ * attrs = new_attrs;
82114 }
83115
84116 /// Parse and expand a single `cfg_attr` attribute into a list of attributes
@@ -88,9 +120,9 @@ impl<'a> StripUnconfigured<'a> {
88120 /// Gives a compiler warning when the `cfg_attr` contains no attributes and
89121 /// is in the original source file. Gives a compiler error if the syntax of
90122 /// the attribute is incorrect
91- fn process_cfg_attr ( & mut self , attr : ast:: Attribute ) -> Vec < ast:: Attribute > {
123+ fn process_cfg_attr ( & mut self , attr : ast:: Attribute ) -> SmallVec < [ ast:: Attribute ; 1 ] > {
92124 if !attr. check_name ( "cfg_attr" ) {
93- return vec ! [ attr] ;
125+ return smallvec ! [ attr] ;
94126 }
95127
96128 let ( cfg_predicate, expanded_attrs) = match attr. parse ( self . sess , |parser| {
@@ -100,7 +132,7 @@ impl<'a> StripUnconfigured<'a> {
100132 parser. expect ( & token:: Comma ) ?;
101133
102134 // Presumably, the majority of the time there will only be one attr.
103- let mut expanded_attrs = Vec :: with_capacity ( 1 ) ;
135+ let mut expanded_attrs: SmallVec < [ _ ; 1 ] > = SmallVec :: new ( ) ;
104136
105137 while !parser. check ( & token:: CloseDelim ( token:: Paren ) ) {
106138 let lo = parser. span . lo ( ) ;
@@ -115,7 +147,7 @@ impl<'a> StripUnconfigured<'a> {
115147 Ok ( result) => result,
116148 Err ( mut e) => {
117149 e. emit ( ) ;
118- return Vec :: new ( ) ;
150+ return SmallVec :: new ( ) ;
119151 }
120152 } ;
121153
@@ -141,7 +173,7 @@ impl<'a> StripUnconfigured<'a> {
141173 } ) )
142174 . collect ( )
143175 } else {
144- Vec :: new ( )
176+ SmallVec :: new ( )
145177 }
146178 }
147179
@@ -286,7 +318,7 @@ impl<'a> StripUnconfigured<'a> {
286318 }
287319 }
288320
289- pub fn configure_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast :: Expr > {
321+ pub fn configure_expr ( & mut self , expr : & mut ast:: Expr ) {
290322 self . visit_expr_attrs ( expr. attrs ( ) ) ;
291323
292324 // If an expr is valid to cfg away it will have been removed by the
@@ -300,7 +332,6 @@ impl<'a> StripUnconfigured<'a> {
300332 let msg = "removing an expression is not supported in this position" ;
301333 self . sess . span_diagnostic . span_err ( attr. span , msg) ;
302334 }
303-
304335 self . process_cfg_attrs ( expr)
305336 }
306337
@@ -343,57 +374,81 @@ impl<'a> StripUnconfigured<'a> {
343374 }
344375}
345376
346- impl < ' a > fold:: Folder for StripUnconfigured < ' a > {
347- fn fold_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
348- let foreign_mod = self . configure_foreign_mod ( foreign_mod) ;
349- fold:: noop_fold_foreign_mod ( foreign_mod, self )
377+ impl < ' a > visit_mut:: MutVisitor for StripUnconfigured < ' a > {
378+ fn visit_foreign_item ( & mut self , i : & mut ast:: ForeignItem ) -> Action < ast:: ForeignItem > {
379+ self . keep_then ( i, |this, i| visit_mut:: walk_foreign_item ( this, i) )
350380 }
351381
352- fn fold_item_kind ( & mut self , item : ast:: ItemKind ) -> ast:: ItemKind {
353- let item = self . configure_item_kind ( item) ;
354- fold:: noop_fold_item_kind ( item, self )
382+ fn visit_variant (
383+ & mut self ,
384+ v : & mut ast:: Variant ,
385+ g : & mut ast:: Generics ,
386+ item_id : ast:: NodeId
387+ ) -> Action < ast:: Variant > {
388+ if likely ! ( self . keep( v) ) {
389+ visit_mut:: walk_variant ( self , v, g, item_id) ;
390+ Action :: Reuse
391+ } else {
392+ Action :: Remove
393+ }
394+ }
395+
396+ fn visit_struct_field ( & mut self , s : & mut ast:: StructField ) -> Action < ast:: StructField > {
397+ self . keep_then ( s, |this, s| visit_mut:: walk_struct_field ( this, s) )
355398 }
356399
357- fn fold_expr ( & mut self , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
358- let mut expr = self . configure_expr ( expr) . into_inner ( ) ;
359- expr. node = self . configure_expr_kind ( expr. node ) ;
360- P ( fold:: noop_fold_expr ( expr, self ) )
400+ fn visit_arm ( & mut self , a : & mut ast:: Arm ) -> Action < ast:: Arm > {
401+ self . keep_then ( a, |this, a| visit_mut:: walk_arm ( this, a) )
361402 }
362403
363- fn fold_opt_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
364- let mut expr = configure ! ( self , expr) . into_inner ( ) ;
365- expr. node = self . configure_expr_kind ( expr. node ) ;
366- Some ( P ( fold:: noop_fold_expr ( expr, self ) ) )
404+ fn visit_field ( & mut self , field : & mut ast:: Field ) -> Action < ast:: Field > {
405+ self . keep_then ( field, |this, field| visit_mut:: walk_field ( this, field) )
367406 }
368407
369- fn fold_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVec < [ ast:: Stmt ; 1 ] > {
370- match self . configure_stmt ( stmt) {
371- Some ( stmt) => fold:: noop_fold_stmt ( stmt, self ) ,
372- None => return SmallVec :: new ( ) ,
408+ fn visit_opt_expr ( & mut self , ex : & mut ast:: Expr ) -> bool {
409+ if likely ! ( self . keep( ex) ) {
410+ visit_mut:: walk_expr ( self , ex) ;
411+ true
412+ } else {
413+ false
373414 }
374415 }
375416
376- fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVec < [ P < ast:: Item > ; 1 ] > {
377- fold:: noop_fold_item ( configure ! ( self , item) , self )
417+ fn visit_expr ( & mut self , ex : & mut ast:: Expr ) {
418+ self . configure_expr ( ex) ;
419+ visit_mut:: walk_expr ( self , ex)
378420 }
379421
380- fn fold_impl_item ( & mut self , item : ast:: ImplItem ) -> SmallVec < [ ast:: ImplItem ; 1 ] >
381- {
382- fold:: noop_fold_impl_item ( configure ! ( self , item) , self )
422+ fn visit_stmt ( & mut self , s : & mut ast:: Stmt ) -> Action < ast:: Stmt > {
423+ if likely ! ( self . keep( s) ) {
424+ visit_mut:: walk_stmt ( self , s)
425+ } else {
426+ Action :: Remove
427+ }
428+ }
429+
430+ fn visit_item ( & mut self , i : & mut P < ast:: Item > ) -> Action < P < ast:: Item > > {
431+ self . keep_then ( i, |this, i| visit_mut:: walk_item ( this, i) )
432+ }
433+
434+ fn visit_trait_item ( & mut self , i : & mut ast:: TraitItem ) -> Action < ast:: TraitItem > {
435+ self . keep_then ( i, |this, i| visit_mut:: walk_trait_item ( this, i) )
383436 }
384437
385- fn fold_trait_item ( & mut self , item : ast:: TraitItem ) -> SmallVec < [ ast:: TraitItem ; 1 ] > {
386- fold :: noop_fold_trait_item ( configure ! ( self , item ) , self )
438+ fn visit_impl_item ( & mut self , ii : & mut ast:: ImplItem ) -> Action < ast:: ImplItem > {
439+ self . keep_then ( ii , |this , ii| visit_mut :: walk_impl_item ( this , ii ) )
387440 }
388441
389- fn fold_mac ( & mut self , mac : ast :: Mac ) -> ast:: Mac {
442+ fn visit_mac ( & mut self , _mac : & mut ast:: Mac ) {
390443 // Don't configure interpolated AST (cf. issue #34171).
391444 // Interpolated AST will get configured once the surrounding tokens are parsed.
392- mac
393445 }
394446
395- fn fold_pat ( & mut self , pattern : P < ast:: Pat > ) -> P < ast:: Pat > {
396- fold:: noop_fold_pat ( self . configure_pat ( pattern) , self )
447+ fn visit_field_pat (
448+ & mut self ,
449+ p : & mut Spanned < ast:: FieldPat >
450+ ) -> Action < Spanned < ast:: FieldPat > > {
451+ self . keep_then ( p, |this, p| visit_mut:: walk_field_pat ( this, p) )
397452 }
398453}
399454
0 commit comments