]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Add missing src links for generic impls on trait pages
authorOliver Middleton <olliemail27@gmail.com>
Wed, 27 Dec 2017 23:39:25 +0000 (23:39 +0000)
committerOliver Middleton <olliemail27@gmail.com>
Wed, 27 Dec 2017 23:39:25 +0000 (23:39 +0000)
`implementor2item` would return `None` for generic impls so instead this clones the entire `clean::Item` into the `implementors` map which simplifies some code.

src/librustdoc/html/render.rs
src/test/rustdoc/issue-43893.rs

index 3be44f3095858f1e5d87454d232a3333dae14dc9..59edee7b627576da3e927f7b613da5d81b0a1e02 100644 (file)
@@ -173,14 +173,7 @@ pub enum ExternalLocation {
     Unknown,
 }
 
-/// Metadata about an implementor of a trait.
-pub struct Implementor {
-    pub def_id: DefId,
-    pub stability: Option<clean::Stability>,
-    pub impl_: clean::Impl,
-}
-
-/// Metadata about implementations for a type.
+/// Metadata about implementations for a type or trait.
 #[derive(Clone)]
 pub struct Impl {
     pub impl_item: clean::Item,
@@ -279,7 +272,7 @@ pub struct Cache {
     /// 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
     /// of trait ids to the list of known implementors of the trait
-    pub implementors: FxHashMap<DefId, Vec<Implementor>>,
+    pub implementors: FxHashMap<DefId, Vec<Impl>>,
 
     /// Cache of where external crate documentation can be found.
     pub extern_locations: FxHashMap<CrateNum, (String, PathBuf, ExternalLocation)>,
@@ -965,12 +958,12 @@ fn collect(path: &Path, krate: &str,
             // there's no need to emit information about it (there's inlining
             // going on). If they're in different crates then the crate defining
             // the trait will be interested in our implementation.
-            if imp.def_id.krate == did.krate { continue }
+            if imp.impl_item.def_id.krate == did.krate { continue }
             // If the implementation is from another crate then that crate
             // should add it.
-            if !imp.def_id.is_local() { continue }
+            if !imp.impl_item.def_id.is_local() { continue }
             have_impls = true;
-            write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
+            write!(implementors, "{},", as_json(&imp.inner_impl().to_string())).unwrap();
         }
         implementors.push_str("];");
 
@@ -1202,10 +1195,8 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
             if !self.masked_crates.contains(&item.def_id.krate) {
                 if let Some(did) = i.trait_.def_id() {
                     if i.for_.def_id().map_or(true, |d| !self.masked_crates.contains(&d.krate)) {
-                        self.implementors.entry(did).or_insert(vec![]).push(Implementor {
-                            def_id: item.def_id,
-                            stability: item.stability.clone(),
-                            impl_: i.clone(),
+                        self.implementors.entry(did).or_insert(vec![]).push(Impl {
+                            impl_item: item.clone(),
                         });
                     }
                 }
@@ -2332,18 +2323,6 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     document(w, cx, it)
 }
 
-fn implementor2item<'a>(cache: &'a Cache, imp : &Implementor) -> Option<&'a clean::Item> {
-    if let Some(t_did) = imp.impl_.for_.def_id() {
-        if let Some(impl_item) = cache.impls.get(&t_did).and_then(|i| i.iter()
-            .find(|i| i.impl_item.def_id == imp.def_id))
-        {
-            let i = &impl_item.impl_item;
-            return Some(i);
-        }
-    }
-    None
-}
-
 fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
               t: &clean::Trait) -> fmt::Result {
     let mut bounds = String::new();
@@ -2527,7 +2506,7 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
         // if any Types with the same name but different DefId have been found.
         let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap();
         for implementor in implementors {
-            match implementor.impl_.for_ {
+            match implementor.inner_impl().for_ {
                 clean::ResolvedPath { ref path, did, is_generic: false, .. } |
                 clean::BorrowedRef {
                     type_: box clean::ResolvedPath { ref path, did, is_generic: false, .. },
@@ -2544,7 +2523,7 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
         }
 
         let (local, foreign) = implementors.iter()
-            .partition::<Vec<_>, _>(|i| i.impl_.for_.def_id()
+            .partition::<Vec<_>, _>(|i| i.inner_impl().for_.def_id()
                                          .map_or(true, |d| cache.paths.contains_key(&d)));
 
         if !foreign.is_empty() {
@@ -2555,14 +2534,11 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
             ")?;
 
             for implementor in foreign {
-                if let Some(i) = implementor2item(&cache, implementor) {
-                    let impl_ = Impl { impl_item: i.clone() };
-                    let assoc_link = AssocItemLink::GotoSource(
-                        i.def_id, &implementor.impl_.provided_trait_methods
-                    );
-                    render_impl(w, cx, &impl_, assoc_link,
-                                RenderMode::Normal, i.stable_since(), false)?;
-                }
+                let assoc_link = AssocItemLink::GotoSource(
+                    implementor.impl_item.def_id, &implementor.inner_impl().provided_trait_methods
+                );
+                render_impl(w, cx, &implementor, assoc_link,
+                            RenderMode::Normal, implementor.impl_item.stable_since(), false)?;
             }
         }
 
@@ -2570,18 +2546,16 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
 
         for implementor in local {
             write!(w, "<li>")?;
-            if let Some(item) = implementor2item(&cache, implementor) {
-                if let Some(l) = (Item { cx, item }).src_href() {
-                    write!(w, "<div class='out-of-band'>")?;
-                    write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
-                                l, "goto source code")?;
-                    write!(w, "</div>")?;
-                }
+            if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() {
+                write!(w, "<div class='out-of-band'>")?;
+                write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
+                            l, "goto source code")?;
+                write!(w, "</div>")?;
             }
             write!(w, "<code>")?;
             // If there's already another implementor that has the same abbridged name, use the
             // full path, for example in `std::iter::ExactSizeIterator`
-            let use_absolute = match implementor.impl_.for_ {
+            let use_absolute = match implementor.inner_impl().for_ {
                 clean::ResolvedPath { ref path, is_generic: false, .. } |
                 clean::BorrowedRef {
                     type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
@@ -2589,8 +2563,8 @@ fn trait_item(w: &mut fmt::Formatter, cx: &Context, m: &clean::Item, t: &clean::
                 } => implementor_dups[path.last_name()].1,
                 _ => false,
             };
-            fmt_impl_for_trait_page(&implementor.impl_, w, use_absolute)?;
-            for it in &implementor.impl_.items {
+            fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?;
+            for it in &implementor.inner_impl().items {
                 if let clean::TypedefItem(ref tydef, _) = it.inner {
                     write!(w, "<span class=\"where fmt-newline\">  ")?;
                     assoc_type(w, it, &vec![], Some(&tydef.type_), AssocItemLink::Anchor(None))?;
@@ -3880,20 +3854,16 @@ fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
 
     if let Some(implementors) = c.implementors.get(&it.def_id) {
         let res = implementors.iter()
-                              .filter(|i| i.impl_.for_.def_id()
-                                                      .map_or(false, |d| !c.paths.contains_key(&d)))
+                              .filter(|i| i.inner_impl().for_.def_id()
+                                           .map_or(false, |d| !c.paths.contains_key(&d)))
                               .filter_map(|i| {
-                                  if let Some(item) = implementor2item(&c, i) {
-                                      match extract_for_impl_name(&item) {
-                                          Some((ref name, ref url)) => {
-                                              Some(format!("<a href=\"#impl-{}\">{}</a>",
-                                                           small_url_encode(url),
-                                                           Escape(name)))
-                                          }
-                                          _ => None,
+                                  match extract_for_impl_name(&i.impl_item) {
+                                      Some((ref name, ref url)) => {
+                                          Some(format!("<a href=\"#impl-{}\">{}</a>",
+                                                      small_url_encode(url),
+                                                      Escape(name)))
                                       }
-                                  } else {
-                                      None
+                                      _ => None,
                                   }
                               })
                               .collect::<String>();
index 96bd9d7dc3cc539644947f187662535db5937c07..a5e343ade38637da0d5dc82176bc7bf169464a10 100644 (file)
@@ -22,3 +22,8 @@ impl SomeTrait for usize {}
 impl SomeTrait for SomeStruct {
     // deliberately multi-line impl
 }
+
+pub trait AnotherTrait {}
+
+// @has foo/trait.AnotherTrait.html '//a/@href' '../src/foo/issue-43893.rs.html#29'
+impl<T> AnotherTrait for T {}