diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a46e6a2ca6c..80f05863d0e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2100,6 +2100,7 @@ fn get_all_import_attributes<'hir>( tcx: TyCtxt<'hir>, target_def_id: LocalDefId, attributes: &mut Vec, + is_inline: bool, ) { let hir_map = tcx.hir(); let mut visitor = OneLevelVisitor::new(hir_map, target_def_id); @@ -2107,7 +2108,7 @@ fn get_all_import_attributes<'hir>( // If the item is an import and has at least a path with two parts, we go into it. while let hir::ItemKind::Use(path, _) = item.kind && visited.insert(item.hir_id()) { // We add the attributes from this import into the list. - add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id())); + add_without_unwanted_attributes(attributes, hir_map.attrs(item.hir_id()), is_inline); let def_id = if path.segments.len() > 1 { match path.segments[path.segments.len() - 2].res { @@ -2189,7 +2190,16 @@ fn filter_tokens_from_list( /// * `doc(inline)` /// * `doc(no_inline)` /// * `doc(hidden)` -fn add_without_unwanted_attributes(attrs: &mut Vec, new_attrs: &[ast::Attribute]) { +fn add_without_unwanted_attributes( + attrs: &mut Vec, + new_attrs: &[ast::Attribute], + is_inline: bool, +) { + // If it's `#[doc(inline)]`, we don't want all attributes, otherwise we keep everything. + if !is_inline { + attrs.extend_from_slice(new_attrs); + return; + } for attr in new_attrs { let mut attr = attr.clone(); match attr.kind { @@ -2321,9 +2331,10 @@ fn clean_maybe_renamed_item<'tcx>( { // First, we add the attributes from the current import. extra_attrs.extend_from_slice(inline::load_attrs(cx, import_id.to_def_id())); + let is_inline = extra_attrs.lists(sym::doc).get_word_attr(sym::inline).is_some(); // Then we get all the various imports' attributes. - get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs); - add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id)); + get_all_import_attributes(use_node, cx.tcx, item.owner_id.def_id, &mut extra_attrs, is_inline); + add_without_unwanted_attributes(&mut extra_attrs, inline::load_attrs(cx, def_id), is_inline); } else { // We only keep the item's attributes. extra_attrs.extend_from_slice(inline::load_attrs(cx, def_id)); diff --git a/tests/rustdoc/reexport-attr-merge.rs b/tests/rustdoc/reexport-attr-merge.rs index f1aee08c9c0..f6c23a1365f 100644 --- a/tests/rustdoc/reexport-attr-merge.rs +++ b/tests/rustdoc/reexport-attr-merge.rs @@ -1,5 +1,6 @@ // Regression test for . -// The goal is to ensure that `doc(hidden)`, `doc(inline)` and `doc(no_inline`) +// The goal is to ensure that `doc(hidden)`, `doc(inline)` and `doc(no_inline)` +// are not copied from an item when inlined. #![crate_name = "foo"] #![feature(doc_cfg)] @@ -15,8 +16,9 @@ pub use Foo as Foo1; #[doc(hidden, inline)] pub use Foo1 as Foo2; -// First we ensure that none of the other items are generated. -// @count - '//a[@class="struct"]' 1 +// First we ensure that only the reexport `Bar2` and the inlined struct `Bar` +// are inlined. +// @count - '//a[@class="struct"]' 2 // Then we check that both `cfg` are displayed. // @has - '//*[@class="stab portability"]' 'foo' // @has - '//*[@class="stab portability"]' 'bar' @@ -24,3 +26,8 @@ pub use Foo1 as Foo2; // @has - '//a[@class="struct"]' 'Bar' #[doc(inline)] pub use Foo2 as Bar; + +// This one should appear but `Bar2` won't be linked because there is no +// `#[doc(inline)]`. +// @has - '//*[@id="reexport.Bar2"]' 'pub use Foo2 as Bar2;' +pub use Foo2 as Bar2;