1
Fork 0

Auto merge of #80987 - GuillaumeGomez:remove-cache-key, r=jyn514

Remove CACHE_KEY global

We realized in https://github.com/rust-lang/rust/pull/80914 that the cache handling (through a global) needed to be updated to make it much easier to handle.

r? `@jyn514`
This commit is contained in:
bors 2021-01-27 10:19:51 +00:00
commit 613ef740f3
14 changed files with 792 additions and 623 deletions

View file

@ -2329,14 +2329,14 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
if matchers.len() <= 1 { if matchers.len() <= 1 {
format!( format!(
"{}macro {}{} {{\n ...\n}}", "{}macro {}{} {{\n ...\n}}",
vis.print_with_space(cx.tcx, def_id), vis.print_with_space(cx.tcx, def_id, &cx.cache),
name, name,
matchers.iter().map(|span| span.to_src(cx)).collect::<String>(), matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
) )
} else { } else {
format!( format!(
"{}macro {} {{\n{}}}", "{}macro {} {{\n{}}}",
vis.print_with_space(cx.tcx, def_id), vis.print_with_space(cx.tcx, def_id, &cx.cache),
name, name,
matchers matchers
.iter() .iter()

View file

@ -37,7 +37,7 @@ use crate::clean::inline;
use crate::clean::types::Type::{QPath, ResolvedPath}; use crate::clean::types::Type::{QPath, ResolvedPath};
use crate::clean::Clean; use crate::clean::Clean;
use crate::core::DocContext; use crate::core::DocContext;
use crate::formats::cache::cache; use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType; use crate::formats::item_type::ItemType;
use crate::html::render::cache::ExternalLocation; use crate::html::render::cache::ExternalLocation;
@ -169,8 +169,8 @@ impl Item {
self.attrs.collapsed_doc_value() self.attrs.collapsed_doc_value()
} }
crate fn links(&self) -> Vec<RenderedLink> { crate fn links(&self, cache: &Cache) -> Vec<RenderedLink> {
self.attrs.links(&self.def_id.krate) self.attrs.links(&self.def_id.krate, cache)
} }
crate fn is_crate(&self) -> bool { crate fn is_crate(&self) -> bool {
@ -826,7 +826,7 @@ impl Attributes {
/// Gets links as a vector /// Gets links as a vector
/// ///
/// Cache must be populated before call /// Cache must be populated before call
crate fn links(&self, krate: &CrateNum) -> Vec<RenderedLink> { crate fn links(&self, krate: &CrateNum, cache: &Cache) -> Vec<RenderedLink> {
use crate::html::format::href; use crate::html::format::href;
use crate::html::render::CURRENT_DEPTH; use crate::html::render::CURRENT_DEPTH;
@ -835,7 +835,7 @@ impl Attributes {
.filter_map(|ItemLink { link: s, link_text, did, fragment }| { .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
match *did { match *did {
Some(did) => { Some(did) => {
if let Some((mut href, ..)) = href(did) { if let Some((mut href, ..)) = href(did, cache) {
if let Some(ref fragment) = *fragment { if let Some(ref fragment) = *fragment {
href.push('#'); href.push('#');
href.push_str(fragment); href.push_str(fragment);
@ -851,7 +851,6 @@ impl Attributes {
} }
None => { None => {
if let Some(ref fragment) = *fragment { if let Some(ref fragment) = *fragment {
let cache = cache();
let url = match cache.extern_locations.get(krate) { let url = match cache.extern_locations.get(krate) {
Some(&(_, _, ExternalLocation::Local)) => { Some(&(_, _, ExternalLocation::Local)) => {
let depth = CURRENT_DEPTH.with(|l| l.get()); let depth = CURRENT_DEPTH.with(|l| l.get());
@ -1177,6 +1176,13 @@ impl GetDefId for FnRetTy {
DefaultReturn => None, DefaultReturn => None,
} }
} }
fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
match *self {
Return(ref ty) => ty.def_id_full(cache),
DefaultReturn => None,
}
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -1299,13 +1305,31 @@ crate enum TypeKind {
} }
crate trait GetDefId { crate trait GetDefId {
/// Use this method to get the [`DefId`] of a [`clean`] AST node.
/// This will return [`None`] when called on a primitive [`clean::Type`].
/// Use [`Self::def_id_full`] if you want to include primitives.
///
/// [`clean`]: crate::clean
/// [`clean::Type`]: crate::clean::Type
// FIXME: get rid of this function and always use `def_id_full`
fn def_id(&self) -> Option<DefId>; fn def_id(&self) -> Option<DefId>;
/// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s.
///
/// See [`Self::def_id`] for more.
///
/// [clean]: crate::clean
fn def_id_full(&self, cache: &Cache) -> Option<DefId>;
} }
impl<T: GetDefId> GetDefId for Option<T> { impl<T: GetDefId> GetDefId for Option<T> {
fn def_id(&self) -> Option<DefId> { fn def_id(&self) -> Option<DefId> {
self.as_ref().and_then(|d| d.def_id()) self.as_ref().and_then(|d| d.def_id())
} }
fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
self.as_ref().and_then(|d| d.def_id_full(cache))
}
} }
impl Type { impl Type {
@ -1393,30 +1417,40 @@ impl Type {
} }
} }
impl GetDefId for Type { impl Type {
fn def_id(&self) -> Option<DefId> { fn inner_def_id(&self, cache: Option<&Cache>) -> Option<DefId> {
match *self { let t: PrimitiveType = match *self {
ResolvedPath { did, .. } => Some(did), ResolvedPath { did, .. } => return Some(did),
Primitive(p) => cache().primitive_locations.get(&p).cloned(), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()),
BorrowedRef { type_: box Generic(..), .. } => { BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference,
Primitive(PrimitiveType::Reference).def_id() BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache),
}
BorrowedRef { ref type_, .. } => type_.def_id(),
Tuple(ref tys) => { Tuple(ref tys) => {
if tys.is_empty() { if tys.is_empty() {
Primitive(PrimitiveType::Unit).def_id() PrimitiveType::Unit
} else { } else {
Primitive(PrimitiveType::Tuple).def_id() PrimitiveType::Tuple
} }
} }
BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(), BareFunction(..) => PrimitiveType::Fn,
Never => Primitive(PrimitiveType::Never).def_id(), Never => PrimitiveType::Never,
Slice(..) => Primitive(PrimitiveType::Slice).def_id(), Slice(..) => PrimitiveType::Slice,
Array(..) => Primitive(PrimitiveType::Array).def_id(), Array(..) => PrimitiveType::Array,
RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(), RawPointer(..) => PrimitiveType::RawPointer,
QPath { ref self_type, .. } => self_type.def_id(), QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
_ => None, // FIXME: remove this wildcard
} _ => return None,
};
cache.and_then(|c| Primitive(t).def_id_full(c))
}
}
impl GetDefId for Type {
fn def_id(&self) -> Option<DefId> {
self.inner_def_id(None)
}
fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
self.inner_def_id(Some(cache))
} }
} }
@ -1817,6 +1851,10 @@ impl GetDefId for Typedef {
fn def_id(&self) -> Option<DefId> { fn def_id(&self) -> Option<DefId> {
self.type_.def_id() self.type_.def_id()
} }
fn def_id_full(&self, cache: &Cache) -> Option<DefId> {
self.type_.def_id_full(cache)
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

View file

@ -177,7 +177,7 @@ crate fn get_real_types(
return res; return res;
} }
if arg.is_full_generic() { if arg.is_full_generic() {
let arg_s = Symbol::intern(&arg.print().to_string()); let arg_s = Symbol::intern(&arg.print(&cx.cache).to_string());
if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g {
WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(), WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(),
_ => false, _ => false,
@ -473,7 +473,7 @@ crate fn resolve_type(cx: &DocContext<'_>, path: Path, id: hir::HirId) -> Type {
return Generic(kw::SelfUpper); return Generic(kw::SelfUpper);
} }
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => { Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
return Generic(Symbol::intern(&format!("{:#}", path.print()))); return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
} }
Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true, Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
_ => false, _ => false,

View file

@ -261,7 +261,7 @@ crate struct RenderOptions {
} }
/// Temporary storage for data obtained during `RustdocVisitor::clean()`. /// Temporary storage for data obtained during `RustdocVisitor::clean()`.
/// Later on moved into `CACHE_KEY`. /// Later on moved into `cache`.
#[derive(Default, Clone)] #[derive(Default, Clone)]
crate struct RenderInfo { crate struct RenderInfo {
crate inlined: FxHashSet<DefId>, crate inlined: FxHashSet<DefId>,

View file

@ -32,6 +32,7 @@ use crate::clean;
use crate::clean::{AttributesExt, MAX_DEF_ID}; use crate::clean::{AttributesExt, MAX_DEF_ID};
use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::config::{Options as RustdocOptions, RenderOptions};
use crate::config::{OutputFormat, RenderInfo}; use crate::config::{OutputFormat, RenderInfo};
use crate::formats::cache::Cache;
use crate::passes::{self, Condition::*, ConditionalPass}; use crate::passes::{self, Condition::*, ConditionalPass};
crate use rustc_session::config::{DebuggingOptions, Input, Options}; crate use rustc_session::config::{DebuggingOptions, Input, Options};
@ -45,9 +46,9 @@ crate struct DocContext<'tcx> {
/// ///
/// Most of this logic is copied from rustc_lint::late. /// Most of this logic is copied from rustc_lint::late.
crate param_env: Cell<ParamEnv<'tcx>>, crate param_env: Cell<ParamEnv<'tcx>>,
/// Later on moved into `CACHE_KEY` /// Later on moved into `cache`
crate renderinfo: RefCell<RenderInfo>, crate renderinfo: RefCell<RenderInfo>,
/// Later on moved through `clean::Crate` into `CACHE_KEY` /// Later on moved through `clean::Crate` into `cache`
crate external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>, crate external_traits: Rc<RefCell<FxHashMap<DefId, clean::Trait>>>,
/// Used while populating `external_traits` to ensure we don't process the same trait twice at /// Used while populating `external_traits` to ensure we don't process the same trait twice at
/// the same time. /// the same time.
@ -75,6 +76,8 @@ crate struct DocContext<'tcx> {
/// See `collect_intra_doc_links::traits_implemented_by` for more details. /// See `collect_intra_doc_links::traits_implemented_by` for more details.
/// `map<module, set<trait>>` /// `map<module, set<trait>>`
crate module_trait_cache: RefCell<FxHashMap<DefId, FxHashSet<DefId>>>, crate module_trait_cache: RefCell<FxHashMap<DefId, FxHashSet<DefId>>>,
/// Fake empty cache used when cache is required as parameter.
crate cache: Cache,
} }
impl<'tcx> DocContext<'tcx> { impl<'tcx> DocContext<'tcx> {
@ -524,6 +527,7 @@ crate fn run_global_ctxt(
.collect(), .collect(),
render_options, render_options,
module_trait_cache: RefCell::new(FxHashMap::default()), module_trait_cache: RefCell::new(FxHashMap::default()),
cache: Cache::default(),
}; };
debug!("crate: {:?}", tcx.hir().krate()); debug!("crate: {:?}", tcx.hir().krate());

View file

@ -1,8 +1,6 @@
use std::cell::RefCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::mem; use std::mem;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Arc;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
@ -19,8 +17,6 @@ use crate::html::markdown::short_markdown_summary;
use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation}; use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation};
use crate::html::render::IndexItem; use crate::html::render::IndexItem;
thread_local!(crate static CACHE_KEY: RefCell<Arc<Cache>> = Default::default());
/// This cache is used to store information about the [`clean::Crate`] being /// This cache is used to store information about the [`clean::Crate`] being
/// rendered in order to provide more useful documentation. This contains /// rendered in order to provide more useful documentation. This contains
/// information like all implementors of a trait, all traits a type implements, /// information like all implementors of a trait, all traits a type implements,
@ -197,6 +193,7 @@ impl Cache {
} }
cache.stack.push(krate.name.to_string()); cache.stack.push(krate.name.to_string());
krate = cache.fold_crate(krate); krate = cache.fold_crate(krate);
for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) {
@ -319,7 +316,7 @@ impl DocFolder for Cache {
.map_or_else(String::new, |x| short_markdown_summary(&x.as_str())), .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())),
parent, parent,
parent_idx: None, parent_idx: None,
search_type: get_index_search_type(&item), search_type: get_index_search_type(&item, None),
}); });
for alias in item.attrs.get_doc_aliases() { for alias in item.attrs.get_doc_aliases() {
@ -477,7 +474,3 @@ impl DocFolder for Cache {
ret ret
} }
} }
crate fn cache() -> Arc<Cache> {
CACHE_KEY.with(|c| c.borrow().clone())
}

View file

@ -8,6 +8,7 @@ use rustc_span::def_id::DefId;
use crate::clean; use crate::clean;
use crate::clean::types::GetDefId; use crate::clean::types::GetDefId;
use crate::formats::cache::Cache;
/// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// Specifies whether rendering directly implemented trait items or ones from a certain Deref
/// impl. /// impl.
@ -41,4 +42,8 @@ impl Impl {
crate fn trait_did(&self) -> Option<DefId> { crate fn trait_did(&self) -> Option<DefId> {
self.inner_impl().trait_.def_id() self.inner_impl().trait_.def_id()
} }
crate fn trait_did_full(&self, cache: &Cache) -> Option<DefId> {
self.inner_impl().trait_.def_id_full(cache)
}
} }

View file

@ -1,12 +1,10 @@
use std::sync::Arc;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use crate::clean; use crate::clean;
use crate::config::{RenderInfo, RenderOptions}; use crate::config::{RenderInfo, RenderOptions};
use crate::error::Error; use crate::error::Error;
use crate::formats::cache::{Cache, CACHE_KEY}; use crate::formats::cache::Cache;
/// Allows for different backends to rustdoc to be used with the `run_format()` function. Each /// Allows for different backends to rustdoc to be used with the `run_format()` function. Each
/// backend renderer has hooks for initialization, documenting an item, entering and exiting a /// backend renderer has hooks for initialization, documenting an item, entering and exiting a
@ -22,20 +20,15 @@ crate trait FormatRenderer<'tcx>: Clone {
options: RenderOptions, options: RenderOptions,
render_info: RenderInfo, render_info: RenderInfo,
edition: Edition, edition: Edition,
cache: &mut Cache, cache: Cache,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
) -> Result<(Self, clean::Crate), Error>; ) -> Result<(Self, clean::Crate), Error>;
/// Renders a single non-module item. This means no recursive sub-item rendering is required. /// Renders a single non-module item. This means no recursive sub-item rendering is required.
fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error>; fn item(&mut self, item: clean::Item) -> Result<(), Error>;
/// Renders a module (should not handle recursing into children). /// Renders a module (should not handle recursing into children).
fn mod_item_in( fn mod_item_in(&mut self, item: &clean::Item, item_name: &str) -> Result<(), Error>;
&mut self,
item: &clean::Item,
item_name: &str,
cache: &Cache,
) -> Result<(), Error>;
/// Runs after recursively rendering all sub-items of a module. /// Runs after recursively rendering all sub-items of a module.
fn mod_item_out(&mut self, item_name: &str) -> Result<(), Error>; fn mod_item_out(&mut self, item_name: &str) -> Result<(), Error>;
@ -46,9 +39,10 @@ crate trait FormatRenderer<'tcx>: Clone {
fn after_krate( fn after_krate(
&mut self, &mut self,
krate: &clean::Crate, krate: &clean::Crate,
cache: &Cache,
diag: &rustc_errors::Handler, diag: &rustc_errors::Handler,
) -> Result<(), Error>; ) -> Result<(), Error>;
fn cache(&self) -> &Cache;
} }
/// Main method for rendering a crate. /// Main method for rendering a crate.
@ -60,7 +54,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
edition: Edition, edition: Edition,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let (krate, mut cache) = tcx.sess.time("create_format_cache", || { let (krate, cache) = tcx.sess.time("create_format_cache", || {
Cache::from_krate( Cache::from_krate(
render_info.clone(), render_info.clone(),
options.document_private, options.document_private,
@ -73,12 +67,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
let (mut format_renderer, mut krate) = prof let (mut format_renderer, mut krate) = prof
.extra_verbose_generic_activity("create_renderer", T::descr()) .extra_verbose_generic_activity("create_renderer", T::descr())
.run(|| T::init(krate, options, render_info, edition, &mut cache, tcx))?; .run(|| T::init(krate, options, render_info, edition, cache, tcx))?;
let cache = Arc::new(cache);
// Freeze the cache now that the index has been built. Put an Arc into TLS for future
// parallelization opportunities
CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone());
let mut item = match krate.module.take() { let mut item = match krate.module.take() {
Some(i) => i, Some(i) => i,
@ -101,7 +90,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
} }
let _timer = prof.generic_activity_with_arg("render_mod_item", name.as_str()); let _timer = prof.generic_activity_with_arg("render_mod_item", name.as_str());
cx.mod_item_in(&item, &name, &cache)?; cx.mod_item_in(&item, &name)?;
let module = match *item.kind { let module = match *item.kind {
clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m, clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m,
_ => unreachable!(), _ => unreachable!(),
@ -114,9 +103,9 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
cx.mod_item_out(&name)?; cx.mod_item_out(&name)?;
} else if item.name.is_some() { } else if item.name.is_some() {
prof.generic_activity_with_arg("render_item", &*item.name.unwrap_or(unknown).as_str()) prof.generic_activity_with_arg("render_item", &*item.name.unwrap_or(unknown).as_str())
.run(|| cx.item(item, &cache))?; .run(|| cx.item(item))?;
} }
} }
prof.extra_verbose_generic_activity("renderer_after_krate", T::descr()) prof.extra_verbose_generic_activity("renderer_after_krate", T::descr())
.run(|| format_renderer.after_krate(&krate, &cache, diag)) .run(|| format_renderer.after_krate(&krate, diag))
} }

File diff suppressed because it is too large Load diff

View file

@ -67,31 +67,31 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
let mut crate_items = Vec::with_capacity(cache.search_index.len()); let mut crate_items = Vec::with_capacity(cache.search_index.len());
let mut crate_paths = vec![]; let mut crate_paths = vec![];
let Cache { ref mut search_index, ref orphan_impl_items, ref paths, ref mut aliases, .. } =
*cache;
// Attach all orphan items to the type's definition if the type // Attach all orphan items to the type's definition if the type
// has since been learned. // has since been learned.
for &(did, ref item) in orphan_impl_items { for &(did, ref item) in &cache.orphan_impl_items {
if let Some(&(ref fqp, _)) = paths.get(&did) { if let Some(&(ref fqp, _)) = cache.paths.get(&did) {
search_index.push(IndexItem { cache.search_index.push(IndexItem {
ty: item.type_(), ty: item.type_(),
name: item.name.unwrap().to_string(), name: item.name.unwrap().to_string(),
path: fqp[..fqp.len() - 1].join("::"), path: fqp[..fqp.len() - 1].join("::"),
desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)), desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)),
parent: Some(did), parent: Some(did),
parent_idx: None, parent_idx: None,
search_type: get_index_search_type(&item), search_type: get_index_search_type(&item, None),
}); });
for alias in item.attrs.get_doc_aliases() { for alias in item.attrs.get_doc_aliases() {
aliases cache
.aliases
.entry(alias.to_lowercase()) .entry(alias.to_lowercase())
.or_insert(Vec::new()) .or_insert(Vec::new())
.push(search_index.len() - 1); .push(cache.search_index.len() - 1);
} }
} }
} }
let Cache { ref mut search_index, ref paths, ref mut aliases, .. } = *cache;
// Reduce `DefId` in paths into smaller sequential numbers, // Reduce `DefId` in paths into smaller sequential numbers,
// and prune the paths that do not appear in the index. // and prune the paths that do not appear in the index.
let mut lastpath = String::new(); let mut lastpath = String::new();
@ -164,7 +164,10 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
) )
} }
crate fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionType> { crate fn get_index_search_type(
item: &clean::Item,
cache: Option<&Cache>,
) -> Option<IndexItemFunctionType> {
let (all_types, ret_types) = match *item.kind { let (all_types, ret_types) = match *item.kind {
clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types), clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types),
clean::MethodItem(ref m, _) => (&m.all_types, &m.ret_types), clean::MethodItem(ref m, _) => (&m.all_types, &m.ret_types),
@ -174,12 +177,12 @@ crate fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionTy
let inputs = all_types let inputs = all_types
.iter() .iter()
.map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty, &cache), *kind)))
.filter(|a| a.ty.name.is_some()) .filter(|a| a.ty.name.is_some())
.collect(); .collect();
let output = ret_types let output = ret_types
.iter() .iter()
.map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty, &cache), *kind)))
.filter(|a| a.ty.name.is_some()) .filter(|a| a.ty.name.is_some())
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let output = if output.is_empty() { None } else { Some(output) }; let output = if output.is_empty() { None } else { Some(output) };
@ -187,12 +190,12 @@ crate fn get_index_search_type(item: &clean::Item) -> Option<IndexItemFunctionTy
Some(IndexItemFunctionType { inputs, output }) Some(IndexItemFunctionType { inputs, output })
} }
fn get_index_type(clean_type: &clean::Type) -> RenderType { fn get_index_type(clean_type: &clean::Type, cache: &Option<&Cache>) -> RenderType {
RenderType { RenderType {
ty: clean_type.def_id(), ty: cache.map_or_else(|| clean_type.def_id(), |cache| clean_type.def_id_full(cache)),
idx: None, idx: None,
name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()),
generics: get_generics(clean_type), generics: get_generics(clean_type, cache),
} }
} }
@ -216,14 +219,14 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
} }
} }
fn get_generics(clean_type: &clean::Type) -> Option<Vec<Generic>> { fn get_generics(clean_type: &clean::Type, cache: &Option<&Cache>) -> Option<Vec<Generic>> {
clean_type.generics().and_then(|types| { clean_type.generics().and_then(|types| {
let r = types let r = types
.iter() .iter()
.filter_map(|t| { .filter_map(|t| {
get_index_type_name(t, false).map(|name| Generic { get_index_type_name(t, false).map(|name| Generic {
name: name.as_str().to_ascii_lowercase(), name: name.as_str().to_ascii_lowercase(),
defid: t.def_id(), defid: cache.map_or_else(|| t.def_id(), |cache| t.def_id_full(cache)),
idx: None, idx: None,
}) })
}) })

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,7 @@ crate struct JsonRenderer<'tcx> {
index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>, index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
/// The directory where the blob will be written to. /// The directory where the blob will be written to.
out_path: PathBuf, out_path: PathBuf,
cache: Rc<Cache>,
} }
impl JsonRenderer<'_> { impl JsonRenderer<'_> {
@ -39,12 +40,8 @@ impl JsonRenderer<'_> {
self.tcx.sess self.tcx.sess
} }
fn get_trait_implementors( fn get_trait_implementors(&mut self, id: rustc_span::def_id::DefId) -> Vec<types::Id> {
&mut self, Rc::clone(&self.cache)
id: rustc_span::def_id::DefId,
cache: &Cache,
) -> Vec<types::Id> {
cache
.implementors .implementors
.get(&id) .get(&id)
.map(|implementors| { .map(|implementors| {
@ -52,7 +49,7 @@ impl JsonRenderer<'_> {
.iter() .iter()
.map(|i| { .map(|i| {
let item = &i.impl_item; let item = &i.impl_item;
self.item(item.clone(), cache).unwrap(); self.item(item.clone()).unwrap();
item.def_id.into() item.def_id.into()
}) })
.collect() .collect()
@ -60,8 +57,8 @@ impl JsonRenderer<'_> {
.unwrap_or_default() .unwrap_or_default()
} }
fn get_impls(&mut self, id: rustc_span::def_id::DefId, cache: &Cache) -> Vec<types::Id> { fn get_impls(&mut self, id: rustc_span::def_id::DefId) -> Vec<types::Id> {
cache Rc::clone(&self.cache)
.impls .impls
.get(&id) .get(&id)
.map(|impls| { .map(|impls| {
@ -70,7 +67,7 @@ impl JsonRenderer<'_> {
.filter_map(|i| { .filter_map(|i| {
let item = &i.impl_item; let item = &i.impl_item;
if item.def_id.is_local() { if item.def_id.is_local() {
self.item(item.clone(), cache).unwrap(); self.item(item.clone()).unwrap();
Some(item.def_id.into()) Some(item.def_id.into())
} else { } else {
None None
@ -81,24 +78,25 @@ impl JsonRenderer<'_> {
.unwrap_or_default() .unwrap_or_default()
} }
fn get_trait_items(&mut self, cache: &Cache) -> Vec<(types::Id, types::Item)> { fn get_trait_items(&mut self) -> Vec<(types::Id, types::Item)> {
cache Rc::clone(&self.cache)
.traits .traits
.iter() .iter()
.filter_map(|(&id, trait_item)| { .filter_map(|(&id, trait_item)| {
// only need to synthesize items for external traits // only need to synthesize items for external traits
if !id.is_local() { if !id.is_local() {
trait_item.items.clone().into_iter().for_each(|i| self.item(i, cache).unwrap()); trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
Some(( Some((
id.into(), id.into(),
types::Item { types::Item {
id: id.into(), id: id.into(),
crate_id: id.krate.as_u32(), crate_id: id.krate.as_u32(),
name: cache name: self
.cache
.paths .paths
.get(&id) .get(&id)
.unwrap_or_else(|| { .unwrap_or_else(|| {
cache self.cache
.external_paths .external_paths
.get(&id) .get(&id)
.expect("Trait should either be in local or external paths") .expect("Trait should either be in local or external paths")
@ -134,7 +132,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
options: RenderOptions, options: RenderOptions,
_render_info: RenderInfo, _render_info: RenderInfo,
_edition: Edition, _edition: Edition,
_cache: &mut Cache, cache: Cache,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
) -> Result<(Self, clean::Crate), Error> { ) -> Result<(Self, clean::Crate), Error> {
debug!("Initializing json renderer"); debug!("Initializing json renderer");
@ -143,6 +141,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
tcx, tcx,
index: Rc::new(RefCell::new(FxHashMap::default())), index: Rc::new(RefCell::new(FxHashMap::default())),
out_path: options.output, out_path: options.output,
cache: Rc::new(cache),
}, },
krate, krate,
)) ))
@ -151,18 +150,18 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
/// Inserts an item into the index. This should be used rather than directly calling insert on /// Inserts an item into the index. This should be used rather than directly calling insert on
/// the hashmap because certain items (traits and types) need to have their mappings for trait /// the hashmap because certain items (traits and types) need to have their mappings for trait
/// implementations filled out before they're inserted. /// implementations filled out before they're inserted.
fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> { fn item(&mut self, item: clean::Item) -> Result<(), Error> {
// Flatten items that recursively store other items // Flatten items that recursively store other items
item.kind.inner_items().for_each(|i| self.item(i.clone(), cache).unwrap()); item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());
let id = item.def_id; let id = item.def_id;
if let Some(mut new_item) = self.convert_item(item) { if let Some(mut new_item) = self.convert_item(item) {
if let types::ItemEnum::TraitItem(ref mut t) = new_item.inner { if let types::ItemEnum::TraitItem(ref mut t) = new_item.inner {
t.implementors = self.get_trait_implementors(id, cache) t.implementors = self.get_trait_implementors(id)
} else if let types::ItemEnum::StructItem(ref mut s) = new_item.inner { } else if let types::ItemEnum::StructItem(ref mut s) = new_item.inner {
s.impls = self.get_impls(id, cache) s.impls = self.get_impls(id)
} else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner { } else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner {
e.impls = self.get_impls(id, cache) e.impls = self.get_impls(id)
} }
let removed = self.index.borrow_mut().insert(id.into(), new_item.clone()); let removed = self.index.borrow_mut().insert(id.into(), new_item.clone());
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
@ -175,27 +174,20 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
Ok(()) Ok(())
} }
fn mod_item_in( fn mod_item_in(&mut self, item: &clean::Item, _module_name: &str) -> Result<(), Error> {
&mut self,
item: &clean::Item,
_module_name: &str,
cache: &Cache,
) -> Result<(), Error> {
use clean::types::ItemKind::*; use clean::types::ItemKind::*;
if let ModuleItem(m) = &*item.kind { if let ModuleItem(m) = &*item.kind {
for item in &m.items { for item in &m.items {
match &*item.kind { match &*item.kind {
// These don't have names so they don't get added to the output by default // These don't have names so they don't get added to the output by default
ImportItem(_) => self.item(item.clone(), cache).unwrap(), ImportItem(_) => self.item(item.clone()).unwrap(),
ExternCrateItem(_, _) => self.item(item.clone(), cache).unwrap(), ExternCrateItem(_, _) => self.item(item.clone()).unwrap(),
ImplItem(i) => { ImplItem(i) => i.items.iter().for_each(|i| self.item(i.clone()).unwrap()),
i.items.iter().for_each(|i| self.item(i.clone(), cache).unwrap())
}
_ => {} _ => {}
} }
} }
} }
self.item(item.clone(), cache).unwrap(); self.item(item.clone()).unwrap();
Ok(()) Ok(())
} }
@ -206,22 +198,22 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
fn after_krate( fn after_krate(
&mut self, &mut self,
krate: &clean::Crate, krate: &clean::Crate,
cache: &Cache,
_diag: &rustc_errors::Handler, _diag: &rustc_errors::Handler,
) -> Result<(), Error> { ) -> Result<(), Error> {
debug!("Done with crate"); debug!("Done with crate");
let mut index = (*self.index).clone().into_inner(); let mut index = (*self.index).clone().into_inner();
index.extend(self.get_trait_items(cache)); index.extend(self.get_trait_items());
let output = types::Crate { let output = types::Crate {
root: types::Id(String::from("0:0")), root: types::Id(String::from("0:0")),
crate_version: krate.version.clone(), crate_version: krate.version.clone(),
includes_private: cache.document_private, includes_private: self.cache.document_private,
index, index,
paths: cache paths: self
.cache
.paths .paths
.clone() .clone()
.into_iter() .into_iter()
.chain(cache.external_paths.clone().into_iter()) .chain(self.cache.external_paths.clone().into_iter())
.map(|(k, (path, kind))| { .map(|(k, (path, kind))| {
( (
k.into(), k.into(),
@ -229,7 +221,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
) )
}) })
.collect(), .collect(),
external_crates: cache external_crates: self
.cache
.extern_locations .extern_locations
.iter() .iter()
.map(|(k, v)| { .map(|(k, v)| {
@ -254,4 +247,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
serde_json::ser::to_writer(&file, &output).unwrap(); serde_json::ser::to_writer(&file, &output).unwrap();
Ok(()) Ok(())
} }
fn cache(&self) -> &Cache {
&self.cache
}
} }

View file

@ -218,7 +218,12 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
clean::ImplItem(ref impl_) => { clean::ImplItem(ref impl_) => {
let filename = i.source.filename(self.ctx.sess()); let filename = i.source.filename(self.ctx.sess());
if let Some(ref tr) = impl_.trait_ { if let Some(ref tr) = impl_.trait_ {
debug!("impl {:#} for {:#} in {}", tr.print(), impl_.for_.print(), filename,); debug!(
"impl {:#} for {:#} in {}",
tr.print(&self.ctx.cache),
impl_.for_.print(&self.ctx.cache),
filename,
);
// don't count trait impls, the missing-docs lint doesn't so we shouldn't // don't count trait impls, the missing-docs lint doesn't so we shouldn't
// either // either
@ -227,7 +232,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
// inherent impls *can* be documented, and those docs show up, but in most // inherent impls *can* be documented, and those docs show up, but in most
// cases it doesn't make sense, as all methods on a type are in one single // cases it doesn't make sense, as all methods on a type are in one single
// impl block // impl block
debug!("impl {:#} in {}", impl_.for_.print(), filename); debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename);
} }
} }
_ => { _ => {

View file

@ -0,0 +1,75 @@
const QUERY = [
'i8',
'u32',
'str',
'char',
'unit',
'tuple',
'fn',
];
const EXPECTED = [
{
'others': [
{
'path': 'std',
'name': 'i8',
'href': '../std/primitive.i8.html',
},
]
},
{
'others': [
{
'path': 'std',
'name': 'u32',
'href': '../std/primitive.u32.html',
},
]
},
{
'others': [
{
'path': 'std',
'name': 'str',
'href': '../std/primitive.str.html',
},
]
},
{
'others': [
{
'path': 'std',
'name': 'char',
'href': '../std/primitive.char.html',
},
]
},
{
'others': [
{
'path': 'std',
'name': 'unit',
'href': '../std/primitive.unit.html',
},
]
},
{
'others': [
{
'path': 'std',
'name': 'tuple',
'href': '../std/primitive.tuple.html',
},
]
},
{
'others': [
{
'path': 'std',
'name': 'fn',
'href': '../std/primitive.fn.html',
},
]
},
];