]> git.lizzy.rs Git - rust.git/blob - src/librustc_front/fold.rs
Rustfmting librustc_front (again).
[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 }| {
435         Spanned {
436             node: Variant_ {
437                 name: name,
438                 attrs: fold_attrs(attrs, fld),
439                 data: fld.fold_variant_data(data),
440                 disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
441             },
442             span: fld.new_span(span),
443         }
444     })
445 }
446
447 pub fn noop_fold_name<T: Folder>(n: Name, _: &mut T) -> Name {
448     n
449 }
450
451 pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
452     i
453 }
454
455 pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
456     i
457 }
458
459 pub fn noop_fold_path<T: Folder>(Path { global, segments, span }: Path, fld: &mut T) -> Path {
460     Path {
461         global: global,
462         segments: segments.move_map(|PathSegment { identifier, parameters }| {
463             PathSegment {
464                 identifier: fld.fold_ident(identifier),
465                 parameters: fld.fold_path_parameters(parameters),
466             }
467         }),
468         span: fld.new_span(span),
469     }
470 }
471
472 pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters,
473                                             fld: &mut T)
474                                             -> PathParameters {
475     match path_parameters {
476         AngleBracketedParameters(data) =>
477             AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)),
478         ParenthesizedParameters(data) =>
479             ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)),
480     }
481 }
482
483 pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
484                                                            fld: &mut T)
485                                                            -> AngleBracketedParameterData {
486     let AngleBracketedParameterData { lifetimes, types, bindings } = data;
487     AngleBracketedParameterData {
488         lifetimes: fld.fold_lifetimes(lifetimes),
489         types: types.move_map(|ty| fld.fold_ty(ty)),
490         bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
491     }
492 }
493
494 pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
495                                                          fld: &mut T)
496                                                          -> ParenthesizedParameterData {
497     let ParenthesizedParameterData { inputs, output, span } = data;
498     ParenthesizedParameterData {
499         inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
500         output: output.map(|ty| fld.fold_ty(ty)),
501         span: fld.new_span(span),
502     }
503 }
504
505 pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
506     l.map(|Local { id, pat, ty, init, span }| {
507         Local {
508             id: fld.new_id(id),
509             ty: ty.map(|t| fld.fold_ty(t)),
510             pat: fld.fold_pat(pat),
511             init: init.map(|e| fld.fold_expr(e)),
512             span: fld.new_span(span),
513         }
514     })
515 }
516
517 pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attribute> {
518     let Spanned {node: Attribute_ {id, style, value, is_sugared_doc}, span} = at;
519     Some(Spanned {
520         node: Attribute_ {
521             id: id,
522             style: style,
523             value: fld.fold_meta_item(value),
524             is_sugared_doc: is_sugared_doc,
525         },
526         span: fld.new_span(span),
527     })
528 }
529
530 pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_,
531                                                      fld: &mut T)
532                                                      -> ExplicitSelf_ {
533     match es {
534         SelfStatic | SelfValue(_) => es,
535         SelfRegion(lifetime, m, name) => {
536             SelfRegion(fld.fold_opt_lifetime(lifetime), m, name)
537         }
538         SelfExplicit(typ, name) => {
539             SelfExplicit(fld.fold_ty(typ), name)
540         }
541     }
542 }
543
544 pub fn noop_fold_explicit_self<T: Folder>(Spanned { span, node }: ExplicitSelf,
545                                           fld: &mut T)
546                                           -> ExplicitSelf {
547     Spanned {
548         node: fld.fold_explicit_self_underscore(node),
549         span: fld.new_span(span),
550     }
551 }
552
553 pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
554     mi.map(|Spanned { node, span }| {
555         Spanned {
556             node: match node {
557                 MetaWord(id) => MetaWord(id),
558                 MetaList(id, mis) => {
559                     MetaList(id, mis.move_map(|e| fld.fold_meta_item(e)))
560                 }
561                 MetaNameValue(id, s) => MetaNameValue(id, s),
562             },
563             span: fld.new_span(span),
564         }
565     })
566 }
567
568 pub fn noop_fold_arg<T: Folder>(Arg { id, pat, ty }: Arg, fld: &mut T) -> Arg {
569     Arg {
570         id: fld.new_id(id),
571         pat: fld.fold_pat(pat),
572         ty: fld.fold_ty(ty),
573     }
574 }
575
576 pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
577     decl.map(|FnDecl { inputs, output, variadic }| {
578         FnDecl {
579             inputs: inputs.move_map(|x| fld.fold_arg(x)),
580             output: match output {
581                 Return(ty) => Return(fld.fold_ty(ty)),
582                 DefaultReturn(span) => DefaultReturn(span),
583                 NoReturn(span) => NoReturn(span),
584             },
585             variadic: variadic,
586         }
587     })
588 }
589
590 pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T) -> TyParamBound
591     where T: Folder
592 {
593     match tpb {
594         TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
595         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
596     }
597 }
598
599 pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
600     let TyParam {id, name, bounds, default, span} = tp;
601     TyParam {
602         id: fld.new_id(id),
603         name: name,
604         bounds: fld.fold_bounds(bounds),
605         default: default.map(|x| fld.fold_ty(x)),
606         span: span,
607     }
608 }
609
610 pub fn noop_fold_ty_params<T: Folder>(tps: OwnedSlice<TyParam>,
611                                       fld: &mut T)
612                                       -> OwnedSlice<TyParam> {
613     tps.move_map(|tp| fld.fold_ty_param(tp))
614 }
615
616 pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
617     Lifetime {
618         id: fld.new_id(l.id),
619         name: l.name,
620         span: fld.new_span(l.span),
621     }
622 }
623
624 pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T) -> LifetimeDef {
625     LifetimeDef {
626         lifetime: fld.fold_lifetime(l.lifetime),
627         bounds: fld.fold_lifetimes(l.bounds),
628     }
629 }
630
631 pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Lifetime> {
632     lts.move_map(|l| fld.fold_lifetime(l))
633 }
634
635 pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T) -> Vec<LifetimeDef> {
636     lts.move_map(|l| fld.fold_lifetime_def(l))
637 }
638
639 pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T) -> Option<Lifetime> {
640     o_lt.map(|lt| fld.fold_lifetime(lt))
641 }
642
643 pub fn noop_fold_generics<T: Folder>(Generics { ty_params, lifetimes, where_clause }: Generics,
644                                      fld: &mut T)
645                                      -> Generics {
646     Generics {
647         ty_params: fld.fold_ty_params(ty_params),
648         lifetimes: fld.fold_lifetime_defs(lifetimes),
649         where_clause: fld.fold_where_clause(where_clause),
650     }
651 }
652
653 pub fn noop_fold_where_clause<T: Folder>(WhereClause { id, predicates }: WhereClause,
654                                          fld: &mut T)
655                                          -> WhereClause {
656     WhereClause {
657         id: fld.new_id(id),
658         predicates: predicates.move_map(|predicate| fld.fold_where_predicate(predicate)),
659     }
660 }
661
662 pub fn noop_fold_where_predicate<T: Folder>(pred: WherePredicate, fld: &mut T) -> WherePredicate {
663     match pred {
664         hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{bound_lifetimes,
665                                                                      bounded_ty,
666                                                                      bounds,
667                                                                      span}) => {
668             hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
669                 bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes),
670                 bounded_ty: fld.fold_ty(bounded_ty),
671                 bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
672                 span: fld.new_span(span),
673             })
674         }
675         hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{lifetime,
676                                                                        bounds,
677                                                                        span}) => {
678             hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
679                 span: fld.new_span(span),
680                 lifetime: fld.fold_lifetime(lifetime),
681                 bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)),
682             })
683         }
684         hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id,
685                                                                path,
686                                                                ty,
687                                                                span}) => {
688             hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
689                 id: fld.new_id(id),
690                 path: fld.fold_path(path),
691                 ty: fld.fold_ty(ty),
692                 span: fld.new_span(span),
693             })
694         }
695     }
696 }
697
698 pub fn noop_fold_variant_data<T: Folder>(vdata: VariantData, fld: &mut T) -> VariantData {
699     match vdata {
700         VariantData::Struct(fields, id) => {
701             VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)),
702                                 fld.new_id(id))
703         }
704         VariantData::Tuple(fields, id) => {
705             VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)),
706                                fld.new_id(id))
707         }
708         VariantData::Unit(id) => VariantData::Unit(fld.new_id(id)),
709     }
710 }
711
712 pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
713     let id = fld.new_id(p.ref_id);
714     let TraitRef {
715         path,
716         ref_id: _,
717     } = p;
718     hir::TraitRef {
719         path: fld.fold_path(path),
720         ref_id: id,
721     }
722 }
723
724 pub fn noop_fold_poly_trait_ref<T: Folder>(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef {
725     hir::PolyTraitRef {
726         bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes),
727         trait_ref: fld.fold_trait_ref(p.trait_ref),
728         span: fld.new_span(p.span),
729     }
730 }
731
732 pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructField {
733     let StructField {node: StructField_ {id, kind, ty, attrs}, span} = f;
734     Spanned {
735         node: StructField_ {
736             id: fld.new_id(id),
737             kind: kind,
738             ty: fld.fold_ty(ty),
739             attrs: fold_attrs(attrs, fld),
740         },
741         span: fld.new_span(span),
742     }
743 }
744
745 pub fn noop_fold_field<T: Folder>(Field { name, expr, span }: Field, folder: &mut T) -> Field {
746     Field {
747         name: respan(folder.new_span(name.span), folder.fold_name(name.node)),
748         expr: folder.fold_expr(expr),
749         span: folder.new_span(span),
750     }
751 }
752
753 pub fn noop_fold_mt<T: Folder>(MutTy { ty, mutbl }: MutTy, folder: &mut T) -> MutTy {
754     MutTy {
755         ty: folder.fold_ty(ty),
756         mutbl: mutbl,
757     }
758 }
759
760 pub fn noop_fold_opt_bounds<T: Folder>(b: Option<OwnedSlice<TyParamBound>>,
761                                        folder: &mut T)
762                                        -> Option<OwnedSlice<TyParamBound>> {
763     b.map(|bounds| folder.fold_bounds(bounds))
764 }
765
766 fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T) -> TyParamBounds {
767     bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
768 }
769
770 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
771     b.map(|Block { id, stmts, expr, rules, span }| {
772         Block {
773             id: folder.new_id(id),
774             stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
775             expr: expr.map(|x| folder.fold_expr(x)),
776             rules: rules,
777             span: folder.new_span(span),
778         }
779     })
780 }
781
782 pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
783     match i {
784         ItemExternCrate(string) => ItemExternCrate(string),
785         ItemUse(view_path) => {
786             ItemUse(folder.fold_view_path(view_path))
787         }
788         ItemStatic(t, m, e) => {
789             ItemStatic(folder.fold_ty(t), m, folder.fold_expr(e))
790         }
791         ItemConst(t, e) => {
792             ItemConst(folder.fold_ty(t), folder.fold_expr(e))
793         }
794         ItemFn(decl, unsafety, constness, abi, generics, body) => {
795             ItemFn(folder.fold_fn_decl(decl),
796                    unsafety,
797                    constness,
798                    abi,
799                    folder.fold_generics(generics),
800                    folder.fold_block(body))
801         }
802         ItemMod(m) => ItemMod(folder.fold_mod(m)),
803         ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
804         ItemTy(t, generics) => {
805             ItemTy(folder.fold_ty(t), folder.fold_generics(generics))
806         }
807         ItemEnum(enum_definition, generics) => {
808             ItemEnum(hir::EnumDef {
809                          variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
810                      },
811                      folder.fold_generics(generics))
812         }
813         ItemStruct(struct_def, generics) => {
814             let struct_def = folder.fold_variant_data(struct_def);
815             ItemStruct(struct_def, folder.fold_generics(generics))
816         }
817         ItemDefaultImpl(unsafety, ref trait_ref) => {
818             ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
819         }
820         ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
821             let new_impl_items = impl_items.into_iter()
822                                            .flat_map(|item| {
823                                                folder.fold_impl_item(item).into_iter()
824                                            })
825                                            .collect();
826             let ifce = match ifce {
827                 None => None,
828                 Some(ref trait_ref) => {
829                     Some(folder.fold_trait_ref((*trait_ref).clone()))
830                 }
831             };
832             ItemImpl(unsafety,
833                      polarity,
834                      folder.fold_generics(generics),
835                      ifce,
836                      folder.fold_ty(ty),
837                      new_impl_items)
838         }
839         ItemTrait(unsafety, generics, bounds, items) => {
840             let bounds = folder.fold_bounds(bounds);
841             let items = items.into_iter()
842                              .flat_map(|item| folder.fold_trait_item(item).into_iter())
843                              .collect();
844             ItemTrait(unsafety, folder.fold_generics(generics), bounds, items)
845         }
846     }
847 }
848
849 pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>,
850                                        folder: &mut T)
851                                        -> SmallVector<P<TraitItem>> {
852     SmallVector::one(i.map(|TraitItem { id, name, attrs, node, span }| {
853         TraitItem {
854             id: folder.new_id(id),
855             name: folder.fold_name(name),
856             attrs: fold_attrs(attrs, folder),
857             node: match node {
858                 ConstTraitItem(ty, default) => {
859                     ConstTraitItem(folder.fold_ty(ty), default.map(|x| folder.fold_expr(x)))
860                 }
861                 MethodTraitItem(sig, body) => {
862                     MethodTraitItem(noop_fold_method_sig(sig, folder),
863                                     body.map(|x| folder.fold_block(x)))
864                 }
865                 TypeTraitItem(bounds, default) => {
866                     TypeTraitItem(folder.fold_bounds(bounds),
867                                   default.map(|x| folder.fold_ty(x)))
868                 }
869             },
870             span: folder.new_span(span),
871         }
872     }))
873 }
874
875 pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T) -> SmallVector<P<ImplItem>> {
876     SmallVector::one(i.map(|ImplItem { id, name, attrs, node, vis, span }| {
877         ImplItem {
878             id: folder.new_id(id),
879             name: folder.fold_name(name),
880             attrs: fold_attrs(attrs, folder),
881             vis: vis,
882             node: match node {
883                 ConstImplItem(ty, expr) => {
884                     ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
885                 }
886                 MethodImplItem(sig, body) => {
887                     MethodImplItem(noop_fold_method_sig(sig, folder), 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), folder.fold_generics(generics))
985                 }
986                 ForeignItemStatic(t, m) => {
987                     ForeignItemStatic(folder.fold_ty(t), m)
988                 }
989             },
990             vis: vis,
991             span: folder.new_span(span),
992         }
993     })
994 }
995
996 pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig {
997     MethodSig {
998         generics: folder.fold_generics(sig.generics),
999         abi: sig.abi,
1000         explicit_self: folder.fold_explicit_self(sig.explicit_self),
1001         unsafety: sig.unsafety,
1002         constness: sig.constness,
1003         decl: folder.fold_fn_decl(sig.decl),
1004     }
1005 }
1006
1007 pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
1008     p.map(|Pat { id, node, span }| {
1009         Pat {
1010             id: folder.new_id(id),
1011             node: match node {
1012                 PatWild => PatWild,
1013                 PatIdent(binding_mode, pth1, sub) => {
1014                     PatIdent(binding_mode,
1015                              Spanned {
1016                                  span: folder.new_span(pth1.span),
1017                                  node: folder.fold_ident(pth1.node),
1018                              },
1019                              sub.map(|x| folder.fold_pat(x)))
1020                 }
1021                 PatLit(e) => PatLit(folder.fold_expr(e)),
1022                 PatEnum(pth, pats) => {
1023                     PatEnum(folder.fold_path(pth),
1024                             pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
1025                 }
1026                 PatQPath(qself, pth) => {
1027                     let qself = QSelf { ty: folder.fold_ty(qself.ty), ..qself };
1028                     PatQPath(qself, folder.fold_path(pth))
1029                 }
1030                 PatStruct(pth, fields, etc) => {
1031                     let pth = folder.fold_path(pth);
1032                     let fs = fields.move_map(|f| {
1033                         Spanned {
1034                             span: folder.new_span(f.span),
1035                             node: hir::FieldPat {
1036                                 name: f.node.name,
1037                                 pat: folder.fold_pat(f.node.pat),
1038                                 is_shorthand: f.node.is_shorthand,
1039                             },
1040                         }
1041                     });
1042                     PatStruct(pth, fs, etc)
1043                 }
1044                 PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
1045                 PatBox(inner) => PatBox(folder.fold_pat(inner)),
1046                 PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
1047                 PatRange(e1, e2) => {
1048                     PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
1049                 }
1050                 PatVec(before, slice, after) => {
1051                     PatVec(before.move_map(|x| folder.fold_pat(x)),
1052                            slice.map(|x| folder.fold_pat(x)),
1053                            after.move_map(|x| folder.fold_pat(x)))
1054                 }
1055             },
1056             span: folder.new_span(span),
1057         }
1058     })
1059 }
1060
1061 pub fn noop_fold_expr<T: Folder>(Expr { id, node, span }: Expr, folder: &mut T) -> Expr {
1062     Expr {
1063         id: folder.new_id(id),
1064         node: match node {
1065             ExprBox(e) => {
1066                 ExprBox(folder.fold_expr(e))
1067             }
1068             ExprVec(exprs) => {
1069                 ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
1070             }
1071             ExprRepeat(expr, count) => {
1072                 ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count))
1073             }
1074             ExprTup(elts) => ExprTup(elts.move_map(|x| folder.fold_expr(x))),
1075             ExprCall(f, args) => {
1076                 ExprCall(folder.fold_expr(f), args.move_map(|x| folder.fold_expr(x)))
1077             }
1078             ExprMethodCall(name, tps, args) => {
1079                 ExprMethodCall(respan(folder.new_span(name.span), folder.fold_name(name.node)),
1080                                tps.move_map(|x| folder.fold_ty(x)),
1081                                args.move_map(|x| folder.fold_expr(x)))
1082             }
1083             ExprBinary(binop, lhs, rhs) => {
1084                 ExprBinary(binop, folder.fold_expr(lhs), folder.fold_expr(rhs))
1085             }
1086             ExprUnary(binop, ohs) => {
1087                 ExprUnary(binop, folder.fold_expr(ohs))
1088             }
1089             ExprLit(l) => ExprLit(l),
1090             ExprCast(expr, ty) => {
1091                 ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
1092             }
1093             ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
1094             ExprIf(cond, tr, fl) => {
1095                 ExprIf(folder.fold_expr(cond),
1096                        folder.fold_block(tr),
1097                        fl.map(|x| folder.fold_expr(x)))
1098             }
1099             ExprWhile(cond, body, opt_ident) => {
1100                 ExprWhile(folder.fold_expr(cond),
1101                           folder.fold_block(body),
1102                           opt_ident.map(|i| folder.fold_ident(i)))
1103             }
1104             ExprLoop(body, opt_ident) => {
1105                 ExprLoop(folder.fold_block(body),
1106                          opt_ident.map(|i| folder.fold_ident(i)))
1107             }
1108             ExprMatch(expr, arms, source) => {
1109                 ExprMatch(folder.fold_expr(expr),
1110                           arms.move_map(|x| folder.fold_arm(x)),
1111                           source)
1112             }
1113             ExprClosure(capture_clause, decl, body) => {
1114                 ExprClosure(capture_clause,
1115                             folder.fold_fn_decl(decl),
1116                             folder.fold_block(body))
1117             }
1118             ExprBlock(blk) => ExprBlock(folder.fold_block(blk)),
1119             ExprAssign(el, er) => {
1120                 ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
1121             }
1122             ExprAssignOp(op, el, er) => {
1123                 ExprAssignOp(op, folder.fold_expr(el), folder.fold_expr(er))
1124             }
1125             ExprField(el, name) => {
1126                 ExprField(folder.fold_expr(el),
1127                           respan(folder.new_span(name.span), folder.fold_name(name.node)))
1128             }
1129             ExprTupField(el, index) => {
1130                 ExprTupField(folder.fold_expr(el),
1131                              respan(folder.new_span(index.span), folder.fold_usize(index.node)))
1132             }
1133             ExprIndex(el, er) => {
1134                 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
1135             }
1136             ExprRange(e1, e2) => {
1137                 ExprRange(e1.map(|x| folder.fold_expr(x)),
1138                           e2.map(|x| folder.fold_expr(x)))
1139             }
1140             ExprPath(qself, path) => {
1141                 let qself = qself.map(|QSelf { ty, position }| {
1142                     QSelf {
1143                         ty: folder.fold_ty(ty),
1144                         position: position,
1145                     }
1146                 });
1147                 ExprPath(qself, folder.fold_path(path))
1148             }
1149             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|label| {
1150                 respan(folder.new_span(label.span), folder.fold_ident(label.node))
1151             })),
1152             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|label| {
1153                 respan(folder.new_span(label.span), folder.fold_ident(label.node))
1154             })),
1155             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
1156             ExprInlineAsm(InlineAsm {
1157                 inputs,
1158                 outputs,
1159                 asm,
1160                 asm_str_style,
1161                 clobbers,
1162                 volatile,
1163                 alignstack,
1164                 dialect,
1165                 expn_id,
1166             }) => ExprInlineAsm(InlineAsm {
1167                 inputs: inputs.move_map(|(c, input)| (c, folder.fold_expr(input))),
1168                 outputs: outputs.move_map(|(c, out, is_rw)| (c, folder.fold_expr(out), is_rw)),
1169                 asm: asm,
1170                 asm_str_style: asm_str_style,
1171                 clobbers: clobbers,
1172                 volatile: volatile,
1173                 alignstack: alignstack,
1174                 dialect: dialect,
1175                 expn_id: expn_id,
1176             }),
1177             ExprStruct(path, fields, maybe_expr) => {
1178                 ExprStruct(folder.fold_path(path),
1179                            fields.move_map(|x| folder.fold_field(x)),
1180                            maybe_expr.map(|x| folder.fold_expr(x)))
1181             }
1182         },
1183         span: folder.new_span(span),
1184     }
1185 }
1186
1187 pub fn noop_fold_stmt<T: Folder>(Spanned { node, span }: Stmt,
1188                                  folder: &mut T)
1189                                  -> SmallVector<P<Stmt>> {
1190     let span = folder.new_span(span);
1191     match node {
1192         StmtDecl(d, id) => {
1193             let id = folder.new_id(id);
1194             folder.fold_decl(d)
1195                   .into_iter()
1196                   .map(|d| {
1197                       P(Spanned {
1198                           node: StmtDecl(d, id),
1199                           span: span,
1200                       })
1201                   })
1202                   .collect()
1203         }
1204         StmtExpr(e, id) => {
1205             let id = folder.new_id(id);
1206             SmallVector::one(P(Spanned {
1207                 node: StmtExpr(folder.fold_expr(e), id),
1208                 span: span,
1209             }))
1210         }
1211         StmtSemi(e, id) => {
1212             let id = folder.new_id(id);
1213             SmallVector::one(P(Spanned {
1214                 node: StmtSemi(folder.fold_expr(e), id),
1215                 span: span,
1216             }))
1217         }
1218     }
1219 }