@@ -7,9 +7,9 @@ use rustc_hir::def::{DefKind, Res};
77use rustc_hir:: def_id:: DefId ;
88use rustc_hir:: Node ;
99use rustc_middle:: middle:: privacy:: AccessLevel ;
10- use rustc_middle:: ty:: TyCtxt ;
10+ use rustc_middle:: ty:: { TyCtxt , Visibility } ;
1111use rustc_span;
12- use rustc_span:: def_id:: LOCAL_CRATE ;
12+ use rustc_span:: def_id:: { CRATE_DEF_ID , LOCAL_CRATE } ;
1313use rustc_span:: source_map:: Spanned ;
1414use rustc_span:: symbol:: { kw, sym, Symbol } ;
1515
@@ -73,13 +73,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
7373
7474 crate fn visit ( mut self , krate : & ' tcx hir:: Crate < ' _ > ) -> Module < ' tcx > {
7575 let span = krate. module ( ) . inner ;
76- let top_level_module = self . visit_mod_contents (
76+ let mut top_level_module = self . visit_mod_contents (
7777 & Spanned { span, node : hir:: VisibilityKind :: Public } ,
7878 hir:: CRATE_HIR_ID ,
7979 & krate. module ( ) ,
8080 self . cx . tcx . crate_name ( LOCAL_CRATE ) ,
8181 ) ;
8282
83+ // `#[macro_export] macro_rules!` items are reexported at the top level of the
84+ // crate, regardless of where they're defined. We want to document the
85+ // top level rexport of the macro, not its original definition, since
86+ // the rexport defines the path that a user will actually see. Accordingly,
87+ // we add the rexport as an item here, and then skip over the original
88+ // definition in `visit_item()` below.
89+ for export in self . cx . tcx . module_exports ( CRATE_DEF_ID ) . unwrap_or ( & [ ] ) {
90+ if let Res :: Def ( DefKind :: Macro ( _) , def_id) = export. res {
91+ if let Some ( local_def_id) = def_id. as_local ( ) {
92+ if self . cx . tcx . has_attr ( def_id, sym:: macro_export) {
93+ let hir_id = self . cx . tcx . hir ( ) . local_def_id_to_hir_id ( local_def_id) ;
94+ let item = self . cx . tcx . hir ( ) . expect_item ( hir_id) ;
95+ top_level_module. items . push ( ( item, None ) ) ;
96+ }
97+ }
98+ }
99+ }
100+
83101 self . cx . cache . exact_paths = self . exact_paths ;
84102 top_level_module
85103 }
@@ -210,11 +228,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
210228 debug ! ( "visiting item {:?}" , item) ;
211229 let name = renamed. unwrap_or ( item. ident . name ) ;
212230
213- let is_pub = if let hir:: ItemKind :: Macro { is_exported : true , .. } = item. kind {
214- true
215- } else {
216- item. vis . node . is_pub ( )
217- } ;
231+ let is_pub = self . cx . tcx . visibility ( item. def_id ) == Visibility :: Public ;
218232
219233 if is_pub {
220234 self . store_path ( item. def_id . to_def_id ( ) ) ;
@@ -269,8 +283,27 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
269283 hir:: ItemKind :: Mod ( ref m) => {
270284 om. mods . push ( self . visit_mod_contents ( & item. vis , item. hir_id ( ) , m, name) ) ;
271285 }
286+ hir:: ItemKind :: Macro { ref macro_def, .. } => {
287+ // `#[macro_export] macro_rules!` items are handled seperately in `visit()`,
288+ // above, since they need to be documented at the module top level. Accordingly,
289+ // we only want to handle macros if one of three conditions holds:
290+ //
291+ // 1. This macro was defined by `macro`, and thus isn't covered by the case
292+ // above.
293+ // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered
294+ // by the case above.
295+ // 3. We're inlining, since a reexport where inlining has been requested
296+ // should be inlined even if it is also documented at the top level.
297+
298+ let def_id = item. def_id . to_def_id ( ) ;
299+ let is_macro_2_0 = !macro_def. ast . macro_rules ;
300+ let nonexported = !self . cx . tcx . has_attr ( def_id, sym:: macro_export) ;
301+
302+ if is_macro_2_0 || nonexported || self . inlining {
303+ om. items . push ( ( item, renamed) ) ;
304+ }
305+ }
272306 hir:: ItemKind :: Fn ( ..)
273- | hir:: ItemKind :: Macro { .. }
274307 | hir:: ItemKind :: ExternCrate ( ..)
275308 | hir:: ItemKind :: Enum ( ..)
276309 | hir:: ItemKind :: Struct ( ..)
0 commit comments