Skip to content

Commit 9347710

Browse files
Adjust rustdoc implementation
1 parent 5f9b921 commit 9347710

File tree

2 files changed

+53
-22
lines changed

2 files changed

+53
-22
lines changed

src/librustdoc/doctest.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,10 +1171,17 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx>
11711171
}
11721172

11731173
fn visit_item(&mut self, item: &'hir hir::Item<'_>) {
1174-
let name = if let hir::ItemKind::Impl(impl_) = &item.kind {
1175-
rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
1176-
} else {
1177-
item.ident.to_string()
1174+
let name = match &item.kind {
1175+
hir::ItemKind::Macro { is_exported: false, .. } => {
1176+
// FIXME(#88038): Non exported macros have historically not been tested,
1177+
// but we really ought to start testing them.
1178+
intravisit::walk_item(self, item);
1179+
return;
1180+
}
1181+
hir::ItemKind::Impl(impl_) => {
1182+
rustc_hir_pretty::id_to_string(&self.map, impl_.self_ty.hir_id)
1183+
}
1184+
_ => item.ident.to_string(),
11781185
};
11791186

11801187
self.visit_testable(name, item.hir_id(), item.span, |this| {
@@ -1216,15 +1223,6 @@ impl<'a, 'hir, 'tcx> intravisit::Visitor<'hir> for HirCollector<'a, 'hir, 'tcx>
12161223
intravisit::walk_field_def(this, f);
12171224
});
12181225
}
1219-
1220-
fn visit_macro_def(&mut self, macro_def: &'hir hir::MacroDef<'_>) {
1221-
self.visit_testable(
1222-
macro_def.ident.to_string(),
1223-
macro_def.hir_id(),
1224-
macro_def.span,
1225-
|_| (),
1226-
);
1227-
}
12281226
}
12291227

12301228
#[cfg(test)]

src/librustdoc/visit_ast.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::def_id::DefId;
88
use rustc_hir::Node;
99
use rustc_middle::middle::privacy::AccessLevel;
10-
use rustc_middle::ty::TyCtxt;
10+
use rustc_middle::ty::{TyCtxt, Visibility};
1111
use rustc_span;
12-
use rustc_span::def_id::LOCAL_CRATE;
12+
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
1313
use rustc_span::source_map::Spanned;
1414
use 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

Comments
 (0)