blob: 1d78bef10eae51d07274cdcc542c0a8fa918d55c [file] [log] [blame]
gnzlbg9ae88d82017-01-26 20:45:17 +01001// Adapted from libsyntax.
2
3//! A Folder represents an AST->AST fold; it accepts an AST piece,
David Tolnay70925b72017-01-29 11:20:54 -08004//! and returns a piece of the same type.
gnzlbg9ae88d82017-01-26 20:45:17 +01005
6use super::*;
7
8/// AST->AST fold.
9///
10/// Each method of the Folder trait is a hook to be potentially overridden. Each
11/// method's default implementation recursively visits the substructure of the
12/// input via the `noop_fold` methods, which perform an "identity fold", that
13/// is, they return the same structure that they are given (for example the
14/// `fold_crate` method by default calls `fold::noop_fold_crate`).
15///
16/// If you want to ensure that your code handles every variant explicitly, you
17/// need to override each method and monitor future changes to `Folder` in case
18/// a new method with a new default implementation gets introduced.
19pub trait Folder: Sized {
20 // Any additions to this trait should happen in form
21 // of a call to a public `noop_*` function that only calls
22 // out to the folder again, not other `noop_*` functions.
23 //
24 // This is a necessary API workaround to the problem of not
25 // being able to call out to the super default method
26 // in an overridden default method.
27
28 fn fold_ident(&mut self, _ident: Ident) -> Ident {
29 noop_fold_ident(self, _ident)
30 }
31 fn fold_derive_input(&mut self, derive_input: DeriveInput) -> DeriveInput {
32 noop_fold_derive_input(self, derive_input)
33 }
34 fn fold_ty(&mut self, ty: Ty) -> Ty {
35 noop_fold_ty(self, ty)
36 }
37 fn fold_generics(&mut self, generics: Generics) -> Generics {
38 noop_fold_generics(self, generics)
39 }
40 fn fold_ty_param_bound(&mut self, bound: TyParamBound) -> TyParamBound {
41 noop_fold_ty_param_bound(self, bound)
42 }
43 fn fold_poly_trait_ref(&mut self, trait_ref: PolyTraitRef) -> PolyTraitRef {
44 noop_fold_poly_trait_ref(self, trait_ref)
45 }
46 fn fold_variant_data(&mut self, data: VariantData) -> VariantData {
47 noop_fold_variant_data(self, data)
48 }
49 fn fold_field(&mut self, field: Field) -> Field {
50 noop_fold_field(self, field)
51 }
52 fn fold_variant(&mut self, variant: Variant) -> Variant {
53 noop_fold_variant(self, variant)
54 }
55 fn fold_lifetime(&mut self, _lifetime: Lifetime) -> Lifetime {
56 noop_fold_lifetime(self, _lifetime)
57 }
58 fn fold_lifetime_def(&mut self, lifetime: LifetimeDef) -> LifetimeDef {
59 noop_fold_lifetime_def(self, lifetime)
60 }
61 fn fold_path(&mut self, path: Path) -> Path {
62 noop_fold_path(self, path)
63 }
64 fn fold_path_segment(&mut self, path_segment: PathSegment) -> PathSegment {
65 noop_fold_path_segment(self, path_segment)
66 }
67 fn fold_path_parameters(&mut self, path_parameters: PathParameters) -> PathParameters {
68 noop_fold_path_parameters(self, path_parameters)
69 }
70 fn fold_assoc_type_binding(&mut self, type_binding: TypeBinding) -> TypeBinding {
71 noop_fold_assoc_type_binding(self, type_binding)
72 }
73 fn fold_attribute(&mut self, _attr: Attribute) -> Attribute {
74 noop_fold_attribute(self, _attr)
75 }
76 fn fold_fn_ret_ty(&mut self, ret_ty: FunctionRetTy) -> FunctionRetTy {
77 noop_fold_fn_ret_ty(self, ret_ty)
78 }
79 fn fold_const_expr(&mut self, expr: ConstExpr) -> ConstExpr {
80 noop_fold_const_expr(self, expr)
81 }
82 fn fold_lit(&mut self, _lit: Lit) -> Lit {
83 noop_fold_lit(self, _lit)
84 }
85
86 fn fold_mac(&mut self, mac: Mac) -> Mac {
87 noop_fold_mac(self, mac)
88 }
89
90 #[cfg(feature = "full")]
91 fn fold_crate(&mut self, _crate: Crate) -> Crate {
92 noop_fold_crate(self, _crate)
93 }
94 #[cfg(feature = "full")]
95 fn fold_item(&mut self, item: Item) -> Item {
96 noop_fold_item(self, item)
97 }
98 #[cfg(feature = "full")]
99 fn fold_expr(&mut self, expr: Expr) -> Expr {
100 noop_fold_expr(self, expr)
101 }
102 #[cfg(feature = "full")]
103 fn fold_foreign_item(&mut self, foreign_item: ForeignItem) -> ForeignItem {
104 noop_fold_foreign_item(self, foreign_item)
105 }
106 #[cfg(feature = "full")]
107 fn fold_pat(&mut self, pat: Pat) -> Pat {
108 noop_fold_pat(self, pat)
109 }
110 #[cfg(feature = "full")]
111 fn fold_fn_decl(&mut self, fn_decl: FnDecl) -> FnDecl {
112 noop_fold_fn_decl(self, fn_decl)
113 }
114 #[cfg(feature = "full")]
115 fn fold_trait_item(&mut self, trait_item: TraitItem) -> TraitItem {
116 noop_fold_trait_item(self, trait_item)
117 }
118 #[cfg(feature = "full")]
119 fn fold_impl_item(&mut self, impl_item: ImplItem) -> ImplItem {
120 noop_fold_impl_item(self, impl_item)
121 }
122 #[cfg(feature = "full")]
123 fn fold_method_sig(&mut self, method_sig: MethodSig) -> MethodSig {
124 noop_fold_method_sig(self, method_sig)
125 }
126 #[cfg(feature = "full")]
127 fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
128 noop_fold_stmt(self, stmt)
129 }
130 #[cfg(feature = "full")]
131 fn fold_block(&mut self, block: Block) -> Block {
132 noop_fold_block(self, block)
133 }
134 #[cfg(feature = "full")]
135 fn fold_local(&mut self, local: Local) -> Local {
136 noop_fold_local(self, local)
137 }
138 #[cfg(feature = "full")]
139 fn fold_view_path(&mut self, view_path: ViewPath) -> ViewPath {
140 noop_fold_view_path(self, view_path)
141 }
142}
143
144trait LiftOnce<T, U> {
145 type Output;
146 fn lift<F>(self, f: F) -> Self::Output where F: FnOnce(T) -> U;
147}
148
149impl<T, U> LiftOnce<T, U> for Box<T> {
150 type Output = Box<U>;
151 fn lift<F>(self, f: F) -> Box<U>
152 where F: FnOnce(T) -> U
153 {
154 Box::new(f(*self))
155 }
156}
157
158trait LiftMut<T, U> {
159 type Output;
160 fn lift<F>(self, f: F) -> Self::Output where F: FnMut(T) -> U;
161}
162
163impl<T, U> LiftMut<T, U> for Vec<T> {
164 type Output = Vec<U>;
165 fn lift<F>(self, f: F) -> Vec<U>
166 where F: FnMut(T) -> U
167 {
168 self.into_iter().map(f).collect()
169 }
170}
171
172
173// -
174pub fn noop_fold_ident<F: Folder>(_: &mut F, _ident: Ident) -> Ident {
175 _ident
176}
177
178// -
179pub fn noop_fold_derive_input<F: Folder>(folder: &mut F,
180 DeriveInput{ ident,
181 vis,
182 attrs,
183 generics,
184 body }: DeriveInput) -> DeriveInput {
185 use self::Body::*;
186 DeriveInput {
187 ident: folder.fold_ident(ident),
188 vis: noop_fold_vis(folder, vis),
189 attrs: attrs.lift(|a| folder.fold_attribute(a)),
190 generics: folder.fold_generics(generics),
191 body: match body {
192 Enum(variants) => {
193 Enum(variants.lift(move |v| folder.fold_variant(v)))
194 }
195 Struct(variant_data) => Struct(folder.fold_variant_data(variant_data)),
196 },
197 }
198}
199
200// -
201pub fn noop_fold_ty<F: Folder>(folder: &mut F, ty: Ty) -> Ty {
202 use self::Ty::*;
203 match ty {
204 Slice(inner) => Slice(inner.lift(|v| folder.fold_ty(v))),
205 Paren(inner) => Paren(inner.lift(|v| folder.fold_ty(v))),
206 Ptr(mutable_type) => {
207 let mutable_type_ = *mutable_type;
208 let MutTy { ty, mutability }: MutTy = mutable_type_;
209 Ptr(Box::new(MutTy {
210 ty: folder.fold_ty(ty),
211 mutability: mutability,
212 }))
213 }
214 Rptr(opt_lifetime, mutable_type) => {
215 let mutable_type_ = *mutable_type;
216 let MutTy { ty, mutability }: MutTy = mutable_type_;
217 Rptr(opt_lifetime.map(|l| folder.fold_lifetime(l)),
218 Box::new(MutTy {
219 ty: folder.fold_ty(ty),
220 mutability: mutability,
221 }))
222 }
223 Never => Never,
224 Infer => Infer,
225 Tup(tuple_element_types) => Tup(tuple_element_types.lift(|x| folder.fold_ty(x))),
226 BareFn(bare_fn) => {
227 let bf_ = *bare_fn;
228 let BareFnTy { unsafety, abi, lifetimes, inputs, output, variadic } = bf_;
229 BareFn(Box::new(BareFnTy {
230 unsafety: unsafety,
231 abi: abi,
232 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
233 inputs: inputs.lift(|v| {
234 BareFnArg {
235 name: v.name.map(|n| folder.fold_ident(n)),
236 ty: folder.fold_ty(v.ty),
237 }
238 }),
239 output: folder.fold_fn_ret_ty(output),
240 variadic: variadic,
241 }))
242 }
243 Path(maybe_qself, path) => {
244 Path(maybe_qself.map(|v| noop_fold_qself(folder, v)),
245 folder.fold_path(path))
246 }
247 Array(inner, len) => {
248 Array({
249 inner.lift(|v| folder.fold_ty(v))
250 },
251 folder.fold_const_expr(len))
252 }
253 TraitObject(bounds) => TraitObject(bounds.lift(|v| folder.fold_ty_param_bound(v))),
254 ImplTrait(bounds) => ImplTrait(bounds.lift(|v| folder.fold_ty_param_bound(v))),
255 Mac(mac) => Mac(folder.fold_mac(mac)),
256 }
257}
258
259fn noop_fold_qself<F: Folder>(folder: &mut F, QSelf { ty, position }: QSelf) -> QSelf {
260 QSelf {
261 ty: Box::new(folder.fold_ty(*(ty))),
262 position: position,
263 }
264}
265
266// -
267pub fn noop_fold_generics<F: Folder>(folder: &mut F,
268 Generics { lifetimes, ty_params, where_clause }: Generics)
269 -> Generics {
270 use self::WherePredicate::*;
271 Generics {
272 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
273 ty_params: ty_params.lift(|ty| {
274 TyParam {
275 attrs: ty.attrs.lift(|a| folder.fold_attribute(a)),
276 ident: folder.fold_ident(ty.ident),
277 bounds: ty.bounds
278 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
279 default: ty.default.map(|v| folder.fold_ty(v)),
280 }
281 }),
282 where_clause: WhereClause {
283 predicates: where_clause.predicates
284 .lift(|p| match p {
285 BoundPredicate(bound_predicate) => {
286 BoundPredicate(WhereBoundPredicate {
287 bound_lifetimes: bound_predicate.bound_lifetimes
288 .lift(|l| folder.fold_lifetime_def(l)),
289 bounded_ty: folder.fold_ty(bound_predicate.bounded_ty),
290 bounds: bound_predicate.bounds
291 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
292 })
293 }
294 RegionPredicate(region_predicate) => {
295 RegionPredicate(WhereRegionPredicate {
296 lifetime: folder.fold_lifetime(region_predicate.lifetime),
297 bounds: region_predicate.bounds
298 .lift(|b| folder.fold_lifetime(b)),
299 })
300 }
301 EqPredicate(eq_predicate) => {
302 EqPredicate(WhereEqPredicate {
303 lhs_ty: folder.fold_ty(eq_predicate.lhs_ty),
304 rhs_ty: folder.fold_ty(eq_predicate.rhs_ty),
305 })
306 }
307 }),
308 },
309 }
310}
311
312// -
313pub fn noop_fold_ty_param_bound<F: Folder>(folder: &mut F, bound: TyParamBound) -> TyParamBound {
314 use self::TyParamBound::*;
315 match bound {
316 Trait(ty, modifier) => Trait(folder.fold_poly_trait_ref(ty), modifier),
317 Region(lifetime) => Region(folder.fold_lifetime(lifetime)),
318 }
319}
320
321// -
322pub fn noop_fold_poly_trait_ref<F: Folder>(folder: &mut F, trait_ref: PolyTraitRef)
323 -> PolyTraitRef {
324 PolyTraitRef {
325 bound_lifetimes: trait_ref.bound_lifetimes
326 .lift(|bl| folder.fold_lifetime_def(bl)),
327 trait_ref: folder.fold_path(trait_ref.trait_ref),
328 }
329}
330
331// -
332pub fn noop_fold_variant_data<F: Folder>(folder: &mut F,
333 data: VariantData)
334 -> VariantData {
335 use self::VariantData::*;
336 match data {
337 Struct(fields) => Struct(fields.lift(|f| folder.fold_field(f))),
338 Tuple(fields) => Tuple(fields.lift(|f| folder.fold_field(f))),
339 Unit => Unit,
340 }
341}
342
343// -
344pub fn noop_fold_field<F: Folder>(folder: &mut F, field: Field) -> Field {
345 Field {
346 ident: field.ident.map(|i| folder.fold_ident(i)),
347 vis: noop_fold_vis(folder, field.vis),
348 attrs: field.attrs.lift(|a| folder.fold_attribute(a)),
349 ty: folder.fold_ty(field.ty),
350 }
351}
352
353// -
354pub fn noop_fold_variant<F: Folder>(folder: &mut F,
355 Variant { ident, attrs, data, discriminant }: Variant)
356 -> Variant {
357 Variant {
358 ident: folder.fold_ident(ident),
359 attrs: attrs.lift(|v| folder.fold_attribute(v)),
360 data: folder.fold_variant_data(data),
361 discriminant: discriminant.map(|ce| folder.fold_const_expr(ce)),
362 }
363}
364
365// -
366pub fn noop_fold_lifetime<F: Folder>(folder: &mut F, _lifetime: Lifetime) -> Lifetime {
367 Lifetime { ident: folder.fold_ident(_lifetime.ident) }
368}
369
370// -
371pub fn noop_fold_lifetime_def<F: Folder>(folder: &mut F,
372 LifetimeDef { attrs, lifetime, bounds }: LifetimeDef)
373 -> LifetimeDef {
374 LifetimeDef {
375 attrs: attrs.lift(|x| folder.fold_attribute(x)),
376 lifetime: folder.fold_lifetime(lifetime),
377 bounds: bounds.lift(|l| folder.fold_lifetime(l)),
378 }
379}
380
381// -
382pub fn noop_fold_path<F: Folder>(folder: &mut F, Path { global, segments }: Path) -> Path {
383 Path {
384 global: global,
385 segments: segments.lift(|s| folder.fold_path_segment(s)),
386 }
387}
388
389// -
390pub fn noop_fold_path_segment<F: Folder>(folder: &mut F,
391 PathSegment { ident, parameters }: PathSegment)
392 -> PathSegment {
393 PathSegment {
394 ident: folder.fold_ident(ident),
395 parameters: folder.fold_path_parameters(parameters),
396 }
397}
398
399// -
400pub fn noop_fold_path_parameters<F: Folder>(folder: &mut F,
401 path_parameters: PathParameters)
402 -> PathParameters {
403 use self::PathParameters::*;
404 match path_parameters {
405 AngleBracketed(d) => {
406 let AngleBracketedParameterData { lifetimes, types, bindings } = d;
407 AngleBracketed(AngleBracketedParameterData {
408 lifetimes: lifetimes.into_iter().map(|l| folder.fold_lifetime(l)).collect(),
409 types: types.lift(|ty| folder.fold_ty(ty)),
410 bindings: bindings.lift(|tb| folder.fold_assoc_type_binding(tb)),
411 })
412 }
413 Parenthesized(d) => {
414 let ParenthesizedParameterData { inputs, output } = d;
415 Parenthesized(ParenthesizedParameterData {
416 inputs: inputs.lift(|i| folder.fold_ty(i)),
417 output: output.map(|v| folder.fold_ty(v)),
418 })
419 }
420 }
421}
422
423// -
424pub fn noop_fold_assoc_type_binding<F: Folder>(folder: &mut F,
425 TypeBinding { ident, ty }: TypeBinding)
426 -> TypeBinding {
427 TypeBinding {
428 ident: folder.fold_ident(ident),
429 ty: folder.fold_ty(ty),
430 }
431
432}
433
434// -
435pub fn noop_fold_attribute<F: Folder>(_: &mut F, _attr: Attribute) -> Attribute {
436 _attr
437}
438
439// -
440pub fn noop_fold_fn_ret_ty<F: Folder>(folder: &mut F, ret_ty: FunctionRetTy) -> FunctionRetTy {
441 use self::FunctionRetTy::*;
442 match ret_ty {
443 Default => Default,
444 Ty(ty) => Ty(folder.fold_ty(ty)),
445 }
446}
447
448
449pub fn noop_fold_const_expr<F: Folder>(folder: &mut F, expr: ConstExpr) -> ConstExpr {
450 use self::ConstExpr::*;
451 match expr {
452 Call(f, args) => {
453 Call(f.lift(|e| folder.fold_const_expr(e)),
454 args.lift(|v| folder.fold_const_expr(v)))
455 }
456 Binary(op, lhs, rhs) => {
457 Binary(op,
458 lhs.lift(|e| folder.fold_const_expr(e)),
459 rhs.lift(|e| folder.fold_const_expr(e)))
460 }
461 Unary(op, e) => Unary(op, e.lift(|e| folder.fold_const_expr(e))),
462 Lit(l) => Lit(folder.fold_lit(l)),
463 Cast(e, ty) => {
464 Cast(e.lift(|e| folder.fold_const_expr(e)),
465 ty.lift(|v| folder.fold_ty(v)))
466 }
467 Path(p) => Path(folder.fold_path(p)),
468 Index(o, i) => {
469 Index(o.lift(|e| folder.fold_const_expr(e)),
470 i.lift(|e| folder.fold_const_expr(e)))
471 }
472 Paren(no_op) => Paren(no_op.lift(|e| folder.fold_const_expr(e))),
473 Other(e) => {
474 #[cfg(feature = "full")] {
475 Other(folder.fold_expr(e))
476 }
477 #[cfg(not(feature = "full"))] {
478 Other(e)
479 }
480 }
481 }
482}
483pub fn noop_fold_lit<F: Folder>(_: &mut F, _lit: Lit) -> Lit {
484 _lit
485}
486
487pub fn noop_fold_tt<F: Folder>(folder: &mut F, tt: TokenTree) -> TokenTree {
488 use self::TokenTree::*;
489 use self::Token::*;
490 match tt {
491 Token(token) => Token(match token {
492 Literal(lit) => Literal(folder.fold_lit(lit)),
493 Ident(ident) => Ident(folder.fold_ident(ident)),
494 Lifetime(ident) => Lifetime(folder.fold_ident(ident)),
495 x => x,
496 }),
497 Delimited(super::Delimited{delim, tts}) => Delimited(super::Delimited{delim: delim, tts: tts.lift(|v| noop_fold_tt(folder, v))}),
498 }
499}
500
501pub fn noop_fold_mac<F: Folder>(folder: &mut F, Mac { path, tts }: Mac) -> Mac {
502 Mac {
503 path: folder.fold_path(path),
504 tts: tts.lift(|tt| noop_fold_tt(folder, tt)),
505 }
506}
507
508#[cfg(feature = "full")]
509pub fn noop_fold_crate<F: Folder>(folder: &mut F, Crate { shebang, attrs, items }: Crate) -> Crate {
510 Crate {
511 shebang: shebang,
512 attrs: attrs.lift(|a| folder.fold_attribute(a)),
513 items: items.lift(|i| folder.fold_item(i)),
514 }
515
516}
517
518#[cfg(feature = "full")]
519pub fn noop_fold_block<F: Folder>(folder: &mut F, block: Block) -> Block {
520 Block { stmts: block.stmts.lift(|s| folder.fold_stmt(s)) }
521}
522
523fn noop_fold_vis<F: Folder>(folder: &mut F, vis: Visibility) -> Visibility {
524 use self::Visibility::*;
525 match vis {
526 Crate => Crate,
527 Inherited => Inherited,
528 Public => Public,
529 Restricted(path) => Restricted(path.lift(|p| folder.fold_path(p))),
530 }
531}
532
533#[cfg(feature = "full")]
534pub fn noop_fold_item<F: Folder>(folder: &mut F, Item { ident, vis, attrs, node }: Item) -> Item {
535 use self::ItemKind::*;
536 Item {
537 ident: folder.fold_ident(ident.clone()),
538 vis: noop_fold_vis(folder, vis),
539 attrs: attrs.lift(|a| folder.fold_attribute(a)),
540 node: match node {
541 ExternCrate(name) => ExternCrate(name.map(|i| folder.fold_ident(i))),
542 Use(view_path) => Use(Box::new(folder.fold_view_path(*view_path))),
543 Static(ty, mutability, expr) => {
544 Static(Box::new(folder.fold_ty(*ty)),
545 mutability,
546 expr.lift(|e| folder.fold_expr(e)))
547 }
548 Const(ty, expr) => {
549 Const(ty.lift(|ty| folder.fold_ty(ty)),
550 expr.lift(|e| folder.fold_expr(e)))
551 }
552 Fn(fn_decl, unsafety, constness, abi, generics, block) => {
553 Fn(fn_decl.lift(|v| folder.fold_fn_decl(v)),
554 unsafety,
555 constness,
556 abi,
557 folder.fold_generics(generics),
558 block.lift(|v| folder.fold_block(v)))
559 }
560 Mod(items) => Mod(items.map(|items| items.lift(|i| folder.fold_item(i)))),
561 ForeignMod(super::ForeignMod { abi, items }) => {
562 ForeignMod(super::ForeignMod {
563 abi: abi,
564 items: items.lift(|foreign_item| folder.fold_foreign_item(foreign_item)),
565 })
566 }
567 Ty(ty, generics) => {
568 Ty(ty.lift(|ty| folder.fold_ty(ty)),
569 folder.fold_generics(generics))
570 }
571 Enum(variants, generics) => {
572 Enum(variants.lift(|v| folder.fold_variant(v, generics.clone())),
573 folder.fold_generics(generics))
574 }
575 Struct(variant_data, generics) => {
576 Struct(folder.fold_variant_data(variant_data, ident, generics.clone()),
577 folder.fold_generics(generics))
578 }
579 Union(variant_data, generics) => {
580 Union(folder.fold_variant_data(variant_data, ident, generics.clone()),
581 folder.fold_generics(generics))
582 }
583 Trait(unsafety, generics, typbs, trait_items) => {
584 Trait(unsafety,
585 folder.fold_generics(generics),
586 typbs.lift(|typb| folder.fold_ty_param_bound(typb)),
587 trait_items.lift(|ti| folder.fold_trait_item(ti)))
588 }
589 DefaultImpl(unsafety, path) => DefaultImpl(unsafety, folder.fold_path(path)),
590 Impl(unsafety, impl_polarity, generics, path, ty, impl_items) => {
591 Impl(unsafety,
592 impl_polarity,
593 folder.fold_generics(generics),
594 path.map(|p| folder.fold_path(p)),
595 ty.lift(|ty| folder.fold_ty(ty)),
596 impl_items.lift(|i| folder.fold_impl_item(i)))
597 }
598 Mac(mac) => Mac(folder.fold_mac(mac)),
599 },
600 }
601}
602
603
604// -
605#[cfg(feature = "full")]
606pub fn noop_fold_expr<F: Folder>(folder: &mut F, Expr { node, attrs }: Expr) -> Expr {
607 use self::ExprKind::*;
608 Expr {
609 node: match node {
610 ExprKind::Box(e) => ExprKind::Box(e.lift(|e| folder.fold_expr(e))),
611 InPlace(place, value) => {
612 InPlace(place.lift(|e| folder.fold_expr(e)),
613 value.lift(|e| folder.fold_expr(e)))
614 }
615 Array(array) => Array(array.lift(|e| folder.fold_expr(e))),
616 Call(function, args) => {
617 Call(function.lift(|e| folder.fold_expr(e)),
618 args.lift(|e| folder.fold_expr(e)))
619 }
620 MethodCall(method, tys, args) => {
621 MethodCall(folder.fold_ident(method),
622 tys.lift(|t| folder.fold_ty(t)),
623 args.lift(|e| folder.fold_expr(e)))
624 }
625 Tup(args) => Tup(args.lift(|e| folder.fold_expr(e))),
626 Binary(bop, lhs, rhs) => {
627 Binary(bop,
628 lhs.lift(|e| folder.fold_expr(e)),
629 rhs.lift(|e| folder.fold_expr(e)))
630 }
631 Unary(uop, e) => Unary(uop, e.lift(|e| folder.fold_expr(e))),
632 Lit(lit) => Lit(folder.fold_lit(lit)),
633 Cast(e, ty) => {
634 Cast(e.lift(|e| folder.fold_expr(e)),
635 ty.lift(|t| folder.fold_ty(t)))
636 }
637 Type(e, ty) => {
638 Type(e.lift(|e| folder.fold_expr(e)),
639 ty.lift(|t| folder.fold_ty(t)))
640 }
641 If(e, if_block, else_block) => {
642 If(e.lift(|e| folder.fold_expr(e)),
643 folder.fold_block(if_block),
644 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
645 }
646 IfLet(pat, expr, block, else_block) => {
647 IfLet(pat.lift(|p| folder.fold_pat(p)),
648 expr.lift(|e| folder.fold_expr(e)),
649 folder.fold_block(block),
650 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
651 }
652 While(e, block, label) => {
653 While(e.lift(|e| folder.fold_expr(e)),
654 folder.fold_block(block),
655 label.map(|i| folder.fold_ident(i)))
656 }
657 WhileLet(pat, expr, block, label) => {
658 WhileLet(pat.lift(|p| folder.fold_pat(p)),
659 expr.lift(|e| folder.fold_expr(e)),
660 folder.fold_block(block),
661 label.map(|i| folder.fold_ident(i)))
662 }
663 ForLoop(pat, expr, block, label) => {
664 ForLoop(pat.lift(|p| folder.fold_pat(p)),
665 expr.lift(|e| folder.fold_expr(e)),
666 folder.fold_block(block),
667 label.map(|i| folder.fold_ident(i)))
668 }
669 Loop(block, label) => {
670 Loop(folder.fold_block(block),
671 label.map(|i| folder.fold_ident(i)))
672 }
673 Match(e, arms) => {
674 Match(e.lift(|e| folder.fold_expr(e)),
675 arms.lift(|Arm { attrs, pats, guard, body }: Arm| {
676 Arm {
677 attrs: attrs.lift(|a| folder.fold_attribute(a)),
678 pats: pats.lift(|p| folder.fold_pat(p)),
679 guard: guard.map(|v| v.lift(|e| folder.fold_expr(e))),
680 body: body.lift(|e| folder.fold_expr(e)),
681 }
682 }))
683 }
684 Closure(capture_by, fn_decl, expr) => {
685 Closure(capture_by,
686 fn_decl.lift(|v| folder.fold_fn_decl(v)),
687 expr.lift(|e| folder.fold_expr(e)))
688 }
689 Block(unsafety, block) => Block(unsafety, folder.fold_block(block)),
690 Assign(lhs, rhs) => {
691 Assign(lhs.lift(|e| folder.fold_expr(e)),
692 rhs.lift(|e| folder.fold_expr(e)))
693 }
694 AssignOp(bop, lhs, rhs) => {
695 AssignOp(bop,
696 lhs.lift(|e| folder.fold_expr(e)),
697 rhs.lift(|e| folder.fold_expr(e)))
698 }
699 Field(expr, name) => Field(expr.lift(|e| folder.fold_expr(e)), folder.fold_ident(name)),
700 TupField(expr, index) => TupField(expr.lift(|e| folder.fold_expr(e)), index),
701 Index(expr, index) => {
702 Index(expr.lift(|e| folder.fold_expr(e)),
703 index.lift(|e| folder.fold_expr(e)))
704 }
705 Range(lhs, rhs, limits) => {
706 Range(lhs.map(|v| v.lift(|e| folder.fold_expr(e))),
707 rhs.map(|v| v.lift(|e| folder.fold_expr(e))),
708 limits)
709 }
710 Path(qself, path) => {
711 Path(qself.map(|v| noop_fold_qself(folder, v)),
712 folder.fold_path(path))
713 }
714 AddrOf(mutability, expr) => AddrOf(mutability, expr.lift(|e| folder.fold_expr(e))),
715 Break(label, expr) => {
716 Break(label.map(|i| folder.fold_ident(i)),
717 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
718 }
719 Continue(label) => Continue(label.map(|i| folder.fold_ident(i))),
720 Ret(expr) => Ret(expr.map(|v| v.lift(|e| folder.fold_expr(e)))),
721 ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)),
722 Struct(path, fields, expr) => {
723 Struct(folder.fold_path(path),
724 fields.lift(|FieldValue { ident, expr, is_shorthand, attrs }: FieldValue| {
725 FieldValue {
726 ident: folder.fold_ident(ident),
727 expr: folder.fold_expr(expr),
728 is_shorthand: is_shorthand,
729 attrs: attrs.lift(|v| folder.fold_attribute(v)),
730 }
731 }),
732 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
733 }
734 Repeat(element, number) => {
735 Repeat(element.lift(|e| folder.fold_expr(e)),
736 number.lift(|e| folder.fold_expr(e)))
737 }
738 Paren(expr) => Paren(expr.lift(|e| folder.fold_expr(e))),
739 Try(expr) => Try(expr.lift(|e| folder.fold_expr(e))),
740 },
741 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
742 }
743}
744
745// -
746#[cfg(feature = "full")]
747pub fn noop_fold_foreign_item<F: Folder>(folder: &mut F,
748 ForeignItem { ident, attrs, node, vis }: ForeignItem)
749 -> ForeignItem {
750 ForeignItem {
751 ident: folder.fold_ident(ident),
752 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
753 node: match node {
754 ForeignItemKind::Fn(fn_dcl, generics) => {
755 ForeignItemKind::Fn(fn_dcl.lift(|v| folder.fold_fn_decl(v)),
756 folder.fold_generics(generics))
757 }
758 ForeignItemKind::Static(ty, mutability) => {
759 ForeignItemKind::Static(ty.lift(|v| folder.fold_ty(v)), mutability)
760 }
761 },
762 vis: noop_fold_vis(folder, vis),
763 }
764}
765
766// -
767#[cfg(feature = "full")]
768pub fn noop_fold_pat<F: Folder>(folder: &mut F, pat: Pat) -> Pat {
769 use self::Pat::*;
770 match pat {
771 Wild => Wild,
772 Ident(binding_mode, ident, pat) => {
773 Ident(binding_mode,
774 folder.fold_ident(ident),
775 pat.map(|p| p.lift(|p| folder.fold_pat(p))))
776 }
777 Struct(path, field_patterns, dots) => {
778 Struct(folder.fold_path(path),
779 field_patterns.lift(|FieldPat { ident, pat, is_shorthand, attrs }: FieldPat| {
780 FieldPat {
781 ident: folder.fold_ident(ident),
782 pat: pat.lift(|p| folder.fold_pat(p)),
783 is_shorthand: is_shorthand,
784 attrs: attrs.lift(|a| folder.fold_attribute(a)),
785 }
786 }),
787 dots)
788 }
789 TupleStruct(path, pats, len) => {
790 TupleStruct(folder.fold_path(path),
791 pats.lift(|p| folder.fold_pat(p)),
792 len)
793 }
794 Path(qself, path) => {
795 Path(qself.map(|v| noop_fold_qself(folder, v)),
796 folder.fold_path(path))
797 }
798 Tuple(pats, len) => Tuple(pats.lift(|p| folder.fold_pat(p)), len),
799 Box(b) => Box(b.lift(|p| folder.fold_pat(p))),
800 Ref(b, mutability) => Ref(b.lift(|p| folder.fold_pat(p)), mutability),
801 Lit(expr) => Lit(expr.lift(|e| folder.fold_expr(e))),
802 Range(l, r) => {
803 Range(l.lift(|e| folder.fold_expr(e)),
804 r.lift(|e| folder.fold_expr(e)))
805 }
806 Slice(lefts, pat, rights) => {
807 Slice(lefts.lift(|p| folder.fold_pat(p)),
808 pat.map(|v| v.lift(|p| folder.fold_pat(p))),
809 rights.lift(|p| folder.fold_pat(p)))
810 }
811 Mac(mac) => Mac(folder.fold_mac(mac)),
812 }
813}
814
815// -
816#[cfg(feature = "full")]
817pub fn noop_fold_fn_decl<F: Folder>(folder: &mut F,
818 FnDecl { inputs, output, variadic }: FnDecl)
819 -> FnDecl {
820
821 FnDecl {
822 inputs: inputs.lift(|a| {
823 use self::FnArg::*;
824 match a {
825 SelfRef(lifetime, mutability) => {
826 SelfRef(lifetime.map(|v| folder.fold_lifetime(v)), mutability)
827 }
828 SelfValue(mutability) => SelfValue(mutability),
829 Captured(pat, ty) => Captured(folder.fold_pat(pat), folder.fold_ty(ty)),
830 Ignored(ty) => Ignored(folder.fold_ty(ty)),
831 }
832 }),
833 output: folder.fold_fn_ret_ty(output),
834 variadic: variadic,
835 }
836
837}
838
839// -
840#[cfg(feature = "full")]
841pub fn noop_fold_trait_item<F: Folder>(folder: &mut F,
842 TraitItem { ident, attrs, node }: TraitItem)
843 -> TraitItem {
844 use self::TraitItemKind::*;
845 TraitItem {
846 ident: folder.fold_ident(ident),
847 attrs: attrs.lift(|v| folder.fold_attribute(v)),
848 node: match node {
849 Const(ty, expr) => Const(folder.fold_ty(ty), expr.map(|v| folder.fold_expr(v))),
850 Method(sig, block) => {
851 Method(folder.fold_method_sig(sig),
852 block.map(|v| folder.fold_block(v)))
853 }
854 Type(ty_pbs, ty) => {
855 Type(ty_pbs.lift(|v| folder.fold_ty_param_bound(v)),
856 ty.map(|v| folder.fold_ty(v)))
857 }
David Tolnay70925b72017-01-29 11:20:54 -0800858 Macro(mac) => Macro(folder.fold_mac(mac)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100859 },
860 }
861}
862
863// -
864#[cfg(feature = "full")]
865pub fn noop_fold_impl_item<F: Folder>(folder: &mut F,
866 ImplItem { ident, vis, defaultness, attrs, node }: ImplItem)
867 -> ImplItem {
868 use self::ImplItemKind::*;
869 ImplItem {
870 ident: folder.fold_ident(ident),
871 vis: noop_fold_vis(folder, vis),
872 defaultness: defaultness,
873 attrs: attrs.lift(|v| folder.fold_attribute(v)),
874 node: match node {
875 Const(ty, expr) => Const(folder.fold_ty(ty), folder.fold_expr(expr)),
876 Method(sig, block) => {
877 Method(folder.fold_method_sig(sig), folder.fold_block(block))
878 }
879 Type(ty) => Type(folder.fold_ty(ty)),
880 Macro(mac) => Macro(folder.fold_mac(mac)),
881 },
882 }
883}
884
885// -
886#[cfg(feature = "full")]
887pub fn noop_fold_method_sig<F: Folder>(folder: &mut F, MethodSig{unsafety, constness, abi, decl, generics}:MethodSig) -> MethodSig {
888 MethodSig {
889 unsafety: unsafety,
890 constness: constness,
891 abi: abi,
892 decl: folder.fold_fn_decl(decl),
893 generics: folder.fold_generics(generics),
894 }
895
896}
897
898// -
899#[cfg(feature = "full")]
900pub fn noop_fold_stmt<F: Folder>(folder: &mut F, stmt: Stmt) -> Stmt {
901 use self::Stmt::*;
902 match stmt {
903 Local(local) => Local(local.lift(|l| folder.fold_local(l))),
904 Item(item) => Item(item.lift(|v| folder.fold_item(v))),
905 Expr(expr) => Expr(expr.lift(|v| folder.fold_expr(v))),
906 Semi(expr) => Semi(expr.lift(|v| folder.fold_expr(v))),
907 Mac(mac_stmt) => {
908 Mac(mac_stmt.lift(|(mac, style, attrs)| {
909 (folder.fold_mac(mac), style, attrs.lift(|a| folder.fold_attribute(a)))
910 }))
911 }
912 }
913
914}
915
916// -
917#[cfg(feature = "full")]
918pub fn noop_fold_local<F: Folder>(folder: &mut F, Local { pat, ty, init, attrs }: Local) -> Local {
919 Local {
920 pat: pat.lift(|v| folder.fold_pat(v)),
921 ty: ty.map(|v| v.lift(|t| folder.fold_ty(t))),
922 init: init.map(|v| v.lift(|e| folder.fold_expr(e))),
923 attrs: attrs.lift(|a| folder.fold_attribute(a)),
924 }
925}
926
927#[cfg(feature = "full")]
928pub fn noop_fold_view_path<F: Folder>(folder: &mut F, view_path: ViewPath) -> ViewPath {
929 use self::ViewPath::*;
930 match view_path {
931 Simple(path, ident) => Simple(folder.fold_path(path), ident.map(|i| folder.fold_ident(i))),
932 Glob(path) => Glob(folder.fold_path(path)),
933 List(path, items) => {
934 List(folder.fold_path(path),
935 items.lift(|PathListItem { name, rename }: PathListItem| {
936 PathListItem {
937 name: folder.fold_ident(name),
938 rename: rename.map(|i| folder.fold_ident(i)),
939 }
940 }))
941 }
942 }
943}