about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/clean/inline.rs58
-rw-r--r--src/librustdoc/clean/mod.rs20
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs6
-rw-r--r--src/test/rustdoc/inline_cross/add-docs.rs9
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/add-docs.rs4
5 files changed, 73 insertions, 24 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 9259b3b5d3a..8463fbfbd20 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -24,6 +24,8 @@ use crate::clean::{
 
 use super::Clean;
 
+type Attrs<'hir> = rustc::ty::Attributes<'hir>;
+
 /// Attempt to inline a definition into this AST.
 ///
 /// This function will fetch the definition specified, and if it is
@@ -40,6 +42,7 @@ pub fn try_inline(
     cx: &DocContext<'_>,
     res: Res,
     name: ast::Name,
+    attrs: Option<Attrs<'_>>,
     visited: &mut FxHashSet<DefId>
 ) -> Option<Vec<clean::Item>> {
     let did = if let Some(did) = res.opt_def_id() {
@@ -49,10 +52,13 @@ pub fn try_inline(
     };
     if did.is_local() { return None }
     let mut ret = Vec::new();
+
+    let attrs_clone = attrs.clone();
+
     let inner = match res {
         Res::Def(DefKind::Trait, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Trait);
-            ret.extend(build_impls(cx, did));
+            ret.extend(build_impls(cx, did, attrs));
             clean::TraitItem(build_external_trait(cx, did))
         }
         Res::Def(DefKind::Fn, did) => {
@@ -61,27 +67,27 @@ pub fn try_inline(
         }
         Res::Def(DefKind::Struct, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Struct);
-            ret.extend(build_impls(cx, did));
+            ret.extend(build_impls(cx, did, attrs));
             clean::StructItem(build_struct(cx, did))
         }
         Res::Def(DefKind::Union, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Union);
-            ret.extend(build_impls(cx, did));
+            ret.extend(build_impls(cx, did, attrs));
             clean::UnionItem(build_union(cx, did))
         }
         Res::Def(DefKind::TyAlias, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Typedef);
-            ret.extend(build_impls(cx, did));
+            ret.extend(build_impls(cx, did, attrs));
             clean::TypedefItem(build_type_alias(cx, did), false)
         }
         Res::Def(DefKind::Enum, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Enum);
-            ret.extend(build_impls(cx, did));
+            ret.extend(build_impls(cx, did, attrs));
             clean::EnumItem(build_enum(cx, did))
         }
         Res::Def(DefKind::ForeignTy, did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Foreign);
-            ret.extend(build_impls(cx, did));
+            ret.extend(build_impls(cx, did, attrs));
             clean::ForeignTypeItem
         }
         // Never inline enum variants but leave them shown as re-exports.
@@ -113,11 +119,15 @@ pub fn try_inline(
         }
         _ => return None,
     };
+
+    let target_attrs = load_attrs(cx, did);
+    let attrs = merge_attrs(cx, target_attrs,  attrs_clone);
+
     cx.renderinfo.borrow_mut().inlined.insert(did);
     ret.push(clean::Item {
         source: cx.tcx.def_span(did).clean(cx),
         name: Some(name.clean(cx)),
-        attrs: load_attrs(cx, did),
+        attrs,
         inner,
         visibility: Some(clean::Public),
         stability: cx.tcx.lookup_stability(did).clean(cx),
@@ -144,8 +154,8 @@ pub fn try_inline_glob(cx: &DocContext<'_>, res: Res, visited: &mut FxHashSet<De
     }
 }
 
-pub fn load_attrs(cx: &DocContext<'_>, did: DefId) -> clean::Attributes {
-    cx.tcx.get_attrs(did).clean(cx)
+pub fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> {
+    cx.tcx.get_attrs(did)
 }
 
 /// Record an external fully qualified name in the external_paths cache.
@@ -187,7 +197,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait {
     let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
-    let is_spotlight = load_attrs(cx, did).has_doc_flag(sym::spotlight);
+    let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
     let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         auto: auto_trait,
@@ -274,23 +284,41 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
     }
 }
 
-pub fn build_impls(cx: &DocContext<'_>, did: DefId) -> Vec<clean::Item> {
+pub fn build_impls(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>) -> Vec<clean::Item> {
     let tcx = cx.tcx;
     let mut impls = Vec::new();
 
     for &did in tcx.inherent_impls(did).iter() {
-        build_impl(cx, did, &mut impls);
+        build_impl(cx, did, attrs.clone(), &mut impls);
     }
 
     impls
 }
 
-pub fn build_impl(cx: &DocContext<'_>, did: DefId, ret: &mut Vec<clean::Item>) {
+fn merge_attrs(cx: &DocContext<'_>, attrs: Attrs<'_>, other_attrs: Option<Attrs<'_>>
+) -> clean::Attributes {
+    let mut merged_attrs: Vec<ast::Attribute> = Vec::with_capacity(attrs.len());
+    // If we have additional attributes (from a re-export),
+    // always insert them first. This ensure that re-export
+    // doc comments show up before the original doc comments
+    // when we render them.
+    if let Some(a) = other_attrs {
+        merged_attrs.extend(a.iter().cloned());
+    }
+    merged_attrs.extend(attrs.to_vec());
+    merged_attrs.clean(cx)
+}
+
+pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>,
+                  ret: &mut Vec<clean::Item>
+) {
     if !cx.renderinfo.borrow_mut().inlined.insert(did) {
         return
     }
 
-    let attrs = load_attrs(cx, did);
+    let attrs = merge_attrs(cx, load_attrs(cx, did), attrs);
+
+
     let tcx = cx.tcx;
     let associated_trait = tcx.impl_trait_ref(did);
 
@@ -416,7 +444,7 @@ fn build_module(
             let def_id = item.res.def_id();
             if item.vis == ty::Visibility::Public {
                 if did == def_id || !visited.insert(def_id) { continue }
-                if let Some(i) = try_inline(cx, item.res, item.ident.name, visited) {
+                if let Some(i) = try_inline(cx, item.res, item.ident.name, None, visited) {
                     items.extend(i)
                 }
             }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a41b12e29b0..a7fb18c3f2c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2429,7 +2429,7 @@ impl Clean<Item> for ty::AssocItem {
             stability: get_stability(cx, self.def_id),
             deprecation: get_deprecation(cx, self.def_id),
             def_id: self.def_id,
-            attrs: inline::load_attrs(cx, self.def_id),
+            attrs: inline::load_attrs(cx, self.def_id).clean(cx),
             source: cx.tcx.def_span(self.def_id).clean(cx),
             inner,
         }
@@ -3372,7 +3372,7 @@ impl Clean<Item> for ty::VariantDef {
         };
         Item {
             name: Some(self.ident.clean(cx)),
-            attrs: inline::load_attrs(cx, self.def_id),
+            attrs: inline::load_attrs(cx, self.def_id).clean(cx),
             source: cx.tcx.def_span(self.def_id).clean(cx),
             visibility: Some(Inherited),
             def_id: self.def_id,
@@ -3856,7 +3856,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>,
         let primitive = match *target {
             ResolvedPath { did, .. } if did.is_local() => continue,
             ResolvedPath { did, .. } => {
-                ret.extend(inline::build_impls(cx, did));
+                ret.extend(inline::build_impls(cx, did, None));
                 continue
             }
             _ => match target.primitive_type() {
@@ -3894,7 +3894,7 @@ fn build_deref_target_impls(cx: &DocContext<'_>,
         };
         if let Some(did) = did {
             if !did.is_local() {
-                inline::build_impl(cx, did, ret);
+                inline::build_impl(cx, did, None, ret);
             }
         }
     }
@@ -3921,7 +3921,11 @@ impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
                 },
             );
 
-            if let Some(items) = inline::try_inline(cx, res, self.name, &mut visited) {
+            if let Some(items) = inline::try_inline(
+                cx, res, self.name,
+                Some(rustc::ty::Attributes::Borrowed(self.attrs)),
+                &mut visited
+            ) {
                 return items;
             }
         }
@@ -3981,7 +3985,11 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
             }
             if !denied {
                 let mut visited = FxHashSet::default();
-                if let Some(items) = inline::try_inline(cx, path.res, name, &mut visited) {
+                if let Some(items) = inline::try_inline(
+                    cx, path.res, name,
+                    Some(rustc::ty::Attributes::Borrowed(self.attrs)),
+                    &mut visited
+                ) {
                     return items;
                 }
             }
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index a2a6b1efe82..cd488b9df78 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -30,7 +30,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
 
     for &cnum in cx.tcx.crates().iter() {
         for &did in cx.tcx.all_trait_implementations(cnum).iter() {
-            inline::build_impl(cx, did, &mut new_items);
+            inline::build_impl(cx, did, None, &mut new_items);
         }
     }
 
@@ -66,7 +66,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
 
     for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
         if !def_id.is_local() {
-            inline::build_impl(cx, def_id, &mut new_items);
+            inline::build_impl(cx, def_id, None, &mut new_items);
 
             // FIXME(eddyb) is this `doc(hidden)` check needed?
             if !cx.tcx.get_attrs(def_id).lists(sym::doc).has_word(sym::hidden) {
@@ -119,7 +119,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
     for &trait_did in cx.all_traits.iter() {
         for &impl_node in cx.tcx.hir().trait_impls(trait_did) {
             let impl_did = cx.tcx.hir().local_def_id(impl_node);
-            inline::build_impl(cx, impl_did, &mut new_items);
+            inline::build_impl(cx, impl_did, None, &mut new_items);
         }
     }
 
diff --git a/src/test/rustdoc/inline_cross/add-docs.rs b/src/test/rustdoc/inline_cross/add-docs.rs
new file mode 100644
index 00000000000..1af5e8f03b4
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/add-docs.rs
@@ -0,0 +1,9 @@
+// aux-build:add-docs.rs
+
+extern crate inner;
+
+
+// @has add_docs/struct.MyStruct.html
+// @has add_docs/struct.MyStruct.html "Doc comment from 'pub use', Doc comment from definition"
+/// Doc comment from 'pub use',
+pub use inner::MyStruct;
diff --git a/src/test/rustdoc/inline_cross/auxiliary/add-docs.rs b/src/test/rustdoc/inline_cross/auxiliary/add-docs.rs
new file mode 100644
index 00000000000..85efa508f30
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/add-docs.rs
@@ -0,0 +1,4 @@
+#![crate_name = "inner"]
+
+/// Doc comment from definition
+pub struct MyStruct;