Auto merge of #33002 - mitaa:rdoc-cross-impls, r=alexcrichton

rustdoc: refine cross-crate impl inlining

This changes the current rule that impls within `doc(hidden)` modules aren't inlined, to only inlining impls where the implemented trait and type are reachable in documentation.

fixes #14586
fixes #31948

.. and also applies the reachability checking to cross-crate links.

fixes #28480

r? @alexcrichton
This commit is contained in:
bors 2016-04-19 05:00:10 -07:00
commit 478a33dabc
18 changed files with 473 additions and 130 deletions

View file

@ -24,6 +24,7 @@ use syntax::abi::Abi;
use rustc::hir;
use clean;
use core::DocAccessLevels;
use html::item_type::ItemType;
use html::render;
use html::render::{cache, CURRENT_LOCATION_KEY};
@ -298,6 +299,9 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
let mut url = if did.is_local() || cache.inlined.contains(&did) {
repeat("../").take(loc.len()).collect::<String>()
} else {
if !cache.access_levels.is_doc_reachable(did) {
return None
}
match cache.extern_locations[&did.krate] {
(_, render::Remote(ref s)) => s.to_string(),
(_, render::Local) => repeat("../").take(loc.len()).collect(),

View file

@ -247,6 +247,11 @@ pub struct Cache {
/// Set of definitions which have been inlined from external crates.
pub inlined: HashSet<DefId>,
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
// the access levels from crateanalysis.
pub access_levels: Arc<AccessLevels<DefId>>,
// Private fields only used when initially crawling a crate to build a cache
stack: Vec<String>,
@ -254,7 +259,6 @@ pub struct Cache {
parent_is_trait_impl: bool,
search_index: Vec<IndexItem>,
stripped_mod: bool,
access_levels: AccessLevels<DefId>,
deref_trait_did: Option<DefId>,
// In rare case where a structure is defined in one module but implemented
@ -265,6 +269,16 @@ pub struct Cache {
orphan_methods: Vec<(DefId, clean::Item)>,
}
/// Temporary storage for data obtained during `RustdocVisitor::clean()`.
/// Later on moved into `CACHE_KEY`.
#[derive(Default)]
pub struct RenderInfo {
pub inlined: HashSet<DefId>,
pub external_paths: ::core::ExternalPaths,
pub external_typarams: HashMap<DefId, String>,
pub deref_trait_did: Option<DefId>,
}
/// Helper struct to render all source code to HTML pages
struct SourceCollector<'a> {
scx: &'a mut SharedContext,
@ -416,7 +430,8 @@ pub fn run(mut krate: clean::Crate,
external_html: &ExternalHtml,
dst: PathBuf,
passes: HashSet<String>,
css_file_extension: Option<PathBuf>) -> Result<(), Error> {
css_file_extension: Option<PathBuf>,
renderinfo: RenderInfo) -> Result<(), Error> {
let src_root = match krate.src.parent() {
Some(p) => p.to_path_buf(),
None => PathBuf::new(),
@ -483,19 +498,20 @@ pub fn run(mut krate: clean::Crate,
};
// Crawl the crate to build various caches used for the output
let analysis = ::ANALYSISKEY.with(|a| a.clone());
let analysis = analysis.borrow();
let access_levels = analysis.as_ref().map(|a| a.access_levels.clone());
let access_levels = access_levels.unwrap_or(Default::default());
let paths: HashMap<DefId, (Vec<String>, ItemType)> =
analysis.as_ref().map(|a| {
let paths = a.external_paths.borrow_mut().take().unwrap();
paths.into_iter().map(|(k, (v, t))| (k, (v, ItemType::from_type_kind(t)))).collect()
}).unwrap_or(HashMap::new());
let RenderInfo {
inlined,
external_paths,
external_typarams,
deref_trait_did,
} = renderinfo;
let paths = external_paths.into_iter()
.map(|(k, (v, t))| (k, (v, ItemType::from_type_kind(t))))
.collect::<HashMap<_, _>>();
let mut cache = Cache {
impls: HashMap::new(),
external_paths: paths.iter().map(|(&k, v)| (k, v.0.clone()))
.collect(),
external_paths: paths.iter().map(|(&k, v)| (k, v.0.clone())).collect(),
paths: paths,
implementors: HashMap::new(),
stack: Vec::new(),
@ -505,16 +521,12 @@ pub fn run(mut krate: clean::Crate,
extern_locations: HashMap::new(),
primitive_locations: HashMap::new(),
stripped_mod: false,
access_levels: access_levels,
access_levels: krate.access_levels.clone(),
orphan_methods: Vec::new(),
traits: mem::replace(&mut krate.external_traits, HashMap::new()),
deref_trait_did: analysis.as_ref().and_then(|a| a.deref_trait_did),
typarams: analysis.as_ref().map(|a| {
a.external_typarams.borrow_mut().take().unwrap()
}).unwrap_or(HashMap::new()),
inlined: analysis.as_ref().map(|a| {
a.inlined.borrow_mut().take().unwrap()
}).unwrap_or(HashSet::new()),
deref_trait_did: deref_trait_did,
typarams: external_typarams,
inlined: inlined,
};
// Cache where all our extern crates are located