Skip to content

Commit

Permalink
Rollup merge of #103886 - GuillaumeGomez:local-reexport-doc, r=notriddle
Browse files Browse the repository at this point in the history
rustdoc: Fix merge of attributes for reexports of local items

Fixes #84619.

The problem was that we didn't merge attributes between the the reexport and the item.

r? `@notriddle`
  • Loading branch information
matthiaskrgr authored Nov 2, 2022
2 parents bb201b5 + c983bb1 commit 88f9f49
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 18 deletions.
26 changes: 21 additions & 5 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,20 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
// This covers the case where somebody does an import which should pull in an item,
// but there's already an item with the same namespace and same name. Rust gives
// priority to the not-imported one, so we should, too.
items.extend(doc.items.iter().flat_map(|(item, renamed)| {
items.extend(doc.items.iter().flat_map(|(item, renamed, import_id)| {
// First, lower everything other than imports.
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
return Vec::new();
}
let v = clean_maybe_renamed_item(cx, item, *renamed);
let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id);
for item in &v {
if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
inserted.insert((item.type_(), name));
}
}
v
}));
items.extend(doc.items.iter().flat_map(|(item, renamed)| {
items.extend(doc.items.iter().flat_map(|(item, renamed, _)| {
// Now we actually lower the imports, skipping everything else.
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
Expand Down Expand Up @@ -1911,6 +1911,7 @@ fn clean_maybe_renamed_item<'tcx>(
cx: &mut DocContext<'tcx>,
item: &hir::Item<'tcx>,
renamed: Option<Symbol>,
import_id: Option<hir::HirId>,
) -> Vec<Item> {
use hir::ItemKind;

Expand Down Expand Up @@ -1987,8 +1988,23 @@ fn clean_maybe_renamed_item<'tcx>(
}
_ => unreachable!("not yet converted"),
};

vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
if let Some(import_id) = import_id {
let (attrs, cfg) = inline::merge_attrs(
cx,
Some(cx.tcx.parent_module(import_id).to_def_id()),
inline::load_attrs(cx, def_id),
Some(inline::load_attrs(cx, cx.tcx.hir().local_def_id(import_id).to_def_id())),
);
vec![Item::from_def_id_and_attrs_and_parts(
def_id,
Some(name),
kind,
Box::new(attrs),
cfg,
)]
} else {
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
}
})
}

Expand Down
29 changes: 16 additions & 13 deletions src/librustdoc/visit_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pub(crate) struct Module<'hir> {
pub(crate) where_inner: Span,
pub(crate) mods: Vec<Module<'hir>>,
pub(crate) id: hir::HirId,
// (item, renamed)
pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
// (item, renamed, import_id)
pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>, Option<hir::HirId>)>,
pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
}

Expand Down Expand Up @@ -93,6 +93,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
hir::CRATE_HIR_ID,
self.cx.tcx.hir().root_module(),
self.cx.tcx.crate_name(LOCAL_CRATE),
None,
);

// `#[macro_export] macro_rules!` items are reexported at the top level of the
Expand All @@ -113,7 +114,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
if self.cx.tcx.has_attr(def_id, sym::macro_export) {
if inserted.insert(def_id) {
let item = self.cx.tcx.hir().expect_item(local_def_id);
top_level_module.items.push((item, None));
top_level_module.items.push((item, None, None));
}
}
}
Expand Down Expand Up @@ -155,6 +156,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
id: hir::HirId,
m: &'tcx hir::Mod<'tcx>,
name: Symbol,
parent_id: Option<hir::HirId>,
) -> Module<'tcx> {
let mut om = Module::new(name, id, m.spans.inner_span);
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
Expand All @@ -166,15 +168,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
continue;
}
self.visit_item(item, None, &mut om);
self.visit_item(item, None, &mut om, parent_id);
}
for &i in m.item_ids {
let item = self.cx.tcx.hir().item(i);
// To match the way import precedence works, visit glob imports last.
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
// imported items appear last, then they'll be the ones that get discarded.
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
self.visit_item(item, None, &mut om);
self.visit_item(item, None, &mut om, parent_id);
}
}
self.inside_public_path = orig_inside_public_path;
Expand Down Expand Up @@ -247,14 +249,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
let prev = mem::replace(&mut self.inlining, true);
for &i in m.item_ids {
let i = self.cx.tcx.hir().item(i);
self.visit_item(i, None, om);
self.visit_item(i, None, om, Some(id));
}
self.inlining = prev;
true
}
Node::Item(it) if !glob => {
let prev = mem::replace(&mut self.inlining, true);
self.visit_item(it, renamed, om);
self.visit_item(it, renamed, om, Some(id));
self.inlining = prev;
true
}
Expand All @@ -275,6 +277,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
item: &'tcx hir::Item<'_>,
renamed: Option<Symbol>,
om: &mut Module<'tcx>,
parent_id: Option<hir::HirId>,
) {
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
Expand Down Expand Up @@ -330,7 +333,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
}
}

om.items.push((item, renamed))
om.items.push((item, renamed, parent_id))
}
hir::ItemKind::Macro(ref macro_def, _) => {
// `#[macro_export] macro_rules!` items are handled separately in `visit()`,
Expand All @@ -349,11 +352,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
let nonexported = !self.cx.tcx.has_attr(def_id, sym::macro_export);

if is_macro_2_0 || nonexported || self.inlining {
om.items.push((item, renamed));
om.items.push((item, renamed, None));
}
}
hir::ItemKind::Mod(ref m) => {
om.mods.push(self.visit_mod_contents(item.hir_id(), m, name));
om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
}
hir::ItemKind::Fn(..)
| hir::ItemKind::ExternCrate(..)
Expand All @@ -364,19 +367,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
| hir::ItemKind::OpaqueTy(..)
| hir::ItemKind::Static(..)
| hir::ItemKind::Trait(..)
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
hir::ItemKind::Const(..) => {
// Underscore constants do not correspond to a nameable item and
// so are never useful in documentation.
if name != kw::Underscore {
om.items.push((item, renamed));
om.items.push((item, renamed, parent_id));
}
}
hir::ItemKind::Impl(impl_) => {
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
// them up regardless of where they're located.
if !self.inlining && impl_.of_trait.is_none() {
om.items.push((item, None));
om.items.push((item, None, None));
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/test/rustdoc/local-reexport-doc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// This test ensures that the reexports of local items also get the doc from
// the reexport.

#![crate_name = "foo"]

// @has 'foo/fn.g.html'
// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' \
// 'outer module inner module'

mod inner_mod {
/// inner module
pub fn g() {}
}

/// outer module
pub use inner_mod::g;

0 comments on commit 88f9f49

Please sign in to comment.