about summary refs log tree commit diff
path: root/compiler/rustc_ast/src/visit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast/src/visit.rs')
-rw-r--r--compiler/rustc_ast/src/visit.rs328
1 files changed, 197 insertions, 131 deletions
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 968d10ad487..182aa6ed085 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -102,6 +102,15 @@ pub enum LifetimeCtxt {
     GenericArg,
 }
 
+pub trait WalkItemKind: Sized {
+    fn walk<'a, V: Visitor<'a>>(
+        &'a self,
+        item: &'a Item<Self>,
+        ctxt: AssocCtxt,
+        visitor: &mut V,
+    ) -> V::Result;
+}
+
 /// Each method of the `Visitor` trait is a hook to be potentially
 /// overridden. Each method's default implementation recursively visits
 /// the substructure of the input via the corresponding `walk` method;
@@ -120,7 +129,7 @@ pub trait Visitor<'ast>: Sized {
         Self::Result::output()
     }
     fn visit_foreign_item(&mut self, i: &'ast ForeignItem) -> Self::Result {
-        walk_foreign_item(self, i)
+        walk_item(self, i)
     }
     fn visit_item(&mut self, i: &'ast Item) -> Self::Result {
         walk_item(self, i)
@@ -312,86 +321,111 @@ pub fn walk_trait_ref<'a, V: Visitor<'a>>(visitor: &mut V, trait_ref: &'a TraitR
     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
 }
 
-pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) -> V::Result {
-    try_visit!(visitor.visit_vis(&item.vis));
-    try_visit!(visitor.visit_ident(item.ident));
-    match &item.kind {
-        ItemKind::ExternCrate(_) => {}
-        ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
-        ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
-            try_visit!(visitor.visit_ty(ty));
-            visit_opt!(visitor, visit_expr, expr);
-        }
-        ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
-            try_visit!(visitor.visit_generics(generics));
-            try_visit!(visitor.visit_ty(ty));
-            visit_opt!(visitor, visit_expr, expr);
-        }
-        ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
-            let kind =
-                FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
-            try_visit!(visitor.visit_fn(kind, item.span, item.id));
-        }
-        ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
-            ModKind::Loaded(items, _inline, _inner_span) => {
-                walk_list!(visitor, visit_item, items);
+impl WalkItemKind for ItemKind {
+    fn walk<'a, V: Visitor<'a>>(
+        &'a self,
+        item: &'a Item<Self>,
+        _ctxt: AssocCtxt,
+        visitor: &mut V,
+    ) -> V::Result {
+        match self {
+            ItemKind::ExternCrate(_) => {}
+            ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)),
+            ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
+                try_visit!(visitor.visit_ty(ty));
+                visit_opt!(visitor, visit_expr, expr);
             }
-            ModKind::Unloaded => {}
-        },
-        ItemKind::ForeignMod(foreign_module) => {
-            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
-        }
-        ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
-        ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
-            try_visit!(visitor.visit_generics(generics));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            visit_opt!(visitor, visit_ty, ty);
-        }
-        ItemKind::Enum(enum_definition, generics) => {
-            try_visit!(visitor.visit_generics(generics));
-            try_visit!(visitor.visit_enum_def(enum_definition));
-        }
-        ItemKind::Impl(box Impl {
-            defaultness: _,
-            unsafety: _,
-            generics,
-            constness: _,
-            polarity: _,
-            of_trait,
-            self_ty,
-            items,
-        }) => {
-            try_visit!(visitor.visit_generics(generics));
-            visit_opt!(visitor, visit_trait_ref, of_trait);
-            try_visit!(visitor.visit_ty(self_ty));
-            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
-        }
-        ItemKind::Struct(struct_definition, generics)
-        | ItemKind::Union(struct_definition, generics) => {
-            try_visit!(visitor.visit_generics(generics));
-            try_visit!(visitor.visit_variant_data(struct_definition));
-        }
-        ItemKind::Trait(box Trait { unsafety: _, is_auto: _, generics, bounds, items }) => {
-            try_visit!(visitor.visit_generics(generics));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
-            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
-        }
-        ItemKind::TraitAlias(generics, bounds) => {
-            try_visit!(visitor.visit_generics(generics));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-        }
-        ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
-        ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
-        ItemKind::Delegation(box Delegation { id, qself, path, body }) => {
-            if let Some(qself) = qself {
-                try_visit!(visitor.visit_ty(&qself.ty));
+            ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
+                try_visit!(visitor.visit_generics(generics));
+                try_visit!(visitor.visit_ty(ty));
+                visit_opt!(visitor, visit_expr, expr);
+            }
+            ItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
+                let kind =
+                    FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, generics, body.as_deref());
+                try_visit!(visitor.visit_fn(kind, item.span, item.id));
+            }
+            ItemKind::Mod(_unsafety, mod_kind) => match mod_kind {
+                ModKind::Loaded(items, _inline, _inner_span) => {
+                    walk_list!(visitor, visit_item, items);
+                }
+                ModKind::Unloaded => {}
+            },
+            ItemKind::ForeignMod(foreign_module) => {
+                walk_list!(visitor, visit_foreign_item, &foreign_module.items);
+            }
+            ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),
+            ItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
+                try_visit!(visitor.visit_generics(generics));
+                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
+                visit_opt!(visitor, visit_ty, ty);
+            }
+            ItemKind::Enum(enum_definition, generics) => {
+                try_visit!(visitor.visit_generics(generics));
+                try_visit!(visitor.visit_enum_def(enum_definition));
+            }
+            ItemKind::Impl(box Impl {
+                defaultness: _,
+                safety: _,
+                generics,
+                constness: _,
+                polarity: _,
+                of_trait,
+                self_ty,
+                items,
+            }) => {
+                try_visit!(visitor.visit_generics(generics));
+                visit_opt!(visitor, visit_trait_ref, of_trait);
+                try_visit!(visitor.visit_ty(self_ty));
+                walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
+            }
+            ItemKind::Struct(struct_definition, generics)
+            | ItemKind::Union(struct_definition, generics) => {
+                try_visit!(visitor.visit_generics(generics));
+                try_visit!(visitor.visit_variant_data(struct_definition));
+            }
+            ItemKind::Trait(box Trait { safety: _, is_auto: _, generics, bounds, items }) => {
+                try_visit!(visitor.visit_generics(generics));
+                walk_list!(visitor, visit_param_bound, bounds, BoundKind::SuperTraits);
+                walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
+            }
+            ItemKind::TraitAlias(generics, bounds) => {
+                try_visit!(visitor.visit_generics(generics));
+                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
+            }
+            ItemKind::MacCall(mac) => try_visit!(visitor.visit_mac_call(mac)),
+            ItemKind::MacroDef(ts) => try_visit!(visitor.visit_mac_def(ts, item.id)),
+            ItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
+                if let Some(qself) = qself {
+                    try_visit!(visitor.visit_ty(&qself.ty));
+                }
+                try_visit!(visitor.visit_path(path, *id));
+                visit_opt!(visitor, visit_ident, *rename);
+                visit_opt!(visitor, visit_block, body);
+            }
+            ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                if let Some(qself) = qself {
+                    try_visit!(visitor.visit_ty(&qself.ty));
+                }
+                try_visit!(visitor.visit_path(prefix, item.id));
+                for (ident, rename) in suffixes {
+                    visitor.visit_ident(*ident);
+                    if let Some(rename) = rename {
+                        visitor.visit_ident(*rename);
+                    }
+                }
+                visit_opt!(visitor, visit_block, body);
             }
-            try_visit!(visitor.visit_path(path, *id));
-            visit_opt!(visitor, visit_block, body);
         }
+        V::Result::output()
     }
-    walk_list!(visitor, visit_attribute, &item.attrs);
-    V::Result::output()
+}
+
+pub fn walk_item<'a, V: Visitor<'a>>(
+    visitor: &mut V,
+    item: &'a Item<impl WalkItemKind>,
+) -> V::Result {
+    walk_assoc_item(visitor, item, AssocCtxt::Trait /*ignored*/)
 }
 
 pub fn walk_enum_def<'a, V: Visitor<'a>>(
@@ -496,8 +530,8 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
             visit_opt!(visitor, visit_ident, rename);
         }
         UseTreeKind::Glob => {}
-        UseTreeKind::Nested(ref use_trees) => {
-            for &(ref nested_tree, nested_id) in use_trees {
+        UseTreeKind::Nested { ref items, .. } => {
+            for &(ref nested_tree, nested_id) in items {
                 try_visit!(visitor.visit_use_tree(nested_tree, nested_id, true));
             }
         }
@@ -612,30 +646,34 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) -> V::Res
     V::Result::output()
 }
 
-pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) -> V::Result {
-    let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
-    try_visit!(visitor.visit_vis(vis));
-    try_visit!(visitor.visit_ident(ident));
-    walk_list!(visitor, visit_attribute, attrs);
-    match kind {
-        ForeignItemKind::Static(ty, _, expr) => {
-            try_visit!(visitor.visit_ty(ty));
-            visit_opt!(visitor, visit_expr, expr);
-        }
-        ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
-            let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
-            try_visit!(visitor.visit_fn(kind, span, id));
-        }
-        ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
-            try_visit!(visitor.visit_generics(generics));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            visit_opt!(visitor, visit_ty, ty);
-        }
-        ForeignItemKind::MacCall(mac) => {
-            try_visit!(visitor.visit_mac_call(mac));
+impl WalkItemKind for ForeignItemKind {
+    fn walk<'a, V: Visitor<'a>>(
+        &'a self,
+        item: &'a Item<Self>,
+        _ctxt: AssocCtxt,
+        visitor: &mut V,
+    ) -> V::Result {
+        let &Item { id, span, ident, ref vis, .. } = item;
+        match self {
+            ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => {
+                try_visit!(visitor.visit_ty(ty));
+                visit_opt!(visitor, visit_expr, expr);
+            }
+            ForeignItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
+                let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, generics, body.as_deref());
+                try_visit!(visitor.visit_fn(kind, span, id));
+            }
+            ForeignItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
+                try_visit!(visitor.visit_generics(generics));
+                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
+                visit_opt!(visitor, visit_ty, ty);
+            }
+            ForeignItemKind::MacCall(mac) => {
+                try_visit!(visitor.visit_mac_call(mac));
+            }
         }
+        V::Result::output()
     }
-    V::Result::output()
 }
 
 pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) -> V::Result {
@@ -755,41 +793,69 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
     V::Result::output()
 }
 
+impl WalkItemKind for AssocItemKind {
+    fn walk<'a, V: Visitor<'a>>(
+        &'a self,
+        item: &'a Item<Self>,
+        ctxt: AssocCtxt,
+        visitor: &mut V,
+    ) -> V::Result {
+        let &Item { id, span, ident, ref vis, .. } = item;
+        match self {
+            AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
+                try_visit!(visitor.visit_generics(generics));
+                try_visit!(visitor.visit_ty(ty));
+                visit_opt!(visitor, visit_expr, expr);
+            }
+            AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
+                let kind =
+                    FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
+                try_visit!(visitor.visit_fn(kind, span, id));
+            }
+            AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
+                try_visit!(visitor.visit_generics(generics));
+                walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
+                visit_opt!(visitor, visit_ty, ty);
+            }
+            AssocItemKind::MacCall(mac) => {
+                try_visit!(visitor.visit_mac_call(mac));
+            }
+            AssocItemKind::Delegation(box Delegation { id, qself, path, rename, body }) => {
+                if let Some(qself) = qself {
+                    try_visit!(visitor.visit_ty(&qself.ty));
+                }
+                try_visit!(visitor.visit_path(path, *id));
+                visit_opt!(visitor, visit_ident, *rename);
+                visit_opt!(visitor, visit_block, body);
+            }
+            AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => {
+                if let Some(qself) = qself {
+                    try_visit!(visitor.visit_ty(&qself.ty));
+                }
+                try_visit!(visitor.visit_path(prefix, item.id));
+                for (ident, rename) in suffixes {
+                    visitor.visit_ident(*ident);
+                    if let Some(rename) = rename {
+                        visitor.visit_ident(*rename);
+                    }
+                }
+                visit_opt!(visitor, visit_block, body);
+            }
+        }
+        V::Result::output()
+    }
+}
+
 pub fn walk_assoc_item<'a, V: Visitor<'a>>(
     visitor: &mut V,
-    item: &'a AssocItem,
+    item: &'a Item<impl WalkItemKind>,
     ctxt: AssocCtxt,
 ) -> V::Result {
-    let &Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
+    let &Item { id: _, span: _, ident, ref vis, ref attrs, ref kind, tokens: _ } = item;
+    walk_list!(visitor, visit_attribute, attrs);
     try_visit!(visitor.visit_vis(vis));
     try_visit!(visitor.visit_ident(ident));
-    walk_list!(visitor, visit_attribute, attrs);
-    match kind {
-        AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
-            try_visit!(visitor.visit_generics(generics));
-            try_visit!(visitor.visit_ty(ty));
-            visit_opt!(visitor, visit_expr, expr);
-        }
-        AssocItemKind::Fn(box Fn { defaultness: _, generics, sig, body }) => {
-            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
-            try_visit!(visitor.visit_fn(kind, span, id));
-        }
-        AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
-            try_visit!(visitor.visit_generics(generics));
-            walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
-            visit_opt!(visitor, visit_ty, ty);
-        }
-        AssocItemKind::MacCall(mac) => {
-            try_visit!(visitor.visit_mac_call(mac));
-        }
-        AssocItemKind::Delegation(box Delegation { id, qself, path, body }) => {
-            if let Some(qself) = qself {
-                try_visit!(visitor.visit_ty(&qself.ty));
-            }
-            try_visit!(visitor.visit_path(path, *id));
-            visit_opt!(visitor, visit_block, body);
-        }
-    }
+    try_visit!(kind.walk(item, ctxt, visitor));
     V::Result::output()
 }
 
@@ -885,7 +951,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
         ExprKind::Array(subexpressions) => {
             walk_list!(visitor, visit_expr, subexpressions);
         }
-        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_anon_const(anon_const)),
+        ExprKind::ConstBlock(anon_const) => try_visit!(visitor.visit_expr(anon_const)),
         ExprKind::Repeat(element, count) => {
             try_visit!(visitor.visit_expr(element));
             try_visit!(visitor.visit_anon_const(count));