]> git.proxmox.com Git - rustc.git/blobdiff - src/librustdoc/visit_ast.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / src / librustdoc / visit_ast.rs
index b7a3b13cf04919f4575ebb82e760220174036622..b6782fb75df35c62ce8252bd4aef1986125b4b69 100644 (file)
@@ -1,17 +1,15 @@
 //! The Rust AST Visitor. Extracts useful information and massages it into a form
 //! usable for `clean`.
 
-use rustc_ast::ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+use rustc_hir::def_id::DefId;
 use rustc_hir::Node;
 use rustc_middle::middle::privacy::AccessLevel;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::hygiene::MacroKind;
 use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::{self, Span};
 
 use std::mem;
@@ -31,10 +29,20 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec<String> {
     std::iter::once(crate_name).chain(relative).collect()
 }
 
+crate fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut node: hir::HirId) -> bool {
+    while let Some(id) = tcx.hir().get_enclosing_scope(node) {
+        node = id;
+        if tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
+            return true;
+        }
+    }
+    false
+}
+
 // Also, is there some reason that this doesn't use the 'visit'
 // framework from syntax?.
 
-pub struct RustdocVisitor<'a, 'tcx> {
+crate struct RustdocVisitor<'a, 'tcx> {
     cx: &'a mut core::DocContext<'tcx>,
     view_item_stack: FxHashSet<hir::HirId>,
     inlining: bool,
@@ -44,7 +52,7 @@ pub struct RustdocVisitor<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
-    pub fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx> {
+    crate fn new(cx: &'a mut core::DocContext<'tcx>) -> RustdocVisitor<'a, 'tcx> {
         // If the root is re-exported, terminate all recursion.
         let mut stack = FxHashSet::default();
         stack.insert(hir::CRATE_HIR_ID);
@@ -62,201 +70,87 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.exact_paths.entry(did).or_insert_with(|| def_id_to_path(tcx, did));
     }
 
-    pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> {
-        let mut module = self.visit_mod_contents(
+    crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> {
+        let mut top_level_module = self.visit_mod_contents(
             krate.item.span,
-            krate.item.attrs,
             &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public },
             hir::CRATE_HIR_ID,
             &krate.item.module,
             None,
         );
-        // Attach the crate's exported macros to the top-level module:
-        module
-            .macros
-            .extend(krate.exported_macros.iter().map(|def| self.visit_local_macro(def, None)));
-        module.is_crate = true;
-
-        self.cx.renderinfo.get_mut().exact_paths = self.exact_paths;
-
-        module
-    }
-
-    fn visit_variant_data(
-        &mut self,
-        item: &'tcx hir::Item,
-        name: ast::Name,
-        sd: &'tcx hir::VariantData,
-        generics: &'tcx hir::Generics,
-    ) -> Struct<'tcx> {
-        debug!("visiting struct");
-        let struct_type = struct_type_from_def(&*sd);
-        Struct {
-            id: item.hir_id,
-            struct_type,
-            name,
-            vis: &item.vis,
-            attrs: &item.attrs,
-            generics,
-            fields: sd.fields(),
-            whence: item.span,
-        }
-    }
-
-    fn visit_union_data(
-        &mut self,
-        item: &'tcx hir::Item,
-        name: ast::Name,
-        sd: &'tcx hir::VariantData,
-        generics: &'tcx hir::Generics,
-    ) -> Union<'tcx> {
-        debug!("visiting union");
-        let struct_type = struct_type_from_def(&*sd);
-        Union {
-            id: item.hir_id,
-            struct_type,
-            name,
-            vis: &item.vis,
-            attrs: &item.attrs,
-            generics,
-            fields: sd.fields(),
-            whence: item.span,
-        }
-    }
-
-    fn visit_enum_def(
-        &mut self,
-        it: &'tcx hir::Item,
-        name: ast::Name,
-        def: &'tcx hir::EnumDef,
-        generics: &'tcx hir::Generics,
-    ) -> Enum<'tcx> {
-        debug!("visiting enum");
-        Enum {
-            name,
-            variants: def
-                .variants
-                .iter()
-                .map(|v| Variant {
-                    name: v.ident.name,
-                    id: v.id,
-                    attrs: &v.attrs,
-                    def: &v.data,
-                    whence: v.span,
-                })
-                .collect(),
-            vis: &it.vis,
-            generics,
-            attrs: &it.attrs,
-            id: it.hir_id,
-            whence: it.span,
-        }
-    }
-
-    fn visit_fn(
-        &mut self,
-        om: &mut Module<'tcx>,
-        item: &'tcx hir::Item,
-        name: ast::Name,
-        decl: &'tcx hir::FnDecl,
-        header: hir::FnHeader,
-        generics: &'tcx hir::Generics,
-        body: hir::BodyId,
-    ) {
-        debug!("visiting fn");
-        let macro_kind = item
-            .attrs
-            .iter()
-            .filter_map(|a| {
-                if a.check_name(sym::proc_macro) {
-                    Some(MacroKind::Bang)
-                } else if a.check_name(sym::proc_macro_derive) {
-                    Some(MacroKind::Derive)
-                } else if a.check_name(sym::proc_macro_attribute) {
-                    Some(MacroKind::Attr)
-                } else {
-                    None
-                }
-            })
-            .next();
-        match macro_kind {
-            Some(kind) => {
-                let name = if kind == MacroKind::Derive {
-                    item.attrs
-                        .lists(sym::proc_macro_derive)
-                        .filter_map(|mi| mi.ident())
-                        .next()
-                        .expect("proc-macro derives require a name")
-                        .name
-                } else {
-                    name
+        top_level_module.is_crate = true;
+        // Attach the crate's exported macros to the top-level module.
+        // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
+        // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
+        // moving them back to their correct locations.
+        'exported_macros: for def in krate.exported_macros {
+            // The `def` of a macro in `exported_macros` should correspond to either:
+            //  - a `#[macro_export] macro_rules!` macro,
+            //  - a built-in `derive` (or attribute) macro such as the ones in `::core`,
+            //  - a `pub macro`.
+            // Only the last two need to be fixed, thus:
+            if def.ast.macro_rules {
+                top_level_module.macros.push((def, None));
+                continue 'exported_macros;
+            }
+            let tcx = self.cx.tcx;
+            // Note: this is not the same as `.parent_module()`. Indeed, the latter looks
+            // for the closest module _ancestor_, which is not necessarily a direct parent
+            // (since a direct parent isn't necessarily a module, c.f. #77828).
+            let macro_parent_def_id = {
+                use rustc_middle::ty::DefIdTree;
+                tcx.parent(def.def_id.to_def_id()).unwrap()
+            };
+            let macro_parent_path = tcx.def_path(macro_parent_def_id);
+            // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
+            // lookup the module by its name, by looking at each path segment one at a time.
+            let mut cur_mod = &mut top_level_module;
+            for path_segment in macro_parent_path.data {
+                // Path segments may refer to a module (in which case they belong to the type
+                // namespace), which is _necessary_ for the macro to be accessible outside it
+                // (no "associated macros" as of yet). Else we bail with an outer `continue`.
+                let path_segment_ty_ns = match path_segment.data {
+                    rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol,
+                    _ => continue 'exported_macros,
                 };
-
-                let mut helpers = Vec::new();
-                for mi in item.attrs.lists(sym::proc_macro_derive) {
-                    if !mi.check_name(sym::attributes) {
-                        continue;
-                    }
-
-                    if let Some(list) = mi.meta_item_list() {
-                        for inner_mi in list {
-                            if let Some(ident) = inner_mi.ident() {
-                                helpers.push(ident.name);
-                            }
-                        }
-                    }
+                // Descend into the child module that matches this path segment (if any).
+                match cur_mod.mods.iter_mut().find(|child| child.name == Some(path_segment_ty_ns)) {
+                    Some(child_mod) => cur_mod = &mut *child_mod,
+                    None => continue 'exported_macros,
                 }
-
-                om.proc_macros.push(ProcMacro {
-                    name,
-                    id: item.hir_id,
-                    kind,
-                    helpers,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                });
-            }
-            None => {
-                om.fns.push(Function {
-                    id: item.hir_id,
-                    vis: &item.vis,
-                    attrs: &item.attrs,
-                    decl,
-                    name,
-                    whence: item.span,
-                    generics,
-                    header,
-                    body,
-                });
             }
+            let cur_mod_def_id = tcx.hir().local_def_id(cur_mod.id).to_def_id();
+            assert_eq!(cur_mod_def_id, macro_parent_def_id);
+            cur_mod.macros.push((def, None));
         }
+        self.cx.cache.exact_paths = self.exact_paths;
+        top_level_module
     }
 
     fn visit_mod_contents(
         &mut self,
         span: Span,
-        attrs: &'tcx [ast::Attribute],
-        vis: &'tcx hir::Visibility,
+        vis: &'tcx hir::Visibility<'_>,
         id: hir::HirId,
         m: &'tcx hir::Mod<'tcx>,
-        name: Option<ast::Name>,
+        name: Option<Symbol>,
     ) -> Module<'tcx> {
-        let mut om = Module::new(name, attrs, vis);
+        let mut om = Module::new(name);
         om.where_outer = span;
         om.where_inner = m.inner;
         om.id = id;
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
         self.inside_public_path &= vis.node.is_pub();
-        for i in m.item_ids {
-            let item = self.cx.tcx.hir().expect_item(i.id);
+        for &i in m.item_ids {
+            let item = self.cx.tcx.hir().item(i);
             self.visit_item(item, None, &mut om);
         }
         self.inside_public_path = orig_inside_public_path;
         om
     }
 
-    /// Tries to resolve the target of a `pub use` statement and inlines the
+    /// Tries to resolve the target of a `crate use` statement and inlines the
     /// target if it is defined locally and would not be documented otherwise,
     /// or when it is specifically requested with `please_inline`.
     /// (the latter is the case when the import is marked `doc(inline)`)
@@ -269,24 +163,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         &mut self,
         id: hir::HirId,
         res: Res,
-        renamed: Option<ast::Ident>,
+        renamed: Option<Symbol>,
         glob: bool,
         om: &mut Module<'tcx>,
         please_inline: bool,
     ) -> bool {
-        fn inherits_doc_hidden(cx: &core::DocContext<'_>, mut node: hir::HirId) -> bool {
-            while let Some(id) = cx.tcx.hir().get_enclosing_scope(node) {
-                node = id;
-                if cx.tcx.hir().attrs(node).lists(sym::doc).has_word(sym::hidden) {
-                    return true;
-                }
-                if node == hir::CRATE_HIR_ID {
-                    break;
-                }
-            }
-            false
-        }
-
         debug!("maybe_inline_local res: {:?}", res);
 
         let tcx = self.cx.tcx;
@@ -308,36 +189,27 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         if !res_did.is_local() && !is_no_inline {
             let attrs = clean::inline::load_attrs(self.cx, res_did);
             let self_is_hidden = attrs.lists(sym::doc).has_word(sym::hidden);
-            match res {
-                Res::Def(
-                    DefKind::Trait
-                    | DefKind::Struct
-                    | DefKind::Union
-                    | DefKind::Enum
-                    | DefKind::ForeignTy
-                    | DefKind::TyAlias,
-                    did,
-                ) if !self_is_hidden => {
-                    self.cx.renderinfo.get_mut().access_levels.map.insert(did, AccessLevel::Public);
-                }
-                Res::Def(DefKind::Mod, did) => {
-                    if !self_is_hidden {
-                        crate::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did);
+            if !self_is_hidden {
+                if let Res::Def(kind, did) = res {
+                    if kind == DefKind::Mod {
+                        crate::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did)
+                    } else {
+                        // All items need to be handled here in case someone wishes to link
+                        // to them with intra-doc links
+                        self.cx.cache.access_levels.map.insert(did, AccessLevel::Public);
                     }
                 }
-                _ => {}
             }
-
             return false;
         }
 
-        let res_hir_id = match tcx.hir().as_local_hir_id(res_did) {
-            Some(n) => n,
+        let res_hir_id = match res_did.as_local() {
+            Some(n) => tcx.hir().local_def_id_to_hir_id(n),
             None => return false,
         };
 
-        let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(res_did);
-        let is_hidden = inherits_doc_hidden(self.cx, res_hir_id);
+        let is_private = !self.cx.cache.access_levels.is_public(res_did);
+        let is_hidden = inherits_doc_hidden(self.cx.tcx, res_hir_id);
 
         // Only inline if requested or if the item would otherwise be stripped.
         if (!please_inline && !is_private && !is_hidden) || is_no_inline {
@@ -351,8 +223,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let ret = match tcx.hir().get(res_hir_id) {
             Node::Item(&hir::Item { kind: hir::ItemKind::Mod(ref m), .. }) if glob => {
                 let prev = mem::replace(&mut self.inlining, true);
-                for i in m.item_ids {
-                    let i = self.cx.tcx.hir().expect_item(i.id);
+                for &i in m.item_ids {
+                    let i = self.cx.tcx.hir().item(i);
                     self.visit_item(i, None, om);
                 }
                 self.inlining = prev;
@@ -371,7 +243,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 true
             }
             Node::MacroDef(def) if !glob => {
-                om.macros.push(self.visit_local_macro(def, renamed.map(|i| i.name)));
+                om.macros.push((def, renamed));
                 true
             }
             _ => false,
@@ -382,38 +254,27 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     fn visit_item(
         &mut self,
-        item: &'tcx hir::Item,
-        renamed: Option<ast::Ident>,
+        item: &'tcx hir::Item<'_>,
+        renamed: Option<Symbol>,
         om: &mut Module<'tcx>,
     ) {
         debug!("visiting item {:?}", item);
-        let ident = renamed.unwrap_or(item.ident);
+        let name = renamed.unwrap_or(item.ident.name);
 
         if item.vis.node.is_pub() {
-            let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
-            self.store_path(def_id);
+            self.store_path(item.def_id.to_def_id());
         }
 
         match item.kind {
-            hir::ItemKind::ForeignMod(ref fm) => {
-                for item in fm.items {
+            hir::ItemKind::ForeignMod { items, .. } => {
+                for item in items {
+                    let item = self.cx.tcx.hir().foreign_item(item.id);
                     self.visit_foreign_item(item, None, om);
                 }
             }
             // If we're inlining, skip private items.
             _ if self.inlining && !item.vis.node.is_pub() => {}
             hir::ItemKind::GlobalAsm(..) => {}
-            hir::ItemKind::ExternCrate(orig_name) => {
-                let def_id = self.cx.tcx.hir().local_def_id(item.hir_id);
-                om.extern_crates.push(ExternCrate {
-                    cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id).unwrap_or(LOCAL_CRATE),
-                    name: ident.name,
-                    path: orig_name.map(|x| x.to_string()),
-                    vis: &item.vis,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                })
-            }
             hir::ItemKind::Use(_, hir::UseKind::ListStem) => {}
             hir::ItemKind::Use(ref path, kind) => {
                 let is_glob = kind == hir::UseKind::Glob;
@@ -424,18 +285,20 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     return;
                 }
 
+                let attrs = self.cx.tcx.hir().attrs(item.hir_id());
+
                 // If there was a private module in the current path then don't bother inlining
                 // anything as it will probably be stripped anyway.
                 if item.vis.node.is_pub() && self.inside_public_path {
-                    let please_inline = item.attrs.iter().any(|item| match item.meta_item_list() {
-                        Some(ref list) if item.check_name(sym::doc) => {
-                            list.iter().any(|i| i.check_name(sym::inline))
+                    let please_inline = attrs.iter().any(|item| match item.meta_item_list() {
+                        Some(ref list) if item.has_name(sym::doc) => {
+                            list.iter().any(|i| i.has_name(sym::inline))
                         }
                         _ => false,
                     });
-                    let ident = if is_glob { None } else { Some(ident) };
+                    let ident = if is_glob { None } else { Some(name) };
                     if self.maybe_inline_local(
-                        item.hir_id,
+                        item.hir_id(),
                         path.res,
                         ident,
                         is_glob,
@@ -446,150 +309,39 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     }
                 }
 
-                om.imports.push(Import {
-                    name: ident.name,
-                    id: item.hir_id,
-                    vis: &item.vis,
-                    attrs: &item.attrs,
-                    path,
-                    glob: is_glob,
-                    whence: item.span,
-                });
+                om.items.push((item, renamed))
             }
             hir::ItemKind::Mod(ref m) => {
                 om.mods.push(self.visit_mod_contents(
                     item.span,
-                    &item.attrs,
                     &item.vis,
-                    item.hir_id,
+                    item.hir_id(),
                     m,
-                    Some(ident.name),
+                    Some(name),
                 ));
             }
-            hir::ItemKind::Enum(ref ed, ref gen) => {
-                om.enums.push(self.visit_enum_def(item, ident.name, ed, gen))
-            }
-            hir::ItemKind::Struct(ref sd, ref gen) => {
-                om.structs.push(self.visit_variant_data(item, ident.name, sd, gen))
-            }
-            hir::ItemKind::Union(ref sd, ref gen) => {
-                om.unions.push(self.visit_union_data(item, ident.name, sd, gen))
-            }
-            hir::ItemKind::Fn(ref sig, ref gen, body) => {
-                self.visit_fn(om, item, ident.name, &sig.decl, sig.header, gen, body)
-            }
-            hir::ItemKind::TyAlias(ty, ref gen) => {
-                let t = Typedef {
-                    ty,
-                    gen,
-                    name: ident.name,
-                    id: item.hir_id,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                    vis: &item.vis,
-                };
-                om.typedefs.push(t);
-            }
-            hir::ItemKind::OpaqueTy(ref opaque_ty) => {
-                let t = OpaqueTy {
-                    opaque_ty,
-                    name: ident.name,
-                    id: item.hir_id,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                    vis: &item.vis,
-                };
-                om.opaque_tys.push(t);
-            }
-            hir::ItemKind::Static(type_, mutability, expr) => {
-                let s = Static {
-                    type_,
-                    mutability,
-                    expr,
-                    id: item.hir_id,
-                    name: ident.name,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                    vis: &item.vis,
-                };
-                om.statics.push(s);
-            }
-            hir::ItemKind::Const(type_, expr) => {
+            hir::ItemKind::Fn(..)
+            | hir::ItemKind::ExternCrate(..)
+            | hir::ItemKind::Enum(..)
+            | hir::ItemKind::Struct(..)
+            | hir::ItemKind::Union(..)
+            | hir::ItemKind::TyAlias(..)
+            | hir::ItemKind::OpaqueTy(..)
+            | hir::ItemKind::Static(..)
+            | hir::ItemKind::Trait(..)
+            | hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
+            hir::ItemKind::Const(..) => {
                 // Underscore constants do not correspond to a nameable item and
                 // so are never useful in documentation.
-                if ident.name != kw::Underscore {
-                    let s = Constant {
-                        type_,
-                        expr,
-                        id: item.hir_id,
-                        name: ident.name,
-                        attrs: &item.attrs,
-                        whence: item.span,
-                        vis: &item.vis,
-                    };
-                    om.constants.push(s);
+                if name != kw::Underscore {
+                    om.items.push((item, renamed));
                 }
             }
-            hir::ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
-                let items = item_ids.iter().map(|ti| self.cx.tcx.hir().trait_item(ti.id)).collect();
-                let t = Trait {
-                    is_auto,
-                    unsafety,
-                    name: ident.name,
-                    items,
-                    generics,
-                    bounds,
-                    id: item.hir_id,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                    vis: &item.vis,
-                };
-                om.traits.push(t);
-            }
-            hir::ItemKind::TraitAlias(ref generics, ref bounds) => {
-                let t = TraitAlias {
-                    name: ident.name,
-                    generics,
-                    bounds,
-                    id: item.hir_id,
-                    attrs: &item.attrs,
-                    whence: item.span,
-                    vis: &item.vis,
-                };
-                om.trait_aliases.push(t);
-            }
-
-            hir::ItemKind::Impl {
-                unsafety,
-                polarity,
-                defaultness,
-                constness,
-                defaultness_span: _,
-                ref generics,
-                ref of_trait,
-                self_ty,
-                ref items,
-            } => {
+            hir::ItemKind::Impl(ref impl_) => {
                 // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
                 // them up regardless of where they're located.
-                if !self.inlining && of_trait.is_none() {
-                    let items =
-                        items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect();
-                    let i = Impl {
-                        unsafety,
-                        polarity,
-                        defaultness,
-                        constness,
-                        generics,
-                        trait_: of_trait,
-                        for_: self_ty,
-                        items,
-                        attrs: &item.attrs,
-                        id: item.hir_id,
-                        whence: item.span,
-                        vis: &item.vis,
-                    };
-                    om.impls.push(i);
+                if !self.inlining && impl_.of_trait.is_none() {
+                    om.items.push((item, None));
                 }
             }
         }
@@ -597,44 +349,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     fn visit_foreign_item(
         &mut self,
-        item: &'tcx hir::ForeignItem,
-        renamed: Option<ast::Ident>,
+        item: &'tcx hir::ForeignItem<'_>,
+        renamed: Option<Symbol>,
         om: &mut Module<'tcx>,
     ) {
         // If inlining we only want to include public functions.
-        if self.inlining && !item.vis.node.is_pub() {
-            return;
-        }
-
-        om.foreigns.push(ForeignItem {
-            id: item.hir_id,
-            name: renamed.unwrap_or(item.ident).name,
-            kind: &item.kind,
-            vis: &item.vis,
-            attrs: &item.attrs,
-            whence: item.span,
-        });
-    }
-
-    // Convert each `exported_macro` into a doc item.
-    fn visit_local_macro(
-        &self,
-        def: &'tcx hir::MacroDef,
-        renamed: Option<ast::Name>,
-    ) -> Macro<'tcx> {
-        debug!("visit_local_macro: {}", def.ident);
-        let tts = def.ast.body.inner_tokens().trees().collect::<Vec<_>>();
-        // Extract the spans of all matchers. They represent the "interface" of the macro.
-        let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect();
-
-        Macro {
-            hid: def.hir_id,
-            def_id: self.cx.tcx.hir().local_def_id(def.hir_id),
-            attrs: &def.attrs,
-            name: renamed.unwrap_or(def.ident.name),
-            whence: def.span,
-            matchers,
-            imported_from: None,
+        if !self.inlining || item.vis.node.is_pub() {
+            om.foreigns.push((item, renamed));
         }
     }
 }