blob: 055fb78ee47d598fa0bc610e538d06b6ac29402a [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::*;
David Tolnay7a1cda02017-01-29 11:50:31 -08007use constant;
gnzlbg9ae88d82017-01-26 20:45:17 +01008
9/// AST->AST fold.
10///
11/// Each method of the Folder trait is a hook to be potentially overridden. Each
12/// method's default implementation recursively visits the substructure of the
13/// input via the `noop_fold` methods, which perform an "identity fold", that
14/// is, they return the same structure that they are given (for example the
15/// `fold_crate` method by default calls `fold::noop_fold_crate`).
16///
17/// If you want to ensure that your code handles every variant explicitly, you
18/// need to override each method and monitor future changes to `Folder` in case
19/// a new method with a new default implementation gets introduced.
David Tolnay78488252017-01-29 11:22:59 -080020pub trait Folder {
gnzlbg9ae88d82017-01-26 20:45:17 +010021 // Any additions to this trait should happen in form
22 // of a call to a public `noop_*` function that only calls
23 // out to the folder again, not other `noop_*` functions.
24 //
25 // This is a necessary API workaround to the problem of not
26 // being able to call out to the super default method
27 // in an overridden default method.
28
29 fn fold_ident(&mut self, _ident: Ident) -> Ident {
30 noop_fold_ident(self, _ident)
31 }
32 fn fold_derive_input(&mut self, derive_input: DeriveInput) -> DeriveInput {
33 noop_fold_derive_input(self, derive_input)
34 }
35 fn fold_ty(&mut self, ty: Ty) -> Ty {
36 noop_fold_ty(self, ty)
37 }
38 fn fold_generics(&mut self, generics: Generics) -> Generics {
39 noop_fold_generics(self, generics)
40 }
41 fn fold_ty_param_bound(&mut self, bound: TyParamBound) -> TyParamBound {
42 noop_fold_ty_param_bound(self, bound)
43 }
44 fn fold_poly_trait_ref(&mut self, trait_ref: PolyTraitRef) -> PolyTraitRef {
45 noop_fold_poly_trait_ref(self, trait_ref)
46 }
47 fn fold_variant_data(&mut self, data: VariantData) -> VariantData {
48 noop_fold_variant_data(self, data)
49 }
50 fn fold_field(&mut self, field: Field) -> Field {
51 noop_fold_field(self, field)
52 }
53 fn fold_variant(&mut self, variant: Variant) -> Variant {
54 noop_fold_variant(self, variant)
55 }
56 fn fold_lifetime(&mut self, _lifetime: Lifetime) -> Lifetime {
57 noop_fold_lifetime(self, _lifetime)
58 }
59 fn fold_lifetime_def(&mut self, lifetime: LifetimeDef) -> LifetimeDef {
60 noop_fold_lifetime_def(self, lifetime)
61 }
62 fn fold_path(&mut self, path: Path) -> Path {
63 noop_fold_path(self, path)
64 }
65 fn fold_path_segment(&mut self, path_segment: PathSegment) -> PathSegment {
66 noop_fold_path_segment(self, path_segment)
67 }
68 fn fold_path_parameters(&mut self, path_parameters: PathParameters) -> PathParameters {
69 noop_fold_path_parameters(self, path_parameters)
70 }
71 fn fold_assoc_type_binding(&mut self, type_binding: TypeBinding) -> TypeBinding {
72 noop_fold_assoc_type_binding(self, type_binding)
73 }
74 fn fold_attribute(&mut self, _attr: Attribute) -> Attribute {
75 noop_fold_attribute(self, _attr)
76 }
77 fn fold_fn_ret_ty(&mut self, ret_ty: FunctionRetTy) -> FunctionRetTy {
78 noop_fold_fn_ret_ty(self, ret_ty)
79 }
80 fn fold_const_expr(&mut self, expr: ConstExpr) -> ConstExpr {
81 noop_fold_const_expr(self, expr)
82 }
83 fn fold_lit(&mut self, _lit: Lit) -> Lit {
84 noop_fold_lit(self, _lit)
85 }
86
87 fn fold_mac(&mut self, mac: Mac) -> Mac {
88 noop_fold_mac(self, mac)
89 }
90
91 #[cfg(feature = "full")]
92 fn fold_crate(&mut self, _crate: Crate) -> Crate {
93 noop_fold_crate(self, _crate)
94 }
95 #[cfg(feature = "full")]
96 fn fold_item(&mut self, item: Item) -> Item {
97 noop_fold_item(self, item)
98 }
99 #[cfg(feature = "full")]
100 fn fold_expr(&mut self, expr: Expr) -> Expr {
101 noop_fold_expr(self, expr)
102 }
103 #[cfg(feature = "full")]
104 fn fold_foreign_item(&mut self, foreign_item: ForeignItem) -> ForeignItem {
105 noop_fold_foreign_item(self, foreign_item)
106 }
107 #[cfg(feature = "full")]
108 fn fold_pat(&mut self, pat: Pat) -> Pat {
109 noop_fold_pat(self, pat)
110 }
111 #[cfg(feature = "full")]
112 fn fold_fn_decl(&mut self, fn_decl: FnDecl) -> FnDecl {
113 noop_fold_fn_decl(self, fn_decl)
114 }
115 #[cfg(feature = "full")]
116 fn fold_trait_item(&mut self, trait_item: TraitItem) -> TraitItem {
117 noop_fold_trait_item(self, trait_item)
118 }
119 #[cfg(feature = "full")]
120 fn fold_impl_item(&mut self, impl_item: ImplItem) -> ImplItem {
121 noop_fold_impl_item(self, impl_item)
122 }
123 #[cfg(feature = "full")]
124 fn fold_method_sig(&mut self, method_sig: MethodSig) -> MethodSig {
125 noop_fold_method_sig(self, method_sig)
126 }
127 #[cfg(feature = "full")]
128 fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
129 noop_fold_stmt(self, stmt)
130 }
131 #[cfg(feature = "full")]
132 fn fold_block(&mut self, block: Block) -> Block {
133 noop_fold_block(self, block)
134 }
135 #[cfg(feature = "full")]
136 fn fold_local(&mut self, local: Local) -> Local {
137 noop_fold_local(self, local)
138 }
139 #[cfg(feature = "full")]
140 fn fold_view_path(&mut self, view_path: ViewPath) -> ViewPath {
141 noop_fold_view_path(self, view_path)
142 }
143}
144
145trait LiftOnce<T, U> {
146 type Output;
147 fn lift<F>(self, f: F) -> Self::Output where F: FnOnce(T) -> U;
148}
149
150impl<T, U> LiftOnce<T, U> for Box<T> {
151 type Output = Box<U>;
152 fn lift<F>(self, f: F) -> Box<U>
153 where F: FnOnce(T) -> U
154 {
155 Box::new(f(*self))
156 }
157}
158
159trait LiftMut<T, U> {
160 type Output;
161 fn lift<F>(self, f: F) -> Self::Output where F: FnMut(T) -> U;
162}
163
164impl<T, U> LiftMut<T, U> for Vec<T> {
165 type Output = Vec<U>;
166 fn lift<F>(self, f: F) -> Vec<U>
167 where F: FnMut(T) -> U
168 {
169 self.into_iter().map(f).collect()
170 }
171}
172
David Tolnay78488252017-01-29 11:22:59 -0800173pub fn noop_fold_ident<F: ?Sized + Folder>(_: &mut F, _ident: Ident) -> Ident {
gnzlbg9ae88d82017-01-26 20:45:17 +0100174 _ident
175}
176
David Tolnay78488252017-01-29 11:22:59 -0800177pub fn noop_fold_derive_input<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100178 DeriveInput{ ident,
179 vis,
180 attrs,
181 generics,
182 body }: DeriveInput) -> DeriveInput {
David Tolnay7a1cda02017-01-29 11:50:31 -0800183 use Body::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100184 DeriveInput {
185 ident: folder.fold_ident(ident),
186 vis: noop_fold_vis(folder, vis),
187 attrs: attrs.lift(|a| folder.fold_attribute(a)),
188 generics: folder.fold_generics(generics),
189 body: match body {
David Tolnay660b03e2017-01-29 11:26:30 -0800190 Enum(variants) => Enum(variants.lift(move |v| folder.fold_variant(v))),
gnzlbg9ae88d82017-01-26 20:45:17 +0100191 Struct(variant_data) => Struct(folder.fold_variant_data(variant_data)),
192 },
193 }
194}
195
David Tolnay78488252017-01-29 11:22:59 -0800196pub fn noop_fold_ty<F: ?Sized + Folder>(folder: &mut F, ty: Ty) -> Ty {
David Tolnay7a1cda02017-01-29 11:50:31 -0800197 use Ty::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100198 match ty {
199 Slice(inner) => Slice(inner.lift(|v| folder.fold_ty(v))),
200 Paren(inner) => Paren(inner.lift(|v| folder.fold_ty(v))),
201 Ptr(mutable_type) => {
202 let mutable_type_ = *mutable_type;
203 let MutTy { ty, mutability }: MutTy = mutable_type_;
204 Ptr(Box::new(MutTy {
205 ty: folder.fold_ty(ty),
206 mutability: mutability,
207 }))
208 }
209 Rptr(opt_lifetime, mutable_type) => {
210 let mutable_type_ = *mutable_type;
211 let MutTy { ty, mutability }: MutTy = mutable_type_;
212 Rptr(opt_lifetime.map(|l| folder.fold_lifetime(l)),
213 Box::new(MutTy {
214 ty: folder.fold_ty(ty),
215 mutability: mutability,
216 }))
217 }
218 Never => Never,
219 Infer => Infer,
220 Tup(tuple_element_types) => Tup(tuple_element_types.lift(|x| folder.fold_ty(x))),
221 BareFn(bare_fn) => {
222 let bf_ = *bare_fn;
223 let BareFnTy { unsafety, abi, lifetimes, inputs, output, variadic } = bf_;
224 BareFn(Box::new(BareFnTy {
225 unsafety: unsafety,
226 abi: abi,
227 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
228 inputs: inputs.lift(|v| {
229 BareFnArg {
230 name: v.name.map(|n| folder.fold_ident(n)),
231 ty: folder.fold_ty(v.ty),
232 }
233 }),
234 output: folder.fold_fn_ret_ty(output),
235 variadic: variadic,
236 }))
237 }
238 Path(maybe_qself, path) => {
239 Path(maybe_qself.map(|v| noop_fold_qself(folder, v)),
240 folder.fold_path(path))
241 }
242 Array(inner, len) => {
243 Array({
244 inner.lift(|v| folder.fold_ty(v))
245 },
246 folder.fold_const_expr(len))
247 }
248 TraitObject(bounds) => TraitObject(bounds.lift(|v| folder.fold_ty_param_bound(v))),
249 ImplTrait(bounds) => ImplTrait(bounds.lift(|v| folder.fold_ty_param_bound(v))),
250 Mac(mac) => Mac(folder.fold_mac(mac)),
251 }
252}
253
David Tolnay78488252017-01-29 11:22:59 -0800254fn noop_fold_qself<F: ?Sized + Folder>(folder: &mut F, QSelf { ty, position }: QSelf) -> QSelf {
gnzlbg9ae88d82017-01-26 20:45:17 +0100255 QSelf {
256 ty: Box::new(folder.fold_ty(*(ty))),
257 position: position,
258 }
259}
260
David Tolnay78488252017-01-29 11:22:59 -0800261pub fn noop_fold_generics<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100262 Generics { lifetimes, ty_params, where_clause }: Generics)
263 -> Generics {
David Tolnay7a1cda02017-01-29 11:50:31 -0800264 use WherePredicate::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100265 Generics {
266 lifetimes: lifetimes.lift(|l| folder.fold_lifetime_def(l)),
267 ty_params: ty_params.lift(|ty| {
268 TyParam {
269 attrs: ty.attrs.lift(|a| folder.fold_attribute(a)),
270 ident: folder.fold_ident(ty.ident),
271 bounds: ty.bounds
272 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
273 default: ty.default.map(|v| folder.fold_ty(v)),
274 }
275 }),
276 where_clause: WhereClause {
277 predicates: where_clause.predicates
278 .lift(|p| match p {
279 BoundPredicate(bound_predicate) => {
280 BoundPredicate(WhereBoundPredicate {
281 bound_lifetimes: bound_predicate.bound_lifetimes
282 .lift(|l| folder.fold_lifetime_def(l)),
283 bounded_ty: folder.fold_ty(bound_predicate.bounded_ty),
284 bounds: bound_predicate.bounds
285 .lift(|ty_pb| folder.fold_ty_param_bound(ty_pb)),
286 })
287 }
288 RegionPredicate(region_predicate) => {
289 RegionPredicate(WhereRegionPredicate {
290 lifetime: folder.fold_lifetime(region_predicate.lifetime),
291 bounds: region_predicate.bounds
292 .lift(|b| folder.fold_lifetime(b)),
293 })
294 }
295 EqPredicate(eq_predicate) => {
296 EqPredicate(WhereEqPredicate {
297 lhs_ty: folder.fold_ty(eq_predicate.lhs_ty),
298 rhs_ty: folder.fold_ty(eq_predicate.rhs_ty),
299 })
300 }
301 }),
302 },
303 }
304}
305
David Tolnay660b03e2017-01-29 11:26:30 -0800306pub fn noop_fold_ty_param_bound<F: ?Sized + Folder>(folder: &mut F,
307 bound: TyParamBound)
308 -> TyParamBound {
David Tolnay7a1cda02017-01-29 11:50:31 -0800309 use TyParamBound::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100310 match bound {
311 Trait(ty, modifier) => Trait(folder.fold_poly_trait_ref(ty), modifier),
312 Region(lifetime) => Region(folder.fold_lifetime(lifetime)),
313 }
314}
315
David Tolnay660b03e2017-01-29 11:26:30 -0800316pub fn noop_fold_poly_trait_ref<F: ?Sized + Folder>(folder: &mut F,
317 trait_ref: PolyTraitRef)
318 -> PolyTraitRef {
gnzlbg9ae88d82017-01-26 20:45:17 +0100319 PolyTraitRef {
320 bound_lifetimes: trait_ref.bound_lifetimes
321 .lift(|bl| folder.fold_lifetime_def(bl)),
322 trait_ref: folder.fold_path(trait_ref.trait_ref),
323 }
324}
325
David Tolnay78488252017-01-29 11:22:59 -0800326pub fn noop_fold_variant_data<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800327 data: VariantData)
328 -> VariantData {
David Tolnay7a1cda02017-01-29 11:50:31 -0800329 use VariantData::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100330 match data {
331 Struct(fields) => Struct(fields.lift(|f| folder.fold_field(f))),
332 Tuple(fields) => Tuple(fields.lift(|f| folder.fold_field(f))),
333 Unit => Unit,
334 }
335}
336
David Tolnay78488252017-01-29 11:22:59 -0800337pub fn noop_fold_field<F: ?Sized + Folder>(folder: &mut F, field: Field) -> Field {
gnzlbg9ae88d82017-01-26 20:45:17 +0100338 Field {
339 ident: field.ident.map(|i| folder.fold_ident(i)),
340 vis: noop_fold_vis(folder, field.vis),
341 attrs: field.attrs.lift(|a| folder.fold_attribute(a)),
342 ty: folder.fold_ty(field.ty),
343 }
344}
345
David Tolnay78488252017-01-29 11:22:59 -0800346pub fn noop_fold_variant<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100347 Variant { ident, attrs, data, discriminant }: Variant)
348 -> Variant {
349 Variant {
350 ident: folder.fold_ident(ident),
351 attrs: attrs.lift(|v| folder.fold_attribute(v)),
352 data: folder.fold_variant_data(data),
353 discriminant: discriminant.map(|ce| folder.fold_const_expr(ce)),
354 }
355}
356
David Tolnay78488252017-01-29 11:22:59 -0800357pub fn noop_fold_lifetime<F: ?Sized + Folder>(folder: &mut F, _lifetime: Lifetime) -> Lifetime {
gnzlbg9ae88d82017-01-26 20:45:17 +0100358 Lifetime { ident: folder.fold_ident(_lifetime.ident) }
359}
360
David Tolnay78488252017-01-29 11:22:59 -0800361pub fn noop_fold_lifetime_def<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100362 LifetimeDef { attrs, lifetime, bounds }: LifetimeDef)
363 -> LifetimeDef {
364 LifetimeDef {
365 attrs: attrs.lift(|x| folder.fold_attribute(x)),
366 lifetime: folder.fold_lifetime(lifetime),
367 bounds: bounds.lift(|l| folder.fold_lifetime(l)),
368 }
369}
370
David Tolnay78488252017-01-29 11:22:59 -0800371pub fn noop_fold_path<F: ?Sized + Folder>(folder: &mut F, Path { global, segments }: Path) -> Path {
gnzlbg9ae88d82017-01-26 20:45:17 +0100372 Path {
373 global: global,
374 segments: segments.lift(|s| folder.fold_path_segment(s)),
375 }
376}
377
David Tolnay78488252017-01-29 11:22:59 -0800378pub fn noop_fold_path_segment<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800379 PathSegment { ident, parameters }: PathSegment)
380 -> PathSegment {
gnzlbg9ae88d82017-01-26 20:45:17 +0100381 PathSegment {
382 ident: folder.fold_ident(ident),
383 parameters: folder.fold_path_parameters(parameters),
384 }
385}
386
David Tolnay78488252017-01-29 11:22:59 -0800387pub fn noop_fold_path_parameters<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800388 path_parameters: PathParameters)
389 -> PathParameters {
David Tolnay7a1cda02017-01-29 11:50:31 -0800390 use PathParameters::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100391 match path_parameters {
392 AngleBracketed(d) => {
393 let AngleBracketedParameterData { lifetimes, types, bindings } = d;
394 AngleBracketed(AngleBracketedParameterData {
395 lifetimes: lifetimes.into_iter().map(|l| folder.fold_lifetime(l)).collect(),
396 types: types.lift(|ty| folder.fold_ty(ty)),
397 bindings: bindings.lift(|tb| folder.fold_assoc_type_binding(tb)),
398 })
399 }
400 Parenthesized(d) => {
401 let ParenthesizedParameterData { inputs, output } = d;
402 Parenthesized(ParenthesizedParameterData {
403 inputs: inputs.lift(|i| folder.fold_ty(i)),
404 output: output.map(|v| folder.fold_ty(v)),
405 })
406 }
407 }
408}
409
David Tolnay78488252017-01-29 11:22:59 -0800410pub fn noop_fold_assoc_type_binding<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800411 TypeBinding { ident, ty }: TypeBinding)
412 -> TypeBinding {
gnzlbg9ae88d82017-01-26 20:45:17 +0100413 TypeBinding {
414 ident: folder.fold_ident(ident),
415 ty: folder.fold_ty(ty),
416 }
417
418}
419
David Tolnay78488252017-01-29 11:22:59 -0800420pub fn noop_fold_attribute<F: ?Sized + Folder>(_: &mut F, _attr: Attribute) -> Attribute {
gnzlbg9ae88d82017-01-26 20:45:17 +0100421 _attr
422}
423
David Tolnay660b03e2017-01-29 11:26:30 -0800424pub fn noop_fold_fn_ret_ty<F: ?Sized + Folder>(folder: &mut F,
425 ret_ty: FunctionRetTy)
426 -> FunctionRetTy {
David Tolnay7a1cda02017-01-29 11:50:31 -0800427 use FunctionRetTy::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100428 match ret_ty {
429 Default => Default,
430 Ty(ty) => Ty(folder.fold_ty(ty)),
431 }
432}
433
David Tolnay78488252017-01-29 11:22:59 -0800434pub fn noop_fold_const_expr<F: ?Sized + Folder>(folder: &mut F, expr: ConstExpr) -> ConstExpr {
David Tolnay7a1cda02017-01-29 11:50:31 -0800435 use ConstExpr::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100436 match expr {
437 Call(f, args) => {
438 Call(f.lift(|e| folder.fold_const_expr(e)),
439 args.lift(|v| folder.fold_const_expr(v)))
440 }
441 Binary(op, lhs, rhs) => {
442 Binary(op,
443 lhs.lift(|e| folder.fold_const_expr(e)),
444 rhs.lift(|e| folder.fold_const_expr(e)))
445 }
446 Unary(op, e) => Unary(op, e.lift(|e| folder.fold_const_expr(e))),
447 Lit(l) => Lit(folder.fold_lit(l)),
448 Cast(e, ty) => {
449 Cast(e.lift(|e| folder.fold_const_expr(e)),
450 ty.lift(|v| folder.fold_ty(v)))
451 }
452 Path(p) => Path(folder.fold_path(p)),
453 Index(o, i) => {
454 Index(o.lift(|e| folder.fold_const_expr(e)),
455 i.lift(|e| folder.fold_const_expr(e)))
456 }
457 Paren(no_op) => Paren(no_op.lift(|e| folder.fold_const_expr(e))),
David Tolnay4a25fc22017-01-29 11:32:20 -0800458 Other(e) => Other(noop_fold_other_const_expr(folder, e)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100459 }
460}
David Tolnay4a25fc22017-01-29 11:32:20 -0800461
462#[cfg(feature = "full")]
463fn noop_fold_other_const_expr<F: ?Sized + Folder>(folder: &mut F, e: Expr) -> Expr {
464 folder.fold_expr(e)
465}
466
467#[cfg(not(feature = "full"))]
468fn noop_fold_other_const_expr<F: ?Sized + Folder>(_: &mut F, e: constant::Other) -> constant::Other {
469 e
470}
471
David Tolnay78488252017-01-29 11:22:59 -0800472pub fn noop_fold_lit<F: ?Sized + Folder>(_: &mut F, _lit: Lit) -> Lit {
gnzlbg9ae88d82017-01-26 20:45:17 +0100473 _lit
474}
475
David Tolnay78488252017-01-29 11:22:59 -0800476pub fn noop_fold_tt<F: ?Sized + Folder>(folder: &mut F, tt: TokenTree) -> TokenTree {
David Tolnay7a1cda02017-01-29 11:50:31 -0800477 use TokenTree::*;
478 use Token::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100479 match tt {
David Tolnay660b03e2017-01-29 11:26:30 -0800480 Token(token) => {
481 Token(match token {
482 Literal(lit) => Literal(folder.fold_lit(lit)),
483 Ident(ident) => Ident(folder.fold_ident(ident)),
484 Lifetime(ident) => Lifetime(folder.fold_ident(ident)),
485 x => x,
486 })
487 }
488 Delimited(super::Delimited { delim, tts }) => {
489 Delimited(super::Delimited {
490 delim: delim,
491 tts: tts.lift(|v| noop_fold_tt(folder, v)),
492 })
493 }
gnzlbg9ae88d82017-01-26 20:45:17 +0100494 }
495}
496
David Tolnay78488252017-01-29 11:22:59 -0800497pub fn noop_fold_mac<F: ?Sized + Folder>(folder: &mut F, Mac { path, tts }: Mac) -> Mac {
gnzlbg9ae88d82017-01-26 20:45:17 +0100498 Mac {
499 path: folder.fold_path(path),
500 tts: tts.lift(|tt| noop_fold_tt(folder, tt)),
501 }
502}
503
504#[cfg(feature = "full")]
David Tolnay660b03e2017-01-29 11:26:30 -0800505pub fn noop_fold_crate<F: ?Sized + Folder>(folder: &mut F,
506 Crate { shebang, attrs, items }: Crate)
507 -> Crate {
gnzlbg9ae88d82017-01-26 20:45:17 +0100508 Crate {
509 shebang: shebang,
510 attrs: attrs.lift(|a| folder.fold_attribute(a)),
511 items: items.lift(|i| folder.fold_item(i)),
512 }
513
514}
515
516#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800517pub fn noop_fold_block<F: ?Sized + Folder>(folder: &mut F, block: Block) -> Block {
gnzlbg9ae88d82017-01-26 20:45:17 +0100518 Block { stmts: block.stmts.lift(|s| folder.fold_stmt(s)) }
519}
520
David Tolnay78488252017-01-29 11:22:59 -0800521fn noop_fold_vis<F: ?Sized + Folder>(folder: &mut F, vis: Visibility) -> Visibility {
David Tolnay7a1cda02017-01-29 11:50:31 -0800522 use Visibility::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100523 match vis {
524 Crate => Crate,
525 Inherited => Inherited,
526 Public => Public,
527 Restricted(path) => Restricted(path.lift(|p| folder.fold_path(p))),
528 }
529}
530
531#[cfg(feature = "full")]
David Tolnay660b03e2017-01-29 11:26:30 -0800532pub fn noop_fold_item<F: ?Sized + Folder>(folder: &mut F,
533 Item { ident, vis, attrs, node }: Item)
534 -> Item {
David Tolnay7a1cda02017-01-29 11:50:31 -0800535 use ItemKind::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100536 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) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800572 Enum(variants.lift(|v| folder.fold_variant(v)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100573 folder.fold_generics(generics))
574 }
575 Struct(variant_data, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800576 Struct(folder.fold_variant_data(variant_data),
gnzlbg9ae88d82017-01-26 20:45:17 +0100577 folder.fold_generics(generics))
578 }
579 Union(variant_data, generics) => {
David Tolnaya6aa8f12017-01-29 11:23:54 -0800580 Union(folder.fold_variant_data(variant_data),
gnzlbg9ae88d82017-01-26 20:45:17 +0100581 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
gnzlbg9ae88d82017-01-26 20:45:17 +0100603#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800604pub fn noop_fold_expr<F: ?Sized + Folder>(folder: &mut F, Expr { node, attrs }: Expr) -> Expr {
David Tolnay7a1cda02017-01-29 11:50:31 -0800605 use ExprKind::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100606 Expr {
607 node: match node {
608 ExprKind::Box(e) => ExprKind::Box(e.lift(|e| folder.fold_expr(e))),
609 InPlace(place, value) => {
610 InPlace(place.lift(|e| folder.fold_expr(e)),
611 value.lift(|e| folder.fold_expr(e)))
612 }
613 Array(array) => Array(array.lift(|e| folder.fold_expr(e))),
614 Call(function, args) => {
615 Call(function.lift(|e| folder.fold_expr(e)),
616 args.lift(|e| folder.fold_expr(e)))
617 }
618 MethodCall(method, tys, args) => {
619 MethodCall(folder.fold_ident(method),
620 tys.lift(|t| folder.fold_ty(t)),
621 args.lift(|e| folder.fold_expr(e)))
622 }
623 Tup(args) => Tup(args.lift(|e| folder.fold_expr(e))),
624 Binary(bop, lhs, rhs) => {
625 Binary(bop,
626 lhs.lift(|e| folder.fold_expr(e)),
627 rhs.lift(|e| folder.fold_expr(e)))
628 }
629 Unary(uop, e) => Unary(uop, e.lift(|e| folder.fold_expr(e))),
630 Lit(lit) => Lit(folder.fold_lit(lit)),
631 Cast(e, ty) => {
632 Cast(e.lift(|e| folder.fold_expr(e)),
633 ty.lift(|t| folder.fold_ty(t)))
634 }
635 Type(e, ty) => {
636 Type(e.lift(|e| folder.fold_expr(e)),
637 ty.lift(|t| folder.fold_ty(t)))
638 }
639 If(e, if_block, else_block) => {
640 If(e.lift(|e| folder.fold_expr(e)),
641 folder.fold_block(if_block),
642 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
643 }
644 IfLet(pat, expr, block, else_block) => {
645 IfLet(pat.lift(|p| folder.fold_pat(p)),
646 expr.lift(|e| folder.fold_expr(e)),
647 folder.fold_block(block),
648 else_block.map(|v| v.lift(|e| folder.fold_expr(e))))
649 }
650 While(e, block, label) => {
651 While(e.lift(|e| folder.fold_expr(e)),
652 folder.fold_block(block),
653 label.map(|i| folder.fold_ident(i)))
654 }
655 WhileLet(pat, expr, block, label) => {
656 WhileLet(pat.lift(|p| folder.fold_pat(p)),
657 expr.lift(|e| folder.fold_expr(e)),
658 folder.fold_block(block),
659 label.map(|i| folder.fold_ident(i)))
660 }
661 ForLoop(pat, expr, block, label) => {
662 ForLoop(pat.lift(|p| folder.fold_pat(p)),
663 expr.lift(|e| folder.fold_expr(e)),
664 folder.fold_block(block),
665 label.map(|i| folder.fold_ident(i)))
666 }
667 Loop(block, label) => {
668 Loop(folder.fold_block(block),
669 label.map(|i| folder.fold_ident(i)))
670 }
671 Match(e, arms) => {
672 Match(e.lift(|e| folder.fold_expr(e)),
673 arms.lift(|Arm { attrs, pats, guard, body }: Arm| {
674 Arm {
675 attrs: attrs.lift(|a| folder.fold_attribute(a)),
676 pats: pats.lift(|p| folder.fold_pat(p)),
677 guard: guard.map(|v| v.lift(|e| folder.fold_expr(e))),
678 body: body.lift(|e| folder.fold_expr(e)),
679 }
680 }))
681 }
682 Closure(capture_by, fn_decl, expr) => {
683 Closure(capture_by,
684 fn_decl.lift(|v| folder.fold_fn_decl(v)),
685 expr.lift(|e| folder.fold_expr(e)))
686 }
687 Block(unsafety, block) => Block(unsafety, folder.fold_block(block)),
688 Assign(lhs, rhs) => {
689 Assign(lhs.lift(|e| folder.fold_expr(e)),
690 rhs.lift(|e| folder.fold_expr(e)))
691 }
692 AssignOp(bop, lhs, rhs) => {
693 AssignOp(bop,
694 lhs.lift(|e| folder.fold_expr(e)),
695 rhs.lift(|e| folder.fold_expr(e)))
696 }
697 Field(expr, name) => Field(expr.lift(|e| folder.fold_expr(e)), folder.fold_ident(name)),
698 TupField(expr, index) => TupField(expr.lift(|e| folder.fold_expr(e)), index),
699 Index(expr, index) => {
700 Index(expr.lift(|e| folder.fold_expr(e)),
701 index.lift(|e| folder.fold_expr(e)))
702 }
703 Range(lhs, rhs, limits) => {
704 Range(lhs.map(|v| v.lift(|e| folder.fold_expr(e))),
705 rhs.map(|v| v.lift(|e| folder.fold_expr(e))),
706 limits)
707 }
708 Path(qself, path) => {
709 Path(qself.map(|v| noop_fold_qself(folder, v)),
710 folder.fold_path(path))
711 }
712 AddrOf(mutability, expr) => AddrOf(mutability, expr.lift(|e| folder.fold_expr(e))),
713 Break(label, expr) => {
714 Break(label.map(|i| folder.fold_ident(i)),
715 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
716 }
717 Continue(label) => Continue(label.map(|i| folder.fold_ident(i))),
718 Ret(expr) => Ret(expr.map(|v| v.lift(|e| folder.fold_expr(e)))),
719 ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)),
720 Struct(path, fields, expr) => {
721 Struct(folder.fold_path(path),
722 fields.lift(|FieldValue { ident, expr, is_shorthand, attrs }: FieldValue| {
723 FieldValue {
724 ident: folder.fold_ident(ident),
725 expr: folder.fold_expr(expr),
726 is_shorthand: is_shorthand,
727 attrs: attrs.lift(|v| folder.fold_attribute(v)),
728 }
729 }),
730 expr.map(|v| v.lift(|e| folder.fold_expr(e))))
731 }
732 Repeat(element, number) => {
733 Repeat(element.lift(|e| folder.fold_expr(e)),
734 number.lift(|e| folder.fold_expr(e)))
735 }
736 Paren(expr) => Paren(expr.lift(|e| folder.fold_expr(e))),
737 Try(expr) => Try(expr.lift(|e| folder.fold_expr(e))),
738 },
739 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
740 }
741}
742
gnzlbg9ae88d82017-01-26 20:45:17 +0100743#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800744pub fn noop_fold_foreign_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100745 ForeignItem { ident, attrs, node, vis }: ForeignItem)
746 -> ForeignItem {
747 ForeignItem {
748 ident: folder.fold_ident(ident),
749 attrs: attrs.into_iter().map(|a| folder.fold_attribute(a)).collect(),
750 node: match node {
751 ForeignItemKind::Fn(fn_dcl, generics) => {
752 ForeignItemKind::Fn(fn_dcl.lift(|v| folder.fold_fn_decl(v)),
753 folder.fold_generics(generics))
754 }
755 ForeignItemKind::Static(ty, mutability) => {
756 ForeignItemKind::Static(ty.lift(|v| folder.fold_ty(v)), mutability)
757 }
758 },
759 vis: noop_fold_vis(folder, vis),
760 }
761}
762
gnzlbg9ae88d82017-01-26 20:45:17 +0100763#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800764pub fn noop_fold_pat<F: ?Sized + Folder>(folder: &mut F, pat: Pat) -> Pat {
David Tolnay7a1cda02017-01-29 11:50:31 -0800765 use Pat::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100766 match pat {
767 Wild => Wild,
768 Ident(binding_mode, ident, pat) => {
769 Ident(binding_mode,
770 folder.fold_ident(ident),
771 pat.map(|p| p.lift(|p| folder.fold_pat(p))))
772 }
773 Struct(path, field_patterns, dots) => {
774 Struct(folder.fold_path(path),
775 field_patterns.lift(|FieldPat { ident, pat, is_shorthand, attrs }: FieldPat| {
776 FieldPat {
777 ident: folder.fold_ident(ident),
778 pat: pat.lift(|p| folder.fold_pat(p)),
779 is_shorthand: is_shorthand,
780 attrs: attrs.lift(|a| folder.fold_attribute(a)),
781 }
782 }),
783 dots)
784 }
785 TupleStruct(path, pats, len) => {
786 TupleStruct(folder.fold_path(path),
787 pats.lift(|p| folder.fold_pat(p)),
788 len)
789 }
790 Path(qself, path) => {
791 Path(qself.map(|v| noop_fold_qself(folder, v)),
792 folder.fold_path(path))
793 }
794 Tuple(pats, len) => Tuple(pats.lift(|p| folder.fold_pat(p)), len),
795 Box(b) => Box(b.lift(|p| folder.fold_pat(p))),
796 Ref(b, mutability) => Ref(b.lift(|p| folder.fold_pat(p)), mutability),
797 Lit(expr) => Lit(expr.lift(|e| folder.fold_expr(e))),
798 Range(l, r) => {
799 Range(l.lift(|e| folder.fold_expr(e)),
800 r.lift(|e| folder.fold_expr(e)))
801 }
802 Slice(lefts, pat, rights) => {
803 Slice(lefts.lift(|p| folder.fold_pat(p)),
804 pat.map(|v| v.lift(|p| folder.fold_pat(p))),
805 rights.lift(|p| folder.fold_pat(p)))
806 }
807 Mac(mac) => Mac(folder.fold_mac(mac)),
808 }
809}
810
gnzlbg9ae88d82017-01-26 20:45:17 +0100811#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800812pub fn noop_fold_fn_decl<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800813 FnDecl { inputs, output, variadic }: FnDecl)
814 -> FnDecl {
gnzlbg9ae88d82017-01-26 20:45:17 +0100815
816 FnDecl {
817 inputs: inputs.lift(|a| {
David Tolnay7a1cda02017-01-29 11:50:31 -0800818 use FnArg::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100819 match a {
820 SelfRef(lifetime, mutability) => {
821 SelfRef(lifetime.map(|v| folder.fold_lifetime(v)), mutability)
822 }
823 SelfValue(mutability) => SelfValue(mutability),
824 Captured(pat, ty) => Captured(folder.fold_pat(pat), folder.fold_ty(ty)),
825 Ignored(ty) => Ignored(folder.fold_ty(ty)),
826 }
827 }),
828 output: folder.fold_fn_ret_ty(output),
829 variadic: variadic,
830 }
831
832}
833
gnzlbg9ae88d82017-01-26 20:45:17 +0100834#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800835pub fn noop_fold_trait_item<F: ?Sized + Folder>(folder: &mut F,
David Tolnay660b03e2017-01-29 11:26:30 -0800836 TraitItem { ident, attrs, node }: TraitItem)
837 -> TraitItem {
David Tolnay7a1cda02017-01-29 11:50:31 -0800838 use TraitItemKind::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100839 TraitItem {
840 ident: folder.fold_ident(ident),
841 attrs: attrs.lift(|v| folder.fold_attribute(v)),
842 node: match node {
843 Const(ty, expr) => Const(folder.fold_ty(ty), expr.map(|v| folder.fold_expr(v))),
844 Method(sig, block) => {
845 Method(folder.fold_method_sig(sig),
846 block.map(|v| folder.fold_block(v)))
847 }
848 Type(ty_pbs, ty) => {
849 Type(ty_pbs.lift(|v| folder.fold_ty_param_bound(v)),
850 ty.map(|v| folder.fold_ty(v)))
851 }
David Tolnay70925b72017-01-29 11:20:54 -0800852 Macro(mac) => Macro(folder.fold_mac(mac)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100853 },
854 }
855}
856
gnzlbg9ae88d82017-01-26 20:45:17 +0100857#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800858pub fn noop_fold_impl_item<F: ?Sized + Folder>(folder: &mut F,
gnzlbg9ae88d82017-01-26 20:45:17 +0100859 ImplItem { ident, vis, defaultness, attrs, node }: ImplItem)
860 -> ImplItem {
David Tolnay7a1cda02017-01-29 11:50:31 -0800861 use ImplItemKind::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100862 ImplItem {
863 ident: folder.fold_ident(ident),
864 vis: noop_fold_vis(folder, vis),
865 defaultness: defaultness,
866 attrs: attrs.lift(|v| folder.fold_attribute(v)),
867 node: match node {
868 Const(ty, expr) => Const(folder.fold_ty(ty), folder.fold_expr(expr)),
David Tolnay660b03e2017-01-29 11:26:30 -0800869 Method(sig, block) => Method(folder.fold_method_sig(sig), folder.fold_block(block)),
gnzlbg9ae88d82017-01-26 20:45:17 +0100870 Type(ty) => Type(folder.fold_ty(ty)),
871 Macro(mac) => Macro(folder.fold_mac(mac)),
872 },
873 }
874}
875
gnzlbg9ae88d82017-01-26 20:45:17 +0100876#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800877pub 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 +0100878 MethodSig {
879 unsafety: unsafety,
880 constness: constness,
881 abi: abi,
882 decl: folder.fold_fn_decl(decl),
883 generics: folder.fold_generics(generics),
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_stmt<F: ?Sized + Folder>(folder: &mut F, stmt: Stmt) -> Stmt {
David Tolnay7a1cda02017-01-29 11:50:31 -0800890 use Stmt::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100891 match stmt {
892 Local(local) => Local(local.lift(|l| folder.fold_local(l))),
893 Item(item) => Item(item.lift(|v| folder.fold_item(v))),
894 Expr(expr) => Expr(expr.lift(|v| folder.fold_expr(v))),
895 Semi(expr) => Semi(expr.lift(|v| folder.fold_expr(v))),
896 Mac(mac_stmt) => {
897 Mac(mac_stmt.lift(|(mac, style, attrs)| {
898 (folder.fold_mac(mac), style, attrs.lift(|a| folder.fold_attribute(a)))
899 }))
900 }
901 }
902
903}
904
gnzlbg9ae88d82017-01-26 20:45:17 +0100905#[cfg(feature = "full")]
David Tolnay660b03e2017-01-29 11:26:30 -0800906pub fn noop_fold_local<F: ?Sized + Folder>(folder: &mut F,
907 Local { pat, ty, init, attrs }: Local)
908 -> Local {
gnzlbg9ae88d82017-01-26 20:45:17 +0100909 Local {
910 pat: pat.lift(|v| folder.fold_pat(v)),
911 ty: ty.map(|v| v.lift(|t| folder.fold_ty(t))),
912 init: init.map(|v| v.lift(|e| folder.fold_expr(e))),
913 attrs: attrs.lift(|a| folder.fold_attribute(a)),
914 }
915}
916
917#[cfg(feature = "full")]
David Tolnay78488252017-01-29 11:22:59 -0800918pub fn noop_fold_view_path<F: ?Sized + Folder>(folder: &mut F, view_path: ViewPath) -> ViewPath {
David Tolnay7a1cda02017-01-29 11:50:31 -0800919 use ViewPath::*;
gnzlbg9ae88d82017-01-26 20:45:17 +0100920 match view_path {
921 Simple(path, ident) => Simple(folder.fold_path(path), ident.map(|i| folder.fold_ident(i))),
922 Glob(path) => Glob(folder.fold_path(path)),
923 List(path, items) => {
924 List(folder.fold_path(path),
925 items.lift(|PathListItem { name, rename }: PathListItem| {
926 PathListItem {
927 name: folder.fold_ident(name),
928 rename: rename.map(|i| folder.fold_ident(i)),
929 }
930 }))
931 }
932 }
933}