@@ -19,13 +19,31 @@ use ptr::P;
1919
2020use util:: small_vector:: SmallVector ;
2121
22+ pub trait CfgFolder : fold:: Folder {
23+ fn in_cfg ( & mut self , attrs : & [ ast:: Attribute ] ) -> bool ;
24+ fn visit_unconfigurable_expr ( & mut self , _expr : & ast:: Expr ) { }
25+ }
26+
2227/// A folder that strips out items that do not belong in the current
2328/// configuration.
2429struct Context < ' a , F > where F : FnMut ( & [ ast:: Attribute ] ) -> bool {
2530 in_cfg : F ,
2631 diagnostic : & ' a Handler ,
2732}
2833
34+ impl < ' a , F : FnMut ( & [ ast:: Attribute ] ) -> bool > CfgFolder for Context < ' a , F > {
35+ fn in_cfg ( & mut self , attrs : & [ ast:: Attribute ] ) -> bool {
36+ ( self . in_cfg ) ( attrs)
37+ }
38+
39+ fn visit_unconfigurable_expr ( & mut self , expr : & ast:: Expr ) {
40+ if let Some ( attr) = expr. attrs ( ) . iter ( ) . find ( |a| is_cfg ( a) ) {
41+ let msg = "removing an expression is not supported in this position" ;
42+ self . diagnostic . span_err ( attr. span , msg) ;
43+ }
44+ }
45+ }
46+
2947// Support conditional compilation by transforming the AST, stripping out
3048// any items that do not belong in the current configuration
3149pub fn strip_unconfigured_items ( diagnostic : & Handler , krate : ast:: Crate ,
@@ -48,12 +66,12 @@ pub fn strip_unconfigured_items(diagnostic: &Handler, krate: ast::Crate,
4866 } )
4967}
5068
51- impl < ' a , F > fold:: Folder for Context < ' a , F > where F : FnMut ( & [ ast :: Attribute ] ) -> bool {
69+ impl < T : CfgFolder > fold:: Folder for T {
5270 fn fold_foreign_mod ( & mut self , foreign_mod : ast:: ForeignMod ) -> ast:: ForeignMod {
5371 ast:: ForeignMod {
5472 abi : foreign_mod. abi ,
5573 items : foreign_mod. items . into_iter ( ) . filter ( |item| {
56- ( self . in_cfg ) ( & item. attrs )
74+ self . in_cfg ( & item. attrs )
5775 } ) . collect ( ) ,
5876 }
5977 }
@@ -62,12 +80,12 @@ impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) ->
6280 let fold_struct = |this : & mut Self , vdata| match vdata {
6381 ast:: VariantData :: Struct ( fields, id) => {
6482 ast:: VariantData :: Struct ( fields. into_iter ( ) . filter ( |m| {
65- ( this. in_cfg ) ( & m. attrs )
83+ this. in_cfg ( & m. attrs )
6684 } ) . collect ( ) , id)
6785 }
6886 ast:: VariantData :: Tuple ( fields, id) => {
6987 ast:: VariantData :: Tuple ( fields. into_iter ( ) . filter ( |m| {
70- ( this. in_cfg ) ( & m. attrs )
88+ this. in_cfg ( & m. attrs )
7189 } ) . collect ( ) , id)
7290 }
7391 ast:: VariantData :: Unit ( id) => ast:: VariantData :: Unit ( id)
@@ -76,13 +94,13 @@ impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) ->
7694 let item = match item {
7795 ast:: ItemKind :: Impl ( u, o, a, b, c, impl_items) => {
7896 let impl_items = impl_items. into_iter ( )
79- . filter ( |ii| ( self . in_cfg ) ( & ii. attrs ) )
97+ . filter ( |ii| self . in_cfg ( & ii. attrs ) )
8098 . collect ( ) ;
8199 ast:: ItemKind :: Impl ( u, o, a, b, c, impl_items)
82100 }
83101 ast:: ItemKind :: Trait ( u, a, b, methods) => {
84102 let methods = methods. into_iter ( )
85- . filter ( |ti| ( self . in_cfg ) ( & ti. attrs ) )
103+ . filter ( |ti| self . in_cfg ( & ti. attrs ) )
86104 . collect ( ) ;
87105 ast:: ItemKind :: Trait ( u, a, b, methods)
88106 }
@@ -91,7 +109,7 @@ impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) ->
91109 }
92110 ast:: ItemKind :: Enum ( def, generics) => {
93111 let variants = def. variants . into_iter ( ) . filter_map ( |v| {
94- if !( self . in_cfg ) ( & v. node . attrs ) {
112+ if !self . in_cfg ( & v. node . attrs ) {
95113 None
96114 } else {
97115 Some ( Spanned {
@@ -123,23 +141,20 @@ impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) ->
123141 //
124142 // NB: This is intentionally not part of the fold_expr() function
125143 // in order for fold_opt_expr() to be able to avoid this check
126- if let Some ( attr) = expr. attrs ( ) . iter ( ) . find ( |a| is_cfg ( a) ) {
127- self . diagnostic . span_err ( attr. span ,
128- "removing an expression is not supported in this position" ) ;
129- }
144+ self . visit_unconfigurable_expr ( & expr) ;
130145 fold_expr ( self , expr)
131146 }
132147
133148 fn fold_opt_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
134- if ( self . in_cfg ) ( expr. attrs ( ) ) {
149+ if self . in_cfg ( expr. attrs ( ) ) {
135150 Some ( fold_expr ( self , expr) )
136151 } else {
137152 None
138153 }
139154 }
140155
141156 fn fold_stmt ( & mut self , stmt : ast:: Stmt ) -> SmallVector < ast:: Stmt > {
142- if ( self . in_cfg ) ( stmt. node . attrs ( ) ) {
157+ if self . in_cfg ( stmt. node . attrs ( ) ) {
143158 fold:: noop_fold_stmt ( stmt, self )
144159 } else {
145160 SmallVector :: zero ( )
@@ -151,7 +166,7 @@ impl<'a, F> fold::Folder for Context<'a, F> where F: FnMut(&[ast::Attribute]) ->
151166 }
152167
153168 fn fold_item ( & mut self , item : P < ast:: Item > ) -> SmallVector < P < ast:: Item > > {
154- if ( self . in_cfg ) ( & item. attrs ) {
169+ if self . in_cfg ( & item. attrs ) {
155170 SmallVector :: one ( item. map ( |i| self . fold_item_simple ( i) ) )
156171 } else {
157172 SmallVector :: zero ( )
@@ -170,23 +185,21 @@ pub fn strip_items<'a, F>(diagnostic: &'a Handler,
170185 ctxt. fold_crate ( krate)
171186}
172187
173- fn fold_expr < F > ( cx : & mut Context < F > , expr : P < ast:: Expr > ) -> P < ast:: Expr > where
174- F : FnMut ( & [ ast:: Attribute ] ) -> bool
175- {
188+ fn fold_expr < F : CfgFolder > ( folder : & mut F , expr : P < ast:: Expr > ) -> P < ast:: Expr > {
176189 expr. map ( |ast:: Expr { id, span, node, attrs} | {
177190 fold:: noop_fold_expr ( ast:: Expr {
178191 id : id,
179192 node : match node {
180193 ast:: ExprKind :: Match ( m, arms) => {
181194 ast:: ExprKind :: Match ( m, arms. into_iter ( )
182- . filter ( |a| ( cx . in_cfg ) ( & a. attrs ) )
195+ . filter ( |a| folder . in_cfg ( & a. attrs ) )
183196 . collect ( ) )
184197 }
185198 _ => node
186199 } ,
187200 span : span,
188201 attrs : attrs,
189- } , cx )
202+ } , folder )
190203 } )
191204}
192205
0 commit comments