|
1 | 1 | //! HIR walker for walking the contents of nodes.
|
2 | 2 | //!
|
3 |
| -//! **For an overview of the visitor strategy, see the docs on the |
4 |
| -//! `super::itemlikevisit::ItemLikeVisitor` trait.** |
| 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().deep_visit_all_item_likes(&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. |
5 | 38 | //!
|
6 | 39 | //! If you have decided to use this visitor, here are some general
|
7 | 40 | //! notes on how to do so:
|
|
32 | 65 | //! example generator inference, and possibly also HIR borrowck.
|
33 | 66 |
|
34 | 67 | use crate::hir::*;
|
35 |
| -use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; |
| 68 | +use crate::itemlikevisit::ParItemLikeVisitor; |
36 | 69 | use rustc_ast::walk_list;
|
37 | 70 | use rustc_ast::{Attribute, Label};
|
38 | 71 | use rustc_span::symbol::{Ident, Symbol};
|
39 | 72 | use rustc_span::Span;
|
40 | 73 |
|
41 |
| -pub struct DeepVisitor<'v, V> { |
42 |
| - visitor: &'v mut V, |
43 |
| -} |
44 |
| - |
45 |
| -impl<'v, V> DeepVisitor<'v, V> { |
46 |
| - pub fn new(base: &'v mut V) -> Self { |
47 |
| - DeepVisitor { visitor: base } |
48 |
| - } |
49 |
| -} |
50 |
| - |
51 |
| -impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> |
52 |
| -where |
53 |
| - V: Visitor<'hir>, |
54 |
| -{ |
55 |
| - fn visit_item(&mut self, item: &'hir Item<'hir>) { |
56 |
| - self.visitor.visit_item(item); |
57 |
| - } |
58 |
| - |
59 |
| - fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>) { |
60 |
| - self.visitor.visit_trait_item(trait_item); |
61 |
| - } |
62 |
| - |
63 |
| - fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) { |
64 |
| - self.visitor.visit_impl_item(impl_item); |
65 |
| - } |
66 |
| - |
67 |
| - fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) { |
68 |
| - self.visitor.visit_foreign_item(foreign_item); |
69 |
| - } |
70 |
| -} |
71 |
| - |
72 | 74 | pub trait IntoVisitor<'hir> {
|
73 | 75 | type Visitor: Visitor<'hir>;
|
74 | 76 | fn into_visitor(&self) -> Self::Visitor;
|
@@ -315,16 +317,6 @@ pub trait Visitor<'v>: Sized {
|
315 | 317 | walk_body(self, b);
|
316 | 318 | }
|
317 | 319 |
|
318 |
| - /// When invoking `visit_all_item_likes()`, you need to supply an |
319 |
| - /// item-like visitor. This method converts an "intra-visit" |
320 |
| - /// visitor into an item-like visitor that walks the entire tree. |
321 |
| - /// If you use this, you probably don't want to process the |
322 |
| - /// contents of nested item-like things, since the outer loop will |
323 |
| - /// visit them as well. |
324 |
| - fn as_deep_visitor(&mut self) -> DeepVisitor<'_, Self> { |
325 |
| - DeepVisitor::new(self) |
326 |
| - } |
327 |
| - |
328 | 320 | ///////////////////////////////////////////////////////////////////////////
|
329 | 321 |
|
330 | 322 | fn visit_id(&mut self, _hir_id: HirId) {
|
|
0 commit comments