]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_hir/src/intravisit.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / compiler / rustc_hir / src / intravisit.rs
index 977c0eb3cd2bcf11075dc2668488ab009855fdcd..e68274e2ad9788d0f46906c9848ac2f1a98b6b89 100644 (file)
@@ -1,7 +1,40 @@
 //! HIR walker for walking the contents of nodes.
 //!
-//! **For an overview of the visitor strategy, see the docs on the
-//! `super::itemlikevisit::ItemLikeVisitor` trait.**
+//! Here are the three available patterns for the visitor strategy,
+//! in roughly the order of desirability:
+//!
+//! 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
+//!    - Example: find all items with a `#[foo]` attribute on them.
+//!    - How: Use the `hir_crate_items` or `hir_module_items` query to traverse over item-like ids
+//!       (ItemId, TraitItemId, etc.) and use tcx.def_kind and `tcx.hir().item*(id)` to filter and
+//!       access actual item-like thing, respectively.
+//!    - Pro: Efficient; just walks the lists of item ids and gives users control whether to access
+//!       the hir_owners themselves or not.
+//!    - Con: Don't get information about nesting
+//!    - Con: Don't have methods for specific bits of HIR, like "on
+//!      every expr, do this".
+//! 2. **Deep visit**: Want to scan for specific kinds of HIR nodes within
+//!    an item, but don't care about how item-like things are nested
+//!    within one another.
+//!    - Example: Examine each expression to look for its type and do some check or other.
+//!    - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
+//!      `nested_filter::OnlyBodies` (and implement `nested_visit_map`), and use
+//!      `tcx.hir().deep_visit_all_item_likes(&mut visitor)`. Within your
+//!      `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget to invoke
+//!      `intravisit::walk_expr()` to keep walking the subparts).
+//!    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
+//!    - Pro: Integrates well into dependency tracking.
+//!    - Con: Don't get information about nesting between items
+//! 3. **Nested visit**: Want to visit the whole HIR and you care about the nesting between
+//!    item-like things.
+//!    - Example: Lifetime resolution, which wants to bring lifetimes declared on the
+//!      impl into scope while visiting the impl-items, and then back out again.
+//!    - How: Implement `intravisit::Visitor` and override the `NestedFilter` type to
+//!      `nested_filter::All` (and implement `nested_visit_map`). Walk your crate with
+//!      `tcx.hir().walk_toplevel_module(visitor)` invoked on `tcx.hir().krate()`.
+//!    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
+//!    - Pro: Preserves nesting information
+//!    - Con: Does not integrate well into dependency tracking.
 //!
 //! If you have decided to use this visitor, here are some general
 //! notes on how to do so:
 //! example generator inference, and possibly also HIR borrowck.
 
 use crate::hir::*;
-use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
+use crate::itemlikevisit::ParItemLikeVisitor;
 use rustc_ast::walk_list;
 use rustc_ast::{Attribute, Label};
 use rustc_span::symbol::{Ident, Symbol};
 use rustc_span::Span;
 
-pub struct DeepVisitor<'v, V> {
-    visitor: &'v mut V,
-}
-
-impl<'v, V> DeepVisitor<'v, V> {
-    pub fn new(base: &'v mut V) -> Self {
-        DeepVisitor { visitor: base }
-    }
-}
-
-impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
-where
-    V: Visitor<'hir>,
-{
-    fn visit_item(&mut self, item: &'hir Item<'hir>) {
-        self.visitor.visit_item(item);
-    }
-
-    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>) {
-        self.visitor.visit_trait_item(trait_item);
-    }
-
-    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) {
-        self.visitor.visit_impl_item(impl_item);
-    }
-
-    fn visit_foreign_item(&mut self, foreign_item: &'hir ForeignItem<'hir>) {
-        self.visitor.visit_foreign_item(foreign_item);
-    }
-}
-
 pub trait IntoVisitor<'hir> {
     type Visitor: Visitor<'hir>;
     fn into_visitor(&self) -> Self::Visitor;
@@ -315,16 +317,6 @@ pub trait Visitor<'v>: Sized {
         walk_body(self, b);
     }
 
-    /// When invoking `visit_all_item_likes()`, you need to supply an
-    /// item-like visitor. This method converts an "intra-visit"
-    /// visitor into an item-like visitor that walks the entire tree.
-    /// If you use this, you probably don't want to process the
-    /// contents of nested item-like things, since the outer loop will
-    /// visit them as well.
-    fn as_deep_visitor(&mut self) -> DeepVisitor<'_, Self> {
-        DeepVisitor::new(self)
-    }
-
     ///////////////////////////////////////////////////////////////////////////
 
     fn visit_id(&mut self, _hir_id: HirId) {
@@ -474,7 +466,7 @@ pub trait Visitor<'v>: Sized {
     fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) {
         walk_assoc_type_binding(self, type_binding)
     }
-    fn visit_attribute(&mut self, _id: HirId, _attr: &'v Attribute) {}
+    fn visit_attribute(&mut self, _attr: &'v Attribute) {}
     fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) {
         walk_associated_item_kind(self, kind);
     }
@@ -518,11 +510,11 @@ pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
 pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
     visitor.visit_id(lifetime.hir_id);
     match lifetime.name {
-        LifetimeName::Param(ParamName::Plain(ident)) => {
+        LifetimeName::Param(_, ParamName::Plain(ident)) => {
             visitor.visit_ident(ident);
         }
-        LifetimeName::Param(ParamName::Fresh(_))
-        | LifetimeName::Param(ParamName::Error)
+        LifetimeName::Param(_, ParamName::Fresh)
+        | LifetimeName::Param(_, ParamName::Error)
         | LifetimeName::Static
         | LifetimeName::Error
         | LifetimeName::Implicit
@@ -887,7 +879,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
     visitor.visit_id(param.hir_id);
     match param.name {
         ParamName::Plain(ident) => visitor.visit_ident(ident),
-        ParamName::Error | ParamName::Fresh(_) => {}
+        ParamName::Error | ParamName::Fresh => {}
     }
     match param.kind {
         GenericParamKind::Lifetime { .. } => {}
@@ -1176,14 +1168,17 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor
-            .visit_fn(
-                FnKind::Closure,
-                function_declaration,
-                body,
-                expression.span,
-                expression.hir_id,
-            ),
+        ExprKind::Closure {
+            bound_generic_params,
+            ref fn_decl,
+            body,
+            capture_clause: _,
+            fn_decl_span: _,
+            movability: _,
+        } => {
+            walk_list!(visitor, visit_generic_param, bound_generic_params);
+            visitor.visit_fn(FnKind::Closure, fn_decl, body, expression.span, expression.hir_id)
+        }
         ExprKind::Block(ref block, ref opt_label) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);
@@ -1233,9 +1228,8 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
     if let Some(ref g) = arm.guard {
         match g {
             Guard::If(ref e) => visitor.visit_expr(e),
-            Guard::IfLet(ref pat, ref e) => {
-                visitor.visit_pat(pat);
-                visitor.visit_expr(e);
+            Guard::IfLet(ref l) => {
+                visitor.visit_let_expr(l);
             }
         }
     }