]> git.lizzy.rs Git - rust.git/commitdiff
rustdoc: Don't inline all impls all at once
authorAlex Crichton <alex@alexcrichton.com>
Tue, 8 Mar 2016 19:20:16 +0000 (11:20 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 8 Mar 2016 21:44:14 +0000 (13:44 -0800)
Right now whenever rustdoc inlines a struct or enum from another crate it ends
up inlining *all* `impl` items found in the other crate at the same time. The
rationale for this was to discover all trait impls which are otherwise not
probed for. This unfortunately picks up a lot of impls of public traits for
private types, causing lots of broken links.

This commit instead hoards all of those inlined impls into a temporary storage
location which is then selectively drawn from whenever we inline a new type.
This should ensure that we still inline all relevant impls while avoiding all
private ones.

src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/test.rs

index 32f3706675ad24b3b5f42b6f62443b241f440205..1a281a3a8bb85629f25acdd5bab5a27a1d3c473d 100644 (file)
@@ -222,7 +222,8 @@ fn build_type(cx: &DocContext, tcx: &TyCtxt, did: DefId) -> clean::ItemEnum {
     }, false)
 }
 
-pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
+pub fn build_impls(cx: &DocContext,
+                   tcx: &TyCtxt,
                    did: DefId) -> Vec<clean::Item> {
     tcx.populate_inherent_implementations_for_type_if_necessary(did);
     let mut impls = Vec::new();
@@ -241,10 +242,12 @@ pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
     // Primarily, the impls will be used to populate the documentation for this
     // type being inlined, but impls can also be used when generating
     // documentation for primitives (no way to find those specifically).
-    if cx.populated_crate_impls.borrow_mut().insert(did.krate) {
+    if !cx.all_crate_impls.borrow_mut().contains_key(&did.krate) {
+        let mut impls = Vec::new();
         for item in tcx.sess.cstore.crate_top_level_items(did.krate) {
             populate_impls(cx, tcx, item.def, &mut impls);
         }
+        cx.all_crate_impls.borrow_mut().insert(did.krate, impls);
 
         fn populate_impls(cx: &DocContext, tcx: &TyCtxt,
                           def: cstore::DefLike,
@@ -266,6 +269,20 @@ fn populate_impls(cx: &DocContext, tcx: &TyCtxt,
         }
     }
 
+    let mut candidates = cx.all_crate_impls.borrow_mut();
+    let candidates = candidates.get_mut(&did.krate).unwrap();
+    for i in (0..candidates.len()).rev() {
+        let remove = match candidates[i].inner {
+            clean::ImplItem(ref i) => {
+                i.for_.def_id() == Some(did) || i.for_.primitive_type().is_some()
+            }
+            _ => continue,
+        };
+        if remove {
+            impls.push(candidates.swap_remove(i));
+        }
+    }
+
     return impls;
 }
 
index 6c9ee5287820175f60113776e36b78750393c4ef..231829a8ed3535dc05907ec797d07c35b341e615 100644 (file)
@@ -1499,6 +1499,13 @@ pub fn primitive_type(&self) -> Option<PrimitiveType> {
             _ => None,
         }
     }
+
+    fn def_id(&self) -> Option<DefId> {
+        match *self {
+            ResolvedPath { did, .. } => Some(did),
+            _ => None,
+        }
+    }
 }
 
 impl PrimitiveType {
index 345b84e0cac81596f2a421f7b2cdfb76a0540f90..c889a5f87b067d8f6a904db1500d819c53809f49 100644 (file)
@@ -56,7 +56,7 @@ pub struct DocContext<'a, 'tcx: 'a> {
     pub external_traits: RefCell<Option<HashMap<DefId, clean::Trait>>>,
     pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
     pub inlined: RefCell<Option<HashSet<DefId>>>,
-    pub populated_crate_impls: RefCell<HashSet<ast::CrateNum>>,
+    pub all_crate_impls: RefCell<HashMap<ast::CrateNum, Vec<clean::Item>>>,
     pub deref_trait_did: Cell<Option<DefId>>,
 }
 
@@ -179,7 +179,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
             external_typarams: RefCell::new(Some(HashMap::new())),
             external_paths: RefCell::new(Some(HashMap::new())),
             inlined: RefCell::new(Some(HashSet::new())),
-            populated_crate_impls: RefCell::new(HashSet::new()),
+            all_crate_impls: RefCell::new(HashMap::new()),
             deref_trait_did: Cell::new(None),
         };
         debug!("crate: {:?}", ctxt.map.krate());
index e97357f98898b47f90d52b6f4526a08cb8b903d4..8cb3653008a6a51bb710d3b47219efee572d32ee 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(deprecated)]
 
 use std::cell::{RefCell, Cell};
-use std::collections::{HashSet, HashMap};
+use std::collections::HashMap;
 use std::dynamic_lib::DynamicLibrary;
 use std::env;
 use std::ffi::OsString;
@@ -114,7 +114,7 @@ pub fn run(input: &str,
         external_traits: RefCell::new(None),
         external_typarams: RefCell::new(None),
         inlined: RefCell::new(None),
-        populated_crate_impls: RefCell::new(HashSet::new()),
+        all_crate_impls: RefCell::new(HashMap::new()),
         deref_trait_did: Cell::new(None),
     };