diff options
Diffstat (limited to 'src/librustdoc/html/render.rs')
| -rw-r--r-- | src/librustdoc/html/render.rs | 44 |
1 files changed, 37 insertions, 7 deletions
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1879abe659c..3e1720f8b8a 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -313,7 +313,7 @@ pub struct Cache { // 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>>, + pub access_levels: AccessLevels<DefId>, /// The version of the crate being documented, if given from the `--crate-version` flag. pub crate_version: Option<String>, @@ -337,6 +337,15 @@ pub struct Cache { // and their parent id here and indexes them at the end of crate parsing. orphan_impl_items: Vec<(DefId, clean::Item)>, + // Similarly to `orphan_impl_items`, sometimes trait impls are picked up + // even though the trait itself is not exported. This can happen if a trait + // was defined in function/expression scope, since the impl will be picked + // up by `collect-trait-impls` but the trait won't be scraped out in the HIR + // crawl. In order to prevent crashes when looking for spotlight traits or + // when gathering trait documentation on a type, hold impls here while + // folding and add them to the cache later on if we find the trait. + orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>, + /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. aliases: FxHashMap<String, Vec<IndexItem>>, @@ -350,6 +359,7 @@ pub struct RenderInfo { pub external_paths: ::core::ExternalPaths, pub external_typarams: FxHashMap<DefId, String>, pub exact_paths: FxHashMap<DefId, Vec<String>>, + pub access_levels: AccessLevels<DefId>, pub deref_trait_did: Option<DefId>, pub deref_mut_trait_did: Option<DefId>, pub owned_box_did: Option<DefId>, @@ -569,6 +579,7 @@ pub fn run(mut krate: clean::Crate, external_paths, external_typarams, exact_paths, + access_levels, deref_trait_did, deref_mut_trait_did, owned_box_did, @@ -591,10 +602,11 @@ pub fn run(mut krate: clean::Crate, extern_locations: FxHashMap(), primitive_locations: FxHashMap(), stripped_mod: false, - access_levels: krate.access_levels.clone(), + access_levels, crate_version: krate.version.take(), orphan_impl_items: Vec::new(), - traits: mem::replace(&mut krate.external_traits, FxHashMap()), + orphan_trait_impls: Vec::new(), + traits: krate.external_traits.lock().replace(FxHashMap()), deref_trait_did, deref_mut_trait_did, owned_box_did, @@ -636,6 +648,14 @@ pub fn run(mut krate: clean::Crate, cache.stack.push(krate.name.clone()); krate = cache.fold_crate(krate); + for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { + if cache.traits.contains_key(&trait_did) { + for did in dids { + cache.impls.entry(did).or_insert(vec![]).push(impl_.clone()); + } + } + } + // Build our search index let index = build_index(&krate, &mut cache); @@ -1223,6 +1243,10 @@ impl<'a> SourceCollector<'a> { impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> { + if item.def_id.is_local() { + debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); + } + // If this is a stripped module, // we don't want it or its children in the search index. let orig_stripped_mod = match item.inner { @@ -1453,10 +1477,16 @@ impl DocFolder for Cache { } else { unreachable!() }; - for did in dids { - self.impls.entry(did).or_default().push(Impl { - impl_item: item.clone(), - }); + let impl_item = Impl { + impl_item: item, + }; + if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { + for did in dids { + self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + } + } else { + let trait_did = impl_item.trait_did().unwrap(); + self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None } else { |
