@@ -70,35 +70,36 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
70
70
) ;
71
71
top_level_module. is_crate = true ;
72
72
// 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
75
75
// moving them back to their correct locations.
76
76
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 > > {
84
84
// The `def` of a macro in `exported_macros` should correspond to either:
85
85
// - 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`,
87
87
// - a `pub macro`.
88
88
// Only the last two need to be fixed, thus:
89
89
if def. ast . macro_rules {
90
90
return None ;
91
91
}
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 ( {
93
96
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 ( ) ) ?
100
98
} ) ;
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;
102
103
for path_segment in macro_parent_module. data {
103
104
let path_segment = path_segment. to_string ( ) ;
104
105
cur_mod = cur_mod. mods . iter_mut ( ) . find ( |module| {
@@ -108,9 +109,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
108
109
)
109
110
} ) ?;
110
111
}
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) {
114
116
& mut module. macros
115
117
} else {
116
118
& mut top_level_module. macros
0 commit comments