@@ -70,35 +70,36 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
7070 ) ;
7171 top_level_module. is_crate = true ;
7272 // Attach the crate's exported macros to the top-level module.
73- // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s as well
74- // (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
73+ // In the case of macros 2.0 (`pub macro`), and for built-in `derive`s or attributes as
74+ // well (_e.g._, `Copy`), these are wrongly bundled in there too, so we need to fix that by
7575 // moving them back to their correct locations.
7676 krate. exported_macros . iter ( ) . for_each ( |def| {
77- macro_rules! try_some { ( $ ( $body : tt ) * ) => ( {
78- fn fn_once< R , F : FnOnce ( ) -> R > ( f : F ) -> F { f }
79- fn_once ( || Some ( { $ ( $body ) * } ) ) ( )
80- } ) }
81- // In the case of dummy items, some of the following operations may fail. We propagate
82- // that within a `?`-capturing block, so as to fallback to the basic behavior.
83- let containing_module_of_def = try_some ! {
77+ /// A return value of `None` signifies a fallback to the default behavior (locating
78+ /// the macro at the root of the crate).
79+ fn containing_mod_of_macro < ' module , ' hir > (
80+ def : & ' _ rustc_hir :: MacroDef < ' _ > ,
81+ tcx : TyCtxt < ' _ > ,
82+ top_level_module : & ' module mut Module < ' hir > ,
83+ ) -> Option < & ' module mut Module < ' hir > > {
8484 // The `def` of a macro in `exported_macros` should correspond to either:
8585 // - a `#[macro-export] macro_rules!` macro,
86- // - a built-in `derive` macro such as the ones in `::core`,
86+ // - a built-in `derive` (or attribute) macro such as the ones in `::core`,
8787 // - a `pub macro`.
8888 // Only the last two need to be fixed, thus:
8989 if def. ast . macro_rules {
9090 return None ;
9191 }
92- let macro_parent_module = self . cx. tcx. def_path( {
92+ /* Because of #77828 we cannot do the simpler:
93+ let macro_parent_module = tcx.def_path(tcx.parent_module(def.hir_id).to_def_id());
94+ // and instead have to do: */
95+ let macro_parent_module = tcx. def_path ( {
9396 use rustc_middle:: ty:: DefIdTree ;
94- self . cx
95- . tcx
96- /* Because of #77828 we cannot do the simpler:
97- .parent_module(def.hir_id).to_def_id()
98- // and instead have to do: */
99- . parent( self . cx. tcx. hir( ) . local_def_id( def. hir_id) . to_def_id( ) ) ?
97+ tcx. parent ( tcx. hir ( ) . local_def_id ( def. hir_id ) . to_def_id ( ) ) ?
10098 } ) ;
101- let mut cur_mod = & mut top_level_module;
99+ // HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
100+ // lookup the module by its name, by looking at each path segment one at a time.
101+ // WARNING: this will probably break in the presence of re-exports or shadowing.
102+ let mut cur_mod = top_level_module;
102103 for path_segment in macro_parent_module. data {
103104 let path_segment = path_segment. to_string ( ) ;
104105 cur_mod = cur_mod. mods . iter_mut ( ) . find ( |module| {
@@ -108,9 +109,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
108109 )
109110 } ) ?;
110111 }
111- cur_mod
112- } ;
113- if let Some ( module) = containing_module_of_def {
112+ Some ( cur_mod)
113+ }
114+
115+ if let Some ( module) = containing_mod_of_macro ( def, self . cx . tcx , & mut top_level_module) {
114116 & mut module. macros
115117 } else {
116118 & mut top_level_module. macros
0 commit comments