Skip to content

Commit d3a33eb

Browse files
Fix type/value namespace clashes + test for that
1 parent 7d03870 commit d3a33eb

File tree

3 files changed

+85
-44
lines changed

3 files changed

+85
-44
lines changed

src/librustdoc/visit_ast.rs

Lines changed: 38 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -74,50 +74,46 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
7474
// 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-
/// 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-
// The `def` of a macro in `exported_macros` should correspond to either:
85-
// - a `#[macro-export] macro_rules!` macro,
86-
// - a built-in `derive` (or attribute) macro such as the ones in `::core`,
87-
// - a `pub macro`.
88-
// Only the last two need to be fixed, thus:
89-
if def.ast.macro_rules {
90-
return None;
91-
}
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({
96-
use rustc_middle::ty::DefIdTree;
97-
tcx.parent(tcx.hir().local_def_id(def.hir_id).to_def_id())?
98-
});
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;
103-
for path_segment in macro_parent_module.data {
104-
let path_segment = path_segment.to_string();
105-
cur_mod = cur_mod.mods.iter_mut().find(|module| {
106-
matches!(
107-
module.name, Some(symbol)
108-
if symbol.with(|mod_name| mod_name == path_segment)
109-
)
110-
})?;
111-
}
112-
Some(cur_mod)
77+
let visit_macro = || self.visit_local_macro(def, None);
78+
// The `def` of a macro in `exported_macros` should correspond to either:
79+
// - a `#[macro-export] macro_rules!` macro,
80+
// - a built-in `derive` (or attribute) macro such as the ones in `::core`,
81+
// - a `pub macro`.
82+
// Only the last two need to be fixed, thus:
83+
if def.ast.macro_rules {
84+
top_level_module.macros.push(visit_macro());
85+
return;
11386
}
114-
115-
if let Some(module) = containing_mod_of_macro(def, self.cx.tcx, &mut top_level_module) {
116-
&mut module.macros
117-
} else {
118-
&mut top_level_module.macros
87+
let tcx = self.cx.tcx;
88+
/* Because of #77828 we cannot do the simpler:
89+
let macro_parent_module = tcx.def_path(tcx.parent_module(def.hir_id).to_def_id());
90+
// and instead have to do: */
91+
let macro_parent_module = tcx.def_path({
92+
use rustc_middle::ty::DefIdTree;
93+
tcx.parent(tcx.hir().local_def_id(def.hir_id).to_def_id()).unwrap()
94+
});
95+
// HACK: rustdoc has no way to lookup `doctree::Module`s by their HirId. Instead,
96+
// lookup the module by its name, by looking at each path segment one at a time.
97+
let mut cur_mod = &mut top_level_module;
98+
for path_segment in macro_parent_module.data {
99+
let path_segment_ty_ns = match path_segment.data {
100+
rustc_hir::definitions::DefPathData::TypeNs(symbol) => symbol,
101+
_ => {
102+
// If the path segment is not from the type namespace
103+
// (_e.g._, it can be from a value namespace in the case of `f::` in:
104+
// `fn f() { pub macro m() {} }`
105+
// then the item is not accessible, and should thus act as if it didn't
106+
// exist (unless "associated macros" (inside an `impl`) were a thing…).
107+
return;
108+
}
109+
};
110+
cur_mod = cur_mod
111+
.mods
112+
.iter_mut()
113+
.find(|module| module.name == Some(path_segment_ty_ns))
114+
.unwrap();
119115
}
120-
.push(self.visit_local_macro(def, None));
116+
cur_mod.macros.push(visit_macro());
121117
});
122118

123119
self.cx.renderinfo.get_mut().exact_paths = self.exact_paths;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// edition:2018
2+
3+
#![feature(decl_macro)]
4+
#![crate_name = "external_crate"]
5+
6+
pub mod some_module {
7+
/* == Make sure the logic is not affected by a re-export == */
8+
mod private {
9+
pub macro external_macro() {}
10+
}
11+
// @has external_crate/some_module/macro.external_macro.html
12+
pub use private::external_macro;
13+
}
Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1+
// aux-build:macro_pub_in_module.rs
2+
// edition:2018
3+
// build-aux-docs
4+
// @has external_crate/some_module/macro.external_macro.html
5+
16
//! See issue #74355
27
#![feature(decl_macro, no_core, rustc_attrs)]
38
#![crate_name = "krate"]
49
#![no_core]
510

11+
extern crate external_crate;
12+
613
pub mod inner {
7-
// @has krate/inner/macro.my_macro.html
8-
pub macro my_macro() {}
14+
// @has krate/inner/macro.raw_const.html
15+
pub macro raw_const() {}
916

1017
// @has krate/inner/macro.test.html
1118
#[rustc_builtin_macro]
@@ -14,4 +21,29 @@ pub mod inner {
1421
// @has krate/inner/macro.Clone.html
1522
#[rustc_builtin_macro]
1623
pub macro Clone($item:item) {}
24+
25+
// Make sure the logic is not affected by a re-export.
26+
mod private {
27+
pub macro m() {}
28+
}
29+
// @has krate/inner/macro.renamed.html
30+
pub use private::m as renamed;
31+
32+
// @has krate/inner/macro.external_macro.html
33+
pub use ::external_crate::some_module::external_macro;
34+
}
35+
36+
// Namespaces: Make sure the logic does not mix up a function name with a module name…
37+
fn both_fn_and_mod() {
38+
pub macro m() {}
39+
}
40+
pub mod both_fn_and_mod {
41+
// @!has krate/both_fn_and_mod/macro.m.html
42+
}
43+
44+
const __: () = {
45+
pub macro m() {}
46+
};
47+
pub mod __ {
48+
// @!has krate/__/macro.m.html
1749
}

0 commit comments

Comments
 (0)