]>
Commit | Line | Data |
---|---|---|
1 | //! HIR walker for walking the contents of nodes. | |
2 | //! | |
3 | //! **For an overview of the visitor strategy, see the docs on the | |
4 | //! `super::itemlikevisit::ItemLikeVisitor` trait.** | |
5 | //! | |
6 | //! If you have decided to use this visitor, here are some general | |
7 | //! notes on how to do so: | |
8 | //! | |
9 | //! Each overridden visit method has full control over what | |
10 | //! happens with its node, it can do its own traversal of the node's children, | |
11 | //! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent | |
12 | //! deeper traversal by doing nothing. | |
13 | //! | |
14 | //! When visiting the HIR, the contents of nested items are NOT visited | |
15 | //! by default. This is different from the AST visitor, which does a deep walk. | |
16 | //! Hence this module is called `intravisit`; see the method `visit_nested_item` | |
17 | //! for more details. | |
18 | //! | |
19 | //! Note: it is an important invariant that the default visitor walks | |
20 | //! the body of a function in "execution order" - more concretely, if | |
21 | //! we consider the reverse post-order (RPO) of the CFG implied by the HIR, | |
22 | //! then a pre-order traversal of the HIR is consistent with the CFG RPO | |
23 | //! on the *initial CFG point* of each HIR node, while a post-order traversal | |
24 | //! of the HIR is consistent with the CFG RPO on each *final CFG point* of | |
25 | //! each CFG node. | |
26 | //! | |
27 | //! One thing that follows is that if HIR node A always starts/ends executing | |
28 | //! before HIR node B, then A appears in traversal pre/postorder before B, | |
29 | //! respectively. (This follows from RPO respecting CFG domination). | |
30 | //! | |
31 | //! This order consistency is required in a few places in rustc, for | |
32 | //! example generator inference, and possibly also HIR borrowck. | |
33 | ||
34 | use super::itemlikevisit::DeepVisitor; | |
35 | ||
36 | use crate::hir::*; | |
37 | use crate::hir::map::Map; | |
38 | ||
39 | use syntax::ast::{Ident, Name, Attribute}; | |
40 | use syntax_pos::Span; | |
41 | ||
42 | #[derive(Copy, Clone)] | |
43 | pub enum FnKind<'a> { | |
44 | /// `#[xxx] pub async/const/extern "Abi" fn foo()` | |
45 | ItemFn(Ident, &'a Generics, FnHeader, &'a Visibility, &'a [Attribute]), | |
46 | ||
47 | /// `fn foo(&self)` | |
48 | Method(Ident, &'a FnSig, Option<&'a Visibility>, &'a [Attribute]), | |
49 | ||
50 | /// `|x, y| {}` | |
51 | Closure(&'a [Attribute]), | |
52 | } | |
53 | ||
54 | impl<'a> FnKind<'a> { | |
55 | pub fn attrs(&self) -> &'a [Attribute] { | |
56 | match *self { | |
57 | FnKind::ItemFn(.., attrs) => attrs, | |
58 | FnKind::Method(.., attrs) => attrs, | |
59 | FnKind::Closure(attrs) => attrs, | |
60 | } | |
61 | } | |
62 | ||
63 | pub fn header(&self) -> Option<&FnHeader> { | |
64 | match *self { | |
65 | FnKind::ItemFn(_, _, ref header, _, _) => Some(header), | |
66 | FnKind::Method(_, ref sig, _, _) => Some(&sig.header), | |
67 | FnKind::Closure(_) => None, | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | /// Specifies what nested things a visitor wants to visit. The most | |
73 | /// common choice is `OnlyBodies`, which will cause the visitor to | |
74 | /// visit fn bodies for fns that it encounters, but skip over nested | |
75 | /// item-like things. | |
76 | /// | |
77 | /// See the comments on `ItemLikeVisitor` for more details on the overall | |
78 | /// visit strategy. | |
79 | pub enum NestedVisitorMap<'this, 'tcx> { | |
80 | /// Do not visit any nested things. When you add a new | |
81 | /// "non-nested" thing, you will want to audit such uses to see if | |
82 | /// they remain valid. | |
83 | /// | |
84 | /// Use this if you are only walking some particular kind of tree | |
85 | /// (i.e., a type, or fn signature) and you don't want to thread a | |
86 | /// HIR map around. | |
87 | None, | |
88 | ||
89 | /// Do not visit nested item-like things, but visit nested things | |
90 | /// that are inside of an item-like. | |
91 | /// | |
92 | /// **This is the most common choice.** A very common pattern is | |
93 | /// to use `visit_all_item_likes()` as an outer loop, | |
94 | /// and to have the visitor that visits the contents of each item | |
95 | /// using this setting. | |
96 | OnlyBodies(&'this Map<'tcx>), | |
97 | ||
98 | /// Visits all nested things, including item-likes. | |
99 | /// | |
100 | /// **This is an unusual choice.** It is used when you want to | |
101 | /// process everything within their lexical context. Typically you | |
102 | /// kick off the visit by doing `walk_krate()`. | |
103 | All(&'this Map<'tcx>), | |
104 | } | |
105 | ||
106 | impl<'this, 'tcx> NestedVisitorMap<'this, 'tcx> { | |
107 | /// Returns the map to use for an "intra item-like" thing (if any). | |
108 | /// E.g., function body. | |
109 | pub fn intra(self) -> Option<&'this Map<'tcx>> { | |
110 | match self { | |
111 | NestedVisitorMap::None => None, | |
112 | NestedVisitorMap::OnlyBodies(map) => Some(map), | |
113 | NestedVisitorMap::All(map) => Some(map), | |
114 | } | |
115 | } | |
116 | ||
117 | /// Returns the map to use for an "item-like" thing (if any). | |
118 | /// E.g., item, impl-item. | |
119 | pub fn inter(self) -> Option<&'this Map<'tcx>> { | |
120 | match self { | |
121 | NestedVisitorMap::None => None, | |
122 | NestedVisitorMap::OnlyBodies(_) => None, | |
123 | NestedVisitorMap::All(map) => Some(map), | |
124 | } | |
125 | } | |
126 | } | |
127 | ||
128 | /// Each method of the Visitor trait is a hook to be potentially | |
129 | /// overridden. Each method's default implementation recursively visits | |
130 | /// the substructure of the input via the corresponding `walk` method; | |
131 | /// e.g., the `visit_mod` method by default calls `intravisit::walk_mod`. | |
132 | /// | |
133 | /// Note that this visitor does NOT visit nested items by default | |
134 | /// (this is why the module is called `intravisit`, to distinguish it | |
135 | /// from the AST's `visit` module, which acts differently). If you | |
136 | /// simply want to visit all items in the crate in some order, you | |
137 | /// should call `Crate::visit_all_items`. Otherwise, see the comment | |
138 | /// on `visit_nested_item` for details on how to visit nested items. | |
139 | /// | |
140 | /// If you want to ensure that your code handles every variant | |
141 | /// explicitly, you need to override each method. (And you also need | |
142 | /// to monitor future changes to `Visitor` in case a new method with a | |
143 | /// new default implementation gets introduced.) | |
144 | pub trait Visitor<'v>: Sized { | |
145 | /////////////////////////////////////////////////////////////////////////// | |
146 | // Nested items. | |
147 | ||
148 | /// The default versions of the `visit_nested_XXX` routines invoke | |
149 | /// this method to get a map to use. By selecting an enum variant, | |
150 | /// you control which kinds of nested HIR are visited; see | |
151 | /// `NestedVisitorMap` for details. By "nested HIR", we are | |
152 | /// referring to bits of HIR that are not directly embedded within | |
153 | /// one another but rather indirectly, through a table in the | |
154 | /// crate. This is done to control dependencies during incremental | |
155 | /// compilation: the non-inline bits of HIR can be tracked and | |
156 | /// hashed separately. | |
157 | /// | |
158 | /// **If for some reason you want the nested behavior, but don't | |
159 | /// have a `Map` at your disposal:** then you should override the | |
160 | /// `visit_nested_XXX` methods, and override this method to | |
161 | /// `panic!()`. This way, if a new `visit_nested_XXX` variant is | |
162 | /// added in the future, we will see the panic in your code and | |
163 | /// fix it appropriately. | |
164 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v>; | |
165 | ||
166 | /// Invoked when a nested item is encountered. By default does | |
167 | /// nothing unless you override `nested_visit_map` to return other than | |
168 | /// `None`, in which case it will walk the item. **You probably | |
169 | /// don't want to override this method** -- instead, override | |
170 | /// `nested_visit_map` or use the "shallow" or "deep" visit | |
171 | /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only | |
172 | /// reason to override this method is if you want a nested pattern | |
173 | /// but cannot supply a `Map`; see `nested_visit_map` for advice. | |
174 | #[allow(unused_variables)] | |
175 | fn visit_nested_item(&mut self, id: ItemId) { | |
176 | let opt_item = self.nested_visit_map().inter().map(|map| map.expect_item(id.id)); | |
177 | if let Some(item) = opt_item { | |
178 | self.visit_item(item); | |
179 | } | |
180 | } | |
181 | ||
182 | /// Like `visit_nested_item()`, but for trait items. See | |
183 | /// `visit_nested_item()` for advice on when to override this | |
184 | /// method. | |
185 | #[allow(unused_variables)] | |
186 | fn visit_nested_trait_item(&mut self, id: TraitItemId) { | |
187 | let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id)); | |
188 | if let Some(item) = opt_item { | |
189 | self.visit_trait_item(item); | |
190 | } | |
191 | } | |
192 | ||
193 | /// Like `visit_nested_item()`, but for impl items. See | |
194 | /// `visit_nested_item()` for advice on when to override this | |
195 | /// method. | |
196 | #[allow(unused_variables)] | |
197 | fn visit_nested_impl_item(&mut self, id: ImplItemId) { | |
198 | let opt_item = self.nested_visit_map().inter().map(|map| map.impl_item(id)); | |
199 | if let Some(item) = opt_item { | |
200 | self.visit_impl_item(item); | |
201 | } | |
202 | } | |
203 | ||
204 | /// Invoked to visit the body of a function, method or closure. Like | |
205 | /// visit_nested_item, does nothing by default unless you override | |
206 | /// `nested_visit_map` to return other than `None`, in which case it will walk | |
207 | /// the body. | |
208 | fn visit_nested_body(&mut self, id: BodyId) { | |
209 | let opt_body = self.nested_visit_map().intra().map(|map| map.body(id)); | |
210 | if let Some(body) = opt_body { | |
211 | self.visit_body(body); | |
212 | } | |
213 | } | |
214 | ||
215 | fn visit_param(&mut self, param: &'v Param) { | |
216 | walk_param(self, param) | |
217 | } | |
218 | ||
219 | /// Visits the top-level item and (optionally) nested items / impl items. See | |
220 | /// `visit_nested_item` for details. | |
221 | fn visit_item(&mut self, i: &'v Item) { | |
222 | walk_item(self, i) | |
223 | } | |
224 | ||
225 | fn visit_body(&mut self, b: &'v Body) { | |
226 | walk_body(self, b); | |
227 | } | |
228 | ||
229 | /// When invoking `visit_all_item_likes()`, you need to supply an | |
230 | /// item-like visitor. This method converts a "intra-visit" | |
231 | /// visitor into an item-like visitor that walks the entire tree. | |
232 | /// If you use this, you probably don't want to process the | |
233 | /// contents of nested item-like things, since the outer loop will | |
234 | /// visit them as well. | |
235 | fn as_deep_visitor<'s>(&'s mut self) -> DeepVisitor<'s, Self> { | |
236 | DeepVisitor::new(self) | |
237 | } | |
238 | ||
239 | /////////////////////////////////////////////////////////////////////////// | |
240 | ||
241 | fn visit_id(&mut self, _hir_id: HirId) { | |
242 | // Nothing to do. | |
243 | } | |
244 | fn visit_name(&mut self, _span: Span, _name: Name) { | |
245 | // Nothing to do. | |
246 | } | |
247 | fn visit_ident(&mut self, ident: Ident) { | |
248 | walk_ident(self, ident) | |
249 | } | |
250 | fn visit_mod(&mut self, m: &'v Mod, _s: Span, n: HirId) { | |
251 | walk_mod(self, m, n) | |
252 | } | |
253 | fn visit_foreign_item(&mut self, i: &'v ForeignItem) { | |
254 | walk_foreign_item(self, i) | |
255 | } | |
256 | fn visit_local(&mut self, l: &'v Local) { | |
257 | walk_local(self, l) | |
258 | } | |
259 | fn visit_block(&mut self, b: &'v Block) { | |
260 | walk_block(self, b) | |
261 | } | |
262 | fn visit_stmt(&mut self, s: &'v Stmt) { | |
263 | walk_stmt(self, s) | |
264 | } | |
265 | fn visit_arm(&mut self, a: &'v Arm) { | |
266 | walk_arm(self, a) | |
267 | } | |
268 | fn visit_pat(&mut self, p: &'v Pat) { | |
269 | walk_pat(self, p) | |
270 | } | |
271 | fn visit_anon_const(&mut self, c: &'v AnonConst) { | |
272 | walk_anon_const(self, c) | |
273 | } | |
274 | fn visit_expr(&mut self, ex: &'v Expr) { | |
275 | walk_expr(self, ex) | |
276 | } | |
277 | fn visit_ty(&mut self, t: &'v Ty) { | |
278 | walk_ty(self, t) | |
279 | } | |
280 | fn visit_generic_param(&mut self, p: &'v GenericParam) { | |
281 | walk_generic_param(self, p) | |
282 | } | |
283 | fn visit_generics(&mut self, g: &'v Generics) { | |
284 | walk_generics(self, g) | |
285 | } | |
286 | fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) { | |
287 | walk_where_predicate(self, predicate) | |
288 | } | |
289 | fn visit_fn_decl(&mut self, fd: &'v FnDecl) { | |
290 | walk_fn_decl(self, fd) | |
291 | } | |
292 | fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: BodyId, s: Span, id: HirId) { | |
293 | walk_fn(self, fk, fd, b, s, id) | |
294 | } | |
295 | fn visit_use(&mut self, path: &'v Path, hir_id: HirId) { | |
296 | walk_use(self, path, hir_id) | |
297 | } | |
298 | fn visit_trait_item(&mut self, ti: &'v TraitItem) { | |
299 | walk_trait_item(self, ti) | |
300 | } | |
301 | fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) { | |
302 | walk_trait_item_ref(self, ii) | |
303 | } | |
304 | fn visit_impl_item(&mut self, ii: &'v ImplItem) { | |
305 | walk_impl_item(self, ii) | |
306 | } | |
307 | fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef) { | |
308 | walk_impl_item_ref(self, ii) | |
309 | } | |
310 | fn visit_trait_ref(&mut self, t: &'v TraitRef) { | |
311 | walk_trait_ref(self, t) | |
312 | } | |
313 | fn visit_param_bound(&mut self, bounds: &'v GenericBound) { | |
314 | walk_param_bound(self, bounds) | |
315 | } | |
316 | fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) { | |
317 | walk_poly_trait_ref(self, t, m) | |
318 | } | |
319 | fn visit_variant_data(&mut self, | |
320 | s: &'v VariantData, | |
321 | _: Name, | |
322 | _: &'v Generics, | |
323 | _parent_id: HirId, | |
324 | _: Span) { | |
325 | walk_struct_def(self, s) | |
326 | } | |
327 | fn visit_struct_field(&mut self, s: &'v StructField) { | |
328 | walk_struct_field(self, s) | |
329 | } | |
330 | fn visit_enum_def(&mut self, | |
331 | enum_definition: &'v EnumDef, | |
332 | generics: &'v Generics, | |
333 | item_id: HirId, | |
334 | _: Span) { | |
335 | walk_enum_def(self, enum_definition, generics, item_id) | |
336 | } | |
337 | fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: HirId) { | |
338 | walk_variant(self, v, g, item_id) | |
339 | } | |
340 | fn visit_label(&mut self, label: &'v Label) { | |
341 | walk_label(self, label) | |
342 | } | |
343 | fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg) { | |
344 | match generic_arg { | |
345 | GenericArg::Lifetime(lt) => self.visit_lifetime(lt), | |
346 | GenericArg::Type(ty) => self.visit_ty(ty), | |
347 | GenericArg::Const(ct) => self.visit_anon_const(&ct.value), | |
348 | } | |
349 | } | |
350 | fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { | |
351 | walk_lifetime(self, lifetime) | |
352 | } | |
353 | fn visit_qpath(&mut self, qpath: &'v QPath, id: HirId, span: Span) { | |
354 | walk_qpath(self, qpath, id, span) | |
355 | } | |
356 | fn visit_path(&mut self, path: &'v Path, _id: HirId) { | |
357 | walk_path(self, path) | |
358 | } | |
359 | fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { | |
360 | walk_path_segment(self, path_span, path_segment) | |
361 | } | |
362 | fn visit_generic_args(&mut self, path_span: Span, generic_args: &'v GenericArgs) { | |
363 | walk_generic_args(self, path_span, generic_args) | |
364 | } | |
365 | fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) { | |
366 | walk_assoc_type_binding(self, type_binding) | |
367 | } | |
368 | fn visit_attribute(&mut self, _attr: &'v Attribute) { | |
369 | } | |
370 | fn visit_macro_def(&mut self, macro_def: &'v MacroDef) { | |
371 | walk_macro_def(self, macro_def) | |
372 | } | |
373 | fn visit_vis(&mut self, vis: &'v Visibility) { | |
374 | walk_vis(self, vis) | |
375 | } | |
376 | fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) { | |
377 | walk_associated_item_kind(self, kind); | |
378 | } | |
379 | fn visit_defaultness(&mut self, defaultness: &'v Defaultness) { | |
380 | walk_defaultness(self, defaultness); | |
381 | } | |
382 | } | |
383 | ||
384 | /// Walks the contents of a crate. See also `Crate::visit_all_items`. | |
385 | pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) { | |
386 | visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID); | |
387 | walk_list!(visitor, visit_attribute, &krate.attrs); | |
388 | walk_list!(visitor, visit_macro_def, &krate.exported_macros); | |
389 | } | |
390 | ||
391 | pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) { | |
392 | visitor.visit_id(macro_def.hir_id); | |
393 | visitor.visit_name(macro_def.span, macro_def.name); | |
394 | walk_list!(visitor, visit_attribute, ¯o_def.attrs); | |
395 | } | |
396 | ||
397 | pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod, mod_hir_id: HirId) { | |
398 | visitor.visit_id(mod_hir_id); | |
399 | for &item_id in &module.item_ids { | |
400 | visitor.visit_nested_item(item_id); | |
401 | } | |
402 | } | |
403 | ||
404 | pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) { | |
405 | walk_list!(visitor, visit_param, &body.params); | |
406 | visitor.visit_expr(&body.value); | |
407 | } | |
408 | ||
409 | pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { | |
410 | // Intentionally visiting the expr first - the initialization expr | |
411 | // dominates the local's definition. | |
412 | walk_list!(visitor, visit_expr, &local.init); | |
413 | walk_list!(visitor, visit_attribute, local.attrs.iter()); | |
414 | visitor.visit_id(local.hir_id); | |
415 | visitor.visit_pat(&local.pat); | |
416 | walk_list!(visitor, visit_ty, &local.ty); | |
417 | } | |
418 | ||
419 | pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) { | |
420 | visitor.visit_name(ident.span, ident.name); | |
421 | } | |
422 | ||
423 | pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) { | |
424 | visitor.visit_ident(label.ident); | |
425 | } | |
426 | ||
427 | pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { | |
428 | visitor.visit_id(lifetime.hir_id); | |
429 | match lifetime.name { | |
430 | LifetimeName::Param(ParamName::Plain(ident)) => { | |
431 | visitor.visit_ident(ident); | |
432 | } | |
433 | LifetimeName::Param(ParamName::Fresh(_)) | | |
434 | LifetimeName::Param(ParamName::Error) | | |
435 | LifetimeName::Static | | |
436 | LifetimeName::Error | | |
437 | LifetimeName::Implicit | | |
438 | LifetimeName::ImplicitObjectLifetimeDefault | | |
439 | LifetimeName::Underscore => {} | |
440 | } | |
441 | } | |
442 | ||
443 | pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, | |
444 | trait_ref: &'v PolyTraitRef, | |
445 | _modifier: TraitBoundModifier) | |
446 | where V: Visitor<'v> | |
447 | { | |
448 | walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params); | |
449 | visitor.visit_trait_ref(&trait_ref.trait_ref); | |
450 | } | |
451 | ||
452 | pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef) | |
453 | where V: Visitor<'v> | |
454 | { | |
455 | visitor.visit_id(trait_ref.hir_ref_id); | |
456 | visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id) | |
457 | } | |
458 | ||
459 | pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param) { | |
460 | visitor.visit_id(param.hir_id); | |
461 | visitor.visit_pat(¶m.pat); | |
462 | walk_list!(visitor, visit_attribute, ¶m.attrs); | |
463 | } | |
464 | ||
465 | pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { | |
466 | visitor.visit_vis(&item.vis); | |
467 | visitor.visit_ident(item.ident); | |
468 | match item.kind { | |
469 | ItemKind::ExternCrate(orig_name) => { | |
470 | visitor.visit_id(item.hir_id); | |
471 | if let Some(orig_name) = orig_name { | |
472 | visitor.visit_name(item.span, orig_name); | |
473 | } | |
474 | } | |
475 | ItemKind::Use(ref path, _) => { | |
476 | visitor.visit_use(path, item.hir_id); | |
477 | } | |
478 | ItemKind::Static(ref typ, _, body) | | |
479 | ItemKind::Const(ref typ, body) => { | |
480 | visitor.visit_id(item.hir_id); | |
481 | visitor.visit_ty(typ); | |
482 | visitor.visit_nested_body(body); | |
483 | } | |
484 | ItemKind::Fn(ref sig, ref generics, body_id) => { | |
485 | visitor.visit_fn(FnKind::ItemFn(item.ident, | |
486 | generics, | |
487 | sig.header, | |
488 | &item.vis, | |
489 | &item.attrs), | |
490 | &sig.decl, | |
491 | body_id, | |
492 | item.span, | |
493 | item.hir_id) | |
494 | } | |
495 | ItemKind::Mod(ref module) => { | |
496 | // `visit_mod()` takes care of visiting the `Item`'s `HirId`. | |
497 | visitor.visit_mod(module, item.span, item.hir_id) | |
498 | } | |
499 | ItemKind::ForeignMod(ref foreign_module) => { | |
500 | visitor.visit_id(item.hir_id); | |
501 | walk_list!(visitor, visit_foreign_item, &foreign_module.items); | |
502 | } | |
503 | ItemKind::GlobalAsm(_) => { | |
504 | visitor.visit_id(item.hir_id); | |
505 | } | |
506 | ItemKind::TyAlias(ref ty, ref generics) => { | |
507 | visitor.visit_id(item.hir_id); | |
508 | visitor.visit_ty(ty); | |
509 | visitor.visit_generics(generics) | |
510 | } | |
511 | ItemKind::OpaqueTy(OpaqueTy { | |
512 | ref generics, | |
513 | ref bounds, | |
514 | .. | |
515 | }) => { | |
516 | visitor.visit_id(item.hir_id); | |
517 | walk_generics(visitor, generics); | |
518 | walk_list!(visitor, visit_param_bound, bounds); | |
519 | } | |
520 | ItemKind::Enum(ref enum_definition, ref generics) => { | |
521 | visitor.visit_generics(generics); | |
522 | // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. | |
523 | visitor.visit_enum_def(enum_definition, generics, item.hir_id, item.span) | |
524 | } | |
525 | ItemKind::Impl( | |
526 | .., | |
527 | ref generics, | |
528 | ref opt_trait_reference, | |
529 | ref typ, | |
530 | ref impl_item_refs | |
531 | ) => { | |
532 | visitor.visit_id(item.hir_id); | |
533 | visitor.visit_generics(generics); | |
534 | walk_list!(visitor, visit_trait_ref, opt_trait_reference); | |
535 | visitor.visit_ty(typ); | |
536 | walk_list!(visitor, visit_impl_item_ref, impl_item_refs); | |
537 | } | |
538 | ItemKind::Struct(ref struct_definition, ref generics) | | |
539 | ItemKind::Union(ref struct_definition, ref generics) => { | |
540 | visitor.visit_generics(generics); | |
541 | visitor.visit_id(item.hir_id); | |
542 | visitor.visit_variant_data(struct_definition, item.ident.name, generics, item.hir_id, | |
543 | item.span); | |
544 | } | |
545 | ItemKind::Trait(.., ref generics, ref bounds, ref trait_item_refs) => { | |
546 | visitor.visit_id(item.hir_id); | |
547 | visitor.visit_generics(generics); | |
548 | walk_list!(visitor, visit_param_bound, bounds); | |
549 | walk_list!(visitor, visit_trait_item_ref, trait_item_refs); | |
550 | } | |
551 | ItemKind::TraitAlias(ref generics, ref bounds) => { | |
552 | visitor.visit_id(item.hir_id); | |
553 | visitor.visit_generics(generics); | |
554 | walk_list!(visitor, visit_param_bound, bounds); | |
555 | } | |
556 | } | |
557 | walk_list!(visitor, visit_attribute, &item.attrs); | |
558 | } | |
559 | ||
560 | pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, | |
561 | path: &'v Path, | |
562 | hir_id: HirId) { | |
563 | visitor.visit_id(hir_id); | |
564 | visitor.visit_path(path, hir_id); | |
565 | } | |
566 | ||
567 | pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V, | |
568 | enum_definition: &'v EnumDef, | |
569 | generics: &'v Generics, | |
570 | item_id: HirId) { | |
571 | visitor.visit_id(item_id); | |
572 | walk_list!(visitor, | |
573 | visit_variant, | |
574 | &enum_definition.variants, | |
575 | generics, | |
576 | item_id); | |
577 | } | |
578 | ||
579 | pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V, | |
580 | variant: &'v Variant, | |
581 | generics: &'v Generics, | |
582 | parent_item_id: HirId) { | |
583 | visitor.visit_ident(variant.ident); | |
584 | visitor.visit_id(variant.id); | |
585 | visitor.visit_variant_data(&variant.data, | |
586 | variant.ident.name, | |
587 | generics, | |
588 | parent_item_id, | |
589 | variant.span); | |
590 | walk_list!(visitor, visit_anon_const, &variant.disr_expr); | |
591 | walk_list!(visitor, visit_attribute, &variant.attrs); | |
592 | } | |
593 | ||
594 | pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { | |
595 | visitor.visit_id(typ.hir_id); | |
596 | ||
597 | match typ.kind { | |
598 | TyKind::Slice(ref ty) => { | |
599 | visitor.visit_ty(ty) | |
600 | } | |
601 | TyKind::Ptr(ref mutable_type) => { | |
602 | visitor.visit_ty(&mutable_type.ty) | |
603 | } | |
604 | TyKind::Rptr(ref lifetime, ref mutable_type) => { | |
605 | visitor.visit_lifetime(lifetime); | |
606 | visitor.visit_ty(&mutable_type.ty) | |
607 | } | |
608 | TyKind::Never => {} | |
609 | TyKind::Tup(ref tuple_element_types) => { | |
610 | walk_list!(visitor, visit_ty, tuple_element_types); | |
611 | } | |
612 | TyKind::BareFn(ref function_declaration) => { | |
613 | walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); | |
614 | visitor.visit_fn_decl(&function_declaration.decl); | |
615 | } | |
616 | TyKind::Path(ref qpath) => { | |
617 | visitor.visit_qpath(qpath, typ.hir_id, typ.span); | |
618 | } | |
619 | TyKind::Def(item_id, ref lifetimes) => { | |
620 | visitor.visit_nested_item(item_id); | |
621 | walk_list!(visitor, visit_generic_arg, lifetimes); | |
622 | } | |
623 | TyKind::Array(ref ty, ref length) => { | |
624 | visitor.visit_ty(ty); | |
625 | visitor.visit_anon_const(length) | |
626 | } | |
627 | TyKind::TraitObject(ref bounds, ref lifetime) => { | |
628 | for bound in bounds { | |
629 | visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None); | |
630 | } | |
631 | visitor.visit_lifetime(lifetime); | |
632 | } | |
633 | TyKind::Typeof(ref expression) => { | |
634 | visitor.visit_anon_const(expression) | |
635 | } | |
636 | TyKind::Infer | TyKind::Err => {} | |
637 | } | |
638 | } | |
639 | ||
640 | pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: HirId, span: Span) { | |
641 | match *qpath { | |
642 | QPath::Resolved(ref maybe_qself, ref path) => { | |
643 | if let Some(ref qself) = *maybe_qself { | |
644 | visitor.visit_ty(qself); | |
645 | } | |
646 | visitor.visit_path(path, id) | |
647 | } | |
648 | QPath::TypeRelative(ref qself, ref segment) => { | |
649 | visitor.visit_ty(qself); | |
650 | visitor.visit_path_segment(span, segment); | |
651 | } | |
652 | } | |
653 | } | |
654 | ||
655 | pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { | |
656 | for segment in &path.segments { | |
657 | visitor.visit_path_segment(path.span, segment); | |
658 | } | |
659 | } | |
660 | ||
661 | pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, | |
662 | path_span: Span, | |
663 | segment: &'v PathSegment) { | |
664 | visitor.visit_ident(segment.ident); | |
665 | if let Some(id) = segment.hir_id { | |
666 | visitor.visit_id(id); | |
667 | } | |
668 | if let Some(ref args) = segment.args { | |
669 | visitor.visit_generic_args(path_span, args); | |
670 | } | |
671 | } | |
672 | ||
673 | pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, | |
674 | _path_span: Span, | |
675 | generic_args: &'v GenericArgs) { | |
676 | walk_list!(visitor, visit_generic_arg, &generic_args.args); | |
677 | walk_list!(visitor, visit_assoc_type_binding, &generic_args.bindings); | |
678 | } | |
679 | ||
680 | pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, | |
681 | type_binding: &'v TypeBinding) { | |
682 | visitor.visit_id(type_binding.hir_id); | |
683 | visitor.visit_ident(type_binding.ident); | |
684 | match type_binding.kind { | |
685 | TypeBindingKind::Equality { ref ty } => { | |
686 | visitor.visit_ty(ty); | |
687 | } | |
688 | TypeBindingKind::Constraint { ref bounds } => { | |
689 | walk_list!(visitor, visit_param_bound, bounds); | |
690 | } | |
691 | } | |
692 | } | |
693 | ||
694 | pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) { | |
695 | visitor.visit_id(pattern.hir_id); | |
696 | match pattern.kind { | |
697 | PatKind::TupleStruct(ref qpath, ref children, _) => { | |
698 | visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); | |
699 | walk_list!(visitor, visit_pat, children); | |
700 | } | |
701 | PatKind::Path(ref qpath) => { | |
702 | visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); | |
703 | } | |
704 | PatKind::Struct(ref qpath, ref fields, _) => { | |
705 | visitor.visit_qpath(qpath, pattern.hir_id, pattern.span); | |
706 | for field in fields { | |
707 | visitor.visit_id(field.hir_id); | |
708 | visitor.visit_ident(field.ident); | |
709 | visitor.visit_pat(&field.pat) | |
710 | } | |
711 | } | |
712 | PatKind::Or(ref pats) => walk_list!(visitor, visit_pat, pats), | |
713 | PatKind::Tuple(ref tuple_elements, _) => { | |
714 | walk_list!(visitor, visit_pat, tuple_elements); | |
715 | } | |
716 | PatKind::Box(ref subpattern) | | |
717 | PatKind::Ref(ref subpattern, _) => { | |
718 | visitor.visit_pat(subpattern) | |
719 | } | |
720 | PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => { | |
721 | visitor.visit_ident(ident); | |
722 | walk_list!(visitor, visit_pat, optional_subpattern); | |
723 | } | |
724 | PatKind::Lit(ref expression) => visitor.visit_expr(expression), | |
725 | PatKind::Range(ref lower_bound, ref upper_bound, _) => { | |
726 | visitor.visit_expr(lower_bound); | |
727 | visitor.visit_expr(upper_bound) | |
728 | } | |
729 | PatKind::Wild => (), | |
730 | PatKind::Slice(ref prepatterns, ref slice_pattern, ref postpatterns) => { | |
731 | walk_list!(visitor, visit_pat, prepatterns); | |
732 | walk_list!(visitor, visit_pat, slice_pattern); | |
733 | walk_list!(visitor, visit_pat, postpatterns); | |
734 | } | |
735 | } | |
736 | } | |
737 | ||
738 | pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) { | |
739 | visitor.visit_id(foreign_item.hir_id); | |
740 | visitor.visit_vis(&foreign_item.vis); | |
741 | visitor.visit_ident(foreign_item.ident); | |
742 | ||
743 | match foreign_item.kind { | |
744 | ForeignItemKind::Fn(ref function_declaration, ref param_names, ref generics) => { | |
745 | visitor.visit_generics(generics); | |
746 | visitor.visit_fn_decl(function_declaration); | |
747 | for ¶m_name in param_names { | |
748 | visitor.visit_ident(param_name); | |
749 | } | |
750 | } | |
751 | ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), | |
752 | ForeignItemKind::Type => (), | |
753 | } | |
754 | ||
755 | walk_list!(visitor, visit_attribute, &foreign_item.attrs); | |
756 | } | |
757 | ||
758 | pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound) { | |
759 | match *bound { | |
760 | GenericBound::Trait(ref typ, modifier) => { | |
761 | visitor.visit_poly_trait_ref(typ, modifier); | |
762 | } | |
763 | GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), | |
764 | } | |
765 | } | |
766 | ||
767 | pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) { | |
768 | visitor.visit_id(param.hir_id); | |
769 | walk_list!(visitor, visit_attribute, ¶m.attrs); | |
770 | match param.name { | |
771 | ParamName::Plain(ident) => visitor.visit_ident(ident), | |
772 | ParamName::Error | ParamName::Fresh(_) => {} | |
773 | } | |
774 | match param.kind { | |
775 | GenericParamKind::Lifetime { .. } => {} | |
776 | GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default), | |
777 | GenericParamKind::Const { ref ty } => visitor.visit_ty(ty), | |
778 | } | |
779 | walk_list!(visitor, visit_param_bound, ¶m.bounds); | |
780 | } | |
781 | ||
782 | pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { | |
783 | walk_list!(visitor, visit_generic_param, &generics.params); | |
784 | walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); | |
785 | } | |
786 | ||
787 | pub fn walk_where_predicate<'v, V: Visitor<'v>>( | |
788 | visitor: &mut V, | |
789 | predicate: &'v WherePredicate) | |
790 | { | |
791 | match predicate { | |
792 | &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, | |
793 | ref bounds, | |
794 | ref bound_generic_params, | |
795 | ..}) => { | |
796 | visitor.visit_ty(bounded_ty); | |
797 | walk_list!(visitor, visit_param_bound, bounds); | |
798 | walk_list!(visitor, visit_generic_param, bound_generic_params); | |
799 | } | |
800 | &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, | |
801 | ref bounds, | |
802 | ..}) => { | |
803 | visitor.visit_lifetime(lifetime); | |
804 | walk_list!(visitor, visit_param_bound, bounds); | |
805 | } | |
806 | &WherePredicate::EqPredicate(WhereEqPredicate{hir_id, | |
807 | ref lhs_ty, | |
808 | ref rhs_ty, | |
809 | ..}) => { | |
810 | visitor.visit_id(hir_id); | |
811 | visitor.visit_ty(lhs_ty); | |
812 | visitor.visit_ty(rhs_ty); | |
813 | } | |
814 | } | |
815 | } | |
816 | ||
817 | pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) { | |
818 | if let Return(ref output_ty) = *ret_ty { | |
819 | visitor.visit_ty(output_ty) | |
820 | } | |
821 | } | |
822 | ||
823 | pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) { | |
824 | for ty in &function_declaration.inputs { | |
825 | visitor.visit_ty(ty) | |
826 | } | |
827 | walk_fn_ret_ty(visitor, &function_declaration.output) | |
828 | } | |
829 | ||
830 | pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) { | |
831 | match function_kind { | |
832 | FnKind::ItemFn(_, generics, ..) => { | |
833 | visitor.visit_generics(generics); | |
834 | } | |
835 | FnKind::Method(..) | | |
836 | FnKind::Closure(_) => {} | |
837 | } | |
838 | } | |
839 | ||
840 | pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, | |
841 | function_kind: FnKind<'v>, | |
842 | function_declaration: &'v FnDecl, | |
843 | body_id: BodyId, | |
844 | _span: Span, | |
845 | id: HirId) { | |
846 | visitor.visit_id(id); | |
847 | visitor.visit_fn_decl(function_declaration); | |
848 | walk_fn_kind(visitor, function_kind); | |
849 | visitor.visit_nested_body(body_id) | |
850 | } | |
851 | ||
852 | pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { | |
853 | visitor.visit_ident(trait_item.ident); | |
854 | walk_list!(visitor, visit_attribute, &trait_item.attrs); | |
855 | visitor.visit_generics(&trait_item.generics); | |
856 | match trait_item.kind { | |
857 | TraitItemKind::Const(ref ty, default) => { | |
858 | visitor.visit_id(trait_item.hir_id); | |
859 | visitor.visit_ty(ty); | |
860 | walk_list!(visitor, visit_nested_body, default); | |
861 | } | |
862 | TraitItemKind::Method(ref sig, TraitMethod::Required(ref param_names)) => { | |
863 | visitor.visit_id(trait_item.hir_id); | |
864 | visitor.visit_fn_decl(&sig.decl); | |
865 | for ¶m_name in param_names { | |
866 | visitor.visit_ident(param_name); | |
867 | } | |
868 | } | |
869 | TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => { | |
870 | visitor.visit_fn(FnKind::Method(trait_item.ident, | |
871 | sig, | |
872 | None, | |
873 | &trait_item.attrs), | |
874 | &sig.decl, | |
875 | body_id, | |
876 | trait_item.span, | |
877 | trait_item.hir_id); | |
878 | } | |
879 | TraitItemKind::Type(ref bounds, ref default) => { | |
880 | visitor.visit_id(trait_item.hir_id); | |
881 | walk_list!(visitor, visit_param_bound, bounds); | |
882 | walk_list!(visitor, visit_ty, default); | |
883 | } | |
884 | } | |
885 | } | |
886 | ||
887 | pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) { | |
888 | // N.B., deliberately force a compilation error if/when new fields are added. | |
889 | let TraitItemRef { id, ident, ref kind, span: _, ref defaultness } = *trait_item_ref; | |
890 | visitor.visit_nested_trait_item(id); | |
891 | visitor.visit_ident(ident); | |
892 | visitor.visit_associated_item_kind(kind); | |
893 | visitor.visit_defaultness(defaultness); | |
894 | } | |
895 | ||
896 | pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { | |
897 | // N.B., deliberately force a compilation error if/when new fields are added. | |
898 | let ImplItem { | |
899 | hir_id: _, | |
900 | ident, | |
901 | ref vis, | |
902 | ref defaultness, | |
903 | ref attrs, | |
904 | ref generics, | |
905 | ref kind, | |
906 | span: _, | |
907 | } = *impl_item; | |
908 | ||
909 | visitor.visit_ident(ident); | |
910 | visitor.visit_vis(vis); | |
911 | visitor.visit_defaultness(defaultness); | |
912 | walk_list!(visitor, visit_attribute, attrs); | |
913 | visitor.visit_generics(generics); | |
914 | match *kind { | |
915 | ImplItemKind::Const(ref ty, body) => { | |
916 | visitor.visit_id(impl_item.hir_id); | |
917 | visitor.visit_ty(ty); | |
918 | visitor.visit_nested_body(body); | |
919 | } | |
920 | ImplItemKind::Method(ref sig, body_id) => { | |
921 | visitor.visit_fn(FnKind::Method(impl_item.ident, | |
922 | sig, | |
923 | Some(&impl_item.vis), | |
924 | &impl_item.attrs), | |
925 | &sig.decl, | |
926 | body_id, | |
927 | impl_item.span, | |
928 | impl_item.hir_id); | |
929 | } | |
930 | ImplItemKind::TyAlias(ref ty) => { | |
931 | visitor.visit_id(impl_item.hir_id); | |
932 | visitor.visit_ty(ty); | |
933 | } | |
934 | ImplItemKind::OpaqueTy(ref bounds) => { | |
935 | visitor.visit_id(impl_item.hir_id); | |
936 | walk_list!(visitor, visit_param_bound, bounds); | |
937 | } | |
938 | } | |
939 | } | |
940 | ||
941 | pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef) { | |
942 | // N.B., deliberately force a compilation error if/when new fields are added. | |
943 | let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref; | |
944 | visitor.visit_nested_impl_item(id); | |
945 | visitor.visit_ident(ident); | |
946 | visitor.visit_associated_item_kind(kind); | |
947 | visitor.visit_vis(vis); | |
948 | visitor.visit_defaultness(defaultness); | |
949 | } | |
950 | ||
951 | pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) { | |
952 | if let Some(ctor_hir_id) = struct_definition.ctor_hir_id() { | |
953 | visitor.visit_id(ctor_hir_id); | |
954 | } | |
955 | walk_list!(visitor, visit_struct_field, struct_definition.fields()); | |
956 | } | |
957 | ||
958 | pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) { | |
959 | visitor.visit_id(struct_field.hir_id); | |
960 | visitor.visit_vis(&struct_field.vis); | |
961 | visitor.visit_ident(struct_field.ident); | |
962 | visitor.visit_ty(&struct_field.ty); | |
963 | walk_list!(visitor, visit_attribute, &struct_field.attrs); | |
964 | } | |
965 | ||
966 | pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) { | |
967 | visitor.visit_id(block.hir_id); | |
968 | walk_list!(visitor, visit_stmt, &block.stmts); | |
969 | walk_list!(visitor, visit_expr, &block.expr); | |
970 | } | |
971 | ||
972 | pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) { | |
973 | visitor.visit_id(statement.hir_id); | |
974 | match statement.kind { | |
975 | StmtKind::Local(ref local) => visitor.visit_local(local), | |
976 | StmtKind::Item(item) => visitor.visit_nested_item(item), | |
977 | StmtKind::Expr(ref expression) | | |
978 | StmtKind::Semi(ref expression) => { | |
979 | visitor.visit_expr(expression) | |
980 | } | |
981 | } | |
982 | } | |
983 | ||
984 | pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) { | |
985 | visitor.visit_id(constant.hir_id); | |
986 | visitor.visit_nested_body(constant.body); | |
987 | } | |
988 | ||
989 | pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { | |
990 | visitor.visit_id(expression.hir_id); | |
991 | walk_list!(visitor, visit_attribute, expression.attrs.iter()); | |
992 | match expression.kind { | |
993 | ExprKind::Box(ref subexpression) => { | |
994 | visitor.visit_expr(subexpression) | |
995 | } | |
996 | ExprKind::Array(ref subexpressions) => { | |
997 | walk_list!(visitor, visit_expr, subexpressions); | |
998 | } | |
999 | ExprKind::Repeat(ref element, ref count) => { | |
1000 | visitor.visit_expr(element); | |
1001 | visitor.visit_anon_const(count) | |
1002 | } | |
1003 | ExprKind::Struct(ref qpath, ref fields, ref optional_base) => { | |
1004 | visitor.visit_qpath(qpath, expression.hir_id, expression.span); | |
1005 | for field in fields { | |
1006 | visitor.visit_id(field.hir_id); | |
1007 | visitor.visit_ident(field.ident); | |
1008 | visitor.visit_expr(&field.expr) | |
1009 | } | |
1010 | walk_list!(visitor, visit_expr, optional_base); | |
1011 | } | |
1012 | ExprKind::Tup(ref subexpressions) => { | |
1013 | walk_list!(visitor, visit_expr, subexpressions); | |
1014 | } | |
1015 | ExprKind::Call(ref callee_expression, ref arguments) => { | |
1016 | visitor.visit_expr(callee_expression); | |
1017 | walk_list!(visitor, visit_expr, arguments); | |
1018 | } | |
1019 | ExprKind::MethodCall(ref segment, _, ref arguments) => { | |
1020 | visitor.visit_path_segment(expression.span, segment); | |
1021 | walk_list!(visitor, visit_expr, arguments); | |
1022 | } | |
1023 | ExprKind::Binary(_, ref left_expression, ref right_expression) => { | |
1024 | visitor.visit_expr(left_expression); | |
1025 | visitor.visit_expr(right_expression) | |
1026 | } | |
1027 | ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => { | |
1028 | visitor.visit_expr(subexpression) | |
1029 | } | |
1030 | ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { | |
1031 | visitor.visit_expr(subexpression); | |
1032 | visitor.visit_ty(typ) | |
1033 | } | |
1034 | ExprKind::DropTemps(ref subexpression) => { | |
1035 | visitor.visit_expr(subexpression); | |
1036 | } | |
1037 | ExprKind::Loop(ref block, ref opt_label, _) => { | |
1038 | walk_list!(visitor, visit_label, opt_label); | |
1039 | visitor.visit_block(block); | |
1040 | } | |
1041 | ExprKind::Match(ref subexpression, ref arms, _) => { | |
1042 | visitor.visit_expr(subexpression); | |
1043 | walk_list!(visitor, visit_arm, arms); | |
1044 | } | |
1045 | ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => { | |
1046 | visitor.visit_fn(FnKind::Closure(&expression.attrs), | |
1047 | function_declaration, | |
1048 | body, | |
1049 | expression.span, | |
1050 | expression.hir_id) | |
1051 | } | |
1052 | ExprKind::Block(ref block, ref opt_label) => { | |
1053 | walk_list!(visitor, visit_label, opt_label); | |
1054 | visitor.visit_block(block); | |
1055 | } | |
1056 | ExprKind::Assign(ref left_hand_expression, ref right_hand_expression) => { | |
1057 | visitor.visit_expr(right_hand_expression); | |
1058 | visitor.visit_expr(left_hand_expression) | |
1059 | } | |
1060 | ExprKind::AssignOp(_, ref left_expression, ref right_expression) => { | |
1061 | visitor.visit_expr(right_expression); | |
1062 | visitor.visit_expr(left_expression); | |
1063 | } | |
1064 | ExprKind::Field(ref subexpression, ident) => { | |
1065 | visitor.visit_expr(subexpression); | |
1066 | visitor.visit_ident(ident); | |
1067 | } | |
1068 | ExprKind::Index(ref main_expression, ref index_expression) => { | |
1069 | visitor.visit_expr(main_expression); | |
1070 | visitor.visit_expr(index_expression) | |
1071 | } | |
1072 | ExprKind::Path(ref qpath) => { | |
1073 | visitor.visit_qpath(qpath, expression.hir_id, expression.span); | |
1074 | } | |
1075 | ExprKind::Break(ref destination, ref opt_expr) => { | |
1076 | if let Some(ref label) = destination.label { | |
1077 | visitor.visit_label(label); | |
1078 | } | |
1079 | walk_list!(visitor, visit_expr, opt_expr); | |
1080 | } | |
1081 | ExprKind::Continue(ref destination) => { | |
1082 | if let Some(ref label) = destination.label { | |
1083 | visitor.visit_label(label); | |
1084 | } | |
1085 | } | |
1086 | ExprKind::Ret(ref optional_expression) => { | |
1087 | walk_list!(visitor, visit_expr, optional_expression); | |
1088 | } | |
1089 | ExprKind::InlineAsm(ref asm) => { | |
1090 | walk_list!(visitor, visit_expr, &asm.outputs_exprs); | |
1091 | walk_list!(visitor, visit_expr, &asm.inputs_exprs); | |
1092 | } | |
1093 | ExprKind::Yield(ref subexpression, _) => { | |
1094 | visitor.visit_expr(subexpression); | |
1095 | } | |
1096 | ExprKind::Lit(_) | ExprKind::Err => {} | |
1097 | } | |
1098 | } | |
1099 | ||
1100 | pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { | |
1101 | visitor.visit_id(arm.hir_id); | |
1102 | visitor.visit_pat(&arm.pat); | |
1103 | if let Some(ref g) = arm.guard { | |
1104 | match g { | |
1105 | Guard::If(ref e) => visitor.visit_expr(e), | |
1106 | } | |
1107 | } | |
1108 | visitor.visit_expr(&arm.body); | |
1109 | walk_list!(visitor, visit_attribute, &arm.attrs); | |
1110 | } | |
1111 | ||
1112 | pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) { | |
1113 | if let VisibilityKind::Restricted { ref path, hir_id } = vis.node { | |
1114 | visitor.visit_id(hir_id); | |
1115 | visitor.visit_path(path, hir_id) | |
1116 | } | |
1117 | } | |
1118 | ||
1119 | pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) { | |
1120 | // No visitable content here: this fn exists so you can call it if | |
1121 | // the right thing to do, should content be added in the future, | |
1122 | // would be to walk it. | |
1123 | } | |
1124 | ||
1125 | pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) { | |
1126 | // No visitable content here: this fn exists so you can call it if | |
1127 | // the right thing to do, should content be added in the future, | |
1128 | // would be to walk it. | |
1129 | } |