Skip to content

Commit 2289955

Browse files
committed
rustdoc: do not mark the contents of a skipped module as inlined
1 parent 5c54be3 commit 2289955

File tree

4 files changed

+70
-21
lines changed

4 files changed

+70
-21
lines changed

src/librustdoc/clean/inline.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ pub(crate) fn try_inline_glob(
145145
cx: &mut DocContext<'_>,
146146
res: Res,
147147
visited: &mut FxHashSet<DefId>,
148+
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
148149
) -> Option<Vec<clean::Item>> {
149150
let did = res.opt_def_id()?;
150151
if did.is_local() {
@@ -153,8 +154,17 @@ pub(crate) fn try_inline_glob(
153154

154155
match res {
155156
Res::Def(DefKind::Mod, did) => {
156-
let m = build_module(cx, did, visited);
157-
Some(m.items)
157+
let mut items = build_module_items(cx, did, visited, inlined_names);
158+
items.drain_filter(|item| {
159+
if let Some(name) = item.name {
160+
// If an item with the same type and name already exists,
161+
// it takes priority over the inlined stuff.
162+
!inlined_names.insert((item.type_(), name))
163+
} else {
164+
false
165+
}
166+
});
167+
Some(items)
158168
}
159169
// glob imports on things like enums aren't inlined even for local exports, so just bail
160170
_ => None,
@@ -517,6 +527,18 @@ fn build_module(
517527
did: DefId,
518528
visited: &mut FxHashSet<DefId>,
519529
) -> clean::Module {
530+
let items = build_module_items(cx, did, visited, &mut FxHashSet::default());
531+
532+
let span = clean::Span::new(cx.tcx.def_span(did));
533+
clean::Module { items, span }
534+
}
535+
536+
fn build_module_items(
537+
cx: &mut DocContext<'_>,
538+
did: DefId,
539+
visited: &mut FxHashSet<DefId>,
540+
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
541+
) -> Vec<clean::Item> {
520542
let mut items = Vec::new();
521543

522544
// If we're re-exporting a re-export it may actually re-export something in
@@ -526,7 +548,13 @@ fn build_module(
526548
if item.vis.is_public() {
527549
let res = item.res.expect_non_local();
528550
if let Some(def_id) = res.mod_def_id() {
529-
if did == def_id || !visited.insert(def_id) {
551+
// If we're inlining a glob import, it's possible to have
552+
// two distinct modules with the same name. We don't want to
553+
// inline it, or mark any of its contents as visited.
554+
if did == def_id
555+
|| inlined_names.contains(&(ItemType::Module, item.ident.name))
556+
|| !visited.insert(def_id)
557+
{
530558
continue;
531559
}
532560
}
@@ -563,8 +591,7 @@ fn build_module(
563591
}
564592
}
565593

566-
let span = clean::Span::new(cx.tcx.def_span(did));
567-
clean::Module { items, span }
594+
items
568595
}
569596

570597
pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {

src/librustdoc/clean/mod.rs

+11-16
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
7171
// priority to the not-imported one, so we should, too.
7272
items.extend(self.items.iter().flat_map(|(item, renamed)| {
7373
// First, lower everything other than imports.
74-
if matches!(item.kind, hir::ItemKind::Use(..)) {
74+
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
7575
return Vec::new();
7676
}
7777
let v = clean_maybe_renamed_item(cx, item, *renamed);
@@ -84,20 +84,13 @@ impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
8484
}));
8585
items.extend(self.items.iter().flat_map(|(item, renamed)| {
8686
// Now we actually lower the imports, skipping everything else.
87-
if !matches!(item.kind, hir::ItemKind::Use(..)) {
88-
return Vec::new();
87+
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
88+
let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
89+
clean_use_statement(item, name, path, hir::UseKind::Glob, cx, &mut inserted)
90+
} else {
91+
// skip everything else
92+
Vec::new()
8993
}
90-
let mut v = clean_maybe_renamed_item(cx, item, *renamed);
91-
v.drain_filter(|item| {
92-
if let Some(name) = item.name {
93-
// If an item with the same type and name already exists,
94-
// it takes priority over the inlined stuff.
95-
!inserted.insert((item.type_(), name))
96-
} else {
97-
false
98-
}
99-
});
100-
v
10194
}));
10295

10396
// determine if we should display the inner contents or
@@ -1962,7 +1955,7 @@ fn clean_maybe_renamed_item<'tcx>(
19621955
return clean_extern_crate(item, name, orig_name, cx);
19631956
}
19641957
ItemKind::Use(path, kind) => {
1965-
return clean_use_statement(item, name, path, kind, cx);
1958+
return clean_use_statement(item, name, path, kind, cx, &mut FxHashSet::default());
19661959
}
19671960
_ => unreachable!("not yet converted"),
19681961
};
@@ -2083,6 +2076,7 @@ fn clean_use_statement<'tcx>(
20832076
path: &hir::Path<'tcx>,
20842077
kind: hir::UseKind,
20852078
cx: &mut DocContext<'tcx>,
2079+
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
20862080
) -> Vec<Item> {
20872081
// We need this comparison because some imports (for std types for example)
20882082
// are "inserted" as well but directly by the compiler and they should not be
@@ -2148,7 +2142,8 @@ fn clean_use_statement<'tcx>(
21482142
let inner = if kind == hir::UseKind::Glob {
21492143
if !denied {
21502144
let mut visited = FxHashSet::default();
2151-
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
2145+
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited, inlined_names)
2146+
{
21522147
return items;
21532148
}
21542149
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![crate_name="first"]
2+
3+
pub mod prelude {
4+
pub use crate::Bot;
5+
}
6+
7+
pub struct Bot;
8+
9+
impl Bot {
10+
pub fn new() -> Bot {
11+
Bot
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// aux-build:issue-100204-aux.rs
2+
// build-aux-docs
3+
// ignore-cross-compile
4+
5+
#![crate_name="second"]
6+
7+
extern crate first;
8+
9+
pub mod prelude {}
10+
11+
// @has first/struct.Bot.html '//h4[@class="code-header"]' 'pub fn new() -> Bot'
12+
// @has second/struct.Bot.html '//h4[@class="code-header"]' 'pub fn new() -> Bot'
13+
#[doc(inline)]
14+
pub use first::*;

0 commit comments

Comments
 (0)