blob: c2b6d53b13cf202ffd78724a163b43226bdebff5 [file] [log] [blame]
David Tolnay55337722016-09-11 12:58:56 -07001// Adapted from libsyntax.
2
3//! AST walker. Each overridden visit method has full control over what
4//! happens with its node, it can do its own traversal of the node's children,
5//! call `visit::walk_*` to apply the default traversal algorithm, or prevent
6//! deeper traversal by doing nothing.
7//!
8//! Note: it is an important invariant that the default visitor walks the body
9//! of a function in "execution order" (more concretely, reverse post-order
10//! with respect to the CFG implied by the AST), meaning that if AST node A may
11//! execute before AST node B, then A is visited first. The borrow checker in
12//! particular relies on this property.
13//!
14//! Note: walking an AST before macro expansion is probably a bad idea. For
15//! instance, a walker looking for item names in a module will miss all of
16//! those that are created by the expansion of a macro.
17
18use super::*;
19
20/// Each method of the Visitor trait is a hook to be potentially
21/// overridden. Each method's default implementation recursively visits
22/// the substructure of the input via the corresponding `walk` method;
23/// e.g. the `visit_mod` method by default calls `visit::walk_mod`.
24///
25/// If you want to ensure that your code handles every variant
26/// explicitly, you need to override each method. (And you also need
27/// to monitor future changes to `Visitor` in case a new method with a
28/// new default implementation gets introduced.)
29pub trait Visitor: Sized {
30 fn visit_ident(&mut self, _ident: &Ident) {}
David Tolnay0e837402016-12-22 17:25:55 -050031 fn visit_derive_input(&mut self, derive_input: &DeriveInput) {
32 walk_derive_input(self, derive_input)
David Tolnay55337722016-09-11 12:58:56 -070033 }
34 fn visit_ty(&mut self, ty: &Ty) {
35 walk_ty(self, ty)
36 }
37 fn visit_generics(&mut self, generics: &Generics) {
38 walk_generics(self, generics)
39 }
40 fn visit_ty_param_bound(&mut self, bound: &TyParamBound) {
41 walk_ty_param_bound(self, bound)
42 }
43 fn visit_poly_trait_ref(&mut self, trait_ref: &PolyTraitRef, modifier: &TraitBoundModifier) {
44 walk_poly_trait_ref(self, trait_ref, modifier)
45 }
46 fn visit_variant_data(&mut self, data: &VariantData, _ident: &Ident, _generics: &Generics) {
47 walk_variant_data(self, data)
48 }
49 fn visit_field(&mut self, field: &Field) {
50 walk_field(self, field)
51 }
52 fn visit_variant(&mut self, variant: &Variant, generics: &Generics) {
53 walk_variant(self, variant, generics)
54 }
55 fn visit_lifetime(&mut self, _lifetime: &Lifetime) {}
56 fn visit_lifetime_def(&mut self, lifetime: &LifetimeDef) {
57 walk_lifetime_def(self, lifetime)
58 }
59 fn visit_path(&mut self, path: &Path) {
60 walk_path(self, path)
61 }
62 fn visit_path_segment(&mut self, path_segment: &PathSegment) {
63 walk_path_segment(self, path_segment)
64 }
65 fn visit_path_parameters(&mut self, path_parameters: &PathParameters) {
66 walk_path_parameters(self, path_parameters)
67 }
68 fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
69 walk_assoc_type_binding(self, type_binding)
70 }
71 fn visit_attribute(&mut self, _attr: &Attribute) {}
72 fn visit_fn_ret_ty(&mut self, ret_ty: &FunctionRetTy) {
73 walk_fn_ret_ty(self, ret_ty)
74 }
David Tolnay68eb4c32016-10-07 23:30:32 -070075 fn visit_const_expr(&mut self, expr: &ConstExpr) {
76 walk_const_expr(self, expr)
David Tolnay429168f2016-10-05 23:41:04 -070077 }
David Tolnay68eb4c32016-10-07 23:30:32 -070078 fn visit_lit(&mut self, _lit: &Lit) {}
Michael Layzellb52df322017-01-22 17:36:55 -050079
Michael Layzellb52df322017-01-22 17:36:55 -050080 fn visit_mac(&mut self, mac: &Mac) {
81 walk_mac(self, mac);
82 }
83
84 #[cfg(feature = "full")]
85 fn visit_crate(&mut self, _crate: &Crate) {
86 walk_crate(self, _crate);
87 }
88 #[cfg(feature = "full")]
89 fn visit_item(&mut self, item: &Item) {
90 walk_item(self, item);
91 }
92 #[cfg(feature = "full")]
93 fn visit_expr(&mut self, expr: &Expr) {
94 walk_expr(self, expr);
95 }
96 #[cfg(feature = "full")]
97 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
98 walk_foreign_item(self, foreign_item);
99 }
100 #[cfg(feature = "full")]
101 fn visit_pat(&mut self, pat: &Pat) {
102 walk_pat(self, pat);
103 }
104 #[cfg(feature = "full")]
105 fn visit_fn_decl(&mut self, fn_decl: &FnDecl) {
106 walk_fn_decl(self, fn_decl);
107 }
108 #[cfg(feature = "full")]
109 fn visit_trait_item(&mut self, trait_item: &TraitItem) {
110 walk_trait_item(self, trait_item);
111 }
112 #[cfg(feature = "full")]
113 fn visit_impl_item(&mut self, impl_item: &ImplItem) {
114 walk_impl_item(self, impl_item);
115 }
116 #[cfg(feature = "full")]
117 fn visit_method_sig(&mut self, method_sig: &MethodSig) {
118 walk_method_sig(self, method_sig);
119 }
120 #[cfg(feature = "full")]
121 fn visit_stmt(&mut self, stmt: &Stmt) {
122 walk_stmt(self, stmt);
123 }
124 #[cfg(feature = "full")]
125 fn visit_local(&mut self, local: &Local) {
126 walk_local(self, local);
127 }
128 #[cfg(feature = "full")]
129 fn visit_view_path(&mut self, view_path: &ViewPath) {
130 walk_view_path(self, view_path);
131 }
David Tolnay55337722016-09-11 12:58:56 -0700132}
133
David Tolnay55337722016-09-11 12:58:56 -0700134macro_rules! walk_list {
David Tolnaybdae3642017-01-23 00:39:55 -0800135 ($visitor:expr, $method:ident, $list:expr $(, $extra_args:expr)*) => {
David Tolnay55337722016-09-11 12:58:56 -0700136 for elem in $list {
David Tolnaybdae3642017-01-23 00:39:55 -0800137 $visitor.$method(elem $(, $extra_args)*)
David Tolnay55337722016-09-11 12:58:56 -0700138 }
139 };
David Tolnay55337722016-09-11 12:58:56 -0700140}
141
142pub fn walk_opt_ident<V: Visitor>(visitor: &mut V, opt_ident: &Option<Ident>) {
143 if let Some(ref ident) = *opt_ident {
144 visitor.visit_ident(ident);
145 }
146}
147
148pub fn walk_lifetime_def<V: Visitor>(visitor: &mut V, lifetime_def: &LifetimeDef) {
149 visitor.visit_lifetime(&lifetime_def.lifetime);
150 walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
151}
152
153pub fn walk_poly_trait_ref<V>(visitor: &mut V, trait_ref: &PolyTraitRef, _: &TraitBoundModifier)
David Tolnaydaaf7742016-10-03 11:11:43 -0700154 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700155{
156 walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
157 visitor.visit_path(&trait_ref.trait_ref);
158}
159
David Tolnay0e837402016-12-22 17:25:55 -0500160pub fn walk_derive_input<V: Visitor>(visitor: &mut V, derive_input: &DeriveInput) {
161 visitor.visit_ident(&derive_input.ident);
162 visitor.visit_generics(&derive_input.generics);
163 match derive_input.body {
David Tolnay55337722016-09-11 12:58:56 -0700164 Body::Enum(ref variants) => {
David Tolnay0e837402016-12-22 17:25:55 -0500165 walk_list!(visitor, visit_variant, variants, &derive_input.generics);
David Tolnay55337722016-09-11 12:58:56 -0700166 }
167 Body::Struct(ref variant_data) => {
David Tolnay0e837402016-12-22 17:25:55 -0500168 visitor.visit_variant_data(variant_data, &derive_input.ident, &derive_input.generics);
David Tolnay55337722016-09-11 12:58:56 -0700169 }
170 }
David Tolnay0e837402016-12-22 17:25:55 -0500171 walk_list!(visitor, visit_attribute, &derive_input.attrs);
David Tolnay55337722016-09-11 12:58:56 -0700172}
173
174pub fn walk_variant<V>(visitor: &mut V, variant: &Variant, generics: &Generics)
David Tolnaydaaf7742016-10-03 11:11:43 -0700175 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700176{
177 visitor.visit_ident(&variant.ident);
178 visitor.visit_variant_data(&variant.data, &variant.ident, generics);
179 walk_list!(visitor, visit_attribute, &variant.attrs);
180}
181
182pub fn walk_ty<V: Visitor>(visitor: &mut V, ty: &Ty) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 use ty::*;
184
David Tolnay55337722016-09-11 12:58:56 -0700185 match *ty {
Alex Crichton62a0a592017-05-22 13:58:53 -0700186 Ty::Slice(TySlice { ref ty }) |
187 Ty::Paren(TyParen { ref ty }) => visitor.visit_ty(ty),
188 Ty::Ptr(TyPtr { ref ty }) => visitor.visit_ty(&ty.ty),
189 Ty::Rptr(TyRptr { ref lifetime, ref ty }) => {
190 walk_list!(visitor, visit_lifetime, lifetime);
191 visitor.visit_ty(&ty.ty)
David Tolnay55337722016-09-11 12:58:56 -0700192 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700193 Ty::Never(_) | Ty::Infer(_) => {}
194 Ty::Tup(TyTup { ref tys }) => {
195 walk_list!(visitor, visit_ty, tys);
David Tolnay55337722016-09-11 12:58:56 -0700196 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 Ty::BareFn(TyBareFn { ref ty }) => {
198 walk_list!(visitor, visit_lifetime_def, &ty.lifetimes);
199 for argument in &ty.inputs {
David Tolnay1391b522016-10-03 21:05:45 -0700200 walk_opt_ident(visitor, &argument.name);
201 visitor.visit_ty(&argument.ty)
202 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700203 visitor.visit_fn_ret_ty(&ty.output)
David Tolnay55337722016-09-11 12:58:56 -0700204 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700205 Ty::Path(TyPath { ref qself, ref path }) => {
206 if let Some(ref qself) = *qself {
David Tolnay55337722016-09-11 12:58:56 -0700207 visitor.visit_ty(&qself.ty);
208 }
209 visitor.visit_path(path);
210 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700211 Ty::Array(TyArray { ref ty, ref amt }) => {
212 visitor.visit_ty(ty);
213 visitor.visit_const_expr(amt);
David Tolnay55337722016-09-11 12:58:56 -0700214 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700215 Ty::TraitObject(TyTraitObject { ref bounds }) |
216 Ty::ImplTrait(TyImplTrait { ref bounds }) => {
David Tolnay55337722016-09-11 12:58:56 -0700217 walk_list!(visitor, visit_ty_param_bound, bounds);
218 }
Michael Layzellb52df322017-01-22 17:36:55 -0500219 Ty::Mac(ref mac) => {
David Tolnay3f36a0a2017-01-23 17:59:46 -0800220 visitor.visit_mac(mac);
Michael Layzellb52df322017-01-22 17:36:55 -0500221 }
David Tolnay55337722016-09-11 12:58:56 -0700222 }
223}
224
225pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
226 for segment in &path.segments {
227 visitor.visit_path_segment(segment);
228 }
229}
230
231pub fn walk_path_segment<V: Visitor>(visitor: &mut V, segment: &PathSegment) {
232 visitor.visit_ident(&segment.ident);
233 visitor.visit_path_parameters(&segment.parameters);
234}
235
236pub fn walk_path_parameters<V>(visitor: &mut V, path_parameters: &PathParameters)
David Tolnaydaaf7742016-10-03 11:11:43 -0700237 where V: Visitor
David Tolnay55337722016-09-11 12:58:56 -0700238{
239 match *path_parameters {
240 PathParameters::AngleBracketed(ref data) => {
241 walk_list!(visitor, visit_ty, &data.types);
242 walk_list!(visitor, visit_lifetime, &data.lifetimes);
243 walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
244 }
245 PathParameters::Parenthesized(ref data) => {
246 walk_list!(visitor, visit_ty, &data.inputs);
247 walk_list!(visitor, visit_ty, &data.output);
248 }
249 }
250}
251
252pub fn walk_assoc_type_binding<V: Visitor>(visitor: &mut V, type_binding: &TypeBinding) {
253 visitor.visit_ident(&type_binding.ident);
254 visitor.visit_ty(&type_binding.ty);
255}
256
257pub fn walk_ty_param_bound<V: Visitor>(visitor: &mut V, bound: &TyParamBound) {
258 match *bound {
259 TyParamBound::Trait(ref ty, ref modifier) => {
260 visitor.visit_poly_trait_ref(ty, modifier);
261 }
262 TyParamBound::Region(ref lifetime) => {
263 visitor.visit_lifetime(lifetime);
264 }
265 }
266}
267
268pub fn walk_generics<V: Visitor>(visitor: &mut V, generics: &Generics) {
269 for param in &generics.ty_params {
270 visitor.visit_ident(&param.ident);
271 walk_list!(visitor, visit_ty_param_bound, &param.bounds);
272 walk_list!(visitor, visit_ty, &param.default);
273 }
274 walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
275 for predicate in &generics.where_clause.predicates {
276 match *predicate {
David Tolnaydaaf7742016-10-03 11:11:43 -0700277 WherePredicate::BoundPredicate(WhereBoundPredicate { ref bounded_ty,
278 ref bounds,
279 ref bound_lifetimes,
280 .. }) => {
David Tolnay55337722016-09-11 12:58:56 -0700281 visitor.visit_ty(bounded_ty);
282 walk_list!(visitor, visit_ty_param_bound, bounds);
283 walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
284 }
David Tolnaydaaf7742016-10-03 11:11:43 -0700285 WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime,
286 ref bounds,
287 .. }) => {
David Tolnay55337722016-09-11 12:58:56 -0700288 visitor.visit_lifetime(lifetime);
289 walk_list!(visitor, visit_lifetime, bounds);
290 }
David Tolnay05120ef2017-03-12 18:29:26 -0700291 WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
David Tolnayfa23f572017-01-23 00:19:11 -0800292 visitor.visit_ty(lhs_ty);
293 visitor.visit_ty(rhs_ty);
294 }
David Tolnay55337722016-09-11 12:58:56 -0700295 }
296 }
297}
298
299pub fn walk_fn_ret_ty<V: Visitor>(visitor: &mut V, ret_ty: &FunctionRetTy) {
300 if let FunctionRetTy::Ty(ref output_ty) = *ret_ty {
301 visitor.visit_ty(output_ty)
302 }
303}
304
David Tolnay55337722016-09-11 12:58:56 -0700305pub fn walk_variant_data<V: Visitor>(visitor: &mut V, data: &VariantData) {
306 walk_list!(visitor, visit_field, data.fields());
307}
308
309pub fn walk_field<V: Visitor>(visitor: &mut V, field: &Field) {
310 walk_opt_ident(visitor, &field.ident);
311 visitor.visit_ty(&field.ty);
312 walk_list!(visitor, visit_attribute, &field.attrs);
313}
David Tolnay429168f2016-10-05 23:41:04 -0700314
David Tolnay68eb4c32016-10-07 23:30:32 -0700315pub fn walk_const_expr<V: Visitor>(visitor: &mut V, len: &ConstExpr) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700316 use constant::*;
317 use constant::ConstExpr::*;
318
David Tolnay429168f2016-10-05 23:41:04 -0700319 match *len {
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 Call(ConstCall { ref func, ref args }) => {
321 visitor.visit_const_expr(func);
David Tolnay68eb4c32016-10-07 23:30:32 -0700322 walk_list!(visitor, visit_const_expr, args);
323 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700324 Binary(ConstBinary { ref left, ref right, .. }) => {
David Tolnay68eb4c32016-10-07 23:30:32 -0700325 visitor.visit_const_expr(left);
326 visitor.visit_const_expr(right);
327 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700328 Lit(ref lit) => {
David Tolnay68eb4c32016-10-07 23:30:32 -0700329 visitor.visit_lit(lit);
330 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700331 Cast(ConstCast { ref expr, ref ty }) => {
David Tolnay68eb4c32016-10-07 23:30:32 -0700332 visitor.visit_const_expr(expr);
333 visitor.visit_ty(ty);
334 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700335 Path(ref path) => {
David Tolnay429168f2016-10-05 23:41:04 -0700336 visitor.visit_path(path);
337 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 Index(ConstIndex { ref expr, ref index }) => {
David Tolnay67588752016-10-30 12:23:10 -0700339 visitor.visit_const_expr(expr);
340 visitor.visit_const_expr(index);
341 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700342 Unary(ConstUnary { ref expr, .. }) |
343 Paren(ConstParen { ref expr }) => {
David Tolnaye7b0d322016-10-30 10:27:23 -0700344 visitor.visit_const_expr(expr);
345 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700346 Other(ref other) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500347 #[cfg(feature = "full")]
348 fn walk_other<V: Visitor>(visitor: &mut V, other: &Expr) {
349 visitor.visit_expr(other);
350 }
351 #[cfg(not(feature = "full"))]
352 fn walk_other<V: Visitor>(_: &mut V, _: &super::constant::Other) {}
353 walk_other(visitor, other);
354 }
355 }
356}
357
Michael Layzellb52df322017-01-22 17:36:55 -0500358pub fn walk_mac<V: Visitor>(visitor: &mut V, mac: &Mac) {
359 visitor.visit_path(&mac.path);
360}
361
362#[cfg(feature = "full")]
363pub fn walk_crate<V: Visitor>(visitor: &mut V, _crate: &Crate) {
364 walk_list!(visitor, visit_attribute, &_crate.attrs);
365 walk_list!(visitor, visit_item, &_crate.items);
366}
367
368#[cfg(feature = "full")]
369pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700370 use item::*;
371
Michael Layzellb52df322017-01-22 17:36:55 -0500372 visitor.visit_ident(&item.ident);
373 walk_list!(visitor, visit_attribute, &item.attrs);
374 match item.node {
Alex Crichton62a0a592017-05-22 13:58:53 -0700375 ItemKind::ExternCrate(ItemExternCrate { ref original }) => {
376 walk_opt_ident(visitor, original);
Michael Layzellb52df322017-01-22 17:36:55 -0500377 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700378 ItemKind::Use(ItemUse { ref path }) => {
379 visitor.visit_view_path(path);
Michael Layzellb52df322017-01-22 17:36:55 -0500380 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700381 ItemKind::Static(ItemStatic { ref ty, ref expr, .. }) |
382 ItemKind::Const(ItemConst { ref ty, ref expr }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500383 visitor.visit_ty(ty);
384 visitor.visit_expr(expr);
385 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700386 ItemKind::Fn(ItemFn { ref decl, ref generics, ref block, .. }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500387 visitor.visit_fn_decl(decl);
388 visitor.visit_generics(generics);
Alex Crichton62a0a592017-05-22 13:58:53 -0700389 walk_list!(visitor, visit_stmt, &block.stmts);
Michael Layzellb52df322017-01-22 17:36:55 -0500390 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700391 ItemKind::Mod(ItemMod { ref items }) => {
392 if let Some(ref items) = *items {
Michael Layzellb52df322017-01-22 17:36:55 -0500393 walk_list!(visitor, visit_item, items);
394 }
395 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700396 ItemKind::ForeignMod(ItemForeignMod { ref items, .. }) => {
397 walk_list!(visitor, visit_foreign_item, items);
Michael Layzellb52df322017-01-22 17:36:55 -0500398 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700399 ItemKind::Ty(ItemTy { ref ty, ref generics }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500400 visitor.visit_ty(ty);
401 visitor.visit_generics(generics);
402 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 ItemKind::Enum(ItemEnum { ref variants, ref generics }) => {
404 walk_list!(visitor, visit_variant, variants, generics);
Michael Layzellb52df322017-01-22 17:36:55 -0500405 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700406 ItemKind::Struct(ItemStruct { ref data, ref generics }) |
407 ItemKind::Union(ItemUnion { ref data, ref generics }) => {
408 visitor.visit_variant_data(data, &item.ident, generics);
Michael Layzellb52df322017-01-22 17:36:55 -0500409 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700410 ItemKind::Trait(ItemTrait {
411 ref generics,
412 ref supertraits,
413 ref items,
414 ..
415 }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500416 visitor.visit_generics(generics);
Alex Crichton62a0a592017-05-22 13:58:53 -0700417 walk_list!(visitor, visit_ty_param_bound, supertraits);
418 walk_list!(visitor, visit_trait_item, items);
Michael Layzellb52df322017-01-22 17:36:55 -0500419 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700420 ItemKind::DefaultImpl(ItemDefaultImpl { ref path, .. }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500421 visitor.visit_path(path);
422 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700423 ItemKind::Impl(ItemImpl {
424 ref generics,
425 ref trait_,
426 ref self_ty,
427 ref items,
428 ..
429 }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500430 visitor.visit_generics(generics);
Alex Crichton62a0a592017-05-22 13:58:53 -0700431 if let Some(ref path) = *trait_ {
Michael Layzellb52df322017-01-22 17:36:55 -0500432 visitor.visit_path(path);
433 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700434 visitor.visit_ty(self_ty);
435 walk_list!(visitor, visit_impl_item, items);
Michael Layzellb52df322017-01-22 17:36:55 -0500436 }
David Tolnay05120ef2017-03-12 18:29:26 -0700437 ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
Michael Layzellb52df322017-01-22 17:36:55 -0500438 }
439}
440
441#[cfg(feature = "full")]
David Tolnay02a8d472017-02-19 12:59:44 -0800442#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
Michael Layzellb52df322017-01-22 17:36:55 -0500443pub fn walk_expr<V: Visitor>(visitor: &mut V, expr: &Expr) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700444 use expr::*;
445 use expr::ExprKind::*;
446
Michael Layzellb52df322017-01-22 17:36:55 -0500447 walk_list!(visitor, visit_attribute, &expr.attrs);
448 match expr.node {
Alex Crichton62a0a592017-05-22 13:58:53 -0700449 InPlace(ExprInPlace { ref place, ref value }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500450 visitor.visit_expr(place);
451 visitor.visit_expr(value);
452 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700453 Call(ExprCall { ref func, ref args }) => {
454 visitor.visit_expr(func);
Michael Layzellb52df322017-01-22 17:36:55 -0500455 walk_list!(visitor, visit_expr, args);
456 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700457 MethodCall(ExprMethodCall { ref method, ref typarams, ref args }) => {
458 visitor.visit_ident(method);
459 walk_list!(visitor, visit_ty, typarams);
Michael Layzellb52df322017-01-22 17:36:55 -0500460 walk_list!(visitor, visit_expr, args);
461 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700462 Array(ExprArray { ref exprs }) |
463 Tup(ExprTup { args: ref exprs }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500464 walk_list!(visitor, visit_expr, exprs);
465 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700466 Lit(ref lit) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500467 visitor.visit_lit(lit);
468 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700469 Cast(ExprCast { ref expr, ref ty }) |
470 Type(ExprType { ref expr, ref ty }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500471 visitor.visit_expr(expr);
472 visitor.visit_ty(ty);
473 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700474 If(ExprIf { ref cond, ref if_true, ref if_false }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500475 visitor.visit_expr(cond);
Alex Crichton62a0a592017-05-22 13:58:53 -0700476 walk_list!(visitor, visit_stmt, &if_true.stmts);
477 if let Some(ref alt) = *if_false {
Michael Layzellb52df322017-01-22 17:36:55 -0500478 visitor.visit_expr(alt);
479 }
480 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700481 IfLet(ExprIfLet { ref pat, ref expr, ref if_true, ref if_false }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500482 visitor.visit_pat(pat);
Alex Crichton62a0a592017-05-22 13:58:53 -0700483 visitor.visit_expr(expr);
484 walk_list!(visitor, visit_stmt, &if_true.stmts);
485 if let Some(ref alt) = *if_false {
Michael Layzellb52df322017-01-22 17:36:55 -0500486 visitor.visit_expr(alt);
487 }
488 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700489 While(ExprWhile { ref cond, ref body, ref label }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500490 visitor.visit_expr(cond);
491 walk_list!(visitor, visit_stmt, &body.stmts);
492 walk_opt_ident(visitor, label);
493 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700494 WhileLet(ExprWhileLet { ref pat, ref expr, ref body, ref label }) |
495 ForLoop(ExprForLoop { ref pat, ref expr, ref body, ref label }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500496 visitor.visit_pat(pat);
497 visitor.visit_expr(expr);
498 walk_list!(visitor, visit_stmt, &body.stmts);
499 walk_opt_ident(visitor, label);
500 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700501 Loop(ExprLoop { ref body, ref label }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500502 walk_list!(visitor, visit_stmt, &body.stmts);
503 walk_opt_ident(visitor, label);
504 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700505 Match(ExprMatch { ref expr, ref arms }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500506 visitor.visit_expr(expr);
David Tolnay05120ef2017-03-12 18:29:26 -0700507 for &Arm { ref attrs, ref pats, ref guard, ref body } in arms {
Michael Layzellb52df322017-01-22 17:36:55 -0500508 walk_list!(visitor, visit_attribute, attrs);
509 walk_list!(visitor, visit_pat, pats);
510 if let Some(ref guard) = *guard {
511 visitor.visit_expr(guard);
512 }
513 visitor.visit_expr(body);
514 }
515 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700516 Closure(ExprClosure { ref decl, ref body, .. }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500517 visitor.visit_fn_decl(decl);
Alex Crichton62a0a592017-05-22 13:58:53 -0700518 visitor.visit_expr(body);
Michael Layzellb52df322017-01-22 17:36:55 -0500519 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700520 Catch(ExprCatch { ref block }) |
521 Block(ExprBlock { ref block, .. }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500522 walk_list!(visitor, visit_stmt, &block.stmts);
523 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700524 Binary(ExprBinary { ref left, ref right, .. }) |
525 Assign(ExprAssign { ref left, ref right }) |
526 AssignOp(ExprAssignOp { ref left, ref right, .. }) => {
527 visitor.visit_expr(left);
528 visitor.visit_expr(right);
Michael Layzellb52df322017-01-22 17:36:55 -0500529 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700530 Field(ExprField { ref expr, ref field }) => {
531 visitor.visit_expr(expr);
Michael Layzellb52df322017-01-22 17:36:55 -0500532 visitor.visit_ident(field);
533 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700534 Index(ExprIndex { ref expr, ref index }) => {
535 visitor.visit_expr(expr);
536 visitor.visit_expr(index);
Michael Layzellb52df322017-01-22 17:36:55 -0500537 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700538 Range(ExprRange { ref from, ref to, .. }) => {
539 if let Some(ref start) = *from {
Michael Layzellb52df322017-01-22 17:36:55 -0500540 visitor.visit_expr(start);
541 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700542 if let Some(ref end) = *to {
Michael Layzellb52df322017-01-22 17:36:55 -0500543 visitor.visit_expr(end);
544 }
545 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700546 Path(ExprPath { ref qself, ref path }) => {
547 if let Some(ref qself) = *qself {
Michael Layzellb52df322017-01-22 17:36:55 -0500548 visitor.visit_ty(&qself.ty);
549 }
550 visitor.visit_path(path);
551 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700552 Break(ExprBreak { ref label, ref expr }) => {
553 walk_opt_ident(visitor, label);
554 if let Some(ref expr) = *expr {
Michael Layzellb52df322017-01-22 17:36:55 -0500555 visitor.visit_expr(expr);
556 }
557 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700558 Continue(ExprContinue { ref label }) => {
559 walk_opt_ident(visitor, label);
Michael Layzellb52df322017-01-22 17:36:55 -0500560 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700561 Ret(ExprRet { ref expr }) => {
562 if let Some(ref expr) = *expr {
Michael Layzellb52df322017-01-22 17:36:55 -0500563 visitor.visit_expr(expr);
564 }
565 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700566 Mac(ref mac) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500567 visitor.visit_mac(mac);
568 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700569 Struct(ExprStruct { ref path, ref fields, ref rest }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500570 visitor.visit_path(path);
David Tolnay05120ef2017-03-12 18:29:26 -0700571 for &FieldValue { ref ident, ref expr, .. } in fields {
Michael Layzellb52df322017-01-22 17:36:55 -0500572 visitor.visit_ident(ident);
573 visitor.visit_expr(expr);
574 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700575 if let Some(ref base) = *rest {
Michael Layzellb52df322017-01-22 17:36:55 -0500576 visitor.visit_expr(base);
577 }
578 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700579 Repeat(ExprRepeat { ref expr, ref amt }) => {
580 visitor.visit_expr(expr);
581 visitor.visit_expr(amt);
Michael Layzellb52df322017-01-22 17:36:55 -0500582 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700583 TupField(ExprTupField { ref expr, .. }) |
584 Unary(ExprUnary { ref expr, .. }) |
585 Box(ExprBox { ref expr }) |
586 AddrOf(ExprAddrOf { ref expr, .. }) |
587 Paren(ExprParen { ref expr }) |
588 Try(ExprTry { ref expr }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500589 visitor.visit_expr(expr);
590 }
591 }
592}
593
594#[cfg(feature = "full")]
595pub fn walk_foreign_item<V: Visitor>(visitor: &mut V, foreign_item: &ForeignItem) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700596 use item::*;
597
Michael Layzellb52df322017-01-22 17:36:55 -0500598 visitor.visit_ident(&foreign_item.ident);
599 walk_list!(visitor, visit_attribute, &foreign_item.attrs);
600 match foreign_item.node {
Alex Crichton62a0a592017-05-22 13:58:53 -0700601 ForeignItemKind::Fn(ForeignItemFn { ref decl, ref generics }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500602 visitor.visit_fn_decl(decl);
603 visitor.visit_generics(generics);
604 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700605 ForeignItemKind::Static(ForeignItemStatic { ref ty, .. }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500606 visitor.visit_ty(ty);
607 }
608 }
609}
610
611#[cfg(feature = "full")]
612pub fn walk_pat<V: Visitor>(visitor: &mut V, pat: &Pat) {
613 match *pat {
614 Pat::Wild => {}
615 Pat::Ident(_, ref ident, ref maybe_pat) => {
616 visitor.visit_ident(ident);
617 if let Some(ref pat) = *maybe_pat {
618 visitor.visit_pat(pat);
619 }
620 }
621 Pat::Struct(ref path, ref field_pats, _) => {
622 visitor.visit_path(path);
David Tolnay05120ef2017-03-12 18:29:26 -0700623 for &FieldPat { ref ident, ref pat, .. } in field_pats {
Michael Layzellb52df322017-01-22 17:36:55 -0500624 visitor.visit_ident(ident);
625 visitor.visit_pat(pat);
626 }
627 }
628 Pat::TupleStruct(ref path, ref pats, _) => {
629 visitor.visit_path(path);
630 walk_list!(visitor, visit_pat, pats);
631 }
632 Pat::Path(ref maybe_qself, ref path) => {
633 if let Some(ref qself) = *maybe_qself {
634 visitor.visit_ty(&qself.ty);
635 }
636 visitor.visit_path(path);
637 }
638 Pat::Tuple(ref pats, _) => {
639 walk_list!(visitor, visit_pat, pats);
640 }
641 Pat::Box(ref pat) |
642 Pat::Ref(ref pat, _) => {
643 visitor.visit_pat(pat);
644 }
645 Pat::Lit(ref expr) => {
646 visitor.visit_expr(expr);
647 }
Arnavion1992e2f2017-04-25 01:47:46 -0700648 Pat::Range(ref start, ref end, _) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500649 visitor.visit_expr(start);
650 visitor.visit_expr(end);
651 }
652 Pat::Slice(ref start, ref maybe_mid, ref end) => {
653 walk_list!(visitor, visit_pat, start);
654 if let Some(ref mid) = *maybe_mid {
655 visitor.visit_pat(mid);
656 }
657 walk_list!(visitor, visit_pat, end);
658 }
659 Pat::Mac(ref mac) => {
660 visitor.visit_mac(mac);
661 }
662 }
663}
664
665#[cfg(feature = "full")]
666pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, fn_decl: &FnDecl) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700667 use item::*;
668
Michael Layzellb52df322017-01-22 17:36:55 -0500669 for input in &fn_decl.inputs {
670 match *input {
Alex Crichton62a0a592017-05-22 13:58:53 -0700671 FnArg::SelfRef(_) |
David Tolnay05120ef2017-03-12 18:29:26 -0700672 FnArg::SelfValue(_) => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700673 FnArg::Captured(ArgCaptured { ref pat, ref ty }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500674 visitor.visit_pat(pat);
675 visitor.visit_ty(ty);
676 }
677 FnArg::Ignored(ref ty) => {
678 visitor.visit_ty(ty);
679 }
680 }
681 }
682 visitor.visit_fn_ret_ty(&fn_decl.output);
683}
684
685#[cfg(feature = "full")]
686pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700687 use item::*;
688
Michael Layzellb52df322017-01-22 17:36:55 -0500689 visitor.visit_ident(&trait_item.ident);
690 walk_list!(visitor, visit_attribute, &trait_item.attrs);
691 match trait_item.node {
Alex Crichton62a0a592017-05-22 13:58:53 -0700692 TraitItemKind::Const(TraitItemConst { ref ty, ref default }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500693 visitor.visit_ty(ty);
Alex Crichton62a0a592017-05-22 13:58:53 -0700694 if let Some(ref expr) = *default {
Michael Layzellb52df322017-01-22 17:36:55 -0500695 visitor.visit_expr(expr);
696 }
697 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700698 TraitItemKind::Method(TraitItemMethod { ref sig, ref default }) => {
699 visitor.visit_method_sig(sig);
700 if let Some(ref block) = *default {
Michael Layzellb52df322017-01-22 17:36:55 -0500701 walk_list!(visitor, visit_stmt, &block.stmts);
702 }
703 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700704 TraitItemKind::Type(TraitItemType { ref bounds, ref default }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500705 walk_list!(visitor, visit_ty_param_bound, bounds);
Alex Crichton62a0a592017-05-22 13:58:53 -0700706 if let Some(ref ty) = *default {
Michael Layzellb52df322017-01-22 17:36:55 -0500707 visitor.visit_ty(ty);
708 }
709 }
710 TraitItemKind::Macro(ref mac) => {
711 visitor.visit_mac(mac);
712 }
713 }
714}
715
716#[cfg(feature = "full")]
717pub fn walk_impl_item<V: Visitor>(visitor: &mut V, impl_item: &ImplItem) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700718 use item::*;
719
Michael Layzellb52df322017-01-22 17:36:55 -0500720 visitor.visit_ident(&impl_item.ident);
721 walk_list!(visitor, visit_attribute, &impl_item.attrs);
722 match impl_item.node {
Alex Crichton62a0a592017-05-22 13:58:53 -0700723 ImplItemKind::Const(ImplItemConst { ref ty, ref expr }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500724 visitor.visit_ty(ty);
725 visitor.visit_expr(expr);
726 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700727 ImplItemKind::Method(ImplItemMethod { ref sig, ref block }) => {
728 visitor.visit_method_sig(sig);
Michael Layzellb52df322017-01-22 17:36:55 -0500729 walk_list!(visitor, visit_stmt, &block.stmts);
730 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700731 ImplItemKind::Type(ImplItemType { ref ty }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500732 visitor.visit_ty(ty);
733 }
734 ImplItemKind::Macro(ref mac) => {
735 visitor.visit_mac(mac);
736 }
737 }
738}
739
740#[cfg(feature = "full")]
741pub fn walk_method_sig<V: Visitor>(visitor: &mut V, method_sig: &MethodSig) {
742 visitor.visit_fn_decl(&method_sig.decl);
743 visitor.visit_generics(&method_sig.generics);
744}
745
746#[cfg(feature = "full")]
747pub fn walk_stmt<V: Visitor>(visitor: &mut V, stmt: &Stmt) {
748 match *stmt {
749 Stmt::Local(ref local) => {
750 visitor.visit_local(local);
751 }
752 Stmt::Item(ref item) => {
753 visitor.visit_item(item);
754 }
755 Stmt::Expr(ref expr) |
756 Stmt::Semi(ref expr) => {
757 visitor.visit_expr(expr);
758 }
759 Stmt::Mac(ref details) => {
760 let (ref mac, _, ref attrs) = **details;
761 visitor.visit_mac(mac);
762 walk_list!(visitor, visit_attribute, attrs);
763 }
764 }
765}
766
767#[cfg(feature = "full")]
768pub fn walk_local<V: Visitor>(visitor: &mut V, local: &Local) {
769 visitor.visit_pat(&local.pat);
770 if let Some(ref ty) = local.ty {
771 visitor.visit_ty(ty);
772 }
773 if let Some(ref init) = local.init {
774 visitor.visit_expr(init);
775 }
776 walk_list!(visitor, visit_attribute, &local.attrs);
777}
778
779#[cfg(feature = "full")]
780pub fn walk_view_path<V: Visitor>(visitor: &mut V, view_path: &ViewPath) {
Alex Crichton62a0a592017-05-22 13:58:53 -0700781 use item::*;
Michael Layzellb52df322017-01-22 17:36:55 -0500782 match *view_path {
Alex Crichton62a0a592017-05-22 13:58:53 -0700783 ViewPath::Simple(PathSimple { ref path, ref rename }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500784 visitor.visit_path(path);
Alex Crichton62a0a592017-05-22 13:58:53 -0700785 walk_opt_ident(visitor, rename);
Michael Layzellb52df322017-01-22 17:36:55 -0500786 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700787 ViewPath::Glob(PathGlob { ref path }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500788 visitor.visit_path(path);
789 }
Alex Crichton62a0a592017-05-22 13:58:53 -0700790 ViewPath::List(PathList { ref path, ref items }) => {
Michael Layzellb52df322017-01-22 17:36:55 -0500791 visitor.visit_path(path);
David Tolnay05120ef2017-03-12 18:29:26 -0700792 for &PathListItem { ref name, ref rename } in items {
Michael Layzellb52df322017-01-22 17:36:55 -0500793 visitor.visit_ident(name);
794 walk_opt_ident(visitor, rename);
795 }
796 }
David Tolnay429168f2016-10-05 23:41:04 -0700797 }
798}