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)
|
}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_impls(cx: &DocContext, tcx: &TyCtxt,
|
pub fn build_impls(cx: &DocContext,
|
||||||
|
tcx: &TyCtxt,
|
||||||
did: DefId) -> Vec<clean::Item> {
|
did: DefId) -> Vec<clean::Item> {
|
||||||
tcx.populate_inherent_implementations_for_type_if_necessary(did);
|
tcx.populate_inherent_implementations_for_type_if_necessary(did);
|
||||||
let mut impls = Vec::new();
|
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
|
// Primarily, the impls will be used to populate the documentation for this
|
||||||
// type being inlined, but impls can also be used when generating
|
// type being inlined, but impls can also be used when generating
|
||||||
// documentation for primitives (no way to find those specifically).
|
// 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) {
|
for item in tcx.sess.cstore.crate_top_level_items(did.krate) {
|
||||||
populate_impls(cx, tcx, item.def, &mut impls);
|
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,
|
fn populate_impls(cx: &DocContext, tcx: &TyCtxt,
|
||||||
def: cstore::DefLike,
|
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;
|
return impls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1499,6 +1499,13 @@ impl Type {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn def_id(&self) -> Option<DefId> {
|
||||||
|
match *self {
|
||||||
|
ResolvedPath { did, .. } => Some(did),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrimitiveType {
|
impl PrimitiveType {
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub struct DocContext<'a, 'tcx: 'a> {
|
||||||
pub external_traits: RefCell<Option<HashMap<DefId, clean::Trait>>>,
|
pub external_traits: RefCell<Option<HashMap<DefId, clean::Trait>>>,
|
||||||
pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
|
pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
|
||||||
pub inlined: RefCell<Option<HashSet<DefId>>>,
|
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>>,
|
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_typarams: RefCell::new(Some(HashMap::new())),
|
||||||
external_paths: RefCell::new(Some(HashMap::new())),
|
external_paths: RefCell::new(Some(HashMap::new())),
|
||||||
inlined: RefCell::new(Some(HashSet::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),
|
deref_trait_did: Cell::new(None),
|
||||||
};
|
};
|
||||||
debug!("crate: {:?}", ctxt.map.krate());
|
debug!("crate: {:?}", ctxt.map.krate());
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#![allow(deprecated)]
|
#![allow(deprecated)]
|
||||||
|
|
||||||
use std::cell::{RefCell, Cell};
|
use std::cell::{RefCell, Cell};
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::HashMap;
|
||||||
use std::dynamic_lib::DynamicLibrary;
|
use std::dynamic_lib::DynamicLibrary;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
|
@ -114,7 +114,7 @@ pub fn run(input: &str,
|
||||||
external_traits: RefCell::new(None),
|
external_traits: RefCell::new(None),
|
||||||
external_typarams: RefCell::new(None),
|
external_typarams: RefCell::new(None),
|
||||||
inlined: 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),
|
deref_trait_did: Cell::new(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue