about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/clean/inline.rs6
-rw-r--r--src/librustdoc/clean/mod.rs3
-rw-r--r--src/librustdoc/clean/types.rs10
-rw-r--r--src/librustdoc/clean/utils.rs16
-rw-r--r--src/librustdoc/core.rs9
-rw-r--r--src/librustdoc/fold.rs3
-rw-r--r--src/librustdoc/formats/cache.rs8
-rw-r--r--src/librustdoc/html/render/mod.rs9
-rw-r--r--src/librustdoc/json/conversions.rs2
-rw-r--r--src/librustdoc/json/mod.rs1
-rw-r--r--src/test/rustdoc/spotlight-from-dependency.rs24
11 files changed, 73 insertions, 18 deletions
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index ea75d1614bd..f9c63186544 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -195,14 +195,12 @@ crate fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Tra
     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).clean(cx).has_doc_flag(sym::spotlight);
     let is_auto = cx.tcx.trait_is_auto(did);
     clean::Trait {
         unsafety: cx.tcx.trait_def(did).unsafety,
         generics,
         items: trait_items,
         bounds: supertrait_bounds,
-        is_spotlight,
         is_auto,
     }
 }
@@ -626,6 +624,10 @@ crate fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
     debug!("record_extern_trait: {:?}", did);
     let trait_ = build_external_trait(cx, did);
 
+    let trait_ = clean::TraitWithExtraInfo {
+        trait_,
+        is_spotlight: clean::utils::has_doc_flag(cx.tcx.get_attrs(did), sym::spotlight),
+    };
     cx.external_traits.borrow_mut().insert(did, trait_);
     cx.active_extern_traits.remove(&did);
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index b6e70462105..7aa34333e17 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2003,14 +2003,11 @@ impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
                         .iter()
                         .map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
                         .collect();
-                    let attrs = item.attrs.clean(cx);
-                    let is_spotlight = attrs.has_doc_flag(sym::spotlight);
                     TraitItem(Trait {
                         unsafety,
                         items,
                         generics: generics.clean(cx),
                         bounds: bounds.clean(cx),
-                        is_spotlight,
                         is_auto: is_auto.clean(cx),
                     })
                 }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 9a2319f6e37..51bef344e67 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -57,11 +57,18 @@ crate struct Crate {
     crate primitives: Vec<(DefId, PrimitiveType)>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
-    crate external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
+    crate external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
     crate masked_crates: FxHashSet<CrateNum>,
     crate collapsed: bool,
 }
 
+/// This struct is used to wrap additional information added by rustdoc on a `trait` item.
+#[derive(Clone, Debug)]
+crate struct TraitWithExtraInfo {
+    crate trait_: Trait,
+    crate is_spotlight: bool,
+}
+
 #[derive(Clone, Debug)]
 crate struct ExternalCrate {
     crate name: Symbol,
@@ -1185,7 +1192,6 @@ crate struct Trait {
     crate items: Vec<Item>,
     crate generics: Generics,
     crate bounds: Vec<GenericBound>,
-    crate is_spotlight: bool,
     crate is_auto: bool,
 }
 
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index d2eee49f0c9..a0a2b785353 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -520,3 +520,19 @@ crate fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Option<De
         None
     }
 }
+
+/// Checks for the existence of `hidden` in the attribute below if `flag` is `sym::hidden`:
+///
+/// ```
+/// #[doc(hidden)]
+/// pub fn foo() {}
+/// ```
+///
+/// This function exists because it runs on `hir::Attributes` whereas the other is a
+/// `clean::Attributes` method.
+crate fn has_doc_flag(attrs: ty::Attributes<'_>, flag: Symbol) -> bool {
+    attrs.iter().any(|attr| {
+        attr.has_name(sym::doc)
+            && attr.meta_item_list().map_or(false, |l| rustc_attr::list_contains_name(&l, flag))
+    })
+}
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 8fceb00eeae..f0b3159f737 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -30,7 +30,7 @@ use std::{cell::RefCell, collections::hash_map::Entry};
 
 use crate::clean;
 use crate::clean::inline::build_external_trait;
-use crate::clean::{AttributesExt, MAX_DEF_IDX};
+use crate::clean::{AttributesExt, TraitWithExtraInfo, MAX_DEF_IDX};
 use crate::config::{Options as RustdocOptions, RenderOptions};
 use crate::config::{OutputFormat, RenderInfo};
 use crate::formats::cache::Cache;
@@ -55,7 +55,7 @@ crate struct DocContext<'tcx> {
     /// Later on moved into `cache`
     crate renderinfo: RenderInfo,
     /// Later on moved through `clean::Crate` into `cache`
-    crate external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>,
+    crate external_traits: Rc<RefCell<FxHashMap<DefId, clean::TraitWithExtraInfo>>>,
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     crate active_extern_traits: FxHashSet<DefId>,
@@ -538,7 +538,10 @@ crate fn run_global_ctxt(
     if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
         let mut sized_trait = build_external_trait(&mut ctxt, sized_trait_did);
         sized_trait.is_auto = true;
-        ctxt.external_traits.borrow_mut().insert(sized_trait_did, sized_trait);
+        ctxt.external_traits.borrow_mut().insert(
+            sized_trait_did,
+            TraitWithExtraInfo { trait_: sized_trait, is_spotlight: false },
+        );
     }
 
     debug!("crate: {:?}", tcx.hir().krate());
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index b2773a29e29..2b980ebe592 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -92,7 +92,8 @@ crate trait DocFolder: Sized {
         {
             let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
             for (k, mut v) in external_traits {
-                v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+                v.trait_.items =
+                    v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
                 c.external_traits.borrow_mut().insert(k, v);
             }
         }
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index ce1204c7be1..e9c5dd50d59 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -7,6 +7,7 @@ use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
 use rustc_middle::middle::privacy::AccessLevels;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::source_map::FileName;
+use rustc_span::symbol::sym;
 use rustc_span::Symbol;
 
 use crate::clean::{self, GetDefId};
@@ -64,7 +65,7 @@ crate struct Cache {
     /// Implementations of a crate should inherit the documentation of the
     /// parent trait if no extra documentation is specified, and default methods
     /// should show up in documentation about trait implementations.
-    crate traits: FxHashMap<DefId, clean::Trait>,
+    crate traits: FxHashMap<DefId, clean::TraitWithExtraInfo>,
 
     /// When rendering traits, it's often useful to be able to list all
     /// implementors of the trait, and this mapping is exactly, that: a mapping
@@ -247,7 +248,10 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
         // Propagate a trait method's documentation to all implementors of the
         // trait.
         if let clean::TraitItem(ref t) = *item.kind {
-            self.cache.traits.entry(item.def_id).or_insert_with(|| t.clone());
+            self.cache.traits.entry(item.def_id).or_insert_with(|| clean::TraitWithExtraInfo {
+                trait_: t.clone(),
+                is_spotlight: item.attrs.has_doc_flag(sym::spotlight),
+            });
         }
 
         // Collect all the implementors of traits.
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 7f122bb8cb5..b21f6a13392 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -3687,8 +3687,9 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
         if let Some(impls) = cache.impls.get(&did) {
             for i in impls {
                 let impl_ = i.inner_impl();
-                if impl_.trait_.def_id_full(cache).map_or(false, |d| cache.traits[&d].is_spotlight)
-                {
+                if impl_.trait_.def_id().map_or(false, |d| {
+                    cache.traits.get(&d).map(|t| t.is_spotlight).unwrap_or(false)
+                }) {
                     if out.is_empty() {
                         write!(
                             &mut out,
@@ -3979,7 +3980,7 @@ fn render_impl(
             false,
             outer_version,
             outer_const_version,
-            trait_,
+            trait_.map(|t| &t.trait_),
             show_def_docs,
         );
     }
@@ -4028,7 +4029,7 @@ fn render_impl(
             render_default_items(
                 w,
                 cx,
-                t,
+                &t.trait_,
                 &i.inner_impl(),
                 &i.impl_item,
                 render_mode,
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index b248fcdefbe..da09d49a006 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -408,7 +408,7 @@ impl From<clean::FnDecl> for FnDecl {
 
 impl From<clean::Trait> for Trait {
     fn from(trait_: clean::Trait) -> Self {
-        let clean::Trait { unsafety, items, generics, bounds, is_spotlight: _, is_auto } = trait_;
+        let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_;
         Trait {
             is_auto,
             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index ce88e09b174..a3b21467794 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -87,6 +87,7 @@ impl JsonRenderer<'tcx> {
             .filter_map(|(&id, trait_item)| {
                 // only need to synthesize items for external traits
                 if !id.is_local() {
+                    let trait_item = &trait_item.trait_;
                     trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
                     Some((
                         from_def_id(id),
diff --git a/src/test/rustdoc/spotlight-from-dependency.rs b/src/test/rustdoc/spotlight-from-dependency.rs
new file mode 100644
index 00000000000..ed42c435945
--- /dev/null
+++ b/src/test/rustdoc/spotlight-from-dependency.rs
@@ -0,0 +1,24 @@
+#![crate_name = "foo"]
+
+use std::iter::Iterator;
+
+// @has foo/struct.Odd.html
+// @has - '//h4[@id="method.new"]//span[@class="notable-traits"]//code/span' 'impl Iterator for Odd'
+pub struct Odd {
+    current: usize,
+}
+
+impl Odd {
+    pub fn new() -> Odd {
+        Odd { current: 1 }
+    }
+}
+
+impl Iterator for Odd {
+    type Item = usize;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.current += 2;
+        Some(self.current - 2)
+    }
+}