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