rustdoc: Don't inline all impls all at once
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.
This commit is contained in:
parent
8aa268e731
commit
e9cb96a56a
|
@ -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 @@ pub fn build_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1499,6 +1499,13 @@ impl Type {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn def_id(&self) -> Option<DefId> {
|
||||
match *self {
|
||||
ResolvedPath { did, .. } => Some(did),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrimitiveType {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue