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