]> git.lizzy.rs Git - rust.git/blob - src/librustc_front/fold.rs
f4ea4cb9ea5d6cd139e2590a891c6c97e5da4789
[rust.git] / src / librustc_front / fold.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
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
11 //! A Folder represents an HIR->HIR fold; it accepts a HIR piece,
12 //! and returns a piece of the same type.
13
14 use hir::*;
15 use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
16 use syntax::ast::{MetaWord, MetaList, MetaNameValue};
17 use hir;
18 use syntax::codemap::{respan, Span, Spanned};
19 use syntax::owned_slice::OwnedSlice;
20 use syntax::ptr::P;
21 use syntax::parse::token;
22 use std::ptr;
23 use syntax::util::small_vector::SmallVector;
24
25
26 // This could have a better place to live.
27 pub trait MoveMap<T> {
28     fn move_map<F>(self, f: F) -> Self where F: FnMut(T) -> T;
29 }
30
31 impl<T> MoveMap<T> for Vec<T> {
32     fn move_map<F>(mut self, mut f: F) -> Vec<T>
33         where F: FnMut(T) -> T
34     {
35         for p in &mut self {
36             unsafe {
37                 // FIXME(#5016) this shouldn't need to zero to be safe.
38                 ptr::write(p, f(ptr::read_and_drop(p)));
39             }
40         }
41         self
42     }
43 }
44
45 impl<T> MoveMap<T> for OwnedSlice<T> {
46     fn move_map<F>(self, f: F) -> OwnedSlice<T>
47         where F: FnMut(T) -> T
48     {
49         OwnedSlice::from_vec(self.into_vec().move_map(f))
50     }
51 }
52
53 pub trait Folder : Sized {
54     // Any additions to this trait should happen in form
55     // of a call to a public `noop_*` function that only calls
56     // out to the folder again, not other `noop_*` functions.
57     //
58     // This is a necessary API workaround to the problem of not
59     // being able to call out to the super default method
60     // in an overridden default method.
61
62     fn fold_crate(&mut self, c: Crate) -> Crate {
63         noop_fold_crate(c, self)
64     }
65
66     fn fold_meta_items(&mut self, meta_items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
67         noop_fold_meta_items(meta_items, self)
68     }
69
70     fn fold_meta_item(&mut self, meta_item: P<MetaItem>) -> P<MetaItem> {
71         noop_fold_meta_item(meta_item, self)
72     }
73
74     fn fold_view_path(&mut self, view_path: P<ViewPath>) -> P<ViewPath> {
75         noop_fold_view_path(view_path, self)
76     }
77
78     fn fold_foreign_item(&mut self, ni: P<ForeignItem>) -> P<ForeignItem> {
79         noop_fold_foreign_item(ni, self)
80     }
81
82     fn fold_item(&mut self, i: P<Item>) -> SmallVector<P<Item>> {
83         noop_fold_item(i, self)
84     }
85
86     fn fold_item_simple(&mut self, i: Item) -> Item {
87         noop_fold_item_simple(i, self)
88     }
89
90     fn fold_struct_field(&mut self, sf: StructField) -> StructField {
91         noop_fold_struct_field(sf, self)
92     }
93
94     fn fold_item_underscore(&mut self, i: Item_) -> Item_ {
95         noop_fold_item_underscore(i, self)
96     }
97
98     fn fold_trait_item(&mut self, i: P<TraitItem>) -> SmallVector<P<TraitItem>> {
99         noop_fold_trait_item(i, self)
100     }
101
102     fn fold_impl_item(&mut self, i: P<ImplItem>) -> SmallVector<P<ImplItem>> {
103         noop_fold_impl_item(i, self)
104     }
105
106     fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
107         noop_fold_fn_decl(d, self)
108     }
109
110     fn fold_block(&mut self, b: P<Block>) -> P<Block> {
111         noop_fold_block(b, self)
112     }
113
114     fn fold_stmt(&mut self, s: P<Stmt>) -> SmallVector<P<Stmt>> {
115         s.and_then(|s| noop_fold_stmt(s, self))
116     }
117
118     fn fold_arm(&mut self, a: Arm) -> Arm {
119         noop_fold_arm(a, self)
120     }
121
122     fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
123         noop_fold_pat(p, self)
124     }
125
126     fn fold_decl(&mut self, d: P<Decl>) -> SmallVector<P<Decl>> {
127         noop_fold_decl(d, self)
128     }
129
130     fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
131         e.map(|e| noop_fold_expr(e, self))
132     }
133
134     fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
135         noop_fold_ty(t, self)
136     }
137
138     fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
139         noop_fold_ty_binding(t, self)
140     }
141
142     fn fold_mod(&mut self, m: Mod) -> Mod {
143         noop_fold_mod(m, self)
144     }
145
146     fn fold_foreign_mod(&mut self, nm: ForeignMod) -> ForeignMod {
147         noop_fold_foreign_mod(nm, self)
148     }
149
150     fn fold_variant(&mut self, v: P<Variant>) -> P<Variant> {
151         noop_fold_variant(v, self)
152     }
153
154     fn fold_name(&mut self, n: Name) -> Name {
155         noop_fold_name(n, self)
156     }
157
158     fn fold_ident(&mut self, i: Ident) -> Ident {
159         noop_fold_ident(i, self)
160     }
161
162     fn fold_usize(&mut self, i: usize) -> usize {
163         noop_fold_usize(i, self)
164     }
165
166     fn fold_path(&mut self, p: Path) -> Path {
167         noop_fold_path(p, self)
168     }
169
170     fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
171         noop_fold_path_parameters(p, self)
172     }
173
174     fn fold_angle_bracketed_parameter_data(&mut self,
175                                            p: AngleBracketedParameterData)
176                                            -> AngleBracketedParameterData {
177         noop_fold_angle_bracketed_parameter_data(p, self)
178     }
179
180     fn fold_parenthesized_parameter_data(&mut self,
181                                          p: ParenthesizedParameterData)
182                                          -> ParenthesizedParameterData {
183         noop_fold_parenthesized_parameter_data(p, self)
184     }
185
186     fn fold_local(&mut self, l: P<Local>) -> P<Local> {
187         noop_fold_local(l, self)
188     }
189
190     fn fold_explicit_self(&mut self, es: ExplicitSelf) -> ExplicitSelf {
191         noop_fold_explicit_self(es, self)
192     }
193
194     fn fold_explicit_self_underscore(&mut self, es: ExplicitSelf_) -> ExplicitSelf_ {
195         noop_fold_explicit_self_underscore(es, self)
196     }
197
198     fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
199         noop_fold_lifetime(l, self)
200     }
201
202     fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef {
203         noop_fold_lifetime_def(l, self)
204     }
205
206     fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> {
207         noop_fold_attribute(at, self)
208     }
209
210     fn fold_arg(&mut self, a: Arg) -> Arg {
211         noop_fold_arg(a, self)
212     }
213
214     fn fold_generics(&mut self, generics: Generics) -> Generics {
215         noop_fold_generics(generics, self)
216     }
217
218     fn fold_trait_ref(&mut self, p: TraitRef) -> TraitRef {
219         noop_fold_trait_ref(p, self)
220     }
221
222     fn fold_poly_trait_ref(&mut self, p: PolyTraitRef) -> PolyTraitRef {
223         noop_fold_poly_trait_ref(p, self)
224     }
225
226     fn fold_variant_data(&mut self, vdata: VariantData) -> VariantData {
227         noop_fold_variant_data(vdata, self)
228     }
229
230     fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
231         noop_fold_lifetimes(lts, self)
232     }
233
234     fn fold_lifetime_defs(&mut self, lts: Vec<LifetimeDef>) -> Vec<LifetimeDef> {
235         noop_fold_lifetime_defs(lts, self)
236     }
237
238     fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
239         noop_fold_ty_param(tp, self)
240     }
241
242     fn fold_ty_params(&mut self, tps: OwnedSlice<TyParam>) -> OwnedSlice<TyParam> {
243         noop_fold_ty_params(tps, self)
244     }
245
246     fn fold_opt_lifetime(&mut self, o_lt: Option<Lifetime>) -> Option<Lifetime> {
247         noop_fold_opt_lifetime(o_lt, self)
248     }
249
250     fn fold_opt_bounds(&mut self,
251                        b: Option<OwnedSlice<TyParamBound>>)
252                        -> Option<OwnedSlice<TyParamBound>> {
253         noop_fold_opt_bounds(b, self)
254     }
255
256     fn fold_bounds(&mut self, b: OwnedSlice<TyParamBound>) -> OwnedSlice<TyParamBound> {
257         noop_fold_bounds(b, self)
258     }
259
260     fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound {
261         noop_fold_ty_param_bound(tpb, self)
262     }
263
264     fn fold_mt(&mut self, mt: MutTy) -> MutTy {
265         noop_fold_mt(mt, self)
266     }
267
268     fn fold_field(&mut self, field: Field) -> Field {
269         noop_fold_field(field, self)
270     }
271
272     fn fold_where_clause(&mut self, where_clause: WhereClause) -> WhereClause {
273         noop_fold_where_clause(where_clause, self)
274     }
275
276     fn fold_where_predicate(&mut self, where_predicate: WherePredicate) -> WherePredicate {
277         noop_fold_where_predicate(where_predicate, self)
278     }
279
280     fn new_id(&mut self, i: NodeId) -> NodeId {
281         i
282     }
283
284     fn new_span(&mut self, sp: Span) -> Span {
285         sp
286     }
287 }
288
289 pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>,
290                                        fld: &mut T)
291                                        -> Vec<P<MetaItem>> {
292     meta_items.move_map(|x| fld.fold_meta_item(x))
293 }
294
295 pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
296     view_path.map(|Spanned { node, span }| {
297         Spanned {
298             node: match node {
299                 ViewPathSimple(name, path) => {
300                     ViewPathSimple(name, fld.fold_path(path))
301                 }
302                 ViewPathGlob(path) => {
303                     ViewPathGlob(fld.fold_path(path))
304                 }
305                 ViewPathList(path, path_list_idents) => {
306                     ViewPathList(fld.fold_path(path),
307                                  path_list_idents.move_map(|path_list_ident| {
308                                      Spanned {
309                                          node: match path_list_ident.node {
310                                              PathListIdent { id, name, rename } => PathListIdent {
311                                                  id: fld.new_id(id),
312                                                  name: name,
313                                                  rename: rename,
314                                              },
315                                              PathListMod { id, rename } => PathListMod {
316                                                  id: fld.new_id(id),
317                                                  rename: rename,
318                                              },
319                                          },
320                                          span: fld.new_span(path_list_ident.span),
321                                      }
322                                  }))
323                 }
324             },
325             span: fld.new_span(span),
326         }
327     })
328 }
329
330 pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
331     attrs.into_iter().flat_map(|x| fld.fold_attribute(x)).collect()
332 }
333
334 pub fn noop_fold_arm<T: Folder>(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm {
335     Arm {
336         attrs: fold_attrs(attrs, fld),
337         pats: pats.move_map(|x| fld.fold_pat(x)),
338         guard: guard.map(|x| fld.fold_expr(x)),
339         body: fld.fold_expr(body),
340     }
341 }
342
343 pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
344     d.and_then(|Spanned { node, span }| {
345         match node {
346             DeclLocal(l) => SmallVector::one(P(Spanned {
347                 node: DeclLocal(fld.fold_local(l)),
348                 span: fld.new_span(span),
349             })),
350             DeclItem(it) => fld.fold_item(it)
351                                .into_iter()
352                                .map(|i| {
353                                    P(Spanned {
354                                        node: DeclItem(i),
355                                        span: fld.new_span(span),
356                                    })
357                                })
358                                .collect(),
359         }
360     })
361 }
362
363 pub fn noop_fold_ty_binding<T: Folder>(b: P<TypeBinding>, fld: &mut T) -> P<TypeBinding> {
364     b.map(|TypeBinding { id, name, ty, span }| {
365         TypeBinding {
366             id: fld.new_id(id),
367             name: name,
368             ty: fld.fold_ty(ty),
369             span: fld.new_span(span),
370         }
371     })
372 }
373
374 pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
375     t.map(|Ty { id, node, span }| {
376         Ty {
377             id: fld.new_id(id),
378             node: match node {
379                 TyInfer => node,
380                 TyVec(ty) => TyVec(fld.fold_ty(ty)),
381                 TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
382                 TyRptr(region, mt) => {
383                     TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
384                 }
385                 TyBareFn(f) => {
386                     TyBareFn(f.map(|BareFnTy { lifetimes, unsafety, abi, decl }| {
387                         BareFnTy {
388                             lifetimes: fld.fold_lifetime_defs(lifetimes),
389                             unsafety: unsafety,
390                             abi: abi,
391                             decl: fld.fold_fn_decl(decl),
392                         }
393                     }))
394                 }
395                 TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
396                 TyParen(ty) => TyParen(fld.fold_ty(ty)),
397                 TyPath(qself, path) => {
398                     let qself = qself.map(|QSelf { ty, position }| {
399                         QSelf {
400                             ty: fld.fold_ty(ty),
401                             position: position,
402                         }
403                     });
404                     TyPath(qself, fld.fold_path(path))
405                 }
406                 TyObjectSum(ty, bounds) => {
407                     TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds))
408                 }
409                 TyFixedLengthVec(ty, e) => {
410                     TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
411                 }
412                 TyTypeof(expr) => {
413                     TyTypeof(fld.fold_expr(expr))
414                 }
415                 TyPolyTraitRef(bounds) => {
416                     TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
417                 }
418             },
419             span: fld.new_span(span),
420         }
421     })
422 }
423
424 pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod { abi, items }: ForeignMod,
425                                         fld: &mut T)
426                                         -> ForeignMod {
427     ForeignMod {
428         abi: abi,
429         items: items.move_map(|x| fld.fold_foreign_item(x)),
430     }
431 }
432
433 pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
434     v.map(|Spanned {node: Variant_ {name, attrs, data, disr_expr}, span}| Spanned {
435         node: Variant_ {
436             name: name,
437             attrs: fold_attrs(attrs, fld),
438             data: fld.fold_variant_data(data),
439             disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
440         },
441         span: fld.new_span(span),
442     })
443 }
444
445 pub fn noop_fold_name<T: Folder>(n: Name, _: &mut T) -> Name {
446     n
447 }
448
449 pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
450     i
451 }
452
453 pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
454     i
455 }
456
457 pub fn noop_fold_path<T: Folder>(Path { global, segments, span }: Path, fld: &mut T) -> Path {
458     Path {
459         global: global,
460         segments: segments.move_map(|PathSegment { identifier, parameters }| {
461             PathSegment {
462                 identifier: fld.fold_ident(identifier),
463                 parameters: fld.fold_path_parameters(parameters),
464             }
465         }),
466         span: fld.new_span(span),
467     }
468 }
469
470 pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters,
471                                             fld: &mut T)
472                                             -> PathParameters {
473     match path_parameters {
474         AngleBracketedParameters(data) =>
475             AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)),
476         ParenthesizedParameters(data) =>
477             ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)),
478     }
479 }
480
481 pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
482                                                            fld: &mut T)
483                                                            -> AngleBracketedParameterData {
484     let AngleBracketedParameterData { lifetimes, types, bindings } = data;
485     AngleBracketedParameterData {
486         lifetimes: fld.fold_lifetimes(lifetimes),
487         types: types.move_map(|ty| fld.fold_ty(ty)),
488         bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
489     }
490 }
491
492 pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
493                                                          fld: &mut T)
494                                                          -> ParenthesizedParameterData {
495     let ParenthesizedParameterData { inputs, output, span } = data;
496     ParenthesizedParameterData {
497         inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
498         output: output.map(|ty| fld.fold_ty(ty)),
499         span: fld.new_span(span),
500     }
501 }
502
503 pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
504     l.map(|Local { id, pat, ty, init, span }| {
505         Local {
506             id: fld.new_id(id),
507             ty: ty.map(|t| fld.fold_ty(t)),
508             pat: fld.fold_pat(pat),
509             init: init.map(|e| fld.fold_expr(e)),
510             span: fld.new_span(span),
511         }
512     })
513 }
514
515 pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
516     let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
517     Some(Spanned {
518         node: Attribute_ {
519             id: id,
520             style: style,
521             value: fld.fold_meta_item(value),
522             is_sugared_doc: is_sugared_doc,
523         },
524         span: fld.new_span(span),
525     })
526 }
527
528 pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_,
529                                                      fld: &mut T)
530                                                      -> ExplicitSelf_ {
531     match es {
532         SelfStatic | SelfValue(_) => es,
533         SelfRegion(lifetime, m, name) => {
534             SelfRegion(fld.fold_opt_lifetime(lifetime), m, name)
535         }
536         SelfExplicit(typ, name) => {
537             SelfExplicit(fld.fold_ty(typ), name)
538         }
539     }
540 }
541
542 pub fn noop_fold_explicit_self<T: Folder>(Spanned { span, node }: ExplicitSelf,
543                                           fld: &mut T)
544                                           -> ExplicitSelf {
545     Spanned {
546         node: fld.fold_explicit_self_underscore(node),
547         span: fld.new_span(span),
548     }
549 }
550
551 pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
552     mi.map(|Spanned { node, span }| {
553         Spanned {
554             node: match node {
555                 MetaWord(id) => MetaWord(id),
556                 MetaList(id, mis) => {
557                     MetaList(id, mis.move_map(|e| fld.fold_meta_item(e)))
558                 }
559                 MetaNameValue(id, s) => MetaNameValue(id, s),
560             },
561             span: fld.new_span(span),
562         }
563     })
564 }
565
566 pub fn noop_fold_arg<T: Folder>(Arg { id, pat, ty }: Arg, fld: &mut T) -> Arg {
567     Arg {
568         id: fld.new_id(id),
569         pat: fld.fold_pat(pat),
570         ty: fld.fold_ty(ty),
571     }
572 }
573
574 pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
575     decl.map(|FnDecl { inputs, output, variadic }| {
576         FnDecl {
577             inputs: inputs.move_map(|x| fld.fold_arg(x)),
578             output: match output {
579                 Return(ty) => Return(fld.fold_ty(ty)),
580                 DefaultReturn(span) => DefaultReturn(span),
581                 NoReturn(span) => NoReturn(span),
582             },
583             variadic: variadic,
584         }
585     })
586 }
587
588 pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T) -> TyParamBound
589     where T: Folder
590 {
591     match tpb {
592         TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
593         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
594     }
595 }
596
597 pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
598     let TyParam {id, name, bounds, default, span} = tp;
599     TyParam {
600         id: fld.new_id(id),
601         name: name,
602         bounds: fld.fold_bounds(bounds),
603         default: default.map(|x| fld.fold_ty(x)),
604         span: span,
605     }
606 }
607
608 pub fn noop_fold_ty_params<T: Folder>(tps: OwnedSlice<TyParam>,
609                                       fld: &mut T)
610                                       -> OwnedSlice<TyParam> {
611     tps.move_map(|tp| fld.fold_ty_param(tp))
612 }
613
614 pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
615     Lifetime {
616         id: fld.new_id(l.id),
617         name: l.name,
618         span: fld.new_span(l.span),
619     }
620 }
621
622 pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T) -> LifetimeDef {
623     LifetimeDef {
624         lifetime: fld.fold_lifetime(l.lifetime),
625         bounds: fld.fold_lifetimes(l.bounds),
626     }
627 }
628
629 pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Lifetime> {
630     lts.move_map(|l| fld.fold_lifetime(l))
631 }
632
633 pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T) -> Vec<LifetimeDef> {
634     lts.move_map(|l| fld.fold_lifetime_def(l))
635 }
636
637 pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T) -> Option<Lifetime> {
638     o_lt.map(|lt| fld.fold_lifetime(lt))
639 }
640
641 pub fn noop_fold_generics<T: Folder>(Generics { ty_params, lifetimes, where_clause }: Generics,
642                                      fld: &mut T)
643                                      -> Generics {
644     Generics {
645         ty_params: fld.fold_ty_params(ty_params),
646         lifetimes: fld.fold_lifetime_defs(lifetimes),
647         where_clause: fld.fold_where_clause(where_clause),
648     }
649 }
650
651 pub fn noop_fold_where_clause<T: Folder>(WhereClause { id, predicates }: WhereClause,
652                                          fld: &mut T)
653                                          -> WhereClause {
654     WhereClause {
655         id: fld.new_id(id),
656         predicates: predicates.move_map(|predicate| fld.fold_where_predicate(predicate)),
657     }
658 }
659
660 pub fn noop_fold_where_predicate<T: Folder>(pred: WherePredicate, fld: &mut T) -> WherePredicate {
661     match pred {
662         hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{bound_lifetimes,
663                                                                      bounded_ty,
664                                                                      bounds,
665                                                                      span}) => {
666             hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
667                 bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes),
668                 bounded_ty: fld.fold_ty(bounded_ty),
669                 bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
670                 span: fld.new_span(span),
671             })
672         }
673         hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{lifetime,
674                                                                        bounds,
675                                                                        span}) => {
676             hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
677                 span: fld.new_span(span),
678                 lifetime: fld.fold_lifetime(lifetime),
679                 bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)),
680             })
681         }
682         hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id,
683                                                                path,
684                                                                ty,
685                                                                span}) => {
686             hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
687                 id: fld.new_id(id),
688                 path: fld.fold_path(path),
689                 ty: fld.fold_ty(ty),
690                 span: fld.new_span(span),
691             })
692         }
693     }
694 }
695
696 pub fn noop_fold_variant_data<T: Folder>(vdata: VariantData, fld: &mut T) -> VariantData {
697     match vdata {
698         VariantData::Struct(fields, id) => {
699             VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)), fld.new_id(id))
700         }
701         VariantData::Tuple(fields, id) => {
702             VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)), fld.new_id(id))
703         }
704         VariantData::Unit(id) => VariantData::Unit(fld.new_id(id))
705     }
706 }
707
708 pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
709     let id = fld.new_id(p.ref_id);
710     let TraitRef {
711         path,
712         ref_id: _,
713     } = p;
714     hir::TraitRef {
715         path: fld.fold_path(path),
716         ref_id: id,
717     }
718 }
719
720 pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
721     hir::PolyTraitRef {
722         bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
723         trait_ref: fld.fold_trait_ref(p.trait_ref),
724         span: fld.new_span(p.span),
725     }
726 }
727
728 pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructField {
729     let StructField {node: StructField_ {id, kind, ty, attrs}, span} = f;
730     Spanned {
731         node: StructField_ {
732             id: fld.new_id(id),
733             kind: kind,
734             ty: fld.fold_ty(ty),
735             attrs: fold_attrs(attrs, fld),
736         },
737         span: fld.new_span(span),
738     }
739 }
740
741 pub fn noop_fold_field<T: Folder>(Field { name, expr, span }: Field, folder: &mut T) -> Field {
742     Field {
743         name: respan(folder.new_span(name.span),
744                      folder.fold_name(name.node)),
745         expr: folder.fold_expr(expr),
746         span: folder.new_span(span),
747     }
748 }
749
750 pub fn noop_fold_mt<T: Folder>(MutTy { ty, mutbl }: MutTy, folder: &mut T) -> MutTy {
751     MutTy {
752         ty: folder.fold_ty(ty),
753         mutbl: mutbl,
754     }
755 }
756
757 pub fn noop_fold_opt_bounds<T: Folder>(b: Option<OwnedSlice<TyParamBound>>,
758                                        folder: &mut T)
759                                        -> Option<OwnedSlice<TyParamBound>> {
760     b.map(|bounds| folder.fold_bounds(bounds))
761 }
762
763 fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T) -> TyParamBounds {
764     bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
765 }
766
767 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
768     b.map(|Block { id, stmts, expr, rules, span }| {
769         Block {
770             id: folder.new_id(id),
771             stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
772             expr: expr.map(|x| folder.fold_expr(x)),
773             rules: rules,
774             span: folder.new_span(span),
775         }
776     })
777 }
778
779 pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
780     match i {
781         ItemExternCrate(string) => ItemExternCrate(string),
782         ItemUse(view_path) => {
783             ItemUse(folder.fold_view_path(view_path))
784         }
785         ItemStatic(t, m, e) => {
786             ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
787         }
788         ItemConst(t, e) => {
789             ItemConst(folder.fold_ty(t), folder.fold_expr(e))
790         }
791         ItemFn(decl, unsafety, constness, abi, generics, body) => {
792             ItemFn(folder.fold_fn_decl(decl),
793                    unsafety,
794                    constness,
795                    abi,
796                    folder.fold_generics(generics),
797                    folder.fold_block(body))
798         }
799         ItemMod(m) => ItemMod(folder.fold_mod(m)),
800         ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
801         ItemTy(t, generics) => {
802             ItemTy(folder.fold_ty(t), folder.fold_generics(generics))
803         }
804         ItemEnum(enum_definition, generics) => {
805             ItemEnum(hir::EnumDef {
806                          variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
807                      },
808                      folder.fold_generics(generics))
809         }
810         ItemStruct(struct_def, generics) => {
811             let struct_def = folder.fold_variant_data(struct_def);
812             ItemStruct(struct_def, folder.fold_generics(generics))
813         }
814         ItemDefaultImpl(unsafety, ref trait_ref) => {
815             ItemDefaultImpl(unsafety,
816                             folder.fold_trait_ref((*trait_ref).clone()))
817         }
818         ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
819             let new_impl_items = impl_items.into_iter()
820                                            .flat_map(|item| {
821                                                folder.fold_impl_item(item).into_iter()
822                                            })
823                                            .collect();
824             let ifce = match ifce {
825                 None => None,
826                 Some(ref trait_ref) => {
827                     Some(folder.fold_trait_ref((*trait_ref).clone()))
828                 }
829             };
830             ItemImpl(unsafety,
831                      polarity,
832                      folder.fold_generics(generics),
833                      ifce,
834                      folder.fold_ty(ty),
835                      new_impl_items)
836         }
837         ItemTrait(unsafety, generics, bounds, items) => {
838             let bounds = folder.fold_bounds(bounds);
839             let items = items.into_iter()
840                              .flat_map(|item| folder.fold_trait_item(item).into_iter())
841                              .collect();
842             ItemTrait(unsafety, folder.fold_generics(generics), bounds, items)
843         }
844     }
845 }
846
847 pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>,
848                                        folder: &mut T)
849                                        -> SmallVector<P<TraitItem>> {
850     SmallVector::one(i.map(|TraitItem { id, name, attrs, node, span }| {
851         TraitItem {
852             id: folder.new_id(id),
853             name: folder.fold_name(name),
854             attrs: fold_attrs(attrs, folder),
855             node: match node {
856                 ConstTraitItem(ty, default) => {
857                     ConstTraitItem(folder.fold_ty(ty),
858                                    default.map(|x| folder.fold_expr(x)))
859                 }
860                 MethodTraitItem(sig, body) => {
861                     MethodTraitItem(noop_fold_method_sig(sig, folder),
862                                     body.map(|x| folder.fold_block(x)))
863                 }
864                 TypeTraitItem(bounds, default) => {
865                     TypeTraitItem(folder.fold_bounds(bounds),
866                                   default.map(|x| folder.fold_ty(x)))
867                 }
868             },
869             span: folder.new_span(span),
870         }
871     }))
872 }
873
874 pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T) -> SmallVector<P<ImplItem>> {
875     SmallVector::one(i.map(|ImplItem { id, name, attrs, node, vis, span }| {
876         ImplItem {
877             id: folder.new_id(id),
878             name: folder.fold_name(name),
879             attrs: fold_attrs(attrs, folder),
880             vis: vis,
881             node: match node {
882                 ConstImplItem(ty, expr) => {
883                     ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
884                 }
885                 MethodImplItem(sig, body) => {
886                     MethodImplItem(noop_fold_method_sig(sig, folder),
887                                    folder.fold_block(body))
888                 }
889                 TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty)),
890             },
891             span: folder.new_span(span),
892         }
893     }))
894 }
895
896 pub fn noop_fold_mod<T: Folder>(Mod { inner, items }: Mod, folder: &mut T) -> Mod {
897     Mod {
898         inner: folder.new_span(inner),
899         items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(),
900     }
901 }
902
903 pub fn noop_fold_crate<T: Folder>(Crate { module, attrs, config, span, exported_macros }: Crate,
904                                   folder: &mut T)
905                                   -> Crate {
906     let config = folder.fold_meta_items(config);
907
908     let mut items = folder.fold_item(P(hir::Item {
909                               name: token::special_idents::invalid.name,
910                               attrs: attrs,
911                               id: DUMMY_NODE_ID,
912                               vis: hir::Public,
913                               span: span,
914                               node: hir::ItemMod(module),
915                           }))
916                           .into_iter();
917
918     let (module, attrs, span) = match items.next() {
919         Some(item) => {
920             assert!(items.next().is_none(),
921                     "a crate cannot expand to more than one item");
922             item.and_then(|hir::Item { attrs, span, node, .. }| {
923                 match node {
924                     hir::ItemMod(m) => (m, attrs, span),
925                     _ => panic!("fold converted a module to not a module"),
926                 }
927             })
928         }
929         None => (hir::Mod {
930             inner: span,
931             items: vec![],
932         },
933                  vec![],
934                  span),
935     };
936
937     Crate {
938         module: module,
939         attrs: attrs,
940         config: config,
941         span: span,
942         exported_macros: exported_macros,
943     }
944 }
945
946 // fold one item into possibly many items
947 pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> SmallVector<P<Item>> {
948     SmallVector::one(i.map(|i| folder.fold_item_simple(i)))
949 }
950
951 // fold one item into exactly one item
952 pub fn noop_fold_item_simple<T: Folder>(Item { id, name, attrs, node, vis, span }: Item,
953                                         folder: &mut T)
954                                         -> Item {
955     let id = folder.new_id(id);
956     let node = folder.fold_item_underscore(node);
957     // FIXME: we should update the impl_pretty_name, but it uses pretty printing.
958     // let ident = match node {
959     //     // The node may have changed, recompute the "pretty" impl name.
960     //     ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
961     //         impl_pretty_name(maybe_trait, Some(&**ty))
962     //     }
963     //     _ => ident
964     // };
965
966     Item {
967         id: id,
968         name: folder.fold_name(name),
969         attrs: fold_attrs(attrs, folder),
970         node: node,
971         vis: vis,
972         span: folder.new_span(span),
973     }
974 }
975
976 pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) -> P<ForeignItem> {
977     ni.map(|ForeignItem { id, name, attrs, node, span, vis }| {
978         ForeignItem {
979             id: folder.new_id(id),
980             name: folder.fold_name(name),
981             attrs: fold_attrs(attrs, folder),
982             node: match node {
983                 ForeignItemFn(fdec, generics) => {
984                     ForeignItemFn(folder.fold_fn_decl(fdec),
985                                   folder.fold_generics(generics))
986                 }
987                 ForeignItemStatic(t, m) => {
988                     ForeignItemStatic(folder.fold_ty(t), m)
989                 }
990             },
991             vis: vis,
992             span: folder.new_span(span),
993         }
994     })
995 }
996
997 pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig {
998     MethodSig {
999         generics: folder.fold_generics(sig.generics),
1000         abi: sig.abi,
1001         explicit_self: folder.fold_explicit_self(sig.explicit_self),
1002         unsafety: sig.unsafety,
1003         constness: sig.constness,
1004         decl: folder.fold_fn_decl(sig.decl),
1005     }
1006 }
1007
1008 pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
1009     p.map(|Pat { id, node, span }| {
1010         Pat {
1011             id: folder.new_id(id),
1012             node: match node {
1013                 PatWild => PatWild,
1014                 PatIdent(binding_mode, pth1, sub) => {
1015                     PatIdent(binding_mode,
1016                              Spanned {
1017                                  span: folder.new_span(pth1.span),
1018                                  node: folder.fold_ident(pth1.node),
1019                              },
1020                              sub.map(|x| folder.fold_pat(x)))
1021                 }
1022                 PatLit(e) => PatLit(folder.fold_expr(e)),
1023                 PatEnum(pth, pats) => {
1024                     PatEnum(folder.fold_path(pth),
1025                             pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
1026                 }
1027                 PatQPath(qself, pth) => {
1028                     let qself = QSelf { ty: folder.fold_ty(qself.ty), ..qself };
1029                     PatQPath(qself, folder.fold_path(pth))
1030                 }
1031                 PatStruct(pth, fields, etc) => {
1032                     let pth = folder.fold_path(pth);
1033                     let fs = fields.move_map(|f| {
1034                         Spanned {
1035                             span: folder.new_span(f.span),
1036                             node: hir::FieldPat {
1037                                 name: f.node.name,
1038                                 pat: folder.fold_pat(f.node.pat),
1039                                 is_shorthand: f.node.is_shorthand,
1040                             },
1041                         }
1042                     });
1043                     PatStruct(pth, fs, etc)
1044                 }
1045                 PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
1046                 PatBox(inner) => PatBox(folder.fold_pat(inner)),
1047                 PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
1048                 PatRange(e1, e2) => {
1049                     PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
1050                 }
1051                 PatVec(before, slice, after) => {
1052                     PatVec(before.move_map(|x| folder.fold_pat(x)),
1053                            slice.map(|x| folder.fold_pat(x)),
1054                            after.move_map(|x| folder.fold_pat(x)))
1055                 }
1056             },
1057             span: folder.new_span(span),
1058         }
1059     })
1060 }
1061
1062 pub fn noop_fold_expr<T: Folder>(Expr { id, node, span }: Expr, folder: &mut T) -> Expr {
1063     Expr {
1064         id: folder.new_id(id),
1065         node: match node {
1066             ExprBox(e) => {
1067                 ExprBox(folder.fold_expr(e))
1068             }
1069             ExprVec(exprs) => {
1070                 ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
1071             }
1072             ExprRepeat(expr, count) => {
1073                 ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count))
1074             }
1075             ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))),
1076             ExprCall(f, args) => {
1077                 ExprCall(folder.fold_expr(f),
1078                          args.move_map(|x| folder.fold_expr(x)))
1079             }
1080             ExprMethodCall(name, tps, args) => {
1081                 ExprMethodCall(respan(folder.new_span(name.span),
1082                                       folder.fold_name(name.node)),
1083                                tps.move_map(|x| folder.fold_ty(x)),
1084                                args.move_map(|x| folder.fold_expr(x)))
1085             }
1086             ExprBinary(binop, lhs, rhs) => {
1087                 ExprBinary(binop, folder.fold_expr(lhs), folder.fold_expr(rhs))
1088             }
1089             ExprUnary(binop, ohs) => {
1090                 ExprUnary(binop, folder.fold_expr(ohs))
1091             }
1092             ExprLit(l) => ExprLit(l),
1093             ExprCast(expr, ty) => {
1094                 ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
1095             }
1096             ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
1097             ExprIf(cond, tr, fl) => {
1098                 ExprIf(folder.fold_expr(cond),
1099                        folder.fold_block(tr),
1100                        fl.map(|x| folder.fold_expr(x)))
1101             }
1102             ExprWhile(cond, body, opt_ident) => {
1103                 ExprWhile(folder.fold_expr(cond),
1104                           folder.fold_block(body),
1105                           opt_ident.map(|i| folder.fold_ident(i)))
1106             }
1107             ExprLoop(body, opt_ident) => {
1108                 ExprLoop(folder.fold_block(body),
1109                          opt_ident.map(|i| folder.fold_ident(i)))
1110             }
1111             ExprMatch(expr, arms, source) => {
1112                 ExprMatch(folder.fold_expr(expr),
1113                           arms.move_map(|x| folder.fold_arm(x)),
1114                           source)
1115             }
1116             ExprClosure(capture_clause, decl, body) => {
1117                 ExprClosure(capture_clause,
1118                             folder.fold_fn_decl(decl),
1119                             folder.fold_block(body))
1120             }
1121             ExprBlock(blk) => ExprBlock(folder.fold_block(blk)),
1122             ExprAssign(el, er) => {
1123                 ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
1124             }
1125             ExprAssignOp(op, el, er) => {
1126                 ExprAssignOp(op, folder.fold_expr(el), folder.fold_expr(er))
1127             }
1128             ExprField(el, name) => {
1129                 ExprField(folder.fold_expr(el),
1130                           respan(folder.new_span(name.span),
1131                                  folder.fold_name(name.node)))
1132             }
1133             ExprTupField(el, index) => {
1134                 ExprTupField(folder.fold_expr(el),
1135                              respan(folder.new_span(index.span),
1136                                     folder.fold_usize(index.node)))
1137             }
1138             ExprIndex(el, er) => {
1139                 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
1140             }
1141             ExprRange(e1, e2) => {
1142                 ExprRange(e1.map(|x| folder.fold_expr(x)),
1143                           e2.map(|x| folder.fold_expr(x)))
1144             }
1145             ExprPath(qself, path) => {
1146                 let qself = qself.map(|QSelf { ty, position }| {
1147                     QSelf {
1148                         ty: folder.fold_ty(ty),
1149                         position: position,
1150                     }
1151                 });
1152                 ExprPath(qself, folder.fold_path(path))
1153             }
1154             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|label| {
1155                 respan(folder.new_span(label.span),
1156                        folder.fold_ident(label.node))
1157             })),
1158             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|label| {
1159                 respan(folder.new_span(label.span),
1160                        folder.fold_ident(label.node))
1161             })),
1162             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
1163             ExprInlineAsm(InlineAsm {
1164                 inputs,
1165                 outputs,
1166                 asm,
1167                 asm_str_style,
1168                 clobbers,
1169                 volatile,
1170                 alignstack,
1171                 dialect,
1172                 expn_id,
1173             }) => ExprInlineAsm(InlineAsm {
1174                 inputs: inputs.move_map(|(c, input)| (c, folder.fold_expr(input))),
1175                 outputs: outputs.move_map(|(c, out, is_rw)| (c, folder.fold_expr(out), is_rw)),
1176                 asm: asm,
1177                 asm_str_style: asm_str_style,
1178                 clobbers: clobbers,
1179                 volatile: volatile,
1180                 alignstack: alignstack,
1181                 dialect: dialect,
1182                 expn_id: expn_id,
1183             }),
1184             ExprStruct(path, fields, maybe_expr) => {
1185                 ExprStruct(folder.fold_path(path),
1186                            fields.move_map(|x| folder.fold_field(x)),
1187                            maybe_expr.map(|x| folder.fold_expr(x)))
1188             }
1189         },
1190         span: folder.new_span(span),
1191     }
1192 }
1193
1194 pub fn noop_fold_stmt<T: Folder>(Spanned { node, span }: Stmt,
1195                                  folder: &mut T)
1196                                  -> SmallVector<P<Stmt>> {
1197     let span = folder.new_span(span);
1198     match node {
1199         StmtDecl(d, id) => {
1200             let id = folder.new_id(id);
1201             folder.fold_decl(d)
1202                   .into_iter()
1203                   .map(|d| {
1204                       P(Spanned {
1205                           node: StmtDecl(d, id),
1206                           span: span,
1207                       })
1208                   })
1209                   .collect()
1210         }
1211         StmtExpr(e, id) => {
1212             let id = folder.new_id(id);
1213             SmallVector::one(P(Spanned {
1214                 node: StmtExpr(folder.fold_expr(e), id),
1215                 span: span,
1216             }))
1217         }
1218         StmtSemi(e, id) => {
1219             let id = folder.new_id(id);
1220             SmallVector::one(P(Spanned {
1221                 node: StmtSemi(folder.fold_expr(e), id),
1222                 span: span,
1223             }))
1224         }
1225     }
1226 }