blob: 15c5eb4ea2002d7b03bb4b1a4f66100c4cfc5a0e [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 {
David Tolnay660b03e2017-01-29 11:26:30 -0800189 Enum(variants) => Enum(variants.lift(move |v| folder.fold_variant(v))),
gnzlbg9ae88d82017-01-26 20:45:17 +0100190 Struct(variant_data) => Struct(folder.fold_variant_data(variant_data)),
191 },
192 }
193}
194
David Tolnay78488252017-01-29 11:22:59 -0800195pub fn noop_fold_ty<F: ?Sized + Folder>(folder: &mut F, ty: Ty) -> Ty {
gnzlbg9ae88d82017-01-26 20:45:17 +0100196 use self::Ty::*;
197 match ty {
198 Slice(inner) => Slice(inner.lift(|v| folder.fold_ty(v))),
199 Paren(inner) => Paren(inner.lift(|v| folder.fold_ty(v))),
200 Ptr(mutable_type) => {
201 let mutable_type_ = *mutable_type;
202 let MutTy { ty, mutability }: MutTy = mutable_type_;
203 Ptr(Box::new(MutTy {
204 ty: folder.fold_ty(ty),
205 mutability: mutability,
206 }))
207 }
208 Rptr(opt_lifetime, mutable_type) => {
209 let mutable_type_ = *mutable_type;
210 let MutTy { ty, mutability }: MutTy = mutable_type_;
211 Rptr(opt_lifetime.map(|l| folder.fold_lifetime(l)),
212 Box::new(MutTy {
213 ty: folder.fold_ty(ty),
214 mutability: mutability,
215 }))
216 }
217 Never => Never,
218 Infer => Infer,
219 Tup(tuple_element_types) => Tup(tuple_element_types.lift(|x| folder.fold_ty(x))),
220 BareFn(bare_fn) => {
221 let bf_ = *bare_fn;
222 let BareFnTy { unsafety, abi, lifetimes, inputs, output, variadic } = bf_;
223 BareFn(Box::new(BareFnTy {
224 unsafety: unsafety,
225 abi: abi,
226 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
227 inputs: inputs.lift(|v| {
228 BareFnArg {
229 name: v.name.map(|n| folder.fold_ident(n)),
230 ty: folder.fold_ty(v.ty),
231 }
232 }),
233 output: folder.fold_fn_ret_ty(output),
234 variadic: variadic,
235 }))
236 }
237 Path(maybe_qself, path) => {
238 Path(maybe_qself.map(|v| noop_fold_qself(folder, v)),
239 folder.fold_path(path))
240 }
241 Array(inner, len) => {
242 Array({
243 inner.lift(|v| folder.fold_ty(v))
244 },
245 folder.fold_const_expr(len))
246 }
247 TraitObject(bounds) => TraitObject(bounds.lift(|v| folder.fold_ty_param_bound(v))),
248 ImplTrait(bounds) => ImplTrait(bounds.lift(|v| folder.fold_ty_param_bound(v))),
249 Mac(mac) => Mac(folder.fold_mac(mac)),
250 }
251}
252
David Tolnay78488252017-01-29 11:22:59 -0800253fn noop_fold_qself<F: ?Sized + Folder>(folder: &mut F, QSelf { ty, position }: QSelf) -> QSelf {
gnzlbg9ae88d82017-01-26 20:45:17 +0100254 QSelf {
255 ty: Box::new(folder.fold_ty(*(ty))),
256 position: position,
257 }
258}
259
David Tolnay78488252017-01-29 11:22:59 -0800260pub fn noop_fold_generics<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100261 Generics { lifetimes, ty_params, where_clause }: Generics)
262 -> Generics {
263 use self::WherePredicate::*;
264 Generics {
265 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
266 ty_params: ty_params.lift(|ty| {
267 TyParam {
268 attrs: ty.attrs.lift(|a| folder.fold_attribute(a)),
269 ident: folder.fold_ident(ty.ident),
270 bounds: ty.bounds
271 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
272 default: ty.default.map(|v| folder.fold_ty(v)),
273 }
274 }),
275 where_clause: WhereClause {
276 predicates: where_clause.predicates
277 .lift(|p| match p {
278 BoundPredicate(bound_predicate) => {
279 BoundPredicate(WhereBoundPredicate {
280 bound_lifetimes: bound_predicate.bound_lifetimes
281 .lift(|l| folder.fold_lifetime_def(l)),
282 bounded_ty: folder.fold_ty(bound_predicate.bounded_ty),
283 bounds: bound_predicate.bounds
284 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
285 })
286 }
287 RegionPredicate(region_predicate) => {
288 RegionPredicate(WhereRegionPredicate {
289 lifetime: folder.fold_lifetime(region_predicate.lifetime),
290 bounds: region_predicate.bounds
291 .lift(|b| folder.fold_lifetime(b)),
292 })
293 }
294 EqPredicate(eq_predicate) => {
295 EqPredicate(WhereEqPredicate {
296 lhs_ty: folder.fold_ty(eq_predicate.lhs_ty),
297 rhs_ty: folder.fold_ty(eq_predicate.rhs_ty),
298 })
299 }
300 }),
301 },
302 }
303}
304
David Tolnay660b03e2017-01-29 11:26:30 -0800305pub fn noop_fold_ty_param_bound<F: ?Sized + Folder>(folder: &mut F,
306 bound: TyParamBound)
307 -> 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 Tolnay660b03e2017-01-29 11:26:30 -0800315pub fn noop_fold_poly_trait_ref<F: ?Sized + Folder>(folder: &mut F,
316 trait_ref: PolyTraitRef)
317 -> PolyTraitRef {
gnzlbg9ae88d82017-01-26 20:45:17 +0100318 PolyTraitRef {
319 bound_lifetimes: trait_ref.bound_lifetimes
320 .lift(|bl| folder.fold_lifetime_def(bl)),
321 trait_ref: folder.fold_path(trait_ref.trait_ref),
322 }
323}
324
David Tolnay78488252017-01-29 11:22:59 -0800325pub fn noop_fold_variant_data<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800326 data: VariantData)
327 -> VariantData {
gnzlbg9ae88d82017-01-26 20:45:17 +0100328 use self::VariantData::*;
329 match data {
330 Struct(fields) => Struct(fields.lift(|f| folder.fold_field(f))),
331 Tuple(fields) => Tuple(fields.lift(|f| folder.fold_field(f))),
332 Unit => Unit,
333 }
334}
335
David Tolnay78488252017-01-29 11:22:59 -0800336pub fn noop_fold_field<F: ?Sized + Folder>(folder: &mut F, field: Field) -> Field {
gnzlbg9ae88d82017-01-26 20:45:17 +0100337 Field {
338 ident: field.ident.map(|i| folder.fold_ident(i)),
339 vis: noop_fold_vis(folder, field.vis),
340 attrs: field.attrs.lift(|a| folder.fold_attribute(a)),
341 ty: folder.fold_ty(field.ty),
342 }
343}
344
David Tolnay78488252017-01-29 11:22:59 -0800345pub fn noop_fold_variant<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100346 Variant { ident, attrs, data, discriminant }: Variant)
347 -> Variant {
348 Variant {
349 ident: folder.fold_ident(ident),
350 attrs: attrs.lift(|v| folder.fold_attribute(v)),
351 data: folder.fold_variant_data(data),
352 discriminant: discriminant.map(|ce| folder.fold_const_expr(ce)),
353 }
354}
355
David Tolnay78488252017-01-29 11:22:59 -0800356pub fn noop_fold_lifetime<F: ?Sized + Folder>(folder: &mut F, _lifetime: Lifetime) -> Lifetime {
gnzlbg9ae88d82017-01-26 20:45:17 +0100357 Lifetime { ident: folder.fold_ident(_lifetime.ident) }
358}
359
David Tolnay78488252017-01-29 11:22:59 -0800360pub fn noop_fold_lifetime_def<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100361 LifetimeDef { attrs, lifetime, bounds }: LifetimeDef)
362 -> LifetimeDef {
363 LifetimeDef {
364 attrs: attrs.lift(|x| folder.fold_attribute(x)),
365 lifetime: folder.fold_lifetime(lifetime),
366 bounds: bounds.lift(|l| folder.fold_lifetime(l)),
367 }
368}
369
David Tolnay78488252017-01-29 11:22:59 -0800370pub fn noop_fold_path<F: ?Sized + Folder>(folder: &mut F, Path { global, segments }: Path) -> Path {
gnzlbg9ae88d82017-01-26 20:45:17 +0100371 Path {
372 global: global,
373 segments: segments.lift(|s| folder.fold_path_segment(s)),
374 }
375}
376
David Tolnay78488252017-01-29 11:22:59 -0800377pub fn noop_fold_path_segment<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800378 PathSegment { ident, parameters }: PathSegment)
379 -> PathSegment {
gnzlbg9ae88d82017-01-26 20:45:17 +0100380 PathSegment {
381 ident: folder.fold_ident(ident),
382 parameters: folder.fold_path_parameters(parameters),
383 }
384}
385
David Tolnay78488252017-01-29 11:22:59 -0800386pub fn noop_fold_path_parameters<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800387 path_parameters: PathParameters)
388 -> PathParameters {
gnzlbg9ae88d82017-01-26 20:45:17 +0100389 use self::PathParameters::*;
390 match path_parameters {
391 AngleBracketed(d) => {
392 let AngleBracketedParameterData { lifetimes, types, bindings } = d;
393 AngleBracketed(AngleBracketedParameterData {
394 lifetimes: lifetimes.into_iter().map(|l| folder.fold_lifetime(l)).collect(),
395 types: types.lift(|ty| folder.fold_ty(ty)),
396 bindings: bindings.lift(|tb| folder.fold_assoc_type_binding(tb)),
397 })
398 }
399 Parenthesized(d) => {
400 let ParenthesizedParameterData { inputs, output } = d;
401 Parenthesized(ParenthesizedParameterData {
402 inputs: inputs.lift(|i| folder.fold_ty(i)),
403 output: output.map(|v| folder.fold_ty(v)),
404 })
405 }
406 }
407}
408
David Tolnay78488252017-01-29 11:22:59 -0800409pub fn noop_fold_assoc_type_binding<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800410 TypeBinding { ident, ty }: TypeBinding)
411 -> TypeBinding {
gnzlbg9ae88d82017-01-26 20:45:17 +0100412 TypeBinding {
413 ident: folder.fold_ident(ident),
414 ty: folder.fold_ty(ty),
415 }
416
417}
418
David Tolnay78488252017-01-29 11:22:59 -0800419pub fn noop_fold_attribute<F: ?Sized + Folder>(_: &mut F, _attr: Attribute) -> Attribute {
gnzlbg9ae88d82017-01-26 20:45:17 +0100420 _attr
421}
422
David Tolnay660b03e2017-01-29 11:26:30 -0800423pub fn noop_fold_fn_ret_ty<F: ?Sized + Folder>(folder: &mut F,
424 ret_ty: FunctionRetTy)
425 -> FunctionRetTy {
gnzlbg9ae88d82017-01-26 20:45:17 +0100426 use self::FunctionRetTy::*;
427 match ret_ty {
428 Default => Default,
429 Ty(ty) => Ty(folder.fold_ty(ty)),
430 }
431}
432
David Tolnay78488252017-01-29 11:22:59 -0800433pub fn noop_fold_const_expr<F: ?Sized + Folder>(folder: &mut F, expr: ConstExpr) -> ConstExpr {
gnzlbg9ae88d82017-01-26 20:45:17 +0100434 use self::ConstExpr::*;
435 match expr {
436 Call(f, args) => {
437 Call(f.lift(|e| folder.fold_const_expr(e)),
438 args.lift(|v| folder.fold_const_expr(v)))
439 }
440 Binary(op, lhs, rhs) => {
441 Binary(op,
442 lhs.lift(|e| folder.fold_const_expr(e)),
443 rhs.lift(|e| folder.fold_const_expr(e)))
444 }
445 Unary(op, e) => Unary(op, e.lift(|e| folder.fold_const_expr(e))),
446 Lit(l) => Lit(folder.fold_lit(l)),
447 Cast(e, ty) => {
448 Cast(e.lift(|e| folder.fold_const_expr(e)),
449 ty.lift(|v| folder.fold_ty(v)))
450 }
451 Path(p) => Path(folder.fold_path(p)),
452 Index(o, i) => {
453 Index(o.lift(|e| folder.fold_const_expr(e)),
454 i.lift(|e| folder.fold_const_expr(e)))
455 }
456 Paren(no_op) => Paren(no_op.lift(|e| folder.fold_const_expr(e))),
David Tolnay4a25fc22017-01-29 11:32:20 -0800457 Other(e) => Other(noop_fold_other_const_expr(folder, e)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100458 }
459}
David Tolnay4a25fc22017-01-29 11:32:20 -0800460
461#[cfg(feature = "full")]
462fn noop_fold_other_const_expr<F: ?Sized + Folder>(folder: &mut F, e: Expr) -> Expr {
463 folder.fold_expr(e)
464}
465
466#[cfg(not(feature = "full"))]
467fn noop_fold_other_const_expr<F: ?Sized + Folder>(_: &mut F, e: constant::Other) -> constant::Other {
468 e
469}
470
David Tolnay78488252017-01-29 11:22:59 -0800471pub fn noop_fold_lit<F: ?Sized + Folder>(_: &mut F, _lit: Lit) -> Lit {
gnzlbg9ae88d82017-01-26 20:45:17 +0100472 _lit
473}
474
David Tolnay78488252017-01-29 11:22:59 -0800475pub fn noop_fold_tt<F: ?Sized + Folder>(folder: &mut F, tt: TokenTree) -> TokenTree {
gnzlbg9ae88d82017-01-26 20:45:17 +0100476 use self::TokenTree::*;
477 use self::Token::*;
478 match tt {
David Tolnay660b03e2017-01-29 11:26:30 -0800479 Token(token) => {
480 Token(match token {
481 Literal(lit) => Literal(folder.fold_lit(lit)),
482 Ident(ident) => Ident(folder.fold_ident(ident)),
483 Lifetime(ident) => Lifetime(folder.fold_ident(ident)),
484 x => x,
485 })
486 }
487 Delimited(super::Delimited { delim, tts }) => {
488 Delimited(super::Delimited {
489 delim: delim,
490 tts: tts.lift(|v| noop_fold_tt(folder, v)),
491 })
492 }
gnzlbg9ae88d82017-01-26 20:45:17 +0100493 }
494}
495
David Tolnay78488252017-01-29 11:22:59 -0800496pub fn noop_fold_mac<F: ?Sized + Folder>(folder: &mut F, Mac { path, tts }: Mac) -> Mac {
gnzlbg9ae88d82017-01-26 20:45:17 +0100497 Mac {
498 path: folder.fold_path(path),
499 tts: tts.lift(|tt| noop_fold_tt(folder, tt)),
500 }
501}
502
503#[cfg(feature = "full")]
David Tolnay660b03e2017-01-29 11:26:30 -0800504pub fn noop_fold_crate<F: ?Sized + Folder>(folder: &mut F,
505 Crate { shebang, attrs, items }: Crate)
506 -> Crate {
gnzlbg9ae88d82017-01-26 20:45:17 +0100507 Crate {
508 shebang: shebang,
509 attrs: attrs.lift(|a| folder.fold_attribute(a)),
510 items: items.lift(|i| folder.fold_item(i)),
511 }
512
513}
514
515#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800516pub fn noop_fold_block<F: ?Sized + Folder>(folder: &mut F, block: Block) -> Block {
gnzlbg9ae88d82017-01-26 20:45:17 +0100517 Block { stmts: block.stmts.lift(|s| folder.fold_stmt(s)) }
518}
519
David Tolnay78488252017-01-29 11:22:59 -0800520fn noop_fold_vis<F: ?Sized + Folder>(folder: &mut F, vis: Visibility) -> Visibility {
gnzlbg9ae88d82017-01-26 20:45:17 +0100521 use self::Visibility::*;
522 match vis {
523 Crate => Crate,
524 Inherited => Inherited,
525 Public => Public,
526 Restricted(path) => Restricted(path.lift(|p| folder.fold_path(p))),
527 }
528}
529
530#[cfg(feature = "full")]
David Tolnay660b03e2017-01-29 11:26:30 -0800531pub fn noop_fold_item<F: ?Sized + Folder>(folder: &mut F,
532 Item { ident, vis, attrs, node }: Item)
533 -> Item {
gnzlbg9ae88d82017-01-26 20:45:17 +0100534 use self::ItemKind::*;
535 Item {
536 ident: folder.fold_ident(ident.clone()),
537 vis: noop_fold_vis(folder, vis),
538 attrs: attrs.lift(|a| folder.fold_attribute(a)),
539 node: match node {
540 ExternCrate(name) => ExternCrate(name.map(|i| folder.fold_ident(i))),
541 Use(view_path) => Use(Box::new(folder.fold_view_path(*view_path))),
542 Static(ty, mutability, expr) => {
543 Static(Box::new(folder.fold_ty(*ty)),
544 mutability,
545 expr.lift(|e| folder.fold_expr(e)))
546 }
547 Const(ty, expr) => {
548 Const(ty.lift(|ty| folder.fold_ty(ty)),
549 expr.lift(|e| folder.fold_expr(e)))
550 }
551 Fn(fn_decl, unsafety, constness, abi, generics, block) => {
552 Fn(fn_decl.lift(|v| folder.fold_fn_decl(v)),
553 unsafety,
554 constness,
555 abi,
556 folder.fold_generics(generics),
557 block.lift(|v| folder.fold_block(v)))
558 }
559 Mod(items) => Mod(items.map(|items| items.lift(|i| folder.fold_item(i)))),
560 ForeignMod(super::ForeignMod { abi, items }) => {
561 ForeignMod(super::ForeignMod {
562 abi: abi,
563 items: items.lift(|foreign_item| folder.fold_foreign_item(foreign_item)),
564 })
565 }
566 Ty(ty, generics) => {
567 Ty(ty.lift(|ty| folder.fold_ty(ty)),
568 folder.fold_generics(generics))
569 }
570 Enum(variants, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800571 Enum(variants.lift(|v| folder.fold_variant(v)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100572 folder.fold_generics(generics))
573 }
574 Struct(variant_data, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800575 Struct(folder.fold_variant_data(variant_data),
gnzlbg9ae88d82017-01-26 20:45:17 +0100576 folder.fold_generics(generics))
577 }
578 Union(variant_data, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800579 Union(folder.fold_variant_data(variant_data),
gnzlbg9ae88d82017-01-26 20:45:17 +0100580 folder.fold_generics(generics))
581 }
582 Trait(unsafety, generics, typbs, trait_items) => {
583 Trait(unsafety,
584 folder.fold_generics(generics),
585 typbs.lift(|typb| folder.fold_ty_param_bound(typb)),
586 trait_items.lift(|ti| folder.fold_trait_item(ti)))
587 }
588 DefaultImpl(unsafety, path) => DefaultImpl(unsafety, folder.fold_path(path)),
589 Impl(unsafety, impl_polarity, generics, path, ty, impl_items) => {
590 Impl(unsafety,
591 impl_polarity,
592 folder.fold_generics(generics),
593 path.map(|p| folder.fold_path(p)),
594 ty.lift(|ty| folder.fold_ty(ty)),
595 impl_items.lift(|i| folder.fold_impl_item(i)))
596 }
597 Mac(mac) => Mac(folder.fold_mac(mac)),
598 },
599 }
600}
601
gnzlbg9ae88d82017-01-26 20:45:17 +0100602#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800603pub fn noop_fold_expr<F: ?Sized + Folder>(folder: &mut F, Expr { node, attrs }: Expr) -> Expr {
gnzlbg9ae88d82017-01-26 20:45:17 +0100604 use self::ExprKind::*;
605 Expr {
606 node: match node {
607 ExprKind::Box(e) => ExprKind::Box(e.lift(|e| folder.fold_expr(e))),
608 InPlace(place, value) => {
609 InPlace(place.lift(|e| folder.fold_expr(e)),
610 value.lift(|e| folder.fold_expr(e)))
611 }
612 Array(array) => Array(array.lift(|e| folder.fold_expr(e))),
613 Call(function, args) => {
614 Call(function.lift(|e| folder.fold_expr(e)),
615 args.lift(|e| folder.fold_expr(e)))
616 }
617 MethodCall(method, tys, args) => {
618 MethodCall(folder.fold_ident(method),
619 tys.lift(|t| folder.fold_ty(t)),
620 args.lift(|e| folder.fold_expr(e)))
621 }
622 Tup(args) => Tup(args.lift(|e| folder.fold_expr(e))),
623 Binary(bop, lhs, rhs) => {
624 Binary(bop,
625 lhs.lift(|e| folder.fold_expr(e)),
626 rhs.lift(|e| folder.fold_expr(e)))
627 }
628 Unary(uop, e) => Unary(uop, e.lift(|e| folder.fold_expr(e))),
629 Lit(lit) => Lit(folder.fold_lit(lit)),
630 Cast(e, ty) => {
631 Cast(e.lift(|e| folder.fold_expr(e)),
632 ty.lift(|t| folder.fold_ty(t)))
633 }
634 Type(e, ty) => {
635 Type(e.lift(|e| folder.fold_expr(e)),
636 ty.lift(|t| folder.fold_ty(t)))
637 }
638 If(e, if_block, else_block) => {
639 If(e.lift(|e| folder.fold_expr(e)),
640 folder.fold_block(if_block),
641 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
642 }
643 IfLet(pat, expr, block, else_block) => {
644 IfLet(pat.lift(|p| folder.fold_pat(p)),
645 expr.lift(|e| folder.fold_expr(e)),
646 folder.fold_block(block),
647 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
648 }
649 While(e, block, label) => {
650 While(e.lift(|e| folder.fold_expr(e)),
651 folder.fold_block(block),
652 label.map(|i| folder.fold_ident(i)))
653 }
654 WhileLet(pat, expr, block, label) => {
655 WhileLet(pat.lift(|p| folder.fold_pat(p)),
656 expr.lift(|e| folder.fold_expr(e)),
657 folder.fold_block(block),
658 label.map(|i| folder.fold_ident(i)))
659 }
660 ForLoop(pat, expr, block, label) => {
661 ForLoop(pat.lift(|p| folder.fold_pat(p)),
662 expr.lift(|e| folder.fold_expr(e)),
663 folder.fold_block(block),
664 label.map(|i| folder.fold_ident(i)))
665 }
666 Loop(block, label) => {
667 Loop(folder.fold_block(block),
668 label.map(|i| folder.fold_ident(i)))
669 }
670 Match(e, arms) => {
671 Match(e.lift(|e| folder.fold_expr(e)),
672 arms.lift(|Arm { attrs, pats, guard, body }: Arm| {
673 Arm {
674 attrs: attrs.lift(|a| folder.fold_attribute(a)),
675 pats: pats.lift(|p| folder.fold_pat(p)),
676 guard: guard.map(|v| v.lift(|e| folder.fold_expr(e))),
677 body: body.lift(|e| folder.fold_expr(e)),
678 }
679 }))
680 }
681 Closure(capture_by, fn_decl, expr) => {
682 Closure(capture_by,
683 fn_decl.lift(|v| folder.fold_fn_decl(v)),
684 expr.lift(|e| folder.fold_expr(e)))
685 }
686 Block(unsafety, block) => Block(unsafety, folder.fold_block(block)),
687 Assign(lhs, rhs) => {
688 Assign(lhs.lift(|e| folder.fold_expr(e)),
689 rhs.lift(|e| folder.fold_expr(e)))
690 }
691 AssignOp(bop, lhs, rhs) => {
692 AssignOp(bop,
693 lhs.lift(|e| folder.fold_expr(e)),
694 rhs.lift(|e| folder.fold_expr(e)))
695 }
696 Field(expr, name) => Field(expr.lift(|e| folder.fold_expr(e)), folder.fold_ident(name)),
697 TupField(expr, index) => TupField(expr.lift(|e| folder.fold_expr(e)), index),
698 Index(expr, index) => {
699 Index(expr.lift(|e| folder.fold_expr(e)),
700 index.lift(|e| folder.fold_expr(e)))
701 }
702 Range(lhs, rhs, limits) => {
703 Range(lhs.map(|v| v.lift(|e| folder.fold_expr(e))),
704 rhs.map(|v| v.lift(|e| folder.fold_expr(e))),
705 limits)
706 }
707 Path(qself, path) => {
708 Path(qself.map(|v| noop_fold_qself(folder, v)),
709 folder.fold_path(path))
710 }
711 AddrOf(mutability, expr) => AddrOf(mutability, expr.lift(|e| folder.fold_expr(e))),
712 Break(label, expr) => {
713 Break(label.map(|i| folder.fold_ident(i)),
714 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
715 }
716 Continue(label) => Continue(label.map(|i| folder.fold_ident(i))),
717 Ret(expr) => Ret(expr.map(|v| v.lift(|e| folder.fold_expr(e)))),
718 ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)),
719 Struct(path, fields, expr) => {
720 Struct(folder.fold_path(path),
721 fields.lift(|FieldValue { ident, expr, is_shorthand, attrs }: FieldValue| {
722 FieldValue {
723 ident: folder.fold_ident(ident),
724 expr: folder.fold_expr(expr),
725 is_shorthand: is_shorthand,
726 attrs: attrs.lift(|v| folder.fold_attribute(v)),
727 }
728 }),
729 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
730 }
731 Repeat(element, number) => {
732 Repeat(element.lift(|e| folder.fold_expr(e)),
733 number.lift(|e| folder.fold_expr(e)))
734 }
735 Paren(expr) => Paren(expr.lift(|e| folder.fold_expr(e))),
736 Try(expr) => Try(expr.lift(|e| folder.fold_expr(e))),
737 },
738 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
739 }
740}
741
gnzlbg9ae88d82017-01-26 20:45:17 +0100742#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800743pub fn noop_fold_foreign_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100744 ForeignItem { ident, attrs, node, vis }: ForeignItem)
745 -> ForeignItem {
746 ForeignItem {
747 ident: folder.fold_ident(ident),
748 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
749 node: match node {
750 ForeignItemKind::Fn(fn_dcl, generics) => {
751 ForeignItemKind::Fn(fn_dcl.lift(|v| folder.fold_fn_decl(v)),
752 folder.fold_generics(generics))
753 }
754 ForeignItemKind::Static(ty, mutability) => {
755 ForeignItemKind::Static(ty.lift(|v| folder.fold_ty(v)), mutability)
756 }
757 },
758 vis: noop_fold_vis(folder, vis),
759 }
760}
761
gnzlbg9ae88d82017-01-26 20:45:17 +0100762#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800763pub fn noop_fold_pat<F: ?Sized + Folder>(folder: &mut F, pat: Pat) -> Pat {
gnzlbg9ae88d82017-01-26 20:45:17 +0100764 use self::Pat::*;
765 match pat {
766 Wild => Wild,
767 Ident(binding_mode, ident, pat) => {
768 Ident(binding_mode,
769 folder.fold_ident(ident),
770 pat.map(|p| p.lift(|p| folder.fold_pat(p))))
771 }
772 Struct(path, field_patterns, dots) => {
773 Struct(folder.fold_path(path),
774 field_patterns.lift(|FieldPat { ident, pat, is_shorthand, attrs }: FieldPat| {
775 FieldPat {
776 ident: folder.fold_ident(ident),
777 pat: pat.lift(|p| folder.fold_pat(p)),
778 is_shorthand: is_shorthand,
779 attrs: attrs.lift(|a| folder.fold_attribute(a)),
780 }
781 }),
782 dots)
783 }
784 TupleStruct(path, pats, len) => {
785 TupleStruct(folder.fold_path(path),
786 pats.lift(|p| folder.fold_pat(p)),
787 len)
788 }
789 Path(qself, path) => {
790 Path(qself.map(|v| noop_fold_qself(folder, v)),
791 folder.fold_path(path))
792 }
793 Tuple(pats, len) => Tuple(pats.lift(|p| folder.fold_pat(p)), len),
794 Box(b) => Box(b.lift(|p| folder.fold_pat(p))),
795 Ref(b, mutability) => Ref(b.lift(|p| folder.fold_pat(p)), mutability),
796 Lit(expr) => Lit(expr.lift(|e| folder.fold_expr(e))),
797 Range(l, r) => {
798 Range(l.lift(|e| folder.fold_expr(e)),
799 r.lift(|e| folder.fold_expr(e)))
800 }
801 Slice(lefts, pat, rights) => {
802 Slice(lefts.lift(|p| folder.fold_pat(p)),
803 pat.map(|v| v.lift(|p| folder.fold_pat(p))),
804 rights.lift(|p| folder.fold_pat(p)))
805 }
806 Mac(mac) => Mac(folder.fold_mac(mac)),
807 }
808}
809
gnzlbg9ae88d82017-01-26 20:45:17 +0100810#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800811pub fn noop_fold_fn_decl<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800812 FnDecl { inputs, output, variadic }: FnDecl)
813 -> FnDecl {
gnzlbg9ae88d82017-01-26 20:45:17 +0100814
815 FnDecl {
816 inputs: inputs.lift(|a| {
817 use self::FnArg::*;
818 match a {
819 SelfRef(lifetime, mutability) => {
820 SelfRef(lifetime.map(|v| folder.fold_lifetime(v)), mutability)
821 }
822 SelfValue(mutability) => SelfValue(mutability),
823 Captured(pat, ty) => Captured(folder.fold_pat(pat), folder.fold_ty(ty)),
824 Ignored(ty) => Ignored(folder.fold_ty(ty)),
825 }
826 }),
827 output: folder.fold_fn_ret_ty(output),
828 variadic: variadic,
829 }
830
831}
832
gnzlbg9ae88d82017-01-26 20:45:17 +0100833#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800834pub fn noop_fold_trait_item<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800835 TraitItem { ident, attrs, node }: TraitItem)
836 -> TraitItem {
gnzlbg9ae88d82017-01-26 20:45:17 +0100837 use self::TraitItemKind::*;
838 TraitItem {
839 ident: folder.fold_ident(ident),
840 attrs: attrs.lift(|v| folder.fold_attribute(v)),
841 node: match node {
842 Const(ty, expr) => Const(folder.fold_ty(ty), expr.map(|v| folder.fold_expr(v))),
843 Method(sig, block) => {
844 Method(folder.fold_method_sig(sig),
845 block.map(|v| folder.fold_block(v)))
846 }
847 Type(ty_pbs, ty) => {
848 Type(ty_pbs.lift(|v| folder.fold_ty_param_bound(v)),
849 ty.map(|v| folder.fold_ty(v)))
850 }
David Tolnay70925b72017-01-29 11:20:54 -0800851 Macro(mac) => Macro(folder.fold_mac(mac)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100852 },
853 }
854}
855
gnzlbg9ae88d82017-01-26 20:45:17 +0100856#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800857pub fn noop_fold_impl_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100858 ImplItem { ident, vis, defaultness, attrs, node }: ImplItem)
859 -> ImplItem {
860 use self::ImplItemKind::*;
861 ImplItem {
862 ident: folder.fold_ident(ident),
863 vis: noop_fold_vis(folder, vis),
864 defaultness: defaultness,
865 attrs: attrs.lift(|v| folder.fold_attribute(v)),
866 node: match node {
867 Const(ty, expr) => Const(folder.fold_ty(ty), folder.fold_expr(expr)),
David Tolnay660b03e2017-01-29 11:26:30 -0800868 Method(sig, block) => Method(folder.fold_method_sig(sig), folder.fold_block(block)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100869 Type(ty) => Type(folder.fold_ty(ty)),
870 Macro(mac) => Macro(folder.fold_mac(mac)),
871 },
872 }
873}
874
gnzlbg9ae88d82017-01-26 20:45:17 +0100875#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800876pub 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 +0100877 MethodSig {
878 unsafety: unsafety,
879 constness: constness,
880 abi: abi,
881 decl: folder.fold_fn_decl(decl),
882 generics: folder.fold_generics(generics),
883 }
884
885}
886
gnzlbg9ae88d82017-01-26 20:45:17 +0100887#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800888pub fn noop_fold_stmt<F: ?Sized + Folder>(folder: &mut F, stmt: Stmt) -> Stmt {
gnzlbg9ae88d82017-01-26 20:45:17 +0100889 use self::Stmt::*;
890 match stmt {
891 Local(local) => Local(local.lift(|l| folder.fold_local(l))),
892 Item(item) => Item(item.lift(|v| folder.fold_item(v))),
893 Expr(expr) => Expr(expr.lift(|v| folder.fold_expr(v))),
894 Semi(expr) => Semi(expr.lift(|v| folder.fold_expr(v))),
895 Mac(mac_stmt) => {
896 Mac(mac_stmt.lift(|(mac, style, attrs)| {
897 (folder.fold_mac(mac), style, attrs.lift(|a| folder.fold_attribute(a)))
898 }))
899 }
900 }
901
902}
903
gnzlbg9ae88d82017-01-26 20:45:17 +0100904#[cfg(feature = "full")]
David Tolnay660b03e2017-01-29 11:26:30 -0800905pub fn noop_fold_local<F: ?Sized + Folder>(folder: &mut F,
906 Local { pat, ty, init, attrs }: Local)
907 -> Local {
gnzlbg9ae88d82017-01-26 20:45:17 +0100908 Local {
909 pat: pat.lift(|v| folder.fold_pat(v)),
910 ty: ty.map(|v| v.lift(|t| folder.fold_ty(t))),
911 init: init.map(|v| v.lift(|e| folder.fold_expr(e))),
912 attrs: attrs.lift(|a| folder.fold_attribute(a)),
913 }
914}
915
916#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800917pub fn noop_fold_view_path<F: ?Sized + Folder>(folder: &mut F, view_path: ViewPath) -> ViewPath {
gnzlbg9ae88d82017-01-26 20:45:17 +0100918 use self::ViewPath::*;
919 match view_path {
920 Simple(path, ident) => Simple(folder.fold_path(path), ident.map(|i| folder.fold_ident(i))),
921 Glob(path) => Glob(folder.fold_path(path)),
922 List(path, items) => {
923 List(folder.fold_path(path),
924 items.lift(|PathListItem { name, rename }: PathListItem| {
925 PathListItem {
926 name: folder.fold_ident(name),
927 rename: rename.map(|i| folder.fold_ident(i)),
928 }
929 }))
930 }
931 }
932}