]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/fold.rs
Imported Upstream version 1.9.0+dfsg1
[rustc.git] / src / libsyntax / fold.rs
CommitLineData
1a4d82fc 1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
223e47cc
LB
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
1a4d82fc
JJ
11//! A Folder represents an AST->AST fold; it accepts an AST piece,
12//! and returns a piece of the same type. So, for instance, macro
13//! expansion is a Folder that walks over an AST and produces another
14//! AST.
15//!
16//! Note: using a Folder (other than the MacroExpander Folder) on
17//! an AST before macro expansion is probably a bad idea. For instance,
18//! a folder renaming item names in a module will miss all of those
19//! that are created by the expansion of a macro.
20
223e47cc
LB
21use ast::*;
22use ast;
92a42be0 23use attr::{ThinAttributes, ThinAttributesExt};
1a4d82fc 24use codemap::{respan, Span, Spanned};
970d7e83 25use parse::token;
1a4d82fc 26use ptr::P;
1a4d82fc 27use util::small_vector::SmallVector;
92a42be0 28use util::move_map::MoveMap;
1a4d82fc
JJ
29
30use std::rc::Rc;
31
1a4d82fc
JJ
32pub trait Folder : Sized {
33 // Any additions to this trait should happen in form
34 // of a call to a public `noop_*` function that only calls
35 // out to the folder again, not other `noop_*` functions.
36 //
37 // This is a necessary API workaround to the problem of not
38 // being able to call out to the super default method
39 // in an overridden default method.
40
41 fn fold_crate(&mut self, c: Crate) -> Crate {
42 noop_fold_crate(c, self)
223e47cc 43 }
223e47cc 44
1a4d82fc
JJ
45 fn fold_meta_items(&mut self, meta_items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
46 noop_fold_meta_items(meta_items, self)
223e47cc 47 }
223e47cc 48
1a4d82fc
JJ
49 fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
50 noop_fold_meta_item(meta_item, self)
51 }
52
53 fn fold_view_path(&mut self, view_path: P<ViewPath>) -> P<ViewPath> {
54 noop_fold_view_path(view_path, self)
55 }
56
7453a54e 57 fn fold_foreign_item(&mut self, ni: ForeignItem) -> ForeignItem {
1a4d82fc
JJ
58 noop_fold_foreign_item(ni, self)
59 }
60
61 fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
62 noop_fold_item(i, self)
63 }
64
65 fn fold_item_simple(&mut self, i: Item) -> Item {
66 noop_fold_item_simple(i, self)
67 }
68
69 fn fold_struct_field(&mut self, sf: StructField) -> StructField {
70 noop_fold_struct_field(sf, self)
71 }
72
7453a54e
SL
73 fn fold_item_kind(&mut self, i: ItemKind) -> ItemKind {
74 noop_fold_item_kind(i, self)
1a4d82fc
JJ
75 }
76
7453a54e 77 fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
85aaf69f
SL
78 noop_fold_trait_item(i, self)
79 }
80
7453a54e 81 fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
85aaf69f
SL
82 noop_fold_impl_item(i, self)
83 }
84
1a4d82fc
JJ
85 fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
86 noop_fold_fn_decl(d, self)
87 }
88
1a4d82fc
JJ
89 fn fold_block(&mut self, b: P<Block>) -> P<Block> {
90 noop_fold_block(b, self)
91 }
92
7453a54e
SL
93 fn fold_stmt(&mut self, s: Stmt) -> SmallVector<Stmt> {
94 noop_fold_stmt(s, self)
1a4d82fc
JJ
95 }
96
97 fn fold_arm(&mut self, a: Arm) -> Arm {
98 noop_fold_arm(a, self)
99 }
100
101 fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
102 noop_fold_pat(p, self)
103 }
104
105 fn fold_decl(&mut self, d: P<Decl>) -> SmallVector<P<Decl>> {
106 noop_fold_decl(d, self)
107 }
108
109 fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
110 e.map(|e| noop_fold_expr(e, self))
111 }
112
92a42be0
SL
113 fn fold_opt_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
114 noop_fold_opt_expr(e, self)
115 }
116
117 fn fold_exprs(&mut self, es: Vec<P<Expr>>) -> Vec<P<Expr>> {
118 noop_fold_exprs(es, self)
119 }
120
1a4d82fc
JJ
121 fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
122 noop_fold_ty(t, self)
123 }
124
7453a54e 125 fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding {
1a4d82fc
JJ
126 noop_fold_ty_binding(t, self)
127 }
128
129 fn fold_mod(&mut self, m: Mod) -> Mod {
130 noop_fold_mod(m, self)
131 }
132
133 fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod {
134 noop_fold_foreign_mod(nm, self)
135 }
136
7453a54e 137 fn fold_variant(&mut self, v: Variant) -> Variant {
1a4d82fc
JJ
138 noop_fold_variant(v, self)
139 }
140
141 fn fold_ident(&mut self, i: Ident) -> Ident {
142 noop_fold_ident(i, self)
143 }
144
85aaf69f
SL
145 fn fold_usize(&mut self, i: usize) -> usize {
146 noop_fold_usize(i, self)
1a4d82fc
JJ
147 }
148
149 fn fold_path(&mut self, p: Path) -> Path {
150 noop_fold_path(p, self)
151 }
152
153 fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
154 noop_fold_path_parameters(p, self)
155 }
156
157 fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData)
158 -> AngleBracketedParameterData
159 {
160 noop_fold_angle_bracketed_parameter_data(p, self)
161 }
162
163 fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData)
164 -> ParenthesizedParameterData
165 {
166 noop_fold_parenthesized_parameter_data(p, self)
167 }
168
169 fn fold_local(&mut self, l: P<Local>) -> P<Local> {
170 noop_fold_local(l, self)
171 }
172
173 fn fold_mac(&mut self, _mac: Mac) -> Mac {
174 panic!("fold_mac disabled by default");
175 // NB: see note about macros above.
176 // if you really want a folder that
177 // works on macros, use this
178 // definition in your trait impl:
179 // fold::noop_fold_mac(_mac, self)
180 }
181
182 fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf {
183 noop_fold_explicit_self(es, self)
184 }
185
7453a54e
SL
186 fn fold_explicit_self_kind(&mut self, es: SelfKind) -> SelfKind {
187 noop_fold_explicit_self_kind(es, self)
1a4d82fc
JJ
188 }
189
190 fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
191 noop_fold_lifetime(l, self)
192 }
193
194 fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef {
195 noop_fold_lifetime_def(l, self)
196 }
197
85aaf69f 198 fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> {
1a4d82fc
JJ
199 noop_fold_attribute(at, self)
200 }
201
202 fn fold_arg(&mut self, a: Arg) -> Arg {
203 noop_fold_arg(a, self)
204 }
205
206 fn fold_generics(&mut self, generics: Generics) -> Generics {
207 noop_fold_generics(generics, self)
208 }
209
210 fn fold_trait_ref(&mut self, p: TraitRef) -> TraitRef {
211 noop_fold_trait_ref(p, self)
212 }
213
214 fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef {
215 noop_fold_poly_trait_ref(p, self)
216 }
217
b039eaaf
SL
218 fn fold_variant_data(&mut self, vdata: VariantData) -> VariantData {
219 noop_fold_variant_data(vdata, self)
1a4d82fc
JJ
220 }
221
222 fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
223 noop_fold_lifetimes(lts, self)
224 }
225
226 fn fold_lifetime_defs(&mut self, lts: Vec<LifetimeDef>) -> Vec<LifetimeDef> {
227 noop_fold_lifetime_defs(lts, self)
228 }
229
230 fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
231 noop_fold_ty_param(tp, self)
232 }
233
9cc50fc6 234 fn fold_ty_params(&mut self, tps: P<[TyParam]>) -> P<[TyParam]> {
1a4d82fc
JJ
235 noop_fold_ty_params(tps, self)
236 }
237
238 fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
239 noop_fold_tt(tt, self)
240 }
241
242 fn fold_tts(&mut self, tts: &[TokenTree]) -> Vec<TokenTree> {
243 noop_fold_tts(tts, self)
244 }
245
246 fn fold_token(&mut self, t: token::Token) -> token::Token {
247 noop_fold_token(t, self)
248 }
249
250 fn fold_interpolated(&mut self, nt: token::Nonterminal) -> token::Nonterminal {
251 noop_fold_interpolated(nt, self)
252 }
253
254 fn fold_opt_lifetime(&mut self, o_lt: Option<Lifetime>) -> Option<Lifetime> {
255 noop_fold_opt_lifetime(o_lt, self)
256 }
257
9cc50fc6
SL
258 fn fold_opt_bounds(&mut self, b: Option<TyParamBounds>)
259 -> Option<TyParamBounds> {
1a4d82fc
JJ
260 noop_fold_opt_bounds(b, self)
261 }
262
9cc50fc6
SL
263 fn fold_bounds(&mut self, b: TyParamBounds)
264 -> TyParamBounds {
1a4d82fc
JJ
265 noop_fold_bounds(b, self)
266 }
267
268 fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound {
269 noop_fold_ty_param_bound(tpb, self)
270 }
271
272 fn fold_mt(&mut self, mt: MutTy) -> MutTy {
273 noop_fold_mt(mt, self)
274 }
223e47cc 275
1a4d82fc
JJ
276 fn fold_field(&mut self, field: Field) -> Field {
277 noop_fold_field(field, self)
278 }
279
280 fn fold_where_clause(&mut self, where_clause: WhereClause)
281 -> WhereClause {
282 noop_fold_where_clause(where_clause, self)
283 }
284
285 fn fold_where_predicate(&mut self, where_predicate: WherePredicate)
286 -> WherePredicate {
287 noop_fold_where_predicate(where_predicate, self)
288 }
289
54a0048b
SL
290 fn fold_vis(&mut self, vis: Visibility) -> Visibility {
291 noop_fold_vis(vis, self)
292 }
293
1a4d82fc
JJ
294 fn new_id(&mut self, i: NodeId) -> NodeId {
295 i
296 }
297
298 fn new_span(&mut self, sp: Span) -> Span {
299 sp
300 }
223e47cc
LB
301}
302
1a4d82fc
JJ
303pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>, fld: &mut T)
304 -> Vec<P<MetaItem>> {
305 meta_items.move_map(|x| fld.fold_meta_item(x))
223e47cc
LB
306}
307
1a4d82fc
JJ
308pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
309 view_path.map(|Spanned {node, span}| Spanned {
310 node: match node {
85aaf69f
SL
311 ViewPathSimple(ident, path) => {
312 ViewPathSimple(ident, fld.fold_path(path))
1a4d82fc 313 }
85aaf69f
SL
314 ViewPathGlob(path) => {
315 ViewPathGlob(fld.fold_path(path))
1a4d82fc 316 }
85aaf69f 317 ViewPathList(path, path_list_idents) => {
1a4d82fc
JJ
318 ViewPathList(fld.fold_path(path),
319 path_list_idents.move_map(|path_list_ident| {
320 Spanned {
321 node: match path_list_ident.node {
7453a54e
SL
322 PathListItemKind::Ident { id, name, rename } =>
323 PathListItemKind::Ident {
1a4d82fc 324 id: fld.new_id(id),
e9174d1e 325 rename: rename,
1a4d82fc
JJ
326 name: name
327 },
7453a54e
SL
328 PathListItemKind::Mod { id, rename } =>
329 PathListItemKind::Mod {
e9174d1e
SL
330 id: fld.new_id(id),
331 rename: rename
332 }
1a4d82fc
JJ
333 },
334 span: fld.new_span(path_list_ident.span)
335 }
85aaf69f 336 }))
1a4d82fc
JJ
337 }
338 },
339 span: fld.new_span(span)
340 })
223e47cc
LB
341}
342
85aaf69f 343pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
92a42be0
SL
344 attrs.move_flat_map(|x| fld.fold_attribute(x))
345}
346
347pub fn fold_thin_attrs<T: Folder>(attrs: ThinAttributes, fld: &mut T) -> ThinAttributes {
348 attrs.map_thin_attrs(|v| fold_attrs(v, fld))
85aaf69f
SL
349}
350
1a4d82fc
JJ
351pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
352 Arm {
85aaf69f 353 attrs: fold_attrs(attrs, fld),
1a4d82fc
JJ
354 pats: pats.move_map(|x| fld.fold_pat(x)),
355 guard: guard.map(|x| fld.fold_expr(x)),
356 body: fld.fold_expr(body),
357 }
223e47cc
LB
358}
359
1a4d82fc
JJ
360pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
361 d.and_then(|Spanned {node, span}| match node {
7453a54e
SL
362 DeclKind::Local(l) => SmallVector::one(P(Spanned {
363 node: DeclKind::Local(fld.fold_local(l)),
1a4d82fc
JJ
364 span: fld.new_span(span)
365 })),
7453a54e
SL
366 DeclKind::Item(it) => fld.fold_item(it).into_iter().map(|i| P(Spanned {
367 node: DeclKind::Item(i),
1a4d82fc
JJ
368 span: fld.new_span(span)
369 })).collect()
370 })
371}
223e47cc 372
7453a54e
SL
373pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
374 TypeBinding {
375 id: fld.new_id(b.id),
376 ident: b.ident,
377 ty: fld.fold_ty(b.ty),
378 span: fld.new_span(b.span),
379 }
223e47cc
LB
380}
381
1a4d82fc
JJ
382pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
383 t.map(|Ty {id, node, span}| Ty {
384 id: fld.new_id(id),
385 node: match node {
7453a54e
SL
386 TyKind::Infer => node,
387 TyKind::Vec(ty) => TyKind::Vec(fld.fold_ty(ty)),
388 TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)),
389 TyKind::Rptr(region, mt) => {
390 TyKind::Rptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
1a4d82fc 391 }
7453a54e
SL
392 TyKind::BareFn(f) => {
393 TyKind::BareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
1a4d82fc
JJ
394 lifetimes: fld.fold_lifetime_defs(lifetimes),
395 unsafety: unsafety,
396 abi: abi,
397 decl: fld.fold_fn_decl(decl)
398 }))
399 }
7453a54e
SL
400 TyKind::Tup(tys) => TyKind::Tup(tys.move_map(|ty| fld.fold_ty(ty))),
401 TyKind::Paren(ty) => TyKind::Paren(fld.fold_ty(ty)),
402 TyKind::Path(qself, path) => {
c34b1796
AL
403 let qself = qself.map(|QSelf { ty, position }| {
404 QSelf {
405 ty: fld.fold_ty(ty),
406 position: position
407 }
408 });
7453a54e 409 TyKind::Path(qself, fld.fold_path(path))
1a4d82fc 410 }
7453a54e
SL
411 TyKind::ObjectSum(ty, bounds) => {
412 TyKind::ObjectSum(fld.fold_ty(ty),
1a4d82fc
JJ
413 fld.fold_bounds(bounds))
414 }
7453a54e
SL
415 TyKind::FixedLengthVec(ty, e) => {
416 TyKind::FixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
1a4d82fc 417 }
7453a54e
SL
418 TyKind::Typeof(expr) => {
419 TyKind::Typeof(fld.fold_expr(expr))
1a4d82fc 420 }
7453a54e
SL
421 TyKind::PolyTraitRef(bounds) => {
422 TyKind::PolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
1a4d82fc 423 }
7453a54e
SL
424 TyKind::Mac(mac) => {
425 TyKind::Mac(fld.fold_mac(mac))
e9174d1e 426 }
1a4d82fc
JJ
427 },
428 span: fld.new_span(span)
429 })
223e47cc
LB
430}
431
85aaf69f 432pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
1a4d82fc
JJ
433 fld: &mut T) -> ForeignMod {
434 ForeignMod {
435 abi: abi,
1a4d82fc
JJ
436 items: items.move_map(|x| fld.fold_foreign_item(x)),
437 }
438}
223e47cc 439
7453a54e
SL
440pub fn noop_fold_variant<T: Folder>(v: Variant, fld: &mut T) -> Variant {
441 Spanned {
1a4d82fc 442 node: Variant_ {
7453a54e
SL
443 name: v.node.name,
444 attrs: fold_attrs(v.node.attrs, fld),
445 data: fld.fold_variant_data(v.node.data),
446 disr_expr: v.node.disr_expr.map(|e| fld.fold_expr(e)),
1a4d82fc 447 },
7453a54e
SL
448 span: fld.new_span(v.span),
449 }
1a4d82fc
JJ
450}
451
452pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
453 i
454}
455
85aaf69f 456pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
1a4d82fc
JJ
457 i
458}
459
460pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
461 Path {
462 global: global,
463 segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
464 identifier: fld.fold_ident(identifier),
465 parameters: fld.fold_path_parameters(parameters),
466 }),
467 span: fld.new_span(span)
223e47cc
LB
468 }
469}
470
1a4d82fc
JJ
471pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
472 -> PathParameters
473{
474 match path_parameters {
9cc50fc6
SL
475 PathParameters::AngleBracketed(data) =>
476 PathParameters::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)),
477 PathParameters::Parenthesized(data) =>
478 PathParameters::Parenthesized(fld.fold_parenthesized_parameter_data(data)),
1a4d82fc
JJ
479 }
480}
223e47cc 481
1a4d82fc
JJ
482pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
483 fld: &mut T)
484 -> AngleBracketedParameterData
485{
486 let AngleBracketedParameterData { lifetimes, types, bindings } = data;
487 AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes),
488 types: types.move_map(|ty| fld.fold_ty(ty)),
489 bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) }
223e47cc
LB
490}
491
1a4d82fc
JJ
492pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
493 fld: &mut T)
494 -> ParenthesizedParameterData
495{
85aaf69f 496 let ParenthesizedParameterData { inputs, output, span } = data;
1a4d82fc 497 ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
85aaf69f
SL
498 output: output.map(|ty| fld.fold_ty(ty)),
499 span: fld.new_span(span) }
1a4d82fc 500}
970d7e83 501
1a4d82fc 502pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
92a42be0 503 l.map(|Local {id, pat, ty, init, span, attrs}| Local {
1a4d82fc
JJ
504 id: fld.new_id(id),
505 ty: ty.map(|t| fld.fold_ty(t)),
506 pat: fld.fold_pat(pat),
507 init: init.map(|e| fld.fold_expr(e)),
92a42be0
SL
508 span: fld.new_span(span),
509 attrs: attrs.map_thin_attrs(|v| fold_attrs(v, fld)),
1a4d82fc 510 })
223e47cc
LB
511}
512
85aaf69f 513pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
1a4d82fc 514 let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
85aaf69f 515 Some(Spanned {
1a4d82fc
JJ
516 node: Attribute_ {
517 id: id,
518 style: style,
519 value: fld.fold_meta_item(value),
520 is_sugared_doc: is_sugared_doc
521 },
522 span: fld.new_span(span)
85aaf69f 523 })
1a4d82fc
JJ
524}
525
7453a54e
SL
526pub fn noop_fold_explicit_self_kind<T: Folder>(es: SelfKind, fld: &mut T)
527 -> SelfKind {
1a4d82fc 528 match es {
7453a54e
SL
529 SelfKind::Static | SelfKind::Value(_) => es,
530 SelfKind::Region(lifetime, m, ident) => {
531 SelfKind::Region(fld.fold_opt_lifetime(lifetime), m, ident)
223e47cc 532 }
7453a54e
SL
533 SelfKind::Explicit(typ, ident) => {
534 SelfKind::Explicit(fld.fold_ty(typ), ident)
223e47cc
LB
535 }
536 }
537}
538
1a4d82fc
JJ
539pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fld: &mut T)
540 -> ExplicitSelf {
541 Spanned {
7453a54e 542 node: fld.fold_explicit_self_kind(node),
1a4d82fc 543 span: fld.new_span(span)
223e47cc
LB
544 }
545}
546
1a4d82fc
JJ
547
548pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
549 Spanned {
b039eaaf
SL
550 node: Mac_ {
551 path: fld.fold_path(node.path),
552 tts: fld.fold_tts(&node.tts),
553 ctxt: node.ctxt,
1a4d82fc
JJ
554 },
555 span: fld.new_span(span)
223e47cc
LB
556 }
557}
558
1a4d82fc
JJ
559pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
560 mi.map(|Spanned {node, span}| Spanned {
561 node: match node {
7453a54e
SL
562 MetaItemKind::Word(id) => MetaItemKind::Word(id),
563 MetaItemKind::List(id, mis) => {
564 MetaItemKind::List(id, mis.move_map(|e| fld.fold_meta_item(e)))
1a4d82fc 565 }
7453a54e 566 MetaItemKind::NameValue(id, s) => MetaItemKind::NameValue(id, s)
223e47cc 567 },
1a4d82fc
JJ
568 span: fld.new_span(span)
569 })
223e47cc
LB
570}
571
1a4d82fc
JJ
572pub fn noop_fold_arg<T: Folder>(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg {
573 Arg {
574 id: fld.new_id(id),
575 pat: fld.fold_pat(pat),
576 ty: fld.fold_ty(ty)
223e47cc
LB
577 }
578}
579
1a4d82fc
JJ
580pub fn noop_fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree {
581 match *tt {
92a42be0
SL
582 TokenTree::Token(span, ref tok) =>
583 TokenTree::Token(span, fld.fold_token(tok.clone())),
584 TokenTree::Delimited(span, ref delimed) => {
585 TokenTree::Delimited(span, Rc::new(
1a4d82fc
JJ
586 Delimited {
587 delim: delimed.delim,
588 open_span: delimed.open_span,
85aaf69f 589 tts: fld.fold_tts(&delimed.tts),
1a4d82fc
JJ
590 close_span: delimed.close_span,
591 }
592 ))
593 },
92a42be0
SL
594 TokenTree::Sequence(span, ref seq) =>
595 TokenTree::Sequence(span,
1a4d82fc 596 Rc::new(SequenceRepetition {
85aaf69f 597 tts: fld.fold_tts(&seq.tts),
1a4d82fc
JJ
598 separator: seq.separator.clone().map(|tok| fld.fold_token(tok)),
599 ..**seq
600 })),
223e47cc
LB
601 }
602}
603
1a4d82fc 604pub fn noop_fold_tts<T: Folder>(tts: &[TokenTree], fld: &mut T) -> Vec<TokenTree> {
92a42be0
SL
605 // FIXME: Does this have to take a tts slice?
606 // Could use move_map otherwise...
1a4d82fc
JJ
607 tts.iter().map(|tt| fld.fold_tt(tt)).collect()
608}
609
610// apply ident folder if it's an ident, apply other folds to interpolated nodes
611pub fn noop_fold_token<T: Folder>(t: token::Token, fld: &mut T) -> token::Token {
612 match t {
613 token::Ident(id, followed_by_colons) => {
614 token::Ident(fld.fold_ident(id), followed_by_colons)
970d7e83 615 }
1a4d82fc
JJ
616 token::Lifetime(id) => token::Lifetime(fld.fold_ident(id)),
617 token::Interpolated(nt) => token::Interpolated(fld.fold_interpolated(nt)),
618 token::SubstNt(ident, namep) => {
619 token::SubstNt(fld.fold_ident(ident), namep)
970d7e83 620 }
1a4d82fc
JJ
621 token::MatchNt(name, kind, namep, kindp) => {
622 token::MatchNt(fld.fold_ident(name), fld.fold_ident(kind), namep, kindp)
970d7e83 623 }
1a4d82fc 624 _ => t
223e47cc
LB
625 }
626}
627
1a4d82fc
JJ
628/// apply folder to elements of interpolated nodes
629//
630// NB: this can occur only when applying a fold to partially expanded code, where
631// parsed pieces have gotten implanted ito *other* macro invocations. This is relevant
632// for macro hygiene, but possibly not elsewhere.
633//
634// One problem here occurs because the types for fold_item, fold_stmt, etc. allow the
635// folder to return *multiple* items; this is a problem for the nodes here, because
636// they insist on having exactly one piece. One solution would be to mangle the fold
637// trait to include one-to-many and one-to-one versions of these entry points, but that
638// would probably confuse a lot of people and help very few. Instead, I'm just going
639// to put in dynamic checks. I think the performance impact of this will be pretty much
640// nonexistent. The danger is that someone will apply a fold to a partially expanded
641// node, and will be confused by the fact that their "fold_item" or "fold_stmt" isn't
642// getting called on NtItem or NtStmt nodes. Hopefully they'll wind up reading this
643// comment, and doing something appropriate.
644//
645// BTW, design choice: I considered just changing the type of, e.g., NtItem to contain
646// multiple items, but decided against it when I looked at parse_item_or_view_item and
647// tried to figure out what I would do with multiple items there....
648pub fn noop_fold_interpolated<T: Folder>(nt: token::Nonterminal, fld: &mut T)
649 -> token::Nonterminal {
650 match nt {
651 token::NtItem(item) =>
652 token::NtItem(fld.fold_item(item)
653 // this is probably okay, because the only folds likely
654 // to peek inside interpolated nodes will be renamings/markings,
655 // which map single items to single items
656 .expect_one("expected fold to produce exactly one item")),
657 token::NtBlock(block) => token::NtBlock(fld.fold_block(block)),
658 token::NtStmt(stmt) =>
7453a54e 659 token::NtStmt(stmt.map(|stmt| fld.fold_stmt(stmt)
1a4d82fc
JJ
660 // this is probably okay, because the only folds likely
661 // to peek inside interpolated nodes will be renamings/markings,
662 // which map single items to single items
7453a54e 663 .expect_one("expected fold to produce exactly one statement"))),
1a4d82fc
JJ
664 token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
665 token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
666 token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
d9579d0f 667 token::NtIdent(id, is_mod_name) =>
9cc50fc6
SL
668 token::NtIdent(Box::new(Spanned::<Ident>{node: fld.fold_ident(id.node), .. *id}),
669 is_mod_name),
1a4d82fc 670 token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)),
d9579d0f 671 token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))),
92a42be0 672 token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))),
d9579d0f
AL
673 token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)),
674 token::NtImplItem(arm) =>
7453a54e
SL
675 token::NtImplItem(arm.map(|arm| fld.fold_impl_item(arm)
676 .expect_one("expected fold to produce exactly one item"))),
d9579d0f 677 token::NtTraitItem(arm) =>
7453a54e
SL
678 token::NtTraitItem(arm.map(|arm| fld.fold_trait_item(arm)
679 .expect_one("expected fold to produce exactly one item"))),
d9579d0f
AL
680 token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)),
681 token::NtWhereClause(where_clause) =>
682 token::NtWhereClause(fld.fold_where_clause(where_clause)),
92a42be0 683 token::NtArg(arg) => token::NtArg(fld.fold_arg(arg)),
223e47cc
LB
684 }
685}
686
1a4d82fc
JJ
687pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
688 decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
689 inputs: inputs.move_map(|x| fld.fold_arg(x)),
690 output: match output {
7453a54e
SL
691 FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(fld.fold_ty(ty)),
692 FunctionRetTy::Default(span) => FunctionRetTy::Default(span),
693 FunctionRetTy::None(span) => FunctionRetTy::None(span),
223e47cc 694 },
1a4d82fc
JJ
695 variadic: variadic
696 })
697}
698
699pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
700 -> TyParamBound
701 where T: Folder {
702 match tpb {
703 TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
704 RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
223e47cc
LB
705 }
706}
707
1a4d82fc
JJ
708pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
709 let TyParam {id, ident, bounds, default, span} = tp;
710 TyParam {
711 id: fld.new_id(id),
712 ident: ident,
713 bounds: fld.fold_bounds(bounds),
714 default: default.map(|x| fld.fold_ty(x)),
715 span: span
223e47cc
LB
716 }
717}
718
9cc50fc6
SL
719pub fn noop_fold_ty_params<T: Folder>(tps: P<[TyParam]>, fld: &mut T)
720 -> P<[TyParam]> {
1a4d82fc 721 tps.move_map(|tp| fld.fold_ty_param(tp))
223e47cc
LB
722}
723
1a4d82fc
JJ
724pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
725 Lifetime {
726 id: fld.new_id(l.id),
727 name: l.name,
728 span: fld.new_span(l.span)
223e47cc 729 }
1a4d82fc 730}
223e47cc 731
1a4d82fc
JJ
732pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T)
733 -> LifetimeDef {
734 LifetimeDef {
735 lifetime: fld.fold_lifetime(l.lifetime),
736 bounds: fld.fold_lifetimes(l.bounds),
223e47cc
LB
737 }
738}
739
1a4d82fc
JJ
740pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Lifetime> {
741 lts.move_map(|l| fld.fold_lifetime(l))
742}
743
744pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T)
745 -> Vec<LifetimeDef> {
746 lts.move_map(|l| fld.fold_lifetime_def(l))
747}
748
749pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
750 -> Option<Lifetime> {
751 o_lt.map(|lt| fld.fold_lifetime(lt))
752}
753
754pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause}: Generics,
755 fld: &mut T) -> Generics {
756 Generics {
757 ty_params: fld.fold_ty_params(ty_params),
758 lifetimes: fld.fold_lifetime_defs(lifetimes),
759 where_clause: fld.fold_where_clause(where_clause),
223e47cc 760 }
1a4d82fc
JJ
761}
762
763pub fn noop_fold_where_clause<T: Folder>(
764 WhereClause {id, predicates}: WhereClause,
765 fld: &mut T)
766 -> WhereClause {
767 WhereClause {
768 id: fld.new_id(id),
769 predicates: predicates.move_map(|predicate| {
770 fld.fold_where_predicate(predicate)
771 })
970d7e83 772 }
1a4d82fc
JJ
773}
774
775pub fn noop_fold_where_predicate<T: Folder>(
776 pred: WherePredicate,
777 fld: &mut T)
778 -> WherePredicate {
779 match pred {
85aaf69f
SL
780 ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bound_lifetimes,
781 bounded_ty,
1a4d82fc
JJ
782 bounds,
783 span}) => {
784 ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
85aaf69f 785 bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes),
1a4d82fc
JJ
786 bounded_ty: fld.fold_ty(bounded_ty),
787 bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
788 span: fld.new_span(span)
223e47cc
LB
789 })
790 }
1a4d82fc
JJ
791 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime,
792 bounds,
793 span}) => {
794 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
795 span: fld.new_span(span),
796 lifetime: fld.fold_lifetime(lifetime),
797 bounds: bounds.move_map(|bound| fld.fold_lifetime(bound))
223e47cc
LB
798 })
799 }
1a4d82fc
JJ
800 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
801 path,
802 ty,
803 span}) => {
804 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{
805 id: fld.new_id(id),
806 path: fld.fold_path(path),
807 ty:fld.fold_ty(ty),
808 span: fld.new_span(span)
809 })
223e47cc 810 }
223e47cc
LB
811 }
812}
813
b039eaaf
SL
814pub fn noop_fold_variant_data<T: Folder>(vdata: VariantData, fld: &mut T) -> VariantData {
815 match vdata {
816 ast::VariantData::Struct(fields, id) => {
817 ast::VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)),
818 fld.new_id(id))
819 }
820 ast::VariantData::Tuple(fields, id) => {
821 ast::VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)),
822 fld.new_id(id))
823 }
824 ast::VariantData::Unit(id) => ast::VariantData::Unit(fld.new_id(id))
825 }
1a4d82fc
JJ
826}
827
828pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
829 let id = fld.new_id(p.ref_id);
830 let TraitRef {
831 path,
832 ref_id: _,
833 } = p;
834 ast::TraitRef {
835 path: fld.fold_path(path),
836 ref_id: id,
223e47cc 837 }
1a4d82fc 838}
223e47cc 839
1a4d82fc
JJ
840pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
841 ast::PolyTraitRef {
842 bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
85aaf69f
SL
843 trait_ref: fld.fold_trait_ref(p.trait_ref),
844 span: fld.new_span(p.span),
1a4d82fc
JJ
845 }
846}
847
848pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructField {
54a0048b
SL
849 StructField {
850 span: fld.new_span(f.span),
851 id: fld.new_id(f.id),
852 ident: f.ident.map(|ident| fld.fold_ident(ident)),
853 vis: f.vis,
854 ty: fld.fold_ty(f.ty),
855 attrs: fold_attrs(f.attrs, fld),
223e47cc 856 }
1a4d82fc 857}
223e47cc 858
1a4d82fc
JJ
859pub fn noop_fold_field<T: Folder>(Field {ident, expr, span}: Field, folder: &mut T) -> Field {
860 Field {
861 ident: respan(ident.span, folder.fold_ident(ident.node)),
862 expr: folder.fold_expr(expr),
863 span: folder.new_span(span)
864 }
865}
223e47cc 866
1a4d82fc
JJ
867pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutTy {
868 MutTy {
869 ty: folder.fold_ty(ty),
870 mutbl: mutbl,
223e47cc
LB
871 }
872}
873
9cc50fc6
SL
874pub fn noop_fold_opt_bounds<T: Folder>(b: Option<TyParamBounds>, folder: &mut T)
875 -> Option<TyParamBounds> {
1a4d82fc
JJ
876 b.map(|bounds| folder.fold_bounds(bounds))
877}
878
879fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
880 -> TyParamBounds {
881 bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
223e47cc
LB
882}
883
1a4d82fc 884pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
85aaf69f 885 b.map(|Block {id, stmts, expr, rules, span}| Block {
1a4d82fc 886 id: folder.new_id(id),
92a42be0
SL
887 stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
888 expr: expr.and_then(|x| folder.fold_opt_expr(x)),
1a4d82fc
JJ
889 rules: rules,
890 span: folder.new_span(span),
891 })
892}
893
7453a54e 894pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
1a4d82fc 895 match i {
7453a54e
SL
896 ItemKind::ExternCrate(string) => ItemKind::ExternCrate(string),
897 ItemKind::Use(view_path) => {
898 ItemKind::Use(folder.fold_view_path(view_path))
85aaf69f 899 }
7453a54e
SL
900 ItemKind::Static(t, m, e) => {
901 ItemKind::Static(folder.fold_ty(t), m, folder.fold_expr(e))
223e47cc 902 }
7453a54e
SL
903 ItemKind::Const(t, e) => {
904 ItemKind::Const(folder.fold_ty(t), folder.fold_expr(e))
223e47cc 905 }
7453a54e
SL
906 ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
907 ItemKind::Fn(
1a4d82fc
JJ
908 folder.fold_fn_decl(decl),
909 unsafety,
62682a34 910 constness,
1a4d82fc
JJ
911 abi,
912 folder.fold_generics(generics),
913 folder.fold_block(body)
914 )
970d7e83 915 }
7453a54e
SL
916 ItemKind::Mod(m) => ItemKind::Mod(folder.fold_mod(m)),
917 ItemKind::ForeignMod(nm) => ItemKind::ForeignMod(folder.fold_foreign_mod(nm)),
918 ItemKind::Ty(t, generics) => {
919 ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
223e47cc 920 }
7453a54e
SL
921 ItemKind::Enum(enum_definition, generics) => {
922 ItemKind::Enum(
1a4d82fc
JJ
923 ast::EnumDef {
924 variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
925 },
926 folder.fold_generics(generics))
970d7e83 927 }
7453a54e 928 ItemKind::Struct(struct_def, generics) => {
b039eaaf 929 let struct_def = folder.fold_variant_data(struct_def);
7453a54e 930 ItemKind::Struct(struct_def, folder.fold_generics(generics))
223e47cc 931 }
7453a54e
SL
932 ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
933 ItemKind::DefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
c34b1796 934 }
7453a54e 935 ItemKind::Impl(unsafety, polarity, generics, ifce, ty, impl_items) => {
92a42be0
SL
936 let new_impl_items = impl_items.move_flat_map(|item| {
937 folder.fold_impl_item(item)
938 });
1a4d82fc
JJ
939 let ifce = match ifce {
940 None => None,
941 Some(ref trait_ref) => {
942 Some(folder.fold_trait_ref((*trait_ref).clone()))
943 }
944 };
7453a54e 945 ItemKind::Impl(unsafety,
1a4d82fc
JJ
946 polarity,
947 folder.fold_generics(generics),
948 ifce,
949 folder.fold_ty(ty),
950 new_impl_items)
223e47cc 951 }
7453a54e 952 ItemKind::Trait(unsafety, generics, bounds, items) => {
1a4d82fc 953 let bounds = folder.fold_bounds(bounds);
92a42be0
SL
954 let items = items.move_flat_map(|item| {
955 folder.fold_trait_item(item)
956 });
7453a54e 957 ItemKind::Trait(unsafety,
1a4d82fc
JJ
958 folder.fold_generics(generics),
959 bounds,
85aaf69f 960 items)
1a4d82fc 961 }
7453a54e 962 ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)),
223e47cc 963 }
1a4d82fc
JJ
964}
965
7453a54e
SL
966pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T)
967 -> SmallVector<TraitItem> {
968 SmallVector::one(TraitItem {
969 id: folder.new_id(i.id),
970 ident: folder.fold_ident(i.ident),
971 attrs: fold_attrs(i.attrs, folder),
972 node: match i.node {
973 TraitItemKind::Const(ty, default) => {
974 TraitItemKind::Const(folder.fold_ty(ty),
d9579d0f
AL
975 default.map(|x| folder.fold_expr(x)))
976 }
7453a54e
SL
977 TraitItemKind::Method(sig, body) => {
978 TraitItemKind::Method(noop_fold_method_sig(sig, folder),
c34b1796
AL
979 body.map(|x| folder.fold_block(x)))
980 }
7453a54e
SL
981 TraitItemKind::Type(bounds, default) => {
982 TraitItemKind::Type(folder.fold_bounds(bounds),
c34b1796
AL
983 default.map(|x| folder.fold_ty(x)))
984 }
985 },
7453a54e
SL
986 span: folder.new_span(i.span)
987 })
85aaf69f
SL
988}
989
7453a54e
SL
990pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
991 -> SmallVector<ImplItem> {
992 SmallVector::one(ImplItem {
993 id: folder.new_id(i.id),
994 ident: folder.fold_ident(i.ident),
995 attrs: fold_attrs(i.attrs, folder),
54a0048b
SL
996 vis: folder.fold_vis(i.vis),
997 defaultness: i.defaultness,
7453a54e 998 node: match i.node {
92a42be0
SL
999 ast::ImplItemKind::Const(ty, expr) => {
1000 ast::ImplItemKind::Const(folder.fold_ty(ty), folder.fold_expr(expr))
d9579d0f 1001 }
92a42be0
SL
1002 ast::ImplItemKind::Method(sig, body) => {
1003 ast::ImplItemKind::Method(noop_fold_method_sig(sig, folder),
c34b1796
AL
1004 folder.fold_block(body))
1005 }
92a42be0
SL
1006 ast::ImplItemKind::Type(ty) => ast::ImplItemKind::Type(folder.fold_ty(ty)),
1007 ast::ImplItemKind::Macro(mac) => ast::ImplItemKind::Macro(folder.fold_mac(mac))
c34b1796 1008 },
7453a54e
SL
1009 span: folder.new_span(i.span)
1010 })
1a4d82fc
JJ
1011}
1012
85aaf69f 1013pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
1a4d82fc
JJ
1014 Mod {
1015 inner: folder.new_span(inner),
92a42be0 1016 items: items.move_flat_map(|x| folder.fold_item(x)),
223e47cc 1017 }
1a4d82fc
JJ
1018}
1019
1020pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, mut exported_macros, span}: Crate,
1021 folder: &mut T) -> Crate {
1022 let config = folder.fold_meta_items(config);
1023
1024 let mut items = folder.fold_item(P(ast::Item {
1025 ident: token::special_idents::invalid,
1026 attrs: attrs,
1027 id: ast::DUMMY_NODE_ID,
7453a54e 1028 vis: ast::Visibility::Public,
1a4d82fc 1029 span: span,
7453a54e 1030 node: ast::ItemKind::Mod(module),
1a4d82fc
JJ
1031 })).into_iter();
1032
1033 let (module, attrs, span) = match items.next() {
1034 Some(item) => {
1035 assert!(items.next().is_none(),
1036 "a crate cannot expand to more than one item");
1037 item.and_then(|ast::Item { attrs, span, node, .. }| {
1038 match node {
7453a54e 1039 ast::ItemKind::Mod(m) => (m, attrs, span),
1a4d82fc
JJ
1040 _ => panic!("fold converted a module to not a module"),
1041 }
1042 })
1043 }
1044 None => (ast::Mod {
1045 inner: span,
85aaf69f
SL
1046 items: vec![],
1047 }, vec![], span)
1a4d82fc
JJ
1048 };
1049
85aaf69f 1050 for def in &mut exported_macros {
1a4d82fc 1051 def.id = folder.new_id(def.id);
223e47cc 1052 }
1a4d82fc
JJ
1053
1054 Crate {
1055 module: module,
1056 attrs: attrs,
1057 config: config,
1058 exported_macros: exported_macros,
1059 span: span,
223e47cc 1060 }
1a4d82fc
JJ
1061}
1062
1063// fold one item into possibly many items
1064pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> SmallVector<P<Item>> {
1065 SmallVector::one(i.map(|i| folder.fold_item_simple(i)))
1066}
1067
1068// fold one item into exactly one item
1069pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}: Item,
1070 folder: &mut T) -> Item {
1071 let id = folder.new_id(id);
7453a54e 1072 let node = folder.fold_item_kind(node);
1a4d82fc
JJ
1073
1074 Item {
1075 id: id,
1076 ident: folder.fold_ident(ident),
85aaf69f 1077 attrs: fold_attrs(attrs, folder),
1a4d82fc 1078 node: node,
54a0048b 1079 vis: folder.fold_vis(vis),
1a4d82fc 1080 span: folder.new_span(span)
223e47cc
LB
1081 }
1082}
1083
7453a54e
SL
1084pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> ForeignItem {
1085 ForeignItem {
1086 id: folder.new_id(ni.id),
1087 ident: folder.fold_ident(ni.ident),
1088 attrs: fold_attrs(ni.attrs, folder),
1089 node: match ni.node {
1090 ForeignItemKind::Fn(fdec, generics) => {
1091 ForeignItemKind::Fn(folder.fold_fn_decl(fdec), folder.fold_generics(generics))
1a4d82fc 1092 }
7453a54e
SL
1093 ForeignItemKind::Static(t, m) => {
1094 ForeignItemKind::Static(folder.fold_ty(t), m)
1a4d82fc
JJ
1095 }
1096 },
54a0048b 1097 vis: folder.fold_vis(ni.vis),
7453a54e
SL
1098 span: folder.new_span(ni.span)
1099 }
1a4d82fc
JJ
1100}
1101
c34b1796
AL
1102pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig {
1103 MethodSig {
1104 generics: folder.fold_generics(sig.generics),
1105 abi: sig.abi,
1106 explicit_self: folder.fold_explicit_self(sig.explicit_self),
1107 unsafety: sig.unsafety,
62682a34 1108 constness: sig.constness,
c34b1796
AL
1109 decl: folder.fold_fn_decl(sig.decl)
1110 }
970d7e83
LB
1111}
1112
1a4d82fc
JJ
1113pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
1114 p.map(|Pat {id, node, span}| Pat {
1115 id: folder.new_id(id),
1116 node: match node {
7453a54e
SL
1117 PatKind::Wild => PatKind::Wild,
1118 PatKind::Ident(binding_mode, pth1, sub) => {
1119 PatKind::Ident(binding_mode,
1a4d82fc
JJ
1120 Spanned{span: folder.new_span(pth1.span),
1121 node: folder.fold_ident(pth1.node)},
1122 sub.map(|x| folder.fold_pat(x)))
1123 }
7453a54e
SL
1124 PatKind::Lit(e) => PatKind::Lit(folder.fold_expr(e)),
1125 PatKind::TupleStruct(pth, pats) => {
1126 PatKind::TupleStruct(folder.fold_path(pth),
1a4d82fc
JJ
1127 pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
1128 }
7453a54e
SL
1129 PatKind::Path(pth) => {
1130 PatKind::Path(folder.fold_path(pth))
1131 }
1132 PatKind::QPath(qself, pth) => {
d9579d0f 1133 let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself};
7453a54e 1134 PatKind::QPath(qself, folder.fold_path(pth))
d9579d0f 1135 }
7453a54e 1136 PatKind::Struct(pth, fields, etc) => {
1a4d82fc
JJ
1137 let pth = folder.fold_path(pth);
1138 let fs = fields.move_map(|f| {
1139 Spanned { span: folder.new_span(f.span),
1140 node: ast::FieldPat {
1141 ident: f.node.ident,
1142 pat: folder.fold_pat(f.node.pat),
1143 is_shorthand: f.node.is_shorthand,
1144 }}
1145 });
7453a54e 1146 PatKind::Struct(pth, fs, etc)
1a4d82fc 1147 }
7453a54e
SL
1148 PatKind::Tup(elts) => PatKind::Tup(elts.move_map(|x| folder.fold_pat(x))),
1149 PatKind::Box(inner) => PatKind::Box(folder.fold_pat(inner)),
1150 PatKind::Ref(inner, mutbl) => PatKind::Ref(folder.fold_pat(inner), mutbl),
1151 PatKind::Range(e1, e2) => {
1152 PatKind::Range(folder.fold_expr(e1), folder.fold_expr(e2))
1a4d82fc 1153 },
7453a54e
SL
1154 PatKind::Vec(before, slice, after) => {
1155 PatKind::Vec(before.move_map(|x| folder.fold_pat(x)),
1a4d82fc
JJ
1156 slice.map(|x| folder.fold_pat(x)),
1157 after.move_map(|x| folder.fold_pat(x)))
1158 }
7453a54e 1159 PatKind::Mac(mac) => PatKind::Mac(folder.fold_mac(mac))
1a4d82fc
JJ
1160 },
1161 span: folder.new_span(span)
1162 })
1163}
1164
92a42be0 1165pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mut T) -> Expr {
1a4d82fc
JJ
1166 Expr {
1167 id: folder.new_id(id),
1168 node: match node {
7453a54e
SL
1169 ExprKind::Box(e) => {
1170 ExprKind::Box(folder.fold_expr(e))
b039eaaf 1171 }
7453a54e
SL
1172 ExprKind::InPlace(p, e) => {
1173 ExprKind::InPlace(folder.fold_expr(p), folder.fold_expr(e))
1a4d82fc 1174 }
7453a54e
SL
1175 ExprKind::Vec(exprs) => {
1176 ExprKind::Vec(folder.fold_exprs(exprs))
1a4d82fc 1177 }
7453a54e
SL
1178 ExprKind::Repeat(expr, count) => {
1179 ExprKind::Repeat(folder.fold_expr(expr), folder.fold_expr(count))
1a4d82fc 1180 }
7453a54e
SL
1181 ExprKind::Tup(exprs) => ExprKind::Tup(folder.fold_exprs(exprs)),
1182 ExprKind::Call(f, args) => {
1183 ExprKind::Call(folder.fold_expr(f),
92a42be0 1184 folder.fold_exprs(args))
1a4d82fc 1185 }
7453a54e
SL
1186 ExprKind::MethodCall(i, tps, args) => {
1187 ExprKind::MethodCall(
9346a6ac 1188 respan(folder.new_span(i.span), folder.fold_ident(i.node)),
1a4d82fc 1189 tps.move_map(|x| folder.fold_ty(x)),
92a42be0 1190 folder.fold_exprs(args))
1a4d82fc 1191 }
7453a54e
SL
1192 ExprKind::Binary(binop, lhs, rhs) => {
1193 ExprKind::Binary(binop,
1a4d82fc
JJ
1194 folder.fold_expr(lhs),
1195 folder.fold_expr(rhs))
1196 }
7453a54e
SL
1197 ExprKind::Unary(binop, ohs) => {
1198 ExprKind::Unary(binop, folder.fold_expr(ohs))
1a4d82fc 1199 }
7453a54e
SL
1200 ExprKind::Lit(l) => ExprKind::Lit(l),
1201 ExprKind::Cast(expr, ty) => {
1202 ExprKind::Cast(folder.fold_expr(expr), folder.fold_ty(ty))
1a4d82fc 1203 }
7453a54e
SL
1204 ExprKind::Type(expr, ty) => {
1205 ExprKind::Type(folder.fold_expr(expr), folder.fold_ty(ty))
9cc50fc6 1206 }
7453a54e
SL
1207 ExprKind::AddrOf(m, ohs) => ExprKind::AddrOf(m, folder.fold_expr(ohs)),
1208 ExprKind::If(cond, tr, fl) => {
1209 ExprKind::If(folder.fold_expr(cond),
1a4d82fc
JJ
1210 folder.fold_block(tr),
1211 fl.map(|x| folder.fold_expr(x)))
1212 }
7453a54e
SL
1213 ExprKind::IfLet(pat, expr, tr, fl) => {
1214 ExprKind::IfLet(folder.fold_pat(pat),
1a4d82fc
JJ
1215 folder.fold_expr(expr),
1216 folder.fold_block(tr),
1217 fl.map(|x| folder.fold_expr(x)))
1218 }
7453a54e
SL
1219 ExprKind::While(cond, body, opt_ident) => {
1220 ExprKind::While(folder.fold_expr(cond),
1a4d82fc
JJ
1221 folder.fold_block(body),
1222 opt_ident.map(|i| folder.fold_ident(i)))
1223 }
7453a54e
SL
1224 ExprKind::WhileLet(pat, expr, body, opt_ident) => {
1225 ExprKind::WhileLet(folder.fold_pat(pat),
1a4d82fc
JJ
1226 folder.fold_expr(expr),
1227 folder.fold_block(body),
1228 opt_ident.map(|i| folder.fold_ident(i)))
1229 }
7453a54e
SL
1230 ExprKind::ForLoop(pat, iter, body, opt_ident) => {
1231 ExprKind::ForLoop(folder.fold_pat(pat),
1a4d82fc
JJ
1232 folder.fold_expr(iter),
1233 folder.fold_block(body),
1234 opt_ident.map(|i| folder.fold_ident(i)))
1235 }
7453a54e
SL
1236 ExprKind::Loop(body, opt_ident) => {
1237 ExprKind::Loop(folder.fold_block(body),
1a4d82fc
JJ
1238 opt_ident.map(|i| folder.fold_ident(i)))
1239 }
7453a54e
SL
1240 ExprKind::Match(expr, arms) => {
1241 ExprKind::Match(folder.fold_expr(expr),
b039eaaf 1242 arms.move_map(|x| folder.fold_arm(x)))
1a4d82fc 1243 }
7453a54e
SL
1244 ExprKind::Closure(capture_clause, decl, body) => {
1245 ExprKind::Closure(capture_clause,
1a4d82fc
JJ
1246 folder.fold_fn_decl(decl),
1247 folder.fold_block(body))
1248 }
7453a54e
SL
1249 ExprKind::Block(blk) => ExprKind::Block(folder.fold_block(blk)),
1250 ExprKind::Assign(el, er) => {
1251 ExprKind::Assign(folder.fold_expr(el), folder.fold_expr(er))
1a4d82fc 1252 }
7453a54e
SL
1253 ExprKind::AssignOp(op, el, er) => {
1254 ExprKind::AssignOp(op,
1a4d82fc
JJ
1255 folder.fold_expr(el),
1256 folder.fold_expr(er))
1257 }
7453a54e
SL
1258 ExprKind::Field(el, ident) => {
1259 ExprKind::Field(folder.fold_expr(el),
9346a6ac
AL
1260 respan(folder.new_span(ident.span),
1261 folder.fold_ident(ident.node)))
1a4d82fc 1262 }
7453a54e
SL
1263 ExprKind::TupField(el, ident) => {
1264 ExprKind::TupField(folder.fold_expr(el),
9346a6ac
AL
1265 respan(folder.new_span(ident.span),
1266 folder.fold_usize(ident.node)))
1a4d82fc 1267 }
7453a54e
SL
1268 ExprKind::Index(el, er) => {
1269 ExprKind::Index(folder.fold_expr(el), folder.fold_expr(er))
1a4d82fc 1270 }
54a0048b 1271 ExprKind::Range(e1, e2, lim) => {
7453a54e 1272 ExprKind::Range(e1.map(|x| folder.fold_expr(x)),
54a0048b
SL
1273 e2.map(|x| folder.fold_expr(x)),
1274 lim)
1a4d82fc 1275 }
7453a54e 1276 ExprKind::Path(qself, path) => {
c34b1796
AL
1277 let qself = qself.map(|QSelf { ty, position }| {
1278 QSelf {
1279 ty: folder.fold_ty(ty),
1280 position: position
1281 }
1282 });
7453a54e 1283 ExprKind::Path(qself, folder.fold_path(path))
c34b1796 1284 }
7453a54e 1285 ExprKind::Break(opt_ident) => ExprKind::Break(opt_ident.map(|label|
e9174d1e
SL
1286 respan(folder.new_span(label.span),
1287 folder.fold_ident(label.node)))
1288 ),
7453a54e 1289 ExprKind::Again(opt_ident) => ExprKind::Again(opt_ident.map(|label|
e9174d1e
SL
1290 respan(folder.new_span(label.span),
1291 folder.fold_ident(label.node)))
1292 ),
7453a54e
SL
1293 ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))),
1294 ExprKind::InlineAsm(InlineAsm {
1a4d82fc
JJ
1295 inputs,
1296 outputs,
1297 asm,
1298 asm_str_style,
1299 clobbers,
1300 volatile,
1301 alignstack,
1302 dialect,
1303 expn_id,
7453a54e 1304 }) => ExprKind::InlineAsm(InlineAsm {
1a4d82fc
JJ
1305 inputs: inputs.move_map(|(c, input)| {
1306 (c, folder.fold_expr(input))
1307 }),
9cc50fc6
SL
1308 outputs: outputs.move_map(|out| {
1309 InlineAsmOutput {
1310 constraint: out.constraint,
1311 expr: folder.fold_expr(out.expr),
1312 is_rw: out.is_rw,
1313 is_indirect: out.is_indirect,
1314 }
1a4d82fc
JJ
1315 }),
1316 asm: asm,
1317 asm_str_style: asm_str_style,
1318 clobbers: clobbers,
1319 volatile: volatile,
1320 alignstack: alignstack,
1321 dialect: dialect,
1322 expn_id: expn_id,
1323 }),
7453a54e
SL
1324 ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)),
1325 ExprKind::Struct(path, fields, maybe_expr) => {
1326 ExprKind::Struct(folder.fold_path(path),
1a4d82fc
JJ
1327 fields.move_map(|x| folder.fold_field(x)),
1328 maybe_expr.map(|x| folder.fold_expr(x)))
1329 },
54a0048b
SL
1330 ExprKind::Paren(ex) => ExprKind::Paren(folder.fold_expr(ex)),
1331 ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
1a4d82fc 1332 },
92a42be0
SL
1333 span: folder.new_span(span),
1334 attrs: attrs.map_thin_attrs(|v| fold_attrs(v, folder)),
223e47cc
LB
1335 }
1336}
1337
92a42be0
SL
1338pub fn noop_fold_opt_expr<T: Folder>(e: P<Expr>, folder: &mut T) -> Option<P<Expr>> {
1339 Some(folder.fold_expr(e))
1340}
1341
1342pub fn noop_fold_exprs<T: Folder>(es: Vec<P<Expr>>, folder: &mut T) -> Vec<P<Expr>> {
1343 es.move_flat_map(|e| folder.fold_opt_expr(e))
1344}
1345
1a4d82fc 1346pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
7453a54e 1347 -> SmallVector<Stmt> {
1a4d82fc
JJ
1348 let span = folder.new_span(span);
1349 match node {
7453a54e 1350 StmtKind::Decl(d, id) => {
1a4d82fc 1351 let id = folder.new_id(id);
7453a54e
SL
1352 folder.fold_decl(d).into_iter().map(|d| Spanned {
1353 node: StmtKind::Decl(d, id),
1a4d82fc 1354 span: span
7453a54e 1355 }).collect()
1a4d82fc 1356 }
7453a54e 1357 StmtKind::Expr(e, id) => {
1a4d82fc 1358 let id = folder.new_id(id);
92a42be0 1359 if let Some(e) = folder.fold_opt_expr(e) {
7453a54e
SL
1360 SmallVector::one(Spanned {
1361 node: StmtKind::Expr(e, id),
92a42be0 1362 span: span
7453a54e 1363 })
92a42be0
SL
1364 } else {
1365 SmallVector::zero()
1366 }
1a4d82fc 1367 }
7453a54e 1368 StmtKind::Semi(e, id) => {
1a4d82fc 1369 let id = folder.new_id(id);
92a42be0 1370 if let Some(e) = folder.fold_opt_expr(e) {
7453a54e
SL
1371 SmallVector::one(Spanned {
1372 node: StmtKind::Semi(e, id),
92a42be0 1373 span: span
7453a54e 1374 })
92a42be0
SL
1375 } else {
1376 SmallVector::zero()
1377 }
1a4d82fc 1378 }
7453a54e
SL
1379 StmtKind::Mac(mac, semi, attrs) => SmallVector::one(Spanned {
1380 node: StmtKind::Mac(mac.map(|m| folder.fold_mac(m)),
1381 semi,
1382 attrs.map_thin_attrs(|v| fold_attrs(v, folder))),
1a4d82fc 1383 span: span
7453a54e 1384 })
1a4d82fc 1385 }
223e47cc
LB
1386}
1387
54a0048b
SL
1388pub fn noop_fold_vis<T: Folder>(vis: Visibility, folder: &mut T) -> Visibility {
1389 match vis {
1390 Visibility::Restricted { path, id } => Visibility::Restricted {
1391 path: path.map(|path| folder.fold_path(path)),
1392 id: folder.new_id(id)
1393 },
1394 _ => vis,
1395 }
1396}
1397
970d7e83 1398#[cfg(test)]
d9579d0f 1399mod tests {
c34b1796 1400 use std::io;
970d7e83
LB
1401 use ast;
1402 use util::parser_testing::{string_to_crate, matches_codepattern};
1403 use parse::token;
1404 use print::pprust;
1a4d82fc 1405 use fold;
970d7e83
LB
1406 use super::*;
1407
970d7e83 1408 // this version doesn't care about getting comments or docstrings in.
1a4d82fc 1409 fn fake_print_crate(s: &mut pprust::State,
c34b1796 1410 krate: &ast::Crate) -> io::Result<()> {
85aaf69f 1411 s.print_mod(&krate.module, &krate.attrs)
970d7e83
LB
1412 }
1413
1414 // change every identifier to "zz"
1a4d82fc
JJ
1415 struct ToZzIdentFolder;
1416
1417 impl Folder for ToZzIdentFolder {
1418 fn fold_ident(&mut self, _: ast::Ident) -> ast::Ident {
1419 token::str_to_ident("zz")
1420 }
1421 fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
1422 fold::noop_fold_mac(mac, self)
1423 }
970d7e83
LB
1424 }
1425
1426 // maybe add to expand.rs...
1a4d82fc 1427 macro_rules! assert_pred {
970d7e83
LB
1428 ($pred:expr, $predname:expr, $a:expr , $b:expr) => (
1429 {
1430 let pred_val = $pred;
1431 let a_val = $a;
1432 let b_val = $b;
85aaf69f 1433 if !(pred_val(&a_val, &b_val)) {
1a4d82fc 1434 panic!("expected args satisfying {}, got {} and {}",
970d7e83
LB
1435 $predname, a_val, b_val);
1436 }
1437 }
1438 )
1a4d82fc 1439 }
970d7e83
LB
1440
1441 // make sure idents get transformed everywhere
1442 #[test] fn ident_transformation () {
1a4d82fc
JJ
1443 let mut zz_fold = ToZzIdentFolder;
1444 let ast = string_to_crate(
1445 "#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
1446 let folded_crate = zz_fold.fold_crate(ast);
1447 assert_pred!(
1448 matches_codepattern,
1449 "matches_codepattern",
1450 pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1451 "#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string());
970d7e83
LB
1452 }
1453
1454 // even inside macro defs....
1455 #[test] fn ident_transformation_in_defs () {
1a4d82fc
JJ
1456 let mut zz_fold = ToZzIdentFolder;
1457 let ast = string_to_crate(
1458 "macro_rules! a {(b $c:expr $(d $e:token)f+ => \
1459 (g $(d $d $e)+))} ".to_string());
1460 let folded_crate = zz_fold.fold_crate(ast);
1461 assert_pred!(
1462 matches_codepattern,
1463 "matches_codepattern",
1464 pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1465 "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
970d7e83
LB
1466 }
1467}