Skip to content

Commit 6fb4ce9

Browse files
Fix invalid display of inlined re-export
1 parent 6b9236e commit 6fb4ce9

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

src/librustdoc/clean/mod.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,19 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
9090
}
9191
v
9292
}));
93+
items.extend(doc.inlined_foreigns.values().flat_map(|(res, renamed, local_import_id)| {
94+
let Some(def_id) = res.opt_def_id() else { return Vec::new() };
95+
let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id));
96+
let import = cx.tcx.hir().expect_item(*local_import_id);
97+
match import.kind {
98+
hir::ItemKind::Use(path, kind) => {
99+
let hir::UsePath { segments, span, .. } = *path;
100+
let path = hir::Path { segments, res: *res, span };
101+
clean_use_statement_inner(import, name, &path, kind, cx, &mut Default::default())
102+
}
103+
_ => unreachable!(),
104+
}
105+
}));
93106
items.extend(doc.items.values().flat_map(|(item, renamed, _)| {
94107
// Now we actually lower the imports, skipping everything else.
95108
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
@@ -2652,9 +2665,6 @@ fn clean_use_statement<'tcx>(
26522665
let mut items = Vec::new();
26532666
let hir::UsePath { segments, ref res, span } = *path;
26542667
for &res in res {
2655-
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res {
2656-
continue;
2657-
}
26582668
let path = hir::Path { segments, res, span };
26592669
items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names));
26602670
}
@@ -2669,6 +2679,9 @@ fn clean_use_statement_inner<'tcx>(
26692679
cx: &mut DocContext<'tcx>,
26702680
inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
26712681
) -> Vec<Item> {
2682+
if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = path.res {
2683+
return Vec::new();
2684+
}
26722685
// We need this comparison because some imports (for std types for example)
26732686
// are "inserted" as well but directly by the compiler and they should not be
26742687
// taken into account.

src/librustdoc/visit_ast.rs

+26-14
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ pub(crate) struct Module<'hir> {
3535
(LocalDefId, Option<Symbol>),
3636
(&'hir hir::Item<'hir>, Option<Symbol>, Option<LocalDefId>),
3737
>,
38+
/// Same as for `items`.
39+
pub(crate) inlined_foreigns:
40+
FxIndexMap<(DefId, Option<Symbol>), (Res, Option<Symbol>, LocalDefId)>,
3841
pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
3942
}
4043

@@ -54,6 +57,7 @@ impl Module<'_> {
5457
import_id,
5558
mods: Vec::new(),
5659
items: FxIndexMap::default(),
60+
inlined_foreigns: FxIndexMap::default(),
5761
foreigns: Vec::new(),
5862
}
5963
}
@@ -272,21 +276,30 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
272276
return false;
273277
}
274278

275-
// For cross-crate impl inlining we need to know whether items are
276-
// reachable in documentation -- a previously unreachable item can be
277-
// made reachable by cross-crate inlining which we're checking here.
278-
// (this is done here because we need to know this upfront).
279-
if !ori_res_did.is_local() && !is_no_inline {
280-
crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
281-
return false;
282-
}
283-
279+
let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did);
284280
let Some(res_did) = ori_res_did.as_local() else {
285-
return false;
281+
// For cross-crate impl inlining we need to know whether items are
282+
// reachable in documentation -- a previously unreachable item can be
283+
// made reachable by cross-crate inlining which we're checking here.
284+
// (this is done here because we need to know this upfront).
285+
crate::visit_lib::lib_embargo_visit_item(self.cx, ori_res_did);
286+
if is_hidden {
287+
return false;
288+
}
289+
// We store inlined foreign items otherwise, it'd mean that the `use` item would be kept
290+
// around. It's not a problem unless this `use` imports both a local AND a foreign item.
291+
// If a local item is inlined, its `use` is not supposed to still be around in `clean`,
292+
// which would make appear the `use` in the generated documentation like the local item
293+
// was not inlined even though it actually was.
294+
self.modules
295+
.last_mut()
296+
.unwrap()
297+
.inlined_foreigns
298+
.insert((ori_res_did, renamed), (res, renamed, def_id));
299+
return true;
286300
};
287301

288302
let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did);
289-
let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did);
290303
let item = tcx.hir().get_by_def_id(res_did);
291304

292305
if !please_inline {
@@ -314,7 +327,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
314327
return false;
315328
}
316329

317-
let inlined = match tcx.hir().get_by_def_id(res_did) {
330+
let inlined = match item {
318331
// Bang macros are handled a bit on their because of how they are handled by the
319332
// compiler. If they have `#[doc(hidden)]` and the re-export doesn't have
320333
// `#[doc(inline)]`, then we don't inline it.
@@ -346,7 +359,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
346359
};
347360
self.view_item_stack.remove(&res_did);
348361
if inlined {
349-
self.cx.cache.inlined_items.insert(res_did.to_def_id());
362+
self.cx.cache.inlined_items.insert(ori_res_did);
350363
}
351364
inlined
352365
}
@@ -483,7 +496,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
483496
continue;
484497
}
485498
}
486-
487499
self.add_to_current_mod(item, renamed, import_id);
488500
}
489501
}

0 commit comments

Comments
 (0)