@@ -6,13 +6,14 @@ use feature_gate::{
6
6
get_features,
7
7
GateIssue ,
8
8
} ;
9
- use { fold , attr} ;
9
+ use attr;
10
10
use ast;
11
11
use source_map:: Spanned ;
12
12
use edition:: Edition ;
13
13
use parse:: { token, ParseSess } ;
14
14
use smallvec:: SmallVec ;
15
15
use errors:: Applicability ;
16
+ use visit_mut:: { self , Action } ;
16
17
17
18
use ptr:: P ;
18
19
@@ -64,8 +65,26 @@ macro_rules! configure {
64
65
}
65
66
66
67
impl < ' 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) ;
69
88
if self . in_cfg ( node. attrs ( ) ) { Some ( node) } else { None }
70
89
}
71
90
@@ -75,10 +94,23 @@ impl<'a> StripUnconfigured<'a> {
75
94
/// Gives compiler warnigns if any `cfg_attr` does not contain any
76
95
/// attributes and is in the original source code. Gives compiler errors if
77
96
/// 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;
82
114
}
83
115
84
116
/// Parse and expand a single `cfg_attr` attribute into a list of attributes
@@ -88,9 +120,9 @@ impl<'a> StripUnconfigured<'a> {
88
120
/// Gives a compiler warning when the `cfg_attr` contains no attributes and
89
121
/// is in the original source file. Gives a compiler error if the syntax of
90
122
/// 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 ] > {
92
124
if !attr. check_name ( "cfg_attr" ) {
93
- return vec ! [ attr] ;
125
+ return smallvec ! [ attr] ;
94
126
}
95
127
96
128
let ( cfg_predicate, expanded_attrs) = match attr. parse ( self . sess , |parser| {
@@ -100,7 +132,7 @@ impl<'a> StripUnconfigured<'a> {
100
132
parser. expect ( & token:: Comma ) ?;
101
133
102
134
// 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 ( ) ;
104
136
105
137
while !parser. check ( & token:: CloseDelim ( token:: Paren ) ) {
106
138
let lo = parser. span . lo ( ) ;
@@ -115,7 +147,7 @@ impl<'a> StripUnconfigured<'a> {
115
147
Ok ( result) => result,
116
148
Err ( mut e) => {
117
149
e. emit ( ) ;
118
- return Vec :: new ( ) ;
150
+ return SmallVec :: new ( ) ;
119
151
}
120
152
} ;
121
153
@@ -141,7 +173,7 @@ impl<'a> StripUnconfigured<'a> {
141
173
} ) )
142
174
. collect ( )
143
175
} else {
144
- Vec :: new ( )
176
+ SmallVec :: new ( )
145
177
}
146
178
}
147
179
@@ -286,7 +318,7 @@ impl<'a> StripUnconfigured<'a> {
286
318
}
287
319
}
288
320
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 ) {
290
322
self . visit_expr_attrs ( expr. attrs ( ) ) ;
291
323
292
324
// If an expr is valid to cfg away it will have been removed by the
@@ -300,7 +332,6 @@ impl<'a> StripUnconfigured<'a> {
300
332
let msg = "removing an expression is not supported in this position" ;
301
333
self . sess . span_diagnostic . span_err ( attr. span , msg) ;
302
334
}
303
-
304
335
self . process_cfg_attrs ( expr)
305
336
}
306
337
@@ -343,57 +374,81 @@ impl<'a> StripUnconfigured<'a> {
343
374
}
344
375
}
345
376
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) )
350
380
}
351
381
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) )
355
398
}
356
399
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) )
361
402
}
362
403
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) )
367
406
}
368
407
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
373
414
}
374
415
}
375
416
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)
378
420
}
379
421
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) )
383
436
}
384
437
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 ) )
387
440
}
388
441
389
- fn fold_mac ( & mut self , mac : ast :: Mac ) -> ast:: Mac {
442
+ fn visit_mac ( & mut self , _mac : & mut ast:: Mac ) {
390
443
// Don't configure interpolated AST (cf. issue #34171).
391
444
// Interpolated AST will get configured once the surrounding tokens are parsed.
392
- mac
393
445
}
394
446
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) )
397
452
}
398
453
}
399
454
0 commit comments