blob: 474ecf1b1dd85254c2b270a87c5de70787052235 [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.
David Tolnay78488252017-01-29 11:22:59 -080019pub trait Folder {
gnzlbg9ae88d82017-01-26 20:45:17 +010020 // 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
David Tolnay78488252017-01-29 11:22:59 -0800172pub fn noop_fold_ident<F: ?Sized + Folder>(_: &mut F, _ident: Ident) -> Ident {
gnzlbg9ae88d82017-01-26 20:45:17 +0100173 _ident
174}
175
David Tolnay78488252017-01-29 11:22:59 -0800176pub fn noop_fold_derive_input<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100177 DeriveInput{ ident,
178 vis,
179 attrs,
180 generics,
181 body }: DeriveInput) -> DeriveInput {
182 use self::Body::*;
183 DeriveInput {
184 ident: folder.fold_ident(ident),
185 vis: noop_fold_vis(folder, vis),
186 attrs: attrs.lift(|a| folder.fold_attribute(a)),
187 generics: folder.fold_generics(generics),
188 body: match body {
189 Enum(variants) => {
190 Enum(variants.lift(move |v| folder.fold_variant(v)))
191 }
192 Struct(variant_data) => Struct(folder.fold_variant_data(variant_data)),
193 },
194 }
195}
196
David Tolnay78488252017-01-29 11:22:59 -0800197pub fn noop_fold_ty<F: ?Sized + Folder>(folder: &mut F, ty: Ty) -> Ty {
gnzlbg9ae88d82017-01-26 20:45:17 +0100198 use self::Ty::*;
199 match ty {
200 Slice(inner) => Slice(inner.lift(|v| folder.fold_ty(v))),
201 Paren(inner) => Paren(inner.lift(|v| folder.fold_ty(v))),
202 Ptr(mutable_type) => {
203 let mutable_type_ = *mutable_type;
204 let MutTy { ty, mutability }: MutTy = mutable_type_;
205 Ptr(Box::new(MutTy {
206 ty: folder.fold_ty(ty),
207 mutability: mutability,
208 }))
209 }
210 Rptr(opt_lifetime, mutable_type) => {
211 let mutable_type_ = *mutable_type;
212 let MutTy { ty, mutability }: MutTy = mutable_type_;
213 Rptr(opt_lifetime.map(|l| folder.fold_lifetime(l)),
214 Box::new(MutTy {
215 ty: folder.fold_ty(ty),
216 mutability: mutability,
217 }))
218 }
219 Never => Never,
220 Infer => Infer,
221 Tup(tuple_element_types) => Tup(tuple_element_types.lift(|x| folder.fold_ty(x))),
222 BareFn(bare_fn) => {
223 let bf_ = *bare_fn;
224 let BareFnTy { unsafety, abi, lifetimes, inputs, output, variadic } = bf_;
225 BareFn(Box::new(BareFnTy {
226 unsafety: unsafety,
227 abi: abi,
228 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
229 inputs: inputs.lift(|v| {
230 BareFnArg {
231 name: v.name.map(|n| folder.fold_ident(n)),
232 ty: folder.fold_ty(v.ty),
233 }
234 }),
235 output: folder.fold_fn_ret_ty(output),
236 variadic: variadic,
237 }))
238 }
239 Path(maybe_qself, path) => {
240 Path(maybe_qself.map(|v| noop_fold_qself(folder, v)),
241 folder.fold_path(path))
242 }
243 Array(inner, len) => {
244 Array({
245 inner.lift(|v| folder.fold_ty(v))
246 },
247 folder.fold_const_expr(len))
248 }
249 TraitObject(bounds) => TraitObject(bounds.lift(|v| folder.fold_ty_param_bound(v))),
250 ImplTrait(bounds) => ImplTrait(bounds.lift(|v| folder.fold_ty_param_bound(v))),
251 Mac(mac) => Mac(folder.fold_mac(mac)),
252 }
253}
254
David Tolnay78488252017-01-29 11:22:59 -0800255fn noop_fold_qself<F: ?Sized + Folder>(folder: &mut F, QSelf { ty, position }: QSelf) -> QSelf {
gnzlbg9ae88d82017-01-26 20:45:17 +0100256 QSelf {
257 ty: Box::new(folder.fold_ty(*(ty))),
258 position: position,
259 }
260}
261
David Tolnay78488252017-01-29 11:22:59 -0800262pub fn noop_fold_generics<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100263 Generics { lifetimes, ty_params, where_clause }: Generics)
264 -> Generics {
265 use self::WherePredicate::*;
266 Generics {
267 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
268 ty_params: ty_params.lift(|ty| {
269 TyParam {
270 attrs: ty.attrs.lift(|a| folder.fold_attribute(a)),
271 ident: folder.fold_ident(ty.ident),
272 bounds: ty.bounds
273 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
274 default: ty.default.map(|v| folder.fold_ty(v)),
275 }
276 }),
277 where_clause: WhereClause {
278 predicates: where_clause.predicates
279 .lift(|p| match p {
280 BoundPredicate(bound_predicate) => {
281 BoundPredicate(WhereBoundPredicate {
282 bound_lifetimes: bound_predicate.bound_lifetimes
283 .lift(|l| folder.fold_lifetime_def(l)),
284 bounded_ty: folder.fold_ty(bound_predicate.bounded_ty),
285 bounds: bound_predicate.bounds
286 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
287 })
288 }
289 RegionPredicate(region_predicate) => {
290 RegionPredicate(WhereRegionPredicate {
291 lifetime: folder.fold_lifetime(region_predicate.lifetime),
292 bounds: region_predicate.bounds
293 .lift(|b| folder.fold_lifetime(b)),
294 })
295 }
296 EqPredicate(eq_predicate) => {
297 EqPredicate(WhereEqPredicate {
298 lhs_ty: folder.fold_ty(eq_predicate.lhs_ty),
299 rhs_ty: folder.fold_ty(eq_predicate.rhs_ty),
300 })
301 }
302 }),
303 },
304 }
305}
306
David Tolnay78488252017-01-29 11:22:59 -0800307pub fn noop_fold_ty_param_bound<F: ?Sized + Folder>(folder: &mut F, bound: TyParamBound) -> TyParamBound {
gnzlbg9ae88d82017-01-26 20:45:17 +0100308 use self::TyParamBound::*;
309 match bound {
310 Trait(ty, modifier) => Trait(folder.fold_poly_trait_ref(ty), modifier),
311 Region(lifetime) => Region(folder.fold_lifetime(lifetime)),
312 }
313}
314
David Tolnay78488252017-01-29 11:22:59 -0800315pub fn noop_fold_poly_trait_ref<F: ?Sized + Folder>(folder: &mut F, trait_ref: PolyTraitRef)
gnzlbg9ae88d82017-01-26 20:45:17 +0100316 -> PolyTraitRef {
317 PolyTraitRef {
318 bound_lifetimes: trait_ref.bound_lifetimes
319 .lift(|bl| folder.fold_lifetime_def(bl)),
320 trait_ref: folder.fold_path(trait_ref.trait_ref),
321 }
322}
323
David Tolnay78488252017-01-29 11:22:59 -0800324pub fn noop_fold_variant_data<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100325 data: VariantData)
326 -> VariantData {
327 use self::VariantData::*;
328 match data {
329 Struct(fields) => Struct(fields.lift(|f| folder.fold_field(f))),
330 Tuple(fields) => Tuple(fields.lift(|f| folder.fold_field(f))),
331 Unit => Unit,
332 }
333}
334
David Tolnay78488252017-01-29 11:22:59 -0800335pub fn noop_fold_field<F: ?Sized + Folder>(folder: &mut F, field: Field) -> Field {
gnzlbg9ae88d82017-01-26 20:45:17 +0100336 Field {
337 ident: field.ident.map(|i| folder.fold_ident(i)),
338 vis: noop_fold_vis(folder, field.vis),
339 attrs: field.attrs.lift(|a| folder.fold_attribute(a)),
340 ty: folder.fold_ty(field.ty),
341 }
342}
343
David Tolnay78488252017-01-29 11:22:59 -0800344pub fn noop_fold_variant<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100345 Variant { ident, attrs, data, discriminant }: Variant)
346 -> Variant {
347 Variant {
348 ident: folder.fold_ident(ident),
349 attrs: attrs.lift(|v| folder.fold_attribute(v)),
350 data: folder.fold_variant_data(data),
351 discriminant: discriminant.map(|ce| folder.fold_const_expr(ce)),
352 }
353}
354
David Tolnay78488252017-01-29 11:22:59 -0800355pub fn noop_fold_lifetime<F: ?Sized + Folder>(folder: &mut F, _lifetime: Lifetime) -> Lifetime {
gnzlbg9ae88d82017-01-26 20:45:17 +0100356 Lifetime { ident: folder.fold_ident(_lifetime.ident) }
357}
358
David Tolnay78488252017-01-29 11:22:59 -0800359pub fn noop_fold_lifetime_def<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100360 LifetimeDef { attrs, lifetime, bounds }: LifetimeDef)
361 -> LifetimeDef {
362 LifetimeDef {
363 attrs: attrs.lift(|x| folder.fold_attribute(x)),
364 lifetime: folder.fold_lifetime(lifetime),
365 bounds: bounds.lift(|l| folder.fold_lifetime(l)),
366 }
367}
368
David Tolnay78488252017-01-29 11:22:59 -0800369pub fn noop_fold_path<F: ?Sized + Folder>(folder: &mut F, Path { global, segments }: Path) -> Path {
gnzlbg9ae88d82017-01-26 20:45:17 +0100370 Path {
371 global: global,
372 segments: segments.lift(|s| folder.fold_path_segment(s)),
373 }
374}
375
David Tolnay78488252017-01-29 11:22:59 -0800376pub fn noop_fold_path_segment<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100377 PathSegment { ident, parameters }: PathSegment)
378 -> PathSegment {
379 PathSegment {
380 ident: folder.fold_ident(ident),
381 parameters: folder.fold_path_parameters(parameters),
382 }
383}
384
David Tolnay78488252017-01-29 11:22:59 -0800385pub fn noop_fold_path_parameters<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100386 path_parameters: PathParameters)
387 -> PathParameters {
388 use self::PathParameters::*;
389 match path_parameters {
390 AngleBracketed(d) => {
391 let AngleBracketedParameterData { lifetimes, types, bindings } = d;
392 AngleBracketed(AngleBracketedParameterData {
393 lifetimes: lifetimes.into_iter().map(|l| folder.fold_lifetime(l)).collect(),
394 types: types.lift(|ty| folder.fold_ty(ty)),
395 bindings: bindings.lift(|tb| folder.fold_assoc_type_binding(tb)),
396 })
397 }
398 Parenthesized(d) => {
399 let ParenthesizedParameterData { inputs, output } = d;
400 Parenthesized(ParenthesizedParameterData {
401 inputs: inputs.lift(|i| folder.fold_ty(i)),
402 output: output.map(|v| folder.fold_ty(v)),
403 })
404 }
405 }
406}
407
David Tolnay78488252017-01-29 11:22:59 -0800408pub fn noop_fold_assoc_type_binding<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100409 TypeBinding { ident, ty }: TypeBinding)
410 -> TypeBinding {
411 TypeBinding {
412 ident: folder.fold_ident(ident),
413 ty: folder.fold_ty(ty),
414 }
415
416}
417
David Tolnay78488252017-01-29 11:22:59 -0800418pub fn noop_fold_attribute<F: ?Sized + Folder>(_: &mut F, _attr: Attribute) -> Attribute {
gnzlbg9ae88d82017-01-26 20:45:17 +0100419 _attr
420}
421
David Tolnay78488252017-01-29 11:22:59 -0800422pub fn noop_fold_fn_ret_ty<F: ?Sized + Folder>(folder: &mut F, ret_ty: FunctionRetTy) -> FunctionRetTy {
gnzlbg9ae88d82017-01-26 20:45:17 +0100423 use self::FunctionRetTy::*;
424 match ret_ty {
425 Default => Default,
426 Ty(ty) => Ty(folder.fold_ty(ty)),
427 }
428}
429
David Tolnay78488252017-01-29 11:22:59 -0800430pub fn noop_fold_const_expr<F: ?Sized + Folder>(folder: &mut F, expr: ConstExpr) -> ConstExpr {
gnzlbg9ae88d82017-01-26 20:45:17 +0100431 use self::ConstExpr::*;
432 match expr {
433 Call(f, args) => {
434 Call(f.lift(|e| folder.fold_const_expr(e)),
435 args.lift(|v| folder.fold_const_expr(v)))
436 }
437 Binary(op, lhs, rhs) => {
438 Binary(op,
439 lhs.lift(|e| folder.fold_const_expr(e)),
440 rhs.lift(|e| folder.fold_const_expr(e)))
441 }
442 Unary(op, e) => Unary(op, e.lift(|e| folder.fold_const_expr(e))),
443 Lit(l) => Lit(folder.fold_lit(l)),
444 Cast(e, ty) => {
445 Cast(e.lift(|e| folder.fold_const_expr(e)),
446 ty.lift(|v| folder.fold_ty(v)))
447 }
448 Path(p) => Path(folder.fold_path(p)),
449 Index(o, i) => {
450 Index(o.lift(|e| folder.fold_const_expr(e)),
451 i.lift(|e| folder.fold_const_expr(e)))
452 }
453 Paren(no_op) => Paren(no_op.lift(|e| folder.fold_const_expr(e))),
454 Other(e) => {
455 #[cfg(feature = "full")] {
456 Other(folder.fold_expr(e))
457 }
458 #[cfg(not(feature = "full"))] {
459 Other(e)
460 }
461 }
462 }
463}
David Tolnay78488252017-01-29 11:22:59 -0800464pub fn noop_fold_lit<F: ?Sized + Folder>(_: &mut F, _lit: Lit) -> Lit {
gnzlbg9ae88d82017-01-26 20:45:17 +0100465 _lit
466}
467
David Tolnay78488252017-01-29 11:22:59 -0800468pub fn noop_fold_tt<F: ?Sized + Folder>(folder: &mut F, tt: TokenTree) -> TokenTree {
gnzlbg9ae88d82017-01-26 20:45:17 +0100469 use self::TokenTree::*;
470 use self::Token::*;
471 match tt {
472 Token(token) => Token(match token {
473 Literal(lit) => Literal(folder.fold_lit(lit)),
474 Ident(ident) => Ident(folder.fold_ident(ident)),
475 Lifetime(ident) => Lifetime(folder.fold_ident(ident)),
476 x => x,
477 }),
478 Delimited(super::Delimited{delim, tts}) => Delimited(super::Delimited{delim: delim, tts: tts.lift(|v| noop_fold_tt(folder, v))}),
479 }
480}
481
David Tolnay78488252017-01-29 11:22:59 -0800482pub fn noop_fold_mac<F: ?Sized + Folder>(folder: &mut F, Mac { path, tts }: Mac) -> Mac {
gnzlbg9ae88d82017-01-26 20:45:17 +0100483 Mac {
484 path: folder.fold_path(path),
485 tts: tts.lift(|tt| noop_fold_tt(folder, tt)),
486 }
487}
488
489#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800490pub fn noop_fold_crate<F: ?Sized + Folder>(folder: &mut F, Crate { shebang, attrs, items }: Crate) -> Crate {
gnzlbg9ae88d82017-01-26 20:45:17 +0100491 Crate {
492 shebang: shebang,
493 attrs: attrs.lift(|a| folder.fold_attribute(a)),
494 items: items.lift(|i| folder.fold_item(i)),
495 }
496
497}
498
499#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800500pub fn noop_fold_block<F: ?Sized + Folder>(folder: &mut F, block: Block) -> Block {
gnzlbg9ae88d82017-01-26 20:45:17 +0100501 Block { stmts: block.stmts.lift(|s| folder.fold_stmt(s)) }
502}
503
David Tolnay78488252017-01-29 11:22:59 -0800504fn noop_fold_vis<F: ?Sized + Folder>(folder: &mut F, vis: Visibility) -> Visibility {
gnzlbg9ae88d82017-01-26 20:45:17 +0100505 use self::Visibility::*;
506 match vis {
507 Crate => Crate,
508 Inherited => Inherited,
509 Public => Public,
510 Restricted(path) => Restricted(path.lift(|p| folder.fold_path(p))),
511 }
512}
513
514#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800515pub fn noop_fold_item<F: ?Sized + Folder>(folder: &mut F, Item { ident, vis, attrs, node }: Item) -> Item {
gnzlbg9ae88d82017-01-26 20:45:17 +0100516 use self::ItemKind::*;
517 Item {
518 ident: folder.fold_ident(ident.clone()),
519 vis: noop_fold_vis(folder, vis),
520 attrs: attrs.lift(|a| folder.fold_attribute(a)),
521 node: match node {
522 ExternCrate(name) => ExternCrate(name.map(|i| folder.fold_ident(i))),
523 Use(view_path) => Use(Box::new(folder.fold_view_path(*view_path))),
524 Static(ty, mutability, expr) => {
525 Static(Box::new(folder.fold_ty(*ty)),
526 mutability,
527 expr.lift(|e| folder.fold_expr(e)))
528 }
529 Const(ty, expr) => {
530 Const(ty.lift(|ty| folder.fold_ty(ty)),
531 expr.lift(|e| folder.fold_expr(e)))
532 }
533 Fn(fn_decl, unsafety, constness, abi, generics, block) => {
534 Fn(fn_decl.lift(|v| folder.fold_fn_decl(v)),
535 unsafety,
536 constness,
537 abi,
538 folder.fold_generics(generics),
539 block.lift(|v| folder.fold_block(v)))
540 }
541 Mod(items) => Mod(items.map(|items| items.lift(|i| folder.fold_item(i)))),
542 ForeignMod(super::ForeignMod { abi, items }) => {
543 ForeignMod(super::ForeignMod {
544 abi: abi,
545 items: items.lift(|foreign_item| folder.fold_foreign_item(foreign_item)),
546 })
547 }
548 Ty(ty, generics) => {
549 Ty(ty.lift(|ty| folder.fold_ty(ty)),
550 folder.fold_generics(generics))
551 }
552 Enum(variants, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800553 Enum(variants.lift(|v| folder.fold_variant(v)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100554 folder.fold_generics(generics))
555 }
556 Struct(variant_data, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800557 Struct(folder.fold_variant_data(variant_data),
gnzlbg9ae88d82017-01-26 20:45:17 +0100558 folder.fold_generics(generics))
559 }
560 Union(variant_data, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800561 Union(folder.fold_variant_data(variant_data),
gnzlbg9ae88d82017-01-26 20:45:17 +0100562 folder.fold_generics(generics))
563 }
564 Trait(unsafety, generics, typbs, trait_items) => {
565 Trait(unsafety,
566 folder.fold_generics(generics),
567 typbs.lift(|typb| folder.fold_ty_param_bound(typb)),
568 trait_items.lift(|ti| folder.fold_trait_item(ti)))
569 }
570 DefaultImpl(unsafety, path) => DefaultImpl(unsafety, folder.fold_path(path)),
571 Impl(unsafety, impl_polarity, generics, path, ty, impl_items) => {
572 Impl(unsafety,
573 impl_polarity,
574 folder.fold_generics(generics),
575 path.map(|p| folder.fold_path(p)),
576 ty.lift(|ty| folder.fold_ty(ty)),
577 impl_items.lift(|i| folder.fold_impl_item(i)))
578 }
579 Mac(mac) => Mac(folder.fold_mac(mac)),
580 },
581 }
582}
583
gnzlbg9ae88d82017-01-26 20:45:17 +0100584#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800585pub fn noop_fold_expr<F: ?Sized + Folder>(folder: &mut F, Expr { node, attrs }: Expr) -> Expr {
gnzlbg9ae88d82017-01-26 20:45:17 +0100586 use self::ExprKind::*;
587 Expr {
588 node: match node {
589 ExprKind::Box(e) => ExprKind::Box(e.lift(|e| folder.fold_expr(e))),
590 InPlace(place, value) => {
591 InPlace(place.lift(|e| folder.fold_expr(e)),
592 value.lift(|e| folder.fold_expr(e)))
593 }
594 Array(array) => Array(array.lift(|e| folder.fold_expr(e))),
595 Call(function, args) => {
596 Call(function.lift(|e| folder.fold_expr(e)),
597 args.lift(|e| folder.fold_expr(e)))
598 }
599 MethodCall(method, tys, args) => {
600 MethodCall(folder.fold_ident(method),
601 tys.lift(|t| folder.fold_ty(t)),
602 args.lift(|e| folder.fold_expr(e)))
603 }
604 Tup(args) => Tup(args.lift(|e| folder.fold_expr(e))),
605 Binary(bop, lhs, rhs) => {
606 Binary(bop,
607 lhs.lift(|e| folder.fold_expr(e)),
608 rhs.lift(|e| folder.fold_expr(e)))
609 }
610 Unary(uop, e) => Unary(uop, e.lift(|e| folder.fold_expr(e))),
611 Lit(lit) => Lit(folder.fold_lit(lit)),
612 Cast(e, ty) => {
613 Cast(e.lift(|e| folder.fold_expr(e)),
614 ty.lift(|t| folder.fold_ty(t)))
615 }
616 Type(e, ty) => {
617 Type(e.lift(|e| folder.fold_expr(e)),
618 ty.lift(|t| folder.fold_ty(t)))
619 }
620 If(e, if_block, else_block) => {
621 If(e.lift(|e| folder.fold_expr(e)),
622 folder.fold_block(if_block),
623 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
624 }
625 IfLet(pat, expr, block, else_block) => {
626 IfLet(pat.lift(|p| folder.fold_pat(p)),
627 expr.lift(|e| folder.fold_expr(e)),
628 folder.fold_block(block),
629 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
630 }
631 While(e, block, label) => {
632 While(e.lift(|e| folder.fold_expr(e)),
633 folder.fold_block(block),
634 label.map(|i| folder.fold_ident(i)))
635 }
636 WhileLet(pat, expr, block, label) => {
637 WhileLet(pat.lift(|p| folder.fold_pat(p)),
638 expr.lift(|e| folder.fold_expr(e)),
639 folder.fold_block(block),
640 label.map(|i| folder.fold_ident(i)))
641 }
642 ForLoop(pat, expr, block, label) => {
643 ForLoop(pat.lift(|p| folder.fold_pat(p)),
644 expr.lift(|e| folder.fold_expr(e)),
645 folder.fold_block(block),
646 label.map(|i| folder.fold_ident(i)))
647 }
648 Loop(block, label) => {
649 Loop(folder.fold_block(block),
650 label.map(|i| folder.fold_ident(i)))
651 }
652 Match(e, arms) => {
653 Match(e.lift(|e| folder.fold_expr(e)),
654 arms.lift(|Arm { attrs, pats, guard, body }: Arm| {
655 Arm {
656 attrs: attrs.lift(|a| folder.fold_attribute(a)),
657 pats: pats.lift(|p| folder.fold_pat(p)),
658 guard: guard.map(|v| v.lift(|e| folder.fold_expr(e))),
659 body: body.lift(|e| folder.fold_expr(e)),
660 }
661 }))
662 }
663 Closure(capture_by, fn_decl, expr) => {
664 Closure(capture_by,
665 fn_decl.lift(|v| folder.fold_fn_decl(v)),
666 expr.lift(|e| folder.fold_expr(e)))
667 }
668 Block(unsafety, block) => Block(unsafety, folder.fold_block(block)),
669 Assign(lhs, rhs) => {
670 Assign(lhs.lift(|e| folder.fold_expr(e)),
671 rhs.lift(|e| folder.fold_expr(e)))
672 }
673 AssignOp(bop, lhs, rhs) => {
674 AssignOp(bop,
675 lhs.lift(|e| folder.fold_expr(e)),
676 rhs.lift(|e| folder.fold_expr(e)))
677 }
678 Field(expr, name) => Field(expr.lift(|e| folder.fold_expr(e)), folder.fold_ident(name)),
679 TupField(expr, index) => TupField(expr.lift(|e| folder.fold_expr(e)), index),
680 Index(expr, index) => {
681 Index(expr.lift(|e| folder.fold_expr(e)),
682 index.lift(|e| folder.fold_expr(e)))
683 }
684 Range(lhs, rhs, limits) => {
685 Range(lhs.map(|v| v.lift(|e| folder.fold_expr(e))),
686 rhs.map(|v| v.lift(|e| folder.fold_expr(e))),
687 limits)
688 }
689 Path(qself, path) => {
690 Path(qself.map(|v| noop_fold_qself(folder, v)),
691 folder.fold_path(path))
692 }
693 AddrOf(mutability, expr) => AddrOf(mutability, expr.lift(|e| folder.fold_expr(e))),
694 Break(label, expr) => {
695 Break(label.map(|i| folder.fold_ident(i)),
696 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
697 }
698 Continue(label) => Continue(label.map(|i| folder.fold_ident(i))),
699 Ret(expr) => Ret(expr.map(|v| v.lift(|e| folder.fold_expr(e)))),
700 ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)),
701 Struct(path, fields, expr) => {
702 Struct(folder.fold_path(path),
703 fields.lift(|FieldValue { ident, expr, is_shorthand, attrs }: FieldValue| {
704 FieldValue {
705 ident: folder.fold_ident(ident),
706 expr: folder.fold_expr(expr),
707 is_shorthand: is_shorthand,
708 attrs: attrs.lift(|v| folder.fold_attribute(v)),
709 }
710 }),
711 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
712 }
713 Repeat(element, number) => {
714 Repeat(element.lift(|e| folder.fold_expr(e)),
715 number.lift(|e| folder.fold_expr(e)))
716 }
717 Paren(expr) => Paren(expr.lift(|e| folder.fold_expr(e))),
718 Try(expr) => Try(expr.lift(|e| folder.fold_expr(e))),
719 },
720 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
721 }
722}
723
gnzlbg9ae88d82017-01-26 20:45:17 +0100724#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800725pub fn noop_fold_foreign_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100726 ForeignItem { ident, attrs, node, vis }: ForeignItem)
727 -> ForeignItem {
728 ForeignItem {
729 ident: folder.fold_ident(ident),
730 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
731 node: match node {
732 ForeignItemKind::Fn(fn_dcl, generics) => {
733 ForeignItemKind::Fn(fn_dcl.lift(|v| folder.fold_fn_decl(v)),
734 folder.fold_generics(generics))
735 }
736 ForeignItemKind::Static(ty, mutability) => {
737 ForeignItemKind::Static(ty.lift(|v| folder.fold_ty(v)), mutability)
738 }
739 },
740 vis: noop_fold_vis(folder, vis),
741 }
742}
743
gnzlbg9ae88d82017-01-26 20:45:17 +0100744#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800745pub fn noop_fold_pat<F: ?Sized + Folder>(folder: &mut F, pat: Pat) -> Pat {
gnzlbg9ae88d82017-01-26 20:45:17 +0100746 use self::Pat::*;
747 match pat {
748 Wild => Wild,
749 Ident(binding_mode, ident, pat) => {
750 Ident(binding_mode,
751 folder.fold_ident(ident),
752 pat.map(|p| p.lift(|p| folder.fold_pat(p))))
753 }
754 Struct(path, field_patterns, dots) => {
755 Struct(folder.fold_path(path),
756 field_patterns.lift(|FieldPat { ident, pat, is_shorthand, attrs }: FieldPat| {
757 FieldPat {
758 ident: folder.fold_ident(ident),
759 pat: pat.lift(|p| folder.fold_pat(p)),
760 is_shorthand: is_shorthand,
761 attrs: attrs.lift(|a| folder.fold_attribute(a)),
762 }
763 }),
764 dots)
765 }
766 TupleStruct(path, pats, len) => {
767 TupleStruct(folder.fold_path(path),
768 pats.lift(|p| folder.fold_pat(p)),
769 len)
770 }
771 Path(qself, path) => {
772 Path(qself.map(|v| noop_fold_qself(folder, v)),
773 folder.fold_path(path))
774 }
775 Tuple(pats, len) => Tuple(pats.lift(|p| folder.fold_pat(p)), len),
776 Box(b) => Box(b.lift(|p| folder.fold_pat(p))),
777 Ref(b, mutability) => Ref(b.lift(|p| folder.fold_pat(p)), mutability),
778 Lit(expr) => Lit(expr.lift(|e| folder.fold_expr(e))),
779 Range(l, r) => {
780 Range(l.lift(|e| folder.fold_expr(e)),
781 r.lift(|e| folder.fold_expr(e)))
782 }
783 Slice(lefts, pat, rights) => {
784 Slice(lefts.lift(|p| folder.fold_pat(p)),
785 pat.map(|v| v.lift(|p| folder.fold_pat(p))),
786 rights.lift(|p| folder.fold_pat(p)))
787 }
788 Mac(mac) => Mac(folder.fold_mac(mac)),
789 }
790}
791
gnzlbg9ae88d82017-01-26 20:45:17 +0100792#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800793pub fn noop_fold_fn_decl<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100794 FnDecl { inputs, output, variadic }: FnDecl)
795 -> FnDecl {
796
797 FnDecl {
798 inputs: inputs.lift(|a| {
799 use self::FnArg::*;
800 match a {
801 SelfRef(lifetime, mutability) => {
802 SelfRef(lifetime.map(|v| folder.fold_lifetime(v)), mutability)
803 }
804 SelfValue(mutability) => SelfValue(mutability),
805 Captured(pat, ty) => Captured(folder.fold_pat(pat), folder.fold_ty(ty)),
806 Ignored(ty) => Ignored(folder.fold_ty(ty)),
807 }
808 }),
809 output: folder.fold_fn_ret_ty(output),
810 variadic: variadic,
811 }
812
813}
814
gnzlbg9ae88d82017-01-26 20:45:17 +0100815#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800816pub fn noop_fold_trait_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100817 TraitItem { ident, attrs, node }: TraitItem)
818 -> TraitItem {
819 use self::TraitItemKind::*;
820 TraitItem {
821 ident: folder.fold_ident(ident),
822 attrs: attrs.lift(|v| folder.fold_attribute(v)),
823 node: match node {
824 Const(ty, expr) => Const(folder.fold_ty(ty), expr.map(|v| folder.fold_expr(v))),
825 Method(sig, block) => {
826 Method(folder.fold_method_sig(sig),
827 block.map(|v| folder.fold_block(v)))
828 }
829 Type(ty_pbs, ty) => {
830 Type(ty_pbs.lift(|v| folder.fold_ty_param_bound(v)),
831 ty.map(|v| folder.fold_ty(v)))
832 }
David Tolnay70925b72017-01-29 11:20:54 -0800833 Macro(mac) => Macro(folder.fold_mac(mac)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100834 },
835 }
836}
837
gnzlbg9ae88d82017-01-26 20:45:17 +0100838#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800839pub fn noop_fold_impl_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100840 ImplItem { ident, vis, defaultness, attrs, node }: ImplItem)
841 -> ImplItem {
842 use self::ImplItemKind::*;
843 ImplItem {
844 ident: folder.fold_ident(ident),
845 vis: noop_fold_vis(folder, vis),
846 defaultness: defaultness,
847 attrs: attrs.lift(|v| folder.fold_attribute(v)),
848 node: match node {
849 Const(ty, expr) => Const(folder.fold_ty(ty), folder.fold_expr(expr)),
850 Method(sig, block) => {
851 Method(folder.fold_method_sig(sig), folder.fold_block(block))
852 }
853 Type(ty) => Type(folder.fold_ty(ty)),
854 Macro(mac) => Macro(folder.fold_mac(mac)),
855 },
856 }
857}
858
gnzlbg9ae88d82017-01-26 20:45:17 +0100859#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800860pub fn noop_fold_method_sig<F: ?Sized + Folder>(folder: &mut F, MethodSig{unsafety, constness, abi, decl, generics}:MethodSig) -> MethodSig {
gnzlbg9ae88d82017-01-26 20:45:17 +0100861 MethodSig {
862 unsafety: unsafety,
863 constness: constness,
864 abi: abi,
865 decl: folder.fold_fn_decl(decl),
866 generics: folder.fold_generics(generics),
867 }
868
869}
870
gnzlbg9ae88d82017-01-26 20:45:17 +0100871#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800872pub fn noop_fold_stmt<F: ?Sized + Folder>(folder: &mut F, stmt: Stmt) -> Stmt {
gnzlbg9ae88d82017-01-26 20:45:17 +0100873 use self::Stmt::*;
874 match stmt {
875 Local(local) => Local(local.lift(|l| folder.fold_local(l))),
876 Item(item) => Item(item.lift(|v| folder.fold_item(v))),
877 Expr(expr) => Expr(expr.lift(|v| folder.fold_expr(v))),
878 Semi(expr) => Semi(expr.lift(|v| folder.fold_expr(v))),
879 Mac(mac_stmt) => {
880 Mac(mac_stmt.lift(|(mac, style, attrs)| {
881 (folder.fold_mac(mac), style, attrs.lift(|a| folder.fold_attribute(a)))
882 }))
883 }
884 }
885
886}
887
gnzlbg9ae88d82017-01-26 20:45:17 +0100888#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800889pub fn noop_fold_local<F: ?Sized + Folder>(folder: &mut F, Local { pat, ty, init, attrs }: Local) -> Local {
gnzlbg9ae88d82017-01-26 20:45:17 +0100890 Local {
891 pat: pat.lift(|v| folder.fold_pat(v)),
892 ty: ty.map(|v| v.lift(|t| folder.fold_ty(t))),
893 init: init.map(|v| v.lift(|e| folder.fold_expr(e))),
894 attrs: attrs.lift(|a| folder.fold_attribute(a)),
895 }
896}
897
898#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800899pub fn noop_fold_view_path<F: ?Sized + Folder>(folder: &mut F, view_path: ViewPath) -> ViewPath {
gnzlbg9ae88d82017-01-26 20:45:17 +0100900 use self::ViewPath::*;
901 match view_path {
902 Simple(path, ident) => Simple(folder.fold_path(path), ident.map(|i| folder.fold_ident(i))),
903 Glob(path) => Glob(folder.fold_path(path)),
904 List(path, items) => {
905 List(folder.fold_path(path),
906 items.lift(|PathListItem { name, rename }: PathListItem| {
907 PathListItem {
908 name: folder.fold_ident(name),
909 rename: rename.map(|i| folder.fold_ident(i)),
910 }
911 }))
912 }
913 }
914}