Skip to content

Commit 88f9f49

Browse files
authored
Rollup merge of rust-lang#103886 - GuillaumeGomez:local-reexport-doc, r=notriddle
rustdoc: Fix merge of attributes for reexports of local items Fixes rust-lang#84619. The problem was that we didn't merge attributes between the the reexport and the item. r? `@notriddle`
2 parents bb201b5 + c983bb1 commit 88f9f49

File tree

3 files changed

+53
-18
lines changed

3 files changed

+53
-18
lines changed

src/librustdoc/clean/mod.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,20 @@ pub(crate) fn clean_doc_module<'tcx>(doc: &DocModule<'tcx>, cx: &mut DocContext<
7474
// This covers the case where somebody does an import which should pull in an item,
7575
// but there's already an item with the same namespace and same name. Rust gives
7676
// priority to the not-imported one, so we should, too.
77-
items.extend(doc.items.iter().flat_map(|(item, renamed)| {
77+
items.extend(doc.items.iter().flat_map(|(item, renamed, import_id)| {
7878
// First, lower everything other than imports.
7979
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
8080
return Vec::new();
8181
}
82-
let v = clean_maybe_renamed_item(cx, item, *renamed);
82+
let v = clean_maybe_renamed_item(cx, item, *renamed, *import_id);
8383
for item in &v {
8484
if let Some(name) = item.name && !item.attrs.lists(sym::doc).has_word(sym::hidden) {
8585
inserted.insert((item.type_(), name));
8686
}
8787
}
8888
v
8989
}));
90-
items.extend(doc.items.iter().flat_map(|(item, renamed)| {
90+
items.extend(doc.items.iter().flat_map(|(item, renamed, _)| {
9191
// Now we actually lower the imports, skipping everything else.
9292
if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind {
9393
let name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
@@ -1911,6 +1911,7 @@ fn clean_maybe_renamed_item<'tcx>(
19111911
cx: &mut DocContext<'tcx>,
19121912
item: &hir::Item<'tcx>,
19131913
renamed: Option<Symbol>,
1914+
import_id: Option<hir::HirId>,
19141915
) -> Vec<Item> {
19151916
use hir::ItemKind;
19161917

@@ -1987,8 +1988,23 @@ fn clean_maybe_renamed_item<'tcx>(
19871988
}
19881989
_ => unreachable!("not yet converted"),
19891990
};
1990-
1991-
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
1991+
if let Some(import_id) = import_id {
1992+
let (attrs, cfg) = inline::merge_attrs(
1993+
cx,
1994+
Some(cx.tcx.parent_module(import_id).to_def_id()),
1995+
inline::load_attrs(cx, def_id),
1996+
Some(inline::load_attrs(cx, cx.tcx.hir().local_def_id(import_id).to_def_id())),
1997+
);
1998+
vec![Item::from_def_id_and_attrs_and_parts(
1999+
def_id,
2000+
Some(name),
2001+
kind,
2002+
Box::new(attrs),
2003+
cfg,
2004+
)]
2005+
} else {
2006+
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
2007+
}
19922008
})
19932009
}
19942010

src/librustdoc/visit_ast.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ pub(crate) struct Module<'hir> {
2525
pub(crate) where_inner: Span,
2626
pub(crate) mods: Vec<Module<'hir>>,
2727
pub(crate) id: hir::HirId,
28-
// (item, renamed)
29-
pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>)>,
28+
// (item, renamed, import_id)
29+
pub(crate) items: Vec<(&'hir hir::Item<'hir>, Option<Symbol>, Option<hir::HirId>)>,
3030
pub(crate) foreigns: Vec<(&'hir hir::ForeignItem<'hir>, Option<Symbol>)>,
3131
}
3232

@@ -93,6 +93,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
9393
hir::CRATE_HIR_ID,
9494
self.cx.tcx.hir().root_module(),
9595
self.cx.tcx.crate_name(LOCAL_CRATE),
96+
None,
9697
);
9798

9899
// `#[macro_export] macro_rules!` items are reexported at the top level of the
@@ -113,7 +114,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
113114
if self.cx.tcx.has_attr(def_id, sym::macro_export) {
114115
if inserted.insert(def_id) {
115116
let item = self.cx.tcx.hir().expect_item(local_def_id);
116-
top_level_module.items.push((item, None));
117+
top_level_module.items.push((item, None, None));
117118
}
118119
}
119120
}
@@ -155,6 +156,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
155156
id: hir::HirId,
156157
m: &'tcx hir::Mod<'tcx>,
157158
name: Symbol,
159+
parent_id: Option<hir::HirId>,
158160
) -> Module<'tcx> {
159161
let mut om = Module::new(name, id, m.spans.inner_span);
160162
let def_id = self.cx.tcx.hir().local_def_id(id).to_def_id();
@@ -166,15 +168,15 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
166168
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
167169
continue;
168170
}
169-
self.visit_item(item, None, &mut om);
171+
self.visit_item(item, None, &mut om, parent_id);
170172
}
171173
for &i in m.item_ids {
172174
let item = self.cx.tcx.hir().item(i);
173175
// To match the way import precedence works, visit glob imports last.
174176
// Later passes in rustdoc will de-duplicate by name and kind, so if glob-
175177
// imported items appear last, then they'll be the ones that get discarded.
176178
if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) {
177-
self.visit_item(item, None, &mut om);
179+
self.visit_item(item, None, &mut om, parent_id);
178180
}
179181
}
180182
self.inside_public_path = orig_inside_public_path;
@@ -247,14 +249,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
247249
let prev = mem::replace(&mut self.inlining, true);
248250
for &i in m.item_ids {
249251
let i = self.cx.tcx.hir().item(i);
250-
self.visit_item(i, None, om);
252+
self.visit_item(i, None, om, Some(id));
251253
}
252254
self.inlining = prev;
253255
true
254256
}
255257
Node::Item(it) if !glob => {
256258
let prev = mem::replace(&mut self.inlining, true);
257-
self.visit_item(it, renamed, om);
259+
self.visit_item(it, renamed, om, Some(id));
258260
self.inlining = prev;
259261
true
260262
}
@@ -275,6 +277,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
275277
item: &'tcx hir::Item<'_>,
276278
renamed: Option<Symbol>,
277279
om: &mut Module<'tcx>,
280+
parent_id: Option<hir::HirId>,
278281
) {
279282
debug!("visiting item {:?}", item);
280283
let name = renamed.unwrap_or(item.ident.name);
@@ -330,7 +333,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
330333
}
331334
}
332335

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

351354
if is_macro_2_0 || nonexported || self.inlining {
352-
om.items.push((item, renamed));
355+
om.items.push((item, renamed, None));
353356
}
354357
}
355358
hir::ItemKind::Mod(ref m) => {
356-
om.mods.push(self.visit_mod_contents(item.hir_id(), m, name));
359+
om.mods.push(self.visit_mod_contents(item.hir_id(), m, name, parent_id));
357360
}
358361
hir::ItemKind::Fn(..)
359362
| hir::ItemKind::ExternCrate(..)
@@ -364,19 +367,19 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
364367
| hir::ItemKind::OpaqueTy(..)
365368
| hir::ItemKind::Static(..)
366369
| hir::ItemKind::Trait(..)
367-
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed)),
370+
| hir::ItemKind::TraitAlias(..) => om.items.push((item, renamed, parent_id)),
368371
hir::ItemKind::Const(..) => {
369372
// Underscore constants do not correspond to a nameable item and
370373
// so are never useful in documentation.
371374
if name != kw::Underscore {
372-
om.items.push((item, renamed));
375+
om.items.push((item, renamed, parent_id));
373376
}
374377
}
375378
hir::ItemKind::Impl(impl_) => {
376379
// Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
377380
// them up regardless of where they're located.
378381
if !self.inlining && impl_.of_trait.is_none() {
379-
om.items.push((item, None));
382+
om.items.push((item, None, None));
380383
}
381384
}
382385
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// This test ensures that the reexports of local items also get the doc from
2+
// the reexport.
3+
4+
#![crate_name = "foo"]
5+
6+
// @has 'foo/fn.g.html'
7+
// @has - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]' \
8+
// 'outer module inner module'
9+
10+
mod inner_mod {
11+
/// inner module
12+
pub fn g() {}
13+
}
14+
15+
/// outer module
16+
pub use inner_mod::g;

0 commit comments

Comments
 (0)