@@ -9,7 +9,7 @@ use rustc_hir::Node;
99use rustc_middle:: middle:: privacy:: AccessLevel ;
1010use rustc_middle:: ty:: TyCtxt ;
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
@@ -79,49 +79,23 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
7979 & krate. module ( ) ,
8080 self . cx . tcx . crate_name ( LOCAL_CRATE ) ,
8181 ) ;
82- // Attach the crate's exported macros to the top-level module.
83- // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
84- // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
85- // moving them back to their correct locations.
86- ' exported_macros: for def in krate. exported_macros ( ) {
87- // The `def` of a macro in `exported_macros` should correspond to either:
88- // - a `#[macro_export] macro_rules!` macro,
89- // - a built-in `derive` (or attribute) macro such as the ones in `::core`,
90- // - a `pub macro`.
91- // Only the last two need to be fixed, thus:
92- if def. ast . macro_rules {
93- top_level_module. macros . push ( ( def, None ) ) ;
94- continue ' exported_macros;
95- }
96- let tcx = self . cx . tcx ;
97- // Note: this is not the same as `.parent_module()`. Indeed, the latter looks
98- // for the closest module _ancestor_, which is not necessarily a direct parent
99- // (since a direct parent isn't necessarily a module, c.f. #77828).
100- let macro_parent_def_id = {
101- use rustc_middle:: ty:: DefIdTree ;
102- tcx. parent ( def. def_id . to_def_id ( ) ) . unwrap ( )
103- } ;
104- let macro_parent_path = tcx. def_path ( macro_parent_def_id) ;
105- // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
106- // lookup the module by its name, by looking at each path segment one at a time.
107- let mut cur_mod = & mut top_level_module;
108- for path_segment in macro_parent_path. data {
109- // Path segments may refer to a module (in which case they belong to the type
110- // namespace), which is _necessary_ for the macro to be accessible outside it
111- // (no "associated macros" as of yet). Else we bail with an outer `continue`.
112- let path_segment_ty_ns = match path_segment. data {
113- rustc_hir:: definitions:: DefPathData :: TypeNs ( symbol) => symbol,
114- _ => continue ' exported_macros,
115- } ;
116- // Descend into the child module that matches this path segment (if any).
117- match cur_mod. mods . iter_mut ( ) . find ( |child| child. name == path_segment_ty_ns) {
118- Some ( child_mod) => cur_mod = & mut * child_mod,
119- None => continue ' exported_macros,
82+
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+ }
12097 }
12198 }
122- let cur_mod_def_id = tcx. hir ( ) . local_def_id ( cur_mod. id ) . to_def_id ( ) ;
123- assert_eq ! ( cur_mod_def_id, macro_parent_def_id) ;
124- cur_mod. macros . push ( ( def, None ) ) ;
12599 }
126100 self . cx . cache . exact_paths = self . exact_paths ;
127101 top_level_module
@@ -238,10 +212,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
238212 self . inlining = prev;
239213 true
240214 }
241- Node :: MacroDef ( def) if !glob => {
242- om. macros . push ( ( def, renamed) ) ;
243- true
244- }
245215 _ => false ,
246216 } ;
247217 self . view_item_stack . remove ( & res_hir_id) ;
@@ -257,7 +227,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
257227 debug ! ( "visiting item {:?}" , item) ;
258228 let name = renamed. unwrap_or ( item. ident . name ) ;
259229
260- if item. vis . node . is_pub ( ) {
230+ let def_id = item. def_id . to_def_id ( ) ;
231+ let is_pub = item. vis . node . is_pub ( ) || self . cx . tcx . has_attr ( def_id, sym:: macro_export) ;
232+
233+ if is_pub {
261234 self . store_path ( item. def_id . to_def_id ( ) ) ;
262235 }
263236
@@ -269,7 +242,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
269242 }
270243 }
271244 // If we're inlining, skip private items.
272- _ if self . inlining && !item . vis . node . is_pub ( ) => { }
245+ _ if self . inlining && !is_pub => { }
273246 hir:: ItemKind :: GlobalAsm ( ..) => { }
274247 hir:: ItemKind :: Use ( _, hir:: UseKind :: ListStem ) => { }
275248 hir:: ItemKind :: Use ( ref path, kind) => {
@@ -285,7 +258,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
285258
286259 // If there was a private module in the current path then don't bother inlining
287260 // anything as it will probably be stripped anyway.
288- if item . vis . node . is_pub ( ) && self . inside_public_path {
261+ if is_pub && self . inside_public_path {
289262 let please_inline = attrs. iter ( ) . any ( |item| match item. meta_item_list ( ) {
290263 Some ( ref list) if item. has_name ( sym:: doc) => {
291264 list. iter ( ) . any ( |i| i. has_name ( sym:: inline) )
@@ -307,6 +280,26 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
307280
308281 om. items . push ( ( item, renamed) )
309282 }
283+ hir:: ItemKind :: Macro ( ref macro_def) => {
284+ // `#[macro_export] macro_rules!` items are handled seperately in `visit()`,
285+ // above, since they need to be documented at the module top level. Accordingly,
286+ // we only want to handle macros if one of three conditions holds:
287+ //
288+ // 1. This macro was defined by `macro`, and thus isn't covered by the case
289+ // above.
290+ // 2. This macro isn't marked with `#[macro_export]`, and thus isn't covered
291+ // by the case above.
292+ // 3. We're inlining, since a reexport where inlining has been requested
293+ // should be inlined even if it is also documented at the top level.
294+
295+ let def_id = item. def_id . to_def_id ( ) ;
296+ let is_macro_2_0 = !macro_def. macro_rules ;
297+ let nonexported = !self . cx . tcx . has_attr ( def_id, sym:: macro_export) ;
298+
299+ if is_macro_2_0 || nonexported || self . inlining {
300+ om. items . push ( ( item, renamed) ) ;
301+ }
302+ }
310303 hir:: ItemKind :: Mod ( ref m) => {
311304 om. mods . push ( self . visit_mod_contents ( & item. vis , item. hir_id ( ) , m, name) ) ;
312305 }
0 commit comments