From 9fd5a679846a738d1117590a319fb12651711da4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 12 Jan 2021 23:36:04 +0100 Subject: [PATCH 01/10] Remove CACHE_KEY global --- src/librustdoc/clean/inline.rs | 10 +- src/librustdoc/clean/mod.rs | 10 +- src/librustdoc/clean/types.rs | 52 +- src/librustdoc/clean/utils.rs | 28 +- src/librustdoc/config.rs | 2 +- src/librustdoc/core.rs | 8 +- src/librustdoc/formats/cache.rs | 22 +- src/librustdoc/formats/mod.rs | 5 +- src/librustdoc/formats/renderer.rs | 38 +- src/librustdoc/html/format.rs | 507 ++++++++-------- src/librustdoc/html/render/cache.rs | 34 +- src/librustdoc/html/render/mod.rs | 552 +++++++++--------- src/librustdoc/json/mod.rs | 80 +-- .../passes/calculate_doc_coverage.rs | 9 +- src/librustdoc/passes/collect_trait_impls.rs | 20 +- src/librustdoc/passes/strip_hidden.rs | 4 +- src/librustdoc/passes/strip_private.rs | 2 +- src/librustdoc/passes/stripper.rs | 8 +- 18 files changed, 728 insertions(+), 663 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 1f9e7f8ae5cd4..6ef74d6e9920c 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -368,7 +368,7 @@ crate fn build_impl( // Only inline impl if the implementing type is // reachable in rustdoc generated documentation if !did.is_local() { - if let Some(did) = for_.def_id() { + if let Some(did) = for_.def_id(&cx.cache) { if !cx.renderinfo.borrow().access_levels.is_public(did) { return; } @@ -410,19 +410,19 @@ crate fn build_impl( clean::GenericBound::TraitBound(polyt, _) => polyt.trait_, clean::GenericBound::Outlives(..) => unreachable!(), }); - if trait_.def_id() == tcx.lang_items().deref_trait() { + if trait_.def_id(&cx.cache) == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } - if let Some(trait_did) = trait_.def_id() { + if let Some(trait_did) = trait_.def_id(&cx.cache) { record_extern_trait(cx, trait_did); } let provided = trait_ - .def_id() + .def_id(&cx.cache) .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect()) .unwrap_or_default(); - debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); + debug!("build_impl: impl {:?} for {:?}", trait_.def_id(&cx.cache), for_.def_id(&cx.cache)); let mut item = clean::Item::from_def_id_and_parts( did, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a116ed686d90e..dcb0b325b9775 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2089,17 +2089,17 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &DocContext<'_>) -> // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. - if trait_.def_id() == cx.tcx.lang_items().deref_trait() { + if trait_.def_id(&cx.cache) == cx.tcx.lang_items().deref_trait() { build_deref_target_impls(cx, &items, &mut ret); } let provided: FxHashSet = trait_ - .def_id() + .def_id(&cx.cache) .map(|did| cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect()) .unwrap_or_default(); let for_ = impl_.self_ty.clean(cx); - let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) { + let type_alias = for_.def_id(&cx.cache).and_then(|did| match cx.tcx.def_kind(did) { DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)), _ => None, }); @@ -2329,14 +2329,14 @@ impl Clean for (&hir::MacroDef<'_>, Option) { if matchers.len() <= 1 { format!( "{}macro {}{} {{\n ...\n}}", - vis.print_with_space(cx.tcx, def_id), + vis.print_with_space(cx.tcx, def_id, &cx.cache), name, matchers.iter().map(|span| span.to_src(cx)).collect::(), ) } else { format!( "{}macro {} {{\n{}}}", - vis.print_with_space(cx.tcx, def_id), + vis.print_with_space(cx.tcx, def_id, &cx.cache), name, matchers .iter() diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c767b9dd85bf9..d03c457c8965c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -37,7 +37,8 @@ use crate::clean::inline; use crate::clean::types::Type::{QPath, ResolvedPath}; use crate::clean::Clean; use crate::core::DocContext; -use crate::formats::cache::cache; +use crate::doctree; +use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::render::cache::ExternalLocation; @@ -169,8 +170,8 @@ impl Item { self.attrs.collapsed_doc_value() } - crate fn links(&self) -> Vec { - self.attrs.links(&self.def_id.krate) + crate fn links(&self, cache: &Cache) -> Vec { + self.attrs.links(&self.def_id.krate, cache) } crate fn is_crate(&self) -> bool { @@ -826,7 +827,7 @@ impl Attributes { /// Gets links as a vector /// /// Cache must be populated before call - crate fn links(&self, krate: &CrateNum) -> Vec { + crate fn links(&self, krate: &CrateNum, cache: &Cache) -> Vec { use crate::html::format::href; use crate::html::render::CURRENT_DEPTH; @@ -835,7 +836,7 @@ impl Attributes { .filter_map(|ItemLink { link: s, link_text, did, fragment }| { match *did { Some(did) => { - if let Some((mut href, ..)) = href(did) { + if let Some((mut href, ..)) = href(did, cache) { if let Some(ref fragment) = *fragment { href.push('#'); href.push_str(fragment); @@ -851,7 +852,6 @@ impl Attributes { } None => { if let Some(ref fragment) = *fragment { - let cache = cache(); let url = match cache.extern_locations.get(krate) { Some(&(_, _, ExternalLocation::Local)) => { let depth = CURRENT_DEPTH.with(|l| l.get()); @@ -958,7 +958,7 @@ impl GenericBound { crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { use rustc_hir::TraitBoundModifier as TBM; if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { - if trait_.def_id() == cx.tcx.lang_items().sized_trait() { + if trait_.def_id(&cx.cache) == cx.tcx.lang_items().sized_trait() { return true; } } @@ -1171,9 +1171,9 @@ crate enum FnRetTy { } impl GetDefId for FnRetTy { - fn def_id(&self) -> Option { + fn def_id(&self, cache: &Cache) -> Option { match *self { - Return(ref ty) => ty.def_id(), + Return(ref ty) => ty.def_id(cache), DefaultReturn => None, } } @@ -1299,12 +1299,12 @@ crate enum TypeKind { } crate trait GetDefId { - fn def_id(&self) -> Option; + fn def_id(&self, cache: &Cache) -> Option; } impl GetDefId for Option { - fn def_id(&self) -> Option { - self.as_ref().and_then(|d| d.def_id()) + fn def_id(&self, cache: &Cache) -> Option { + self.as_ref().and_then(|d| d.def_id(cache)) } } @@ -1394,27 +1394,27 @@ impl Type { } impl GetDefId for Type { - fn def_id(&self) -> Option { + fn def_id(&self, cache: &Cache) -> Option { match *self { ResolvedPath { did, .. } => Some(did), - Primitive(p) => cache().primitive_locations.get(&p).cloned(), + Primitive(p) => cache.primitive_locations.get(&p).cloned(), BorrowedRef { type_: box Generic(..), .. } => { - Primitive(PrimitiveType::Reference).def_id() + Primitive(PrimitiveType::Reference).def_id(cache) } - BorrowedRef { ref type_, .. } => type_.def_id(), + BorrowedRef { ref type_, .. } => type_.def_id(cache), Tuple(ref tys) => { if tys.is_empty() { - Primitive(PrimitiveType::Unit).def_id() + Primitive(PrimitiveType::Unit).def_id(cache) } else { - Primitive(PrimitiveType::Tuple).def_id() + Primitive(PrimitiveType::Tuple).def_id(cache) } } - BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(), - Never => Primitive(PrimitiveType::Never).def_id(), - Slice(..) => Primitive(PrimitiveType::Slice).def_id(), - Array(..) => Primitive(PrimitiveType::Array).def_id(), - RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(), - QPath { ref self_type, .. } => self_type.def_id(), + BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(cache), + Never => Primitive(PrimitiveType::Never).def_id(cache), + Slice(..) => Primitive(PrimitiveType::Slice).def_id(cache), + Array(..) => Primitive(PrimitiveType::Array).def_id(cache), + RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(cache), + QPath { ref self_type, .. } => self_type.def_id(cache), _ => None, } } @@ -1814,8 +1814,8 @@ crate struct Typedef { } impl GetDefId for Typedef { - fn def_id(&self) -> Option { - self.type_.def_id() + fn def_id(&self, cache: &Cache) -> Option { + self.type_.def_id(cache) } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 0f5495c831058..e6a94926329b9 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -177,9 +177,11 @@ crate fn get_real_types( return res; } 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 { - WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(), + WherePredicate::BoundPredicate { ty, .. } => { + ty.def_id(&cx.cache) == arg.def_id(&cx.cache) + } _ => false, }) { let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); @@ -195,7 +197,7 @@ crate fn get_real_types( res.extend(adds); } else if !ty.is_full_generic() { if let Some(kind) = - ty.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) + ty.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) { res.insert((ty, kind)); } @@ -212,7 +214,9 @@ crate fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - if let Some(kind) = ty.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { + if let Some(kind) = + ty.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) + { res.insert((ty.clone(), kind)); } } @@ -220,7 +224,7 @@ crate fn get_real_types( } } } else { - if let Some(kind) = arg.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { + if let Some(kind) = arg.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) { res.insert((arg.clone(), kind)); } if let Some(gens) = arg.generics() { @@ -230,7 +234,9 @@ crate fn get_real_types( if !adds.is_empty() { res.extend(adds); } - } else if let Some(kind) = gen.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { + } else if let Some(kind) = + gen.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) + { res.insert((gen.clone(), kind)); } } @@ -257,7 +263,9 @@ crate fn get_all_types( if !args.is_empty() { all_types.extend(args); } else { - if let Some(kind) = arg.type_.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { + if let Some(kind) = + arg.type_.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) + { all_types.insert((arg.type_.clone(), kind)); } } @@ -267,7 +275,9 @@ crate fn get_all_types( FnRetTy::Return(ref return_type) => { let mut ret = get_real_types(generics, &return_type, cx, 0); if ret.is_empty() { - if let Some(kind) = return_type.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { + if let Some(kind) = + return_type.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) + { ret.insert((return_type.clone(), kind)); } } @@ -473,7 +483,7 @@ crate fn resolve_type(cx: &DocContext<'_>, path: Path, id: hir::HirId) -> Type { return Generic(kw::SelfUpper); } 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, _ => false, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index fee1bf4c3a6a7..94773ac77ccb0 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -261,7 +261,7 @@ crate struct RenderOptions { } /// Temporary storage for data obtained during `RustdocVisitor::clean()`. -/// Later on moved into `CACHE_KEY`. +/// Later on moved into `cache`. #[derive(Default, Clone)] crate struct RenderInfo { crate inlined: FxHashSet, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 4db5a0bccc85d..16f11e460e6f0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -32,6 +32,7 @@ use crate::clean; use crate::clean::{AttributesExt, MAX_DEF_ID}; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::config::{OutputFormat, RenderInfo}; +use crate::formats::cache::Cache; use crate::passes::{self, Condition::*, ConditionalPass}; 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. crate param_env: Cell>, - /// Later on moved into `CACHE_KEY` + /// Later on moved into `cache` crate renderinfo: RefCell, - /// Later on moved through `clean::Crate` into `CACHE_KEY` + /// Later on moved through `clean::Crate` into `cache` crate external_traits: Rc>>, /// Used while populating `external_traits` to ensure we don't process the same trait twice at /// the same time. @@ -75,6 +76,8 @@ crate struct DocContext<'tcx> { /// See `collect_intra_doc_links::traits_implemented_by` for more details. /// `map>` crate module_trait_cache: RefCell>>, + /// Fake empty cache used when cache is required as parameter. + crate cache: Cache, } impl<'tcx> DocContext<'tcx> { @@ -524,6 +527,7 @@ crate fn run_global_ctxt( .collect(), render_options, module_trait_cache: RefCell::new(FxHashMap::default()), + cache: Cache::default(), }; debug!("crate: {:?}", tcx.hir().krate()); diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c1f8b12cac497..c4c8145a57d0a 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -1,8 +1,6 @@ -use std::cell::RefCell; use std::collections::BTreeMap; use std::mem; use std::path::{Path, PathBuf}; -use std::sync::Arc; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; 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::IndexItem; -thread_local!(crate static CACHE_KEY: RefCell> = Default::default()); - /// This cache is used to store information about the [`clean::Crate`] being /// rendered in order to provide more useful documentation. This contains /// information like all implementors of a trait, all traits a type implements, @@ -230,8 +226,8 @@ impl DocFolder for Cache { // masked crate then remove it completely. if let clean::ImplItem(ref i) = *item.kind { if self.masked_crates.contains(&item.def_id.krate) - || i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) - || i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) + || i.trait_.def_id(self).map_or(false, |d| self.masked_crates.contains(&d.krate)) + || i.for_.def_id(self).map_or(false, |d| self.masked_crates.contains(&d.krate)) { return None; } @@ -245,7 +241,7 @@ impl DocFolder for Cache { // Collect all the implementors of traits. if let clean::ImplItem(ref i) = *item.kind { - if let Some(did) = i.trait_.def_id() { + if let Some(did) = i.trait_.def_id(self) { if i.blanket_impl.is_none() { self.implementors .entry(did) @@ -319,7 +315,7 @@ impl DocFolder for Cache { .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())), parent, parent_idx: None, - search_type: get_index_search_type(&item), + search_type: get_index_search_type(&item, self), }); for alias in item.attrs.get_doc_aliases() { @@ -447,18 +443,18 @@ impl DocFolder for Cache { if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { for bound in generics { - if let Some(did) = bound.def_id() { + if let Some(did) = bound.def_id(self) { dids.insert(did); } } } let impl_item = Impl { impl_item: item }; - if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { + if impl_item.trait_did(self).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().expect("no trait did"); + let trait_did = impl_item.trait_did(self).expect("no trait did"); self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None @@ -477,7 +473,3 @@ impl DocFolder for Cache { ret } } - -crate fn cache() -> Arc { - CACHE_KEY.with(|c| c.borrow().clone()) -} diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 58b9f5fbf0f6c..4d766af98feaf 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -8,6 +8,7 @@ use rustc_span::def_id::DefId; use crate::clean; use crate::clean::types::GetDefId; +use crate::formats::cache::Cache; /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. @@ -38,7 +39,7 @@ impl Impl { } } - crate fn trait_did(&self) -> Option { - self.inner_impl().trait_.def_id() + crate fn trait_did(&self, cache: &Cache) -> Option { + self.inner_impl().trait_.def_id(cache) } } diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 6941fa064ec03..65e2187e4aeab 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,12 +1,10 @@ -use std::sync::Arc; - -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty; use rustc_span::edition::Edition; use crate::clean; use crate::config::{RenderInfo, RenderOptions}; 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 /// backend renderer has hooks for initialization, documenting an item, entering and exiting a @@ -22,20 +20,15 @@ crate trait FormatRenderer<'tcx>: Clone { options: RenderOptions, render_info: RenderInfo, edition: Edition, - cache: &mut Cache, - tcx: TyCtxt<'tcx>, + cache: Cache, + tcx: ty::TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error>; /// 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). - fn mod_item_in( - &mut self, - item: &clean::Item, - item_name: &str, - cache: &Cache, - ) -> Result<(), Error>; + fn mod_item_in(&mut self, item: &clean::Item, item_name: &str) -> Result<(), Error>; /// Runs after recursively rendering all sub-items of a module. fn mod_item_out(&mut self, item_name: &str) -> Result<(), Error>; @@ -46,9 +39,10 @@ crate trait FormatRenderer<'tcx>: Clone { fn after_krate( &mut self, krate: &clean::Crate, - cache: &Cache, diag: &rustc_errors::Handler, ) -> Result<(), Error>; + + fn cache(&self) -> &Cache; } /// Main method for rendering a crate. @@ -60,7 +54,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( edition: Edition, tcx: TyCtxt<'tcx>, ) -> Result<(), Error> { - let (krate, mut cache) = tcx.sess.time("create_format_cache", || { + let (krate, cache) = tcx.sess.time("create_format_cache", || { Cache::from_krate( render_info.clone(), options.document_private, @@ -73,12 +67,10 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( let (mut format_renderer, mut krate) = prof .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 format_renderer, mut krate) = + T::init(krate, options, render_info, edition, cache, tcx)?; let mut item = match krate.module.take() { Some(i) => i, @@ -101,7 +93,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( } 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 { clean::StrippedItem(box clean::ModuleItem(m)) | clean::ModuleItem(m) => m, _ => unreachable!(), @@ -114,9 +106,9 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( cx.mod_item_out(&name)?; } else if item.name.is_some() { 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()) - .run(|| format_renderer.after_krate(&krate, &cache, diag)) + .run(|| format_renderer.after_krate(&krate, diag)) } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 5c2adca3126f7..01915c33a07ad 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -16,7 +16,7 @@ use rustc_span::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_target::spec::abi::Abi; use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType}; -use crate::formats::cache::cache; +use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::render::cache::ExternalLocation; @@ -152,24 +152,27 @@ fn comma_sep(items: impl Iterator) -> impl fmt::Displ }) } -crate fn print_generic_bounds(bounds: &[clean::GenericBound]) -> impl fmt::Display + '_ { +crate fn print_generic_bounds<'a>( + bounds: &'a [clean::GenericBound], + cache: &'a Cache, +) -> impl fmt::Display + 'a { display_fn(move |f| { let mut bounds_dup = FxHashSet::default(); for (i, bound) in - bounds.iter().filter(|b| bounds_dup.insert(b.print().to_string())).enumerate() + bounds.iter().filter(|b| bounds_dup.insert(b.print(cache).to_string())).enumerate() { if i > 0 { f.write_str(" + ")?; } - fmt::Display::fmt(&bound.print(), f)?; + fmt::Display::fmt(&bound.print(cache), f)?; } Ok(()) }) } impl clean::GenericParamDef { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| match self.kind { clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name), clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => { @@ -177,17 +180,17 @@ impl clean::GenericParamDef { if !bounds.is_empty() { if f.alternate() { - write!(f, ": {:#}", print_generic_bounds(bounds))?; + write!(f, ": {:#}", print_generic_bounds(bounds, cache))?; } else { - write!(f, ": {}", print_generic_bounds(bounds))?; + write!(f, ": {}", print_generic_bounds(bounds, cache))?; } } if let Some(ref ty) = default { if f.alternate() { - write!(f, " = {:#}", ty.print())?; + write!(f, " = {:#}", ty.print(cache))?; } else { - write!(f, " = {}", ty.print())?; + write!(f, " = {}", ty.print(cache))?; } } @@ -195,9 +198,9 @@ impl clean::GenericParamDef { } clean::GenericParamDefKind::Const { ref ty, .. } => { if f.alternate() { - write!(f, "const {}: {:#}", self.name, ty.print()) + write!(f, "const {}: {:#}", self.name, ty.print(cache)) } else { - write!(f, "const {}: {}", self.name, ty.print()) + write!(f, "const {}: {}", self.name, ty.print(cache)) } } }) @@ -205,7 +208,7 @@ impl clean::GenericParamDef { } impl clean::Generics { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { let real_params = self.params.iter().filter(|p| !p.is_synthetic_type_param()).collect::>(); @@ -213,98 +216,108 @@ impl clean::Generics { return Ok(()); } if f.alternate() { - write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print()))) + write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache)))) } else { - write!(f, "<{}>", comma_sep(real_params.iter().map(|g| g.print()))) + write!(f, "<{}>", comma_sep(real_params.iter().map(|g| g.print(cache)))) } }) } } -impl<'a> fmt::Display for WhereClause<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let &WhereClause { gens, indent, end_newline } = self; - if gens.where_predicates.is_empty() { - return Ok(()); - } - let mut clause = String::new(); - if f.alternate() { - clause.push_str(" where"); - } else { - if end_newline { - clause.push_str(" where"); - } else { - clause.push_str(" where"); +impl<'a> WhereClause<'a> { + crate fn print<'b>(&'b self, cache: &'b Cache) -> impl fmt::Display + 'b { + display_fn(move |f| { + let &WhereClause { gens, indent, end_newline } = self; + if gens.where_predicates.is_empty() { + return Ok(()); } - } - for (i, pred) in gens.where_predicates.iter().enumerate() { + let mut clause = String::new(); if f.alternate() { - clause.push(' '); + clause.push_str(" where"); } else { - clause.push_str("
"); + if end_newline { + clause.push_str(" where"); + } else { + clause.push_str(" where"); + } } + for (i, pred) in gens.where_predicates.iter().enumerate() { + if f.alternate() { + clause.push(' '); + } else { + clause.push_str("
"); + } - match pred { - clean::WherePredicate::BoundPredicate { ty, bounds } => { - let bounds = bounds; - if f.alternate() { - clause.push_str(&format!( - "{:#}: {:#}", - ty.print(), - print_generic_bounds(bounds) - )); - } else { + match pred { + clean::WherePredicate::BoundPredicate { ty, bounds } => { + let bounds = bounds; + if f.alternate() { + clause.push_str(&format!( + "{:#}: {:#}", + ty.print(cache), + print_generic_bounds(bounds, cache) + )); + } else { + clause.push_str(&format!( + "{}: {}", + ty.print(cache), + print_generic_bounds(bounds, cache) + )); + } + } + clean::WherePredicate::RegionPredicate { lifetime, bounds } => { clause.push_str(&format!( "{}: {}", - ty.print(), - print_generic_bounds(bounds) + lifetime.print(), + bounds + .iter() + .map(|b| b.print(cache).to_string()) + .collect::>() + .join(" + ") )); } - } - clean::WherePredicate::RegionPredicate { lifetime, bounds } => { - clause.push_str(&format!( - "{}: {}", - lifetime.print(), - bounds - .iter() - .map(|b| b.print().to_string()) - .collect::>() - .join(" + ") - )); - } - clean::WherePredicate::EqPredicate { lhs, rhs } => { - if f.alternate() { - clause.push_str(&format!("{:#} == {:#}", lhs.print(), rhs.print())); - } else { - clause.push_str(&format!("{} == {}", lhs.print(), rhs.print())); + clean::WherePredicate::EqPredicate { lhs, rhs } => { + if f.alternate() { + clause.push_str(&format!( + "{:#} == {:#}", + lhs.print(cache), + rhs.print(cache) + )); + } else { + clause.push_str(&format!( + "{} == {}", + lhs.print(cache), + rhs.print(cache) + )); + } } } - } - if i < gens.where_predicates.len() - 1 || end_newline { - clause.push(','); + if i < gens.where_predicates.len() - 1 || end_newline { + clause.push(','); + } } - } - if end_newline { - // add a space so stripping
tags and breaking spaces still renders properly - if f.alternate() { - clause.push(' '); - } else { - clause.push_str(" "); + if end_newline { + // add a space so stripping
tags and breaking spaces still renders properly + if f.alternate() { + clause.push(' '); + } else { + clause.push_str(" "); + } } - } - if !f.alternate() { - clause.push_str("
"); - let padding = " ".repeat(indent + 4); - clause = clause.replace("
", &format!("
{}", padding)); - clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); - if !end_newline { - clause.insert_str(0, "
"); + if !f.alternate() { + clause.push_str("
"); + let padding = " ".repeat(indent + 4); + clause = clause.replace("
", &format!("
{}", padding)); + clause.insert_str(0, &" ".repeat(indent.saturating_sub(1))); + if !end_newline { + clause.insert_str(0, "
"); + } } - } - write!(f, "{}", clause) + write!(f, "{}", clause) + }) } } @@ -327,34 +340,34 @@ impl clean::Constant { } impl clean::PolyTrait { - fn print(&self) -> impl fmt::Display + '_ { + fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { if !self.generic_params.is_empty() { if f.alternate() { write!( f, "for<{:#}> ", - comma_sep(self.generic_params.iter().map(|g| g.print())) + comma_sep(self.generic_params.iter().map(|g| g.print(cache))) )?; } else { write!( f, "for<{}> ", - comma_sep(self.generic_params.iter().map(|g| g.print())) + comma_sep(self.generic_params.iter().map(|g| g.print(cache))) )?; } } if f.alternate() { - write!(f, "{:#}", self.trait_.print()) + write!(f, "{:#}", self.trait_.print(cache)) } else { - write!(f, "{}", self.trait_.print()) + write!(f, "{}", self.trait_.print(cache)) } }) } } impl clean::GenericBound { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| match self { clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()), clean::GenericBound::TraitBound(ty, modifier) => { @@ -364,9 +377,9 @@ impl clean::GenericBound { hir::TraitBoundModifier::MaybeConst => "?const", }; if f.alternate() { - write!(f, "{}{:#}", modifier_str, ty.print()) + write!(f, "{}{:#}", modifier_str, ty.print(cache)) } else { - write!(f, "{}{}", modifier_str, ty.print()) + write!(f, "{}{}", modifier_str, ty.print(cache)) } } }) @@ -374,7 +387,7 @@ impl clean::GenericBound { } impl clean::GenericArgs { - fn print(&self) -> impl fmt::Display + '_ { + fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { match self { clean::GenericArgs::AngleBracketed { args, bindings } => { @@ -391,9 +404,9 @@ impl clean::GenericArgs { } comma = true; if f.alternate() { - write!(f, "{:#}", arg.print())?; + write!(f, "{:#}", arg.print(cache))?; } else { - write!(f, "{}", arg.print())?; + write!(f, "{}", arg.print(cache))?; } } for binding in bindings { @@ -402,9 +415,9 @@ impl clean::GenericArgs { } comma = true; if f.alternate() { - write!(f, "{:#}", binding.print())?; + write!(f, "{:#}", binding.print(cache))?; } else { - write!(f, "{}", binding.print())?; + write!(f, "{}", binding.print(cache))?; } } if f.alternate() { @@ -423,17 +436,17 @@ impl clean::GenericArgs { } comma = true; if f.alternate() { - write!(f, "{:#}", ty.print())?; + write!(f, "{:#}", ty.print(cache))?; } else { - write!(f, "{}", ty.print())?; + write!(f, "{}", ty.print(cache))?; } } f.write_str(")")?; if let Some(ref ty) = *output { if f.alternate() { - write!(f, " -> {:#}", ty.print())?; + write!(f, " -> {:#}", ty.print(cache))?; } else { - write!(f, " -> {}", ty.print())?; + write!(f, " -> {}", ty.print(cache))?; } } } @@ -444,19 +457,19 @@ impl clean::GenericArgs { } impl clean::PathSegment { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { if f.alternate() { - write!(f, "{}{:#}", self.name, self.args.print()) + write!(f, "{}{:#}", self.name, self.args.print(cache)) } else { - write!(f, "{}{}", self.name, self.args.print()) + write!(f, "{}{}", self.name, self.args.print(cache)) } }) } } impl clean::Path { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { if self.global { f.write_str("::")? @@ -467,9 +480,9 @@ impl clean::Path { f.write_str("::")? } if f.alternate() { - write!(f, "{:#}", seg.print())?; + write!(f, "{:#}", seg.print(cache))?; } else { - write!(f, "{}", seg.print())?; + write!(f, "{}", seg.print(cache))?; } } Ok(()) @@ -477,8 +490,7 @@ impl clean::Path { } } -crate fn href(did: DefId) -> Option<(String, ItemType, Vec)> { - let cache = cache(); +crate fn href(did: DefId, cache: &Cache) -> Option<(String, ItemType, Vec)> { if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private { return None; } @@ -526,6 +538,7 @@ fn resolved_path( path: &clean::Path, print_all: bool, use_absolute: bool, + cache: &Cache, ) -> fmt::Result { let last = path.segments.last().unwrap(); @@ -535,18 +548,22 @@ fn resolved_path( } } if w.alternate() { - write!(w, "{}{:#}", &last.name, last.args.print())?; + write!(w, "{}{:#}", &last.name, last.args.print(cache))?; } else { let path = if use_absolute { - if let Some((_, _, fqp)) = href(did) { - format!("{}::{}", fqp[..fqp.len() - 1].join("::"), anchor(did, fqp.last().unwrap())) + if let Some((_, _, fqp)) = href(did, cache) { + format!( + "{}::{}", + fqp[..fqp.len() - 1].join("::"), + anchor(did, fqp.last().unwrap(), cache) + ) } else { last.name.to_string() } } else { - anchor(did, &*last.name.as_str()).to_string() + anchor(did, &*last.name.as_str(), cache).to_string() }; - write!(w, "{}{}", path, last.args.print())?; + write!(w, "{}{}", path, last.args.print(cache))?; } Ok(()) } @@ -555,8 +572,8 @@ fn primitive_link( f: &mut fmt::Formatter<'_>, prim: clean::PrimitiveType, name: &str, + m: &Cache, ) -> fmt::Result { - let m = cache(); let mut needs_termination = false; if !f.alternate() { match m.primitive_locations.get(&prim) { @@ -602,12 +619,15 @@ fn primitive_link( } /// Helper to render type parameters -fn tybounds(param_names: &Option>) -> impl fmt::Display + '_ { +fn tybounds<'a>( + param_names: &'a Option>, + cache: &'a Cache, +) -> impl fmt::Display + 'a { display_fn(move |f| match *param_names { Some(ref params) => { for param in params { write!(f, " + ")?; - fmt::Display::fmt(¶m.print(), f)?; + fmt::Display::fmt(¶m.print(cache), f)?; } Ok(()) } @@ -615,9 +635,9 @@ fn tybounds(param_names: &Option>) -> impl fmt::Display }) } -crate fn anchor(did: DefId, text: &str) -> impl fmt::Display + '_ { +crate fn anchor<'a>(did: DefId, text: &'a str, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { - if let Some((url, short_ty, fqp)) = href(did) { + if let Some((url, short_ty, fqp)) = href(did, cache) { write!( f, r#"{}"#, @@ -633,7 +653,12 @@ crate fn anchor(did: DefId, text: &str) -> impl fmt::Display + '_ { }) } -fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> fmt::Result { +fn fmt_type( + t: &clean::Type, + f: &mut fmt::Formatter<'_>, + use_absolute: bool, + cache: &Cache, +) -> fmt::Result { match *t { clean::Generic(name) => write!(f, "{}", name), clean::ResolvedPath { did, ref param_names, ref path, is_generic } => { @@ -641,11 +666,11 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> f.write_str("dyn ")?; } // Paths like `T::Output` and `Self::Output` should be rendered with all segments. - resolved_path(f, did, path, is_generic, use_absolute)?; - fmt::Display::fmt(&tybounds(param_names), f) + resolved_path(f, did, path, is_generic, use_absolute, cache)?; + fmt::Display::fmt(&tybounds(param_names, cache), f) } clean::Infer => write!(f, "_"), - clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()), + clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cache), clean::BareFunction(ref decl) => { if f.alternate() { write!( @@ -653,8 +678,8 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> "{}{:#}fn{:#}{:#}", decl.unsafety.print_with_space(), print_abi_with_space(decl.abi), - decl.print_generic_params(), - decl.decl.print() + decl.print_generic_params(cache), + decl.decl.print(cache) ) } else { write!( @@ -663,46 +688,46 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> decl.unsafety.print_with_space(), print_abi_with_space(decl.abi) )?; - primitive_link(f, PrimitiveType::Fn, "fn")?; - write!(f, "{}{}", decl.print_generic_params(), decl.decl.print()) + primitive_link(f, PrimitiveType::Fn, "fn", cache)?; + write!(f, "{}{}", decl.print_generic_params(cache), decl.decl.print(cache)) } } clean::Tuple(ref typs) => { match &typs[..] { - &[] => primitive_link(f, PrimitiveType::Unit, "()"), + &[] => primitive_link(f, PrimitiveType::Unit, "()", cache), &[ref one] => { - primitive_link(f, PrimitiveType::Tuple, "(")?; + primitive_link(f, PrimitiveType::Tuple, "(", cache)?; // Carry `f.alternate()` into this display w/o branching manually. - fmt::Display::fmt(&one.print(), f)?; - primitive_link(f, PrimitiveType::Tuple, ",)") + fmt::Display::fmt(&one.print(cache), f)?; + primitive_link(f, PrimitiveType::Tuple, ",)", cache) } many => { - primitive_link(f, PrimitiveType::Tuple, "(")?; + primitive_link(f, PrimitiveType::Tuple, "(", cache)?; for (i, item) in many.iter().enumerate() { if i != 0 { write!(f, ", ")?; } - fmt::Display::fmt(&item.print(), f)?; + fmt::Display::fmt(&item.print(cache), f)?; } - primitive_link(f, PrimitiveType::Tuple, ")") + primitive_link(f, PrimitiveType::Tuple, ")", cache) } } } clean::Slice(ref t) => { - primitive_link(f, PrimitiveType::Slice, "[")?; - fmt::Display::fmt(&t.print(), f)?; - primitive_link(f, PrimitiveType::Slice, "]") + primitive_link(f, PrimitiveType::Slice, "[", cache)?; + fmt::Display::fmt(&t.print(cache), f)?; + primitive_link(f, PrimitiveType::Slice, "]", cache) } clean::Array(ref t, ref n) => { - primitive_link(f, PrimitiveType::Array, "[")?; - fmt::Display::fmt(&t.print(), f)?; + primitive_link(f, PrimitiveType::Array, "[", cache)?; + fmt::Display::fmt(&t.print(cache), f)?; if f.alternate() { - primitive_link(f, PrimitiveType::Array, &format!("; {}]", n)) + primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cache) } else { - primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n))) + primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cache) } } - clean::Never => primitive_link(f, PrimitiveType::Never, "!"), + clean::Never => primitive_link(f, PrimitiveType::Never, "!", cache), clean::RawPointer(m, ref t) => { let m = match m { hir::Mutability::Mut => "mut", @@ -714,19 +739,26 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> primitive_link( f, clean::PrimitiveType::RawPointer, - &format!("*{} {:#}", m, t.print()), + &format!("*{} {:#}", m, t.print(cache)), + cache, ) } else { primitive_link( f, clean::PrimitiveType::RawPointer, - &format!("*{} {}", m, t.print()), + &format!("*{} {}", m, t.print(cache)), + cache, ) } } _ => { - primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m))?; - fmt::Display::fmt(&t.print(), f) + primitive_link( + f, + clean::PrimitiveType::RawPointer, + &format!("*{} ", m), + cache, + )?; + fmt::Display::fmt(&t.print(cache), f) } } } @@ -746,13 +778,15 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> primitive_link( f, PrimitiveType::Slice, - &format!("{}{}{}[{:#}]", amp, lt, m, bt.print()), + &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache)), + cache, ) } else { primitive_link( f, PrimitiveType::Slice, - &format!("{}{}{}[{}]", amp, lt, m, bt.print()), + &format!("{}{}{}[{}]", amp, lt, m, bt.print(cache)), + cache, ) } } @@ -761,36 +795,42 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> f, PrimitiveType::Slice, &format!("{}{}{}[", amp, lt, m), + cache, )?; if f.alternate() { - write!(f, "{:#}", bt.print())?; + write!(f, "{:#}", bt.print(cache))?; } else { - write!(f, "{}", bt.print())?; + write!(f, "{}", bt.print(cache))?; } - primitive_link(f, PrimitiveType::Slice, "]") + primitive_link(f, PrimitiveType::Slice, "]", cache) } } } clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => { write!(f, "{}{}{}(", amp, lt, m)?; - fmt_type(&ty, f, use_absolute)?; + fmt_type(&ty, f, use_absolute, cache)?; write!(f, ")") } clean::Generic(..) => { - primitive_link(f, PrimitiveType::Reference, &format!("{}{}{}", amp, lt, m))?; - fmt_type(&ty, f, use_absolute) + primitive_link( + f, + PrimitiveType::Reference, + &format!("{}{}{}", amp, lt, m), + cache, + )?; + fmt_type(&ty, f, use_absolute, cache) } _ => { write!(f, "{}{}{}", amp, lt, m)?; - fmt_type(&ty, f, use_absolute) + fmt_type(&ty, f, use_absolute, cache) } } } clean::ImplTrait(ref bounds) => { if f.alternate() { - write!(f, "impl {:#}", print_generic_bounds(bounds)) + write!(f, "impl {:#}", print_generic_bounds(bounds, cache)) } else { - write!(f, "impl {}", print_generic_bounds(bounds)) + write!(f, "impl {}", print_generic_bounds(bounds, cache)) } } clean::QPath { ref name, ref self_type, ref trait_ } => { @@ -802,15 +842,15 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> }; if f.alternate() { if should_show_cast { - write!(f, "<{:#} as {:#}>::", self_type.print(), trait_.print())? + write!(f, "<{:#} as {:#}>::", self_type.print(cache), trait_.print(cache))? } else { - write!(f, "{:#}::", self_type.print())? + write!(f, "{:#}::", self_type.print(cache))? } } else { if should_show_cast { - write!(f, "<{} as {}>::", self_type.print(), trait_.print())? + write!(f, "<{} as {}>::", self_type.print(cache), trait_.print(cache))? } else { - write!(f, "{}::", self_type.print())? + write!(f, "{}::", self_type.print(cache))? } }; match *trait_ { @@ -825,7 +865,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> // everything comes in as a fully resolved QPath (hard to // look at). box clean::ResolvedPath { did, ref param_names, .. } => { - match href(did) { + match href(did, cache) { Some((ref url, _, ref path)) if !f.alternate() => { write!( f, @@ -851,22 +891,27 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } impl clean::Type { - crate fn print(&self) -> impl fmt::Display + '_ { - display_fn(move |f| fmt_type(self, f, false)) + crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { + display_fn(move |f| fmt_type(self, f, false, cache)) } } impl clean::Impl { - crate fn print(&self) -> impl fmt::Display + '_ { - self.print_inner(true, false) + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + self.print_inner(true, false, cache) } - fn print_inner(&self, link_trait: bool, use_absolute: bool) -> impl fmt::Display + '_ { + fn print_inner<'a>( + &'a self, + link_trait: bool, + use_absolute: bool, + cache: &'a Cache, + ) -> impl fmt::Display + 'a { display_fn(move |f| { if f.alternate() { - write!(f, "impl{:#} ", self.generics.print())?; + write!(f, "impl{:#} ", self.generics.print(cache))?; } else { - write!(f, "impl{} ", self.generics.print())?; + write!(f, "impl{} ", self.generics.print(cache))?; } if let Some(ref ty) = self.trait_ { @@ -875,7 +920,7 @@ impl clean::Impl { } if link_trait { - fmt::Display::fmt(&ty.print(), f)?; + fmt::Display::fmt(&ty.print(cache), f)?; } else { match ty { clean::ResolvedPath { @@ -883,7 +928,7 @@ impl clean::Impl { } => { let last = path.segments.last().unwrap(); fmt::Display::fmt(&last.name, f)?; - fmt::Display::fmt(&last.args.print(), f)?; + fmt::Display::fmt(&last.args.print(cache), f)?; } _ => unreachable!(), } @@ -892,36 +937,39 @@ impl clean::Impl { } if let Some(ref ty) = self.blanket_impl { - fmt_type(ty, f, use_absolute)?; + fmt_type(ty, f, use_absolute, cache)?; } else { - fmt_type(&self.for_, f, use_absolute)?; + fmt_type(&self.for_, f, use_absolute, cache)?; } - fmt::Display::fmt( - &WhereClause { gens: &self.generics, indent: 0, end_newline: true }, - f, - )?; + let where_clause = WhereClause { gens: &self.generics, indent: 0, end_newline: true }; + fmt::Display::fmt(&where_clause.print(cache), f)?; Ok(()) }) } } // The difference from above is that trait is not hyperlinked. -crate fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut Buffer, use_absolute: bool) { - f.from_display(i.print_inner(false, use_absolute)) +crate fn fmt_impl_for_trait_page( + i: &clean::Impl, + f: &mut Buffer, + use_absolute: bool, + cache: &Cache, +) { + f.from_display(i.print_inner(false, use_absolute, cache)) } impl clean::Arguments { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { for (i, input) in self.values.iter().enumerate() { if !input.name.is_empty() { write!(f, "{}: ", input.name)?; } if f.alternate() { - write!(f, "{:#}", input.type_.print())?; + write!(f, "{:#}", input.type_.print(cache))?; } else { - write!(f, "{}", input.type_.print())?; + write!(f, "{}", input.type_.print(cache))?; } if i + 1 < self.values.len() { write!(f, ", ")?; @@ -933,41 +981,41 @@ impl clean::Arguments { } impl clean::FnRetTy { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| match self { clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()), - clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print()), - clean::Return(ty) => write!(f, " -> {}", ty.print()), + clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache)), + clean::Return(ty) => write!(f, " -> {}", ty.print(cache)), clean::DefaultReturn => Ok(()), }) } } impl clean::BareFunctionDecl { - fn print_generic_params(&self) -> impl fmt::Display + '_ { - comma_sep(self.generic_params.iter().map(|g| g.print())) + fn print_generic_params<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { + comma_sep(self.generic_params.iter().map(move |g| g.print(cache))) } } impl clean::FnDecl { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a { display_fn(move |f| { let ellipsis = if self.c_variadic { ", ..." } else { "" }; if f.alternate() { write!( f, "({args:#}{ellipsis}){arrow:#}", - args = self.inputs.print(), + args = self.inputs.print(cache), ellipsis = ellipsis, - arrow = self.output.print() + arrow = self.output.print(cache) ) } else { write!( f, "({args}{ellipsis}){arrow}", - args = self.inputs.print(), + args = self.inputs.print(cache), ellipsis = ellipsis, - arrow = self.output.print() + arrow = self.output.print(cache) ) } }) @@ -975,7 +1023,7 @@ impl clean::FnDecl { } impl Function<'_> { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { display_fn(move |f| { let &Function { decl, header_len, indent, asyncness } = self; let amp = if f.alternate() { "&" } else { "&" }; @@ -1011,11 +1059,11 @@ impl Function<'_> { } clean::SelfExplicit(ref typ) => { if f.alternate() { - args.push_str(&format!("self: {:#}", typ.print())); + args.push_str(&format!("self: {:#}", typ.print(cache))); } else { - args.push_str(&format!("self: {}", typ.print())); + args.push_str(&format!("self: {}", typ.print(cache))); } - args_plain.push_str(&format!("self: {:#}", typ.print())); + args_plain.push_str(&format!("self: {:#}", typ.print(cache))); } } } else { @@ -1029,11 +1077,11 @@ impl Function<'_> { } if f.alternate() { - args.push_str(&format!("{:#}", input.type_.print())); + args.push_str(&format!("{:#}", input.type_.print(cache))); } else { - args.push_str(&input.type_.print().to_string()); + args.push_str(&input.type_.print(cache).to_string()); } - args_plain.push_str(&format!("{:#}", input.type_.print())); + args_plain.push_str(&format!("{:#}", input.type_.print(cache))); } if i + 1 < decl.inputs.values.len() { args.push(','); @@ -1054,11 +1102,11 @@ impl Function<'_> { Cow::Borrowed(&decl.output) }; - let arrow_plain = format!("{:#}", &output.print()); + let arrow_plain = format!("{:#}", &output.print(cache)); let arrow = if f.alternate() { - format!("{:#}", &output.print()) + format!("{:#}", &output.print(cache)) } else { - output.print().to_string() + output.print(cache).to_string() }; let declaration_len = header_len + args_plain.len() + arrow_plain.len(); @@ -1089,13 +1137,13 @@ impl clean::Visibility { self, tcx: TyCtxt<'tcx>, item_did: DefId, + cache: &Cache, ) -> impl fmt::Display + 'tcx { use rustc_span::symbol::kw; - display_fn(move |f| match self { - clean::Public => f.write_str("pub "), - clean::Inherited => Ok(()), - + let to_print = match self { + clean::Public => "pub ".to_owned(), + clean::Inherited => String::new(), clean::Visibility::Restricted(vis_did) => { // FIXME(camelid): This may not work correctly if `item_did` is a module. // However, rustdoc currently never displays a module's @@ -1103,38 +1151,41 @@ impl clean::Visibility { let parent_module = find_nearest_parent_module(tcx, item_did); if vis_did.index == CRATE_DEF_INDEX { - write!(f, "pub(crate) ") + "pub(crate) ".to_owned() } else if parent_module == Some(vis_did) { // `pub(in foo)` where `foo` is the parent module // is the same as no visibility modifier - Ok(()) + String::new() } else if parent_module .map(|parent| find_nearest_parent_module(tcx, parent)) .flatten() == Some(vis_did) { - write!(f, "pub(super) ") + "pub(super) ".to_owned() } else { - f.write_str("pub(")?; let path = tcx.def_path(vis_did); debug!("path={:?}", path); let first_name = path.data[0].data.get_opt_name().expect("modules are always named"); + // modified from `resolved_path()` to work with `DefPathData` + let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); + let anchor = anchor(vis_did, &last_name.as_str(), cache).to_string(); + + let mut s = "pub(".to_owned(); if path.data.len() != 1 || (first_name != kw::SelfLower && first_name != kw::Super) { - f.write_str("in ")?; + s.push_str("in "); } - // modified from `resolved_path()` to work with `DefPathData` - let last_name = path.data.last().unwrap().data.get_opt_name().unwrap(); for seg in &path.data[..path.data.len() - 1] { - write!(f, "{}::", seg.data.get_opt_name().unwrap())?; + s.push_str(&format!("{}::", seg.data.get_opt_name().unwrap())); } - let path = anchor(vis_did, &last_name.as_str()).to_string(); - write!(f, "{}) ", path) + s.push_str(&format!("{}) ", anchor)); + s } } - }) + }; + display_fn(move |f| f.write_str(&to_print)) } } @@ -1179,20 +1230,20 @@ impl PrintWithSpace for hir::Mutability { } impl clean::Import { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { display_fn(move |f| match self.kind { clean::ImportKind::Simple(name) => { if name == self.source.path.last() { - write!(f, "use {};", self.source.print()) + write!(f, "use {};", self.source.print(cache)) } else { - write!(f, "use {} as {};", self.source.print(), name) + write!(f, "use {} as {};", self.source.print(cache), name) } } clean::ImportKind::Glob => { if self.source.path.segments.is_empty() { write!(f, "use *;") } else { - write!(f, "use {}::*;", self.source.print()) + write!(f, "use {}::*;", self.source.print(cache)) } } }) @@ -1200,16 +1251,16 @@ impl clean::Import { } impl clean::ImportSource { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { display_fn(move |f| match self.did { - Some(did) => resolved_path(f, did, &self.path, true, false), + Some(did) => resolved_path(f, did, &self.path, true, false, cache), _ => { for seg in &self.path.segments[..self.path.segments.len() - 1] { write!(f, "{}::", seg.name)?; } let name = self.path.last_name(); if let hir::def::Res::PrimTy(p) = self.path.res { - primitive_link(f, PrimitiveType::from(p), &*name)?; + primitive_link(f, PrimitiveType::from(p), &*name, cache)?; } else { write!(f, "{}", name)?; } @@ -1220,23 +1271,23 @@ impl clean::ImportSource { } impl clean::TypeBinding { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { display_fn(move |f| { f.write_str(&*self.name.as_str())?; match self.kind { clean::TypeBindingKind::Equality { ref ty } => { if f.alternate() { - write!(f, " = {:#}", ty.print())?; + write!(f, " = {:#}", ty.print(cache))?; } else { - write!(f, " = {}", ty.print())?; + write!(f, " = {}", ty.print(cache))?; } } clean::TypeBindingKind::Constraint { ref bounds } => { if !bounds.is_empty() { if f.alternate() { - write!(f, ": {:#}", print_generic_bounds(bounds))?; + write!(f, ": {:#}", print_generic_bounds(bounds, cache))?; } else { - write!(f, ": {}", print_generic_bounds(bounds))?; + write!(f, ": {}", print_generic_bounds(bounds, cache))?; } } } @@ -1261,10 +1312,10 @@ crate fn print_default_space<'a>(v: bool) -> &'a str { } impl clean::GenericArg { - crate fn print(&self) -> impl fmt::Display + '_ { + crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b { display_fn(move |f| match self { clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(<.print(), f), - clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(), f), + clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache), f), clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(), f), }) } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 497cbbb4250a6..a2fae03d87a2d 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -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_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 // has since been learned. - for &(did, ref item) in orphan_impl_items { - if let Some(&(ref fqp, _)) = paths.get(&did) { - search_index.push(IndexItem { + for &(did, ref item) in &cache.orphan_impl_items { + if let Some(&(ref fqp, _)) = cache.paths.get(&did) { + cache.search_index.push(IndexItem { ty: item.type_(), name: item.name.unwrap().to_string(), path: fqp[..fqp.len() - 1].join("::"), desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)), parent: Some(did), parent_idx: None, - search_type: get_index_search_type(&item), + search_type: get_index_search_type(&item, cache), }); for alias in item.attrs.get_doc_aliases() { - aliases + cache + .aliases .entry(alias.to_lowercase()) .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, // and prune the paths that do not appear in the index. let mut lastpath = String::new(); @@ -164,7 +164,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { ) } -crate fn get_index_search_type(item: &clean::Item) -> Option { +crate fn get_index_search_type(item: &clean::Item, cache: &Cache) -> Option { let (all_types, ret_types) = match *item.kind { clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types), clean::MethodItem(ref m, _) => (&m.all_types, &m.ret_types), @@ -174,12 +174,12 @@ crate fn get_index_search_type(item: &clean::Item) -> Option>(); let output = if output.is_empty() { None } else { Some(output) }; @@ -187,12 +187,12 @@ crate fn get_index_search_type(item: &clean::Item) -> Option RenderType { +fn get_index_type(clean_type: &clean::Type, cache: &Cache) -> RenderType { RenderType { - ty: clean_type.def_id(), + ty: clean_type.def_id(cache), idx: None, 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 +216,14 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } -fn get_generics(clean_type: &clean::Type) -> Option> { +fn get_generics(clean_type: &clean::Type, cache: &Cache) -> Option> { clean_type.generics().and_then(|types| { let r = types .iter() .filter_map(|t| { get_index_type_name(t, false).map(|name| Generic { name: name.as_str().to_ascii_lowercase(), - defid: t.def_id(), + defid: t.def_id(cache), idx: None, }) }) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index ef45c98e40629..88e61403ddbe6 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -69,7 +69,7 @@ use crate::clean::{self, AttributesExt, GetDefId, RenderedLink, SelfTy, TypeKind use crate::config::{RenderInfo, RenderOptions}; use crate::docfs::{DocFS, PathError}; use crate::error::Error; -use crate::formats::cache::{cache, Cache}; +use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::formats::{AssocItemRender, FormatRenderer, Impl, RenderMode}; use crate::html::escape::Escape; @@ -122,6 +122,7 @@ crate struct Context<'tcx> { /// Storage for the errors produced while generating documentation so they /// can be printed together at the end. crate errors: Rc>, + crate cache: Rc, } crate struct SharedContext<'tcx> { @@ -392,8 +393,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { options: RenderOptions, _render_info: RenderInfo, edition: Edition, - cache: &mut Cache, - tcx: TyCtxt<'tcx>, + mut cache: Cache, + tcx: ty::TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error> { // need to save a copy of the options for rendering the index page let md_opts = options.clone(); @@ -503,9 +504,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { krate = sources::render(&dst, &mut scx, krate)?; // Build our search index - let index = build_index(&krate, cache); + let index = build_index(&krate, &mut cache); - let cache = Arc::new(cache); let mut cx = Context { current: Vec::new(), dst, @@ -515,13 +515,14 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { shared: Arc::new(scx), all: Rc::new(RefCell::new(AllTypes::new())), errors: Rc::new(receiver), + cache: Rc::new(cache), }; CURRENT_DEPTH.with(|s| s.set(0)); // Write shared runs within a flock; disable thread dispatching of IO temporarily. Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); - write_shared(&cx, &krate, index, &md_opts, &cache)?; + write_shared(&cx, &krate, index, &md_opts)?; Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); Ok((cx, krate)) } @@ -529,7 +530,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { fn after_krate( &mut self, krate: &clean::Crate, - cache: &Cache, diag: &rustc_errors::Handler, ) -> Result<(), Error> { let final_file = self.dst.join(&*krate.name.as_str()).join("all.html"); @@ -551,7 +551,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { extra_scripts: &[], static_extra_scripts: &[], }; - let sidebar = if let Some(ref version) = cache.crate_version { + let sidebar = if let Some(ref version) = self.cache.crate_version { format!( "

Crate {}

\
\ @@ -605,12 +605,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } } - fn mod_item_in( - &mut self, - item: &clean::Item, - item_name: &str, - cache: &Cache, - ) -> Result<(), Error> { + fn mod_item_in(&mut self, item: &clean::Item, item_name: &str) -> Result<(), Error> { // Stripped modules survive the rustdoc passes (i.e., `strip-private`) // if they contain impls for public types. These modules can also // contain items such as publicly re-exported structures. @@ -627,7 +622,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { info!("Recursing into {}", self.dst.display()); - let buf = self.render_item(item, false, cache); + let buf = self.render_item(item, false); // buf will be empty if the module is stripped and there is no redirect for it if !buf.is_empty() { self.shared.ensure_dir(&self.dst)?; @@ -658,7 +653,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { Ok(()) } - fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> { + fn item(&mut self, item: clean::Item) -> Result<(), Error> { // Stripped modules survive the rustdoc passes (i.e., `strip-private`) // if they contain impls for public types. These modules can also // contain items such as publicly re-exported structures. @@ -670,7 +665,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { self.render_redirect_pages = item.is_stripped(); } - let buf = self.render_item(&item, true, cache); + let buf = self.render_item(&item, true); // buf will be empty if the item is stripped and there is no redirect for it if !buf.is_empty() { let name = item.name.as_ref().unwrap(); @@ -694,6 +689,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { } Ok(()) } + + fn cache(&self) -> &Cache { + &self.cache + } } fn write_shared( @@ -701,7 +700,6 @@ fn write_shared( krate: &clean::Crate, search_index: String, options: &RenderOptions, - cache: &Cache, ) -> Result<(), Error> { // Write out the shared files. Note that these are shared among all rustdoc // docs placed in the output directory, so this needs to be a synchronized @@ -1107,7 +1105,7 @@ themePicker.onblur = handleThemeButtonsBlur; // Update the list of all implementors for traits let dst = cx.dst.join("implementors"); - for (&did, imps) in &cache.implementors { + for (&did, imps) in &cx.cache.implementors { // Private modules can leak through to this phase of rustdoc, which // could contain implementations for otherwise private types. In some // rare cases we could find an implementation for an item which wasn't @@ -1115,9 +1113,9 @@ themePicker.onblur = handleThemeButtonsBlur; // // FIXME: this is a vague explanation for why this can't be a `get`, in // theory it should be... - let &(ref remote_path, remote_item_type) = match cache.paths.get(&did) { + let &(ref remote_path, remote_item_type) = match cx.cache.paths.get(&did) { Some(p) => p, - None => match cache.external_paths.get(&did) { + None => match cx.cache.external_paths.get(&did) { Some(p) => p, None => continue, }, @@ -1144,9 +1142,9 @@ themePicker.onblur = handleThemeButtonsBlur; None } else { Some(Implementor { - text: imp.inner_impl().print().to_string(), + text: imp.inner_impl().print(cx.cache()).to_string(), synthetic: imp.inner_impl().synthetic, - types: collect_paths_for_type(imp.inner_impl().for_.clone()), + types: collect_paths_for_type(imp.inner_impl().for_.clone(), &cx.cache), }) } }) @@ -1155,7 +1153,7 @@ themePicker.onblur = handleThemeButtonsBlur; // Only create a js file if we have impls to add to it. If the trait is // documented locally though we always create the file to avoid dead // links. - if implementors.is_empty() && !cache.paths.contains_key(&did) { + if implementors.is_empty() && !cx.cache.paths.contains_key(&did) { continue; } @@ -1214,8 +1212,8 @@ fn write_minify( } } -fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Cache) { - if let Some(l) = cx.src_href(item, cache) { +fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { + if let Some(l) = cx.src_href(item) { write!( buf, "[src]", @@ -1537,7 +1535,7 @@ impl Context<'_> { "../".repeat(self.current.len()) } - fn render_item(&self, it: &clean::Item, pushname: bool, cache: &Cache) -> String { + fn render_item(&self, it: &clean::Item, pushname: bool) -> String { // A little unfortunate that this is done like this, but it sure // does make formatting *a lot* nicer. CURRENT_DEPTH.with(|slot| { @@ -1590,13 +1588,13 @@ impl Context<'_> { layout::render( &self.shared.layout, &page, - |buf: &mut _| print_sidebar(self, it, buf, cache), - |buf: &mut _| print_item(self, it, buf, cache), + |buf: &mut _| print_sidebar(self, it, buf), + |buf: &mut _| print_item(self, it, buf), &self.shared.style_files, ) } else { let mut url = self.root_path(); - if let Some(&(ref names, ty)) = cache.paths.get(&it.def_id) { + if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id) { for name in &names[..names.len() - 1] { url.push_str(name); url.push('/'); @@ -1647,7 +1645,7 @@ impl Context<'_> { /// If `None` is returned, then a source link couldn't be generated. This /// may happen, for example, with externally inlined items where the source /// of their crate documentation isn't known. - fn src_href(&self, item: &clean::Item, cache: &Cache) -> Option { + fn src_href(&self, item: &clean::Item) -> Option { let mut root = self.root_path(); let mut path = String::new(); let cnum = item.source.cnum(self.sess()); @@ -1667,7 +1665,7 @@ impl Context<'_> { return None; } } else { - let (krate, src_root) = match *cache.extern_locations.get(&cnum)? { + let (krate, src_root) = match *self.cache.extern_locations.get(&cnum)? { (name, ref src, ExternalLocation::Local) => (name, src), (name, ref src, ExternalLocation::Remote(ref s)) => { root = s.to_string(); @@ -1710,7 +1708,7 @@ where write!(w, "
") } -fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Cache) { +fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) { debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top write!(buf, "

"); @@ -1738,7 +1736,7 @@ fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Ca // this page, and this link will be auto-clicked. The `id` attribute is // used to find the link to auto-click. if cx.shared.include_sources && !item.is_primitive() { - write_srclink(cx, item, buf, cache); + write_srclink(cx, item, buf); } write!(buf, ""); // out-of-band @@ -1797,20 +1795,20 @@ fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Ca clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f) => { item_function(buf, cx, item, f) } - clean::TraitItem(ref t) => item_trait(buf, cx, item, t, cache), - clean::StructItem(ref s) => item_struct(buf, cx, item, s, cache), - clean::UnionItem(ref s) => item_union(buf, cx, item, s, cache), - clean::EnumItem(ref e) => item_enum(buf, cx, item, e, cache), - clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t, cache), + clean::TraitItem(ref t) => item_trait(buf, cx, item, t), + clean::StructItem(ref s) => item_struct(buf, cx, item, s), + clean::UnionItem(ref s) => item_union(buf, cx, item, s), + clean::EnumItem(ref e) => item_enum(buf, cx, item, e), + clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t), clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), - clean::PrimitiveItem(_) => item_primitive(buf, cx, item, cache), + clean::PrimitiveItem(_) => item_primitive(buf, cx, item), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i), clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), - clean::ForeignTypeItem => item_foreign_type(buf, cx, item, cache), + clean::ForeignTypeItem => item_foreign_type(buf, cx, item), clean::KeywordItem(_) => item_keyword(buf, cx, item), - clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e, cache), - clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta, cache), + clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e), + clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta), _ => { // We don't generate pages for any other type. unreachable!(); @@ -1884,10 +1882,11 @@ fn document_short( return; } if let Some(s) = item.doc_value() { - let mut summary_html = MarkdownSummaryLine(&s, &item.links()).into_string(); + let mut summary_html = MarkdownSummaryLine(&s, &item.links(&cx.cache)).into_string(); if s.contains('\n') { - let link = format!(r#" Read more"#, naive_assoc_href(item, link)); + let link = + format!(r#" Read more"#, naive_assoc_href(item, link, cx.cache())); if let Some(idx) = summary_html.rfind("

") { summary_html.insert_str(idx, &link); @@ -1922,7 +1921,7 @@ fn document_full( ) { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); - render_markdown(w, cx, &*s, item.links(), prefix, is_hidden); + render_markdown(w, cx, &*s, item.links(&cx.cache), prefix, is_hidden); } else if !prefix.is_empty() { write!( w, @@ -2161,15 +2160,15 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl Some(ref src) => write!( w, "{}extern crate {} as {};", - myitem.visibility.print_with_space(cx.tcx(), myitem.def_id), - anchor(myitem.def_id, &*src.as_str()), + myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()), + anchor(myitem.def_id, &*src.as_str(), cx.cache()), name ), None => write!( w, "{}extern crate {};", - myitem.visibility.print_with_space(cx.tcx(), myitem.def_id), - anchor(myitem.def_id, &*name.as_str()) + myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()), + anchor(myitem.def_id, &*name.as_str(), cx.cache()) ), } write!(w, ""); @@ -2179,8 +2178,8 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl write!( w, "{}{}", - myitem.visibility.print_with_space(cx.tcx(), myitem.def_id), - import.print() + myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()), + import.print(cx.cache()) ); } @@ -2211,7 +2210,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl ", name = *myitem.name.as_ref().unwrap(), stab_tags = extra_info_tags(myitem, item, cx.tcx()), - docs = MarkdownSummaryLine(&doc_value, &myitem.links()).into_string(), + docs = MarkdownSummaryLine(&doc_value, &myitem.links(&cx.cache)).into_string(), class = myitem.type_(), add = add, stab = stab.unwrap_or_else(String::new), @@ -2396,9 +2395,9 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean:: write!( w, "{vis}const {name}: {typ}", - vis = it.visibility.print_with_space(cx.tcx(), it.def_id), + vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), name = it.name.as_ref().unwrap(), - typ = c.type_.print(), + typ = c.type_.print(cx.cache()), ); if c.value.is_some() || c.is_literal { @@ -2430,10 +2429,10 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St write!( w, "{vis}static {mutability}{name}: {typ}", - vis = it.visibility.print_with_space(cx.tcx(), it.def_id), + vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), mutability = s.mutability.print_with_space(), name = it.name.as_ref().unwrap(), - typ = s.type_.print() + typ = s.type_.print(cx.cache()) ); document(w, cx, it, None) } @@ -2441,13 +2440,13 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { let header_len = format!( "{}{}{}{}{:#}fn {}{:#}", - it.visibility.print_with_space(cx.tcx(), it.def_id), + it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), f.header.constness.print_with_space(), f.header.asyncness.print_with_space(), f.header.unsafety.print_with_space(), print_abi_with_space(f.header.abi), it.name.as_ref().unwrap(), - f.generics.print() + f.generics.print(cx.cache()) ) .len(); write!(w, "
");
@@ -2456,17 +2455,18 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
          {name}{generics}{decl}{spotlight}{where_clause}
", - vis = it.visibility.print_with_space(cx.tcx(), it.def_id), + vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), constness = f.header.constness.print_with_space(), asyncness = f.header.asyncness.print_with_space(), unsafety = f.header.unsafety.print_with_space(), abi = print_abi_with_space(f.header.abi), name = it.name.as_ref().unwrap(), - generics = f.generics.print(), - where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true }, + generics = f.generics.print(cx.cache()), + where_clause = + WhereClause { gens: &f.generics, indent: 0, end_newline: true }.print(cx.cache()), decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness } - .print(), - spotlight = spotlight_decl(&f.decl), + .print(cx.cache()), + spotlight = spotlight_decl(&f.decl, &cx.cache), ); document(w, cx, it, None) } @@ -2478,7 +2478,6 @@ fn render_implementor( w: &mut Buffer, implementor_dups: &FxHashMap, aliases: &[String], - cache: &Cache, ) { // If there's already another implementor that has the same abbridged name, use the // full path, for example in `std::iter::ExactSizeIterator` @@ -2504,7 +2503,6 @@ fn render_implementor( false, false, aliases, - cache, ); } @@ -2513,12 +2511,11 @@ fn render_impls( w: &mut Buffer, traits: &[&&Impl], containing_item: &clean::Item, - cache: &Cache, ) { let mut impls = traits .iter() .map(|i| { - let did = i.trait_did().unwrap(); + let did = i.trait_did(cx.cache()).unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; render_impl( @@ -2535,7 +2532,6 @@ fn render_impls( false, true, &[], - cache, ); buffer.into_inner() }) @@ -2544,7 +2540,7 @@ fn render_impls( w.write_str(&impls.join("")); } -fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String { +fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) -> String { let mut bounds = String::new(); if !t_bounds.is_empty() { if !trait_alias { @@ -2554,22 +2550,22 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String { if i > 0 { bounds.push_str(" + "); } - bounds.push_str(&p.print().to_string()); + bounds.push_str(&p.print(cache).to_string()); } } bounds } -fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering { - let lhs = format!("{}", lhs.inner_impl().print()); - let rhs = format!("{}", rhs.inner_impl().print()); +fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cache: &Cache) -> Ordering { + let lhs = format!("{}", lhs.inner_impl().print(cache)); + let rhs = format!("{}", rhs.inner_impl().print(cache)); // lhs and rhs are formatted as HTML, which may be unnecessary compare_names(&lhs, &rhs) } -fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait, cache: &Cache) { - let bounds = bounds(&t.bounds, false); +fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) { + let bounds = bounds(&t.bounds, false, cx.cache()); let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>(); let required = t.items.iter().filter(|m| m.is_ty_method()).collect::>(); @@ -2582,16 +2578,20 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra write!( w, "{}{}{}trait {}{}{}", - it.visibility.print_with_space(cx.tcx(), it.def_id), + it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), t.unsafety.print_with_space(), if t.is_auto { "auto " } else { "" }, it.name.as_ref().unwrap(), - t.generics.print(), + t.generics.print(cx.cache()), bounds ); if !t.generics.where_predicates.is_empty() { - write!(w, "{}", WhereClause { gens: &t.generics, indent: 0, end_newline: true }); + write!( + w, + "{}", + WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()) + ); } else { write!(w, " "); } @@ -2664,13 +2664,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra write!(w, "{}Loading content...", extra_content) } - fn trait_item( - w: &mut Buffer, - cx: &Context<'_>, - m: &clean::Item, - t: &clean::Item, - cache: &Cache, - ) { + fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) { let name = m.name.as_ref().unwrap(); info!("Documenting {} on {:?}", name, t.name); let item_type = m.type_(); @@ -2679,7 +2673,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl, cx); write!(w, "
"); render_stability_since(w, m, t, cx.tcx()); - write_srclink(cx, m, w, cache); + write_srclink(cx, m, w); write!(w, "

"); document(w, cx, m, Some(t)); } @@ -2692,7 +2686,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra "
", ); for t in types { - trait_item(w, cx, t, it, cache); + trait_item(w, cx, t, it); } write_loading_content(w, "
"); } @@ -2705,7 +2699,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra "
", ); for t in consts { - trait_item(w, cx, t, it, cache); + trait_item(w, cx, t, it); } write_loading_content(w, "
"); } @@ -2719,7 +2713,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra "
", ); for m in required { - trait_item(w, cx, m, it, cache); + trait_item(w, cx, m, it); } write_loading_content(w, "
"); } @@ -2731,15 +2725,15 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra "
", ); for m in provided { - trait_item(w, cx, m, it, cache); + trait_item(w, cx, m, it); } write_loading_content(w, "
"); } // If there are methods directly on this trait object, render them here. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache); + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); - if let Some(implementors) = cache.implementors.get(&it.def_id) { + if let Some(implementors) = cx.cache.implementors.get(&it.def_id) { // The DefId is for the first Type found with that name. The bool is // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap = FxHashMap::default(); @@ -2761,14 +2755,14 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } let (local, foreign) = implementors.iter().partition::, _>(|i| { - i.inner_impl().for_.def_id().map_or(true, |d| cache.paths.contains_key(&d)) + i.inner_impl().for_.def_id(cx.cache()).map_or(true, |d| cx.cache.paths.contains_key(&d)) }); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter().partition(|i| i.inner_impl().synthetic); - synthetic.sort_by(compare_impl); - concrete.sort_by(compare_impl); + synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache())); + concrete.sort_by(|a, b| compare_impl(a, b, cx.cache())); if !foreign.is_empty() { write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", ""); @@ -2792,7 +2786,6 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra true, false, &[], - cache, ); } write_loading_content(w, ""); @@ -2805,7 +2798,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra "
", ); for implementor in concrete { - render_implementor(cx, implementor, it, w, &implementor_dups, &[], cache); + render_implementor(cx, implementor, it, w, &implementor_dups, &[]); } write_loading_content(w, "
"); @@ -2823,8 +2816,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra it, w, &implementor_dups, - &collect_paths_for_type(implementor.inner_impl().for_.clone()), - cache, + &collect_paths_for_type(implementor.inner_impl().for_.clone(), &cx.cache), ); } write_loading_content(w, ""); @@ -2860,7 +2852,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra path = if it.def_id.is_local() { cx.current.join("/") } else { - let (ref path, _) = cache.external_paths[&it.def_id]; + let (ref path, _) = cx.cache.external_paths[&it.def_id]; path[..path.len() - 1].join("/") }, ty = it.type_(), @@ -2868,7 +2860,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra ); } -fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String { +fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cache: &Cache) -> String { use crate::formats::item_type::ItemType::*; let name = it.name.as_ref().unwrap(); @@ -2882,7 +2874,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String { AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id), AssocItemLink::Anchor(None) => anchor, AssocItemLink::GotoSource(did, _) => { - href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) + href(did, cache).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor) } } } @@ -2900,10 +2892,10 @@ fn assoc_const( w, "{}{}const {}: {}", extra, - it.visibility.print_with_space(cx.tcx(), it.def_id), - naive_assoc_href(it, link), + it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), + naive_assoc_href(it, link, cx.cache()), it.name.as_ref().unwrap(), - ty.print() + ty.print(cx.cache()) ); } @@ -2914,19 +2906,20 @@ fn assoc_type( default: Option<&clean::Type>, link: AssocItemLink<'_>, extra: &str, + cache: &Cache, ) { write!( w, "{}type {}", extra, - naive_assoc_href(it, link), + naive_assoc_href(it, link, cache), it.name.as_ref().unwrap() ); if !bounds.is_empty() { - write!(w, ": {}", print_generic_bounds(bounds)) + write!(w, ": {}", print_generic_bounds(bounds, cache)) } if let Some(default) = default { - write!(w, " = {}", default.print()) + write!(w, " = {}", default.print(cache)) } } @@ -3005,19 +2998,19 @@ fn render_assoc_item( ItemType::TyMethod }; - href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) + href(did, cx.cache()).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) } }; let mut header_len = format!( "{}{}{}{}{}{:#}fn {}{:#}", - meth.visibility.print_with_space(cx.tcx(), meth.def_id), + meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()), header.constness.print_with_space(), header.asyncness.print_with_space(), header.unsafety.print_with_space(), print_default_space(meth.is_default()), print_abi_with_space(header.abi), name, - g.print() + g.print(cx.cache()) ) .len(); let (indent, end_newline) = if parent == ItemType::Trait { @@ -3032,7 +3025,7 @@ fn render_assoc_item( "{}{}{}{}{}{}{}fn {name}\ {generics}{decl}{spotlight}{where_clause}", if parent == ItemType::Trait { " " } else { "" }, - meth.visibility.print_with_space(cx.tcx(), meth.def_id), + meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()), header.constness.print_with_space(), header.asyncness.print_with_space(), header.unsafety.print_with_space(), @@ -3040,10 +3033,11 @@ fn render_assoc_item( print_abi_with_space(header.abi), href = href, name = name, - generics = g.print(), - decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }.print(), - spotlight = spotlight_decl(&d), - where_clause = WhereClause { gens: g, indent, end_newline } + generics = g.print(cx.cache()), + decl = Function { decl: d, header_len, indent, asyncness: header.asyncness } + .print(cx.cache()), + spotlight = spotlight_decl(&d, cx.cache()), + where_clause = WhereClause { gens: g, indent, end_newline }.print(cx.cache()) ) } match *item.kind { @@ -3070,18 +3064,13 @@ fn render_assoc_item( default.as_ref(), link, if parent == ItemType::Trait { " " } else { "" }, + cx.cache(), ), _ => panic!("render_assoc_item called on non-associated-item"), } } -fn item_struct( - w: &mut Buffer, - cx: &Context<'_>, - it: &clean::Item, - s: &clean::Struct, - cache: &Cache, -) { +fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) { wrap_into_docblock(w, |w| { write!(w, "
");
         render_attributes(w, it, true);
@@ -3122,16 +3111,16 @@ fn item_struct(
                     item_type = ItemType::StructField,
                     id = id,
                     name = field.name.as_ref().unwrap(),
-                    ty = ty.print()
+                    ty = ty.print(cx.cache())
                 );
                 document(w, cx, field, Some(it));
             }
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union, cache: &Cache) {
+fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
     wrap_into_docblock(w, |w| {
         write!(w, "
");
         render_attributes(w, it, true);
@@ -3166,7 +3155,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
                 id = id,
                 name = name,
                 shortty = ItemType::StructField,
-                ty = ty.print()
+                ty = ty.print(cx.cache())
             );
             if let Some(stability_class) = field.stability_class(cx.tcx()) {
                 write!(w, "", stab = stability_class);
@@ -3174,20 +3163,20 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
             document(w, cx, field, Some(it));
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
-fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum, cache: &Cache) {
+fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
     wrap_into_docblock(w, |w| {
         write!(w, "
");
         render_attributes(w, it, true);
         write!(
             w,
             "{}enum {}{}{}",
-            it.visibility.print_with_space(cx.tcx(), it.def_id),
+            it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
             it.name.as_ref().unwrap(),
-            e.generics.print(),
-            WhereClause { gens: &e.generics, indent: 0, end_newline: true }
+            e.generics.print(cx.cache()),
+            WhereClause { gens: &e.generics, indent: 0, end_newline: true }.print(cx.cache())
         );
         if e.variants.is_empty() && !e.variants_stripped {
             write!(w, " {{}}");
@@ -3205,7 +3194,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                                 if i > 0 {
                                     write!(w, ", ")
                                 }
-                                write!(w, "{}", ty.print());
+                                write!(w, "{}", ty.print(cx.cache()));
                             }
                             write!(w, ")");
                         }
@@ -3252,7 +3241,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     if i > 0 {
                         write!(w, ", ");
                     }
-                    write!(w, "{}", ty.print());
+                    write!(w, "{}", ty.print(cx.cache()));
                 }
                 write!(w, ")");
             }
@@ -3289,7 +3278,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                              ",
                             id = id,
                             f = field.name.as_ref().unwrap(),
-                            t = ty.print()
+                            t = ty.print(cx.cache())
                         );
                         document(w, cx, field, Some(variant));
                     }
@@ -3299,7 +3288,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
             render_stability_since(w, variant, it, cx.tcx());
         }
     }
-    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
+    render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
 const ALLOWED_ATTRIBUTES: &[Symbol] = &[
@@ -3357,17 +3346,21 @@ fn render_struct(
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(cx.tcx(), it.def_id),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
         if structhead { "struct " } else { "" },
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
-        write!(w, "{}", g.print())
+        write!(w, "{}", g.print(cx.cache()))
     }
     match ty {
         CtorKind::Fictive => {
             if let Some(g) = g {
-                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true })
+                write!(
+                    w,
+                    "{}",
+                    WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache())
+                )
             }
             let mut has_visible_fields = false;
             write!(w, " {{");
@@ -3377,9 +3370,9 @@ fn render_struct(
                         w,
                         "\n{}    {}{}: {},",
                         tab,
-                        field.visibility.print_with_space(cx.tcx(), field.def_id),
+                        field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
                         field.name.as_ref().unwrap(),
-                        ty.print()
+                        ty.print(cx.cache())
                     );
                     has_visible_fields = true;
                 }
@@ -3409,8 +3402,8 @@ fn render_struct(
                         write!(
                             w,
                             "{}{}",
-                            field.visibility.print_with_space(cx.tcx(), field.def_id),
-                            ty.print()
+                            field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
+                            ty.print(cx.cache())
                         )
                     }
                     _ => unreachable!(),
@@ -3418,14 +3411,22 @@ fn render_struct(
             }
             write!(w, ")");
             if let Some(g) = g {
-                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: false })
+                write!(
+                    w,
+                    "{}",
+                    WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
+                )
             }
             write!(w, ";");
         }
         CtorKind::Const => {
             // Needed for PhantomData.
             if let Some(g) = g {
-                write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: false })
+                write!(
+                    w,
+                    "{}",
+                    WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
+                )
             }
             write!(w, ";");
         }
@@ -3444,13 +3445,13 @@ fn render_union(
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(cx.tcx(), it.def_id),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
         if structhead { "union " } else { "" },
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
-        write!(w, "{}", g.print());
-        write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true });
+        write!(w, "{}", g.print(cx.cache()));
+        write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache()));
     }
 
     write!(w, " {{\n{}", tab);
@@ -3459,9 +3460,9 @@ fn render_union(
             write!(
                 w,
                 "    {}{}: {},\n{}",
-                field.visibility.print_with_space(cx.tcx(), field.def_id),
+                field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
                 field.name.as_ref().unwrap(),
-                ty.print(),
+                ty.print(cx.cache()),
                 tab
             );
         }
@@ -3494,10 +3495,9 @@ fn render_assoc_items(
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
-    cache: &Cache,
 ) {
     info!("Documenting associated items of {:?}", containing_item.name);
-    let v = match cache.impls.get(&it) {
+    let v = match cx.cache.impls.get(&it) {
         Some(v) => v,
         None => return,
     };
@@ -3514,9 +3514,11 @@ fn render_assoc_items(
                 RenderMode::Normal
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
-                let id =
-                    cx.derive_id(small_url_encode(&format!("deref-methods-{:#}", type_.print())));
-                cx.deref_id_map.borrow_mut().insert(type_.def_id().unwrap(), id.clone());
+                let id = cx.derive_id(small_url_encode(&format!(
+                    "deref-methods-{:#}",
+                    type_.print(cx.cache())
+                )));
+                cx.deref_id_map.borrow_mut().insert(type_.def_id(cx.cache()).unwrap(), id.clone());
                 write!(
                     w,
                     "

\ @@ -3524,8 +3526,8 @@ fn render_assoc_items( \

", id = id, - trait_ = trait_.print(), - type_ = type_.print(), + trait_ = trait_.print(cx.cache()), + type_ = type_.print(cx.cache()), ); RenderMode::ForDeref { mut_: deref_mut_ } } @@ -3545,17 +3547,18 @@ fn render_assoc_items( false, true, &[], - cache, ); } } if !traits.is_empty() { - let deref_impl = - traits.iter().find(|t| t.inner_impl().trait_.def_id() == cache.deref_trait_did); + let deref_impl = traits + .iter() + .find(|t| t.inner_impl().trait_.def_id(cx.cache()) == cx.cache.deref_trait_did); if let Some(impl_) = deref_impl { - let has_deref_mut = - traits.iter().any(|t| t.inner_impl().trait_.def_id() == cache.deref_mut_trait_did); - render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, cache); + let has_deref_mut = traits + .iter() + .any(|t| t.inner_impl().trait_.def_id(cx.cache()) == cx.cache.deref_mut_trait_did); + render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } // If we were already one level into rendering deref methods, we don't want to render @@ -3570,7 +3573,7 @@ fn render_assoc_items( concrete.into_iter().partition(|t| t.inner_impl().blanket_impl.is_some()); let mut impls = Buffer::empty_from(&w); - render_impls(cx, &mut impls, &concrete, containing_item, cache); + render_impls(cx, &mut impls, &concrete, containing_item); let impls = impls.into_inner(); if !impls.is_empty() { write!( @@ -3592,7 +3595,7 @@ fn render_assoc_items( \
" ); - render_impls(cx, w, &synthetic, containing_item, cache); + render_impls(cx, w, &synthetic, containing_item); write!(w, "
"); } @@ -3605,7 +3608,7 @@ fn render_assoc_items( \
" ); - render_impls(cx, w, &blanket_impl, containing_item, cache); + render_impls(cx, w, &blanket_impl, containing_item); write!(w, "
"); } } @@ -3617,7 +3620,6 @@ fn render_deref_methods( impl_: &Impl, container_item: &clean::Item, deref_mut: bool, - cache: &Cache, ) { let deref_type = impl_.inner_impl().trait_.as_ref().unwrap(); let (target, real_target) = impl_ @@ -3634,25 +3636,25 @@ fn render_deref_methods( .expect("Expected associated type binding"); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; - if let Some(did) = target.def_id() { - if let Some(type_did) = impl_.inner_impl().for_.def_id() { + if let Some(did) = target.def_id(cx.cache()) { + if let Some(type_did) = impl_.inner_impl().for_.def_id(cx.cache()) { // `impl Deref for S` if did == type_did { // Avoid infinite cycles return; } } - render_assoc_items(w, cx, container_item, did, what, cache); + render_assoc_items(w, cx, container_item, did, what); } else { if let Some(prim) = target.primitive_type() { - if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items(w, cx, container_item, did, what, cache); + if let Some(&did) = cx.cache.primitive_locations.get(&prim) { + render_assoc_items(w, cx, container_item, did, what); } } } } -fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { +fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bool { let self_type_opt = match *item.kind { clean::MethodItem(ref method, _) => method.decl.self_type(), clean::TyMethodItem(ref method) => method.decl.self_type(), @@ -3666,7 +3668,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { (mutability == Mutability::Mut, false, false) } SelfTy::SelfExplicit(clean::ResolvedPath { did, .. }) => { - (false, Some(did) == cache().owned_box_did, false) + (false, Some(did) == cache.owned_box_did, false) } SelfTy::SelfValue => (false, false, true), _ => (false, false, false), @@ -3678,31 +3680,30 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { } } -fn spotlight_decl(decl: &clean::FnDecl) -> String { +fn spotlight_decl(decl: &clean::FnDecl, c: &Cache) -> String { let mut out = Buffer::html(); let mut trait_ = String::new(); - if let Some(did) = decl.output.def_id() { - let c = cache(); + if let Some(did) = decl.output.def_id(c) { if let Some(impls) = c.impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); - if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) { + if impl_.trait_.def_id(c).map_or(false, |d| c.traits[&d].is_spotlight) { if out.is_empty() { out.push_str(&format!( "

Notable traits for {}

\ ", - impl_.for_.print() + impl_.for_.print(c) )); - trait_.push_str(&impl_.for_.print().to_string()); + trait_.push_str(&impl_.for_.print(c).to_string()); } //use the "where" class here to make it small out.push_str(&format!( "{}", - impl_.print() + impl_.print(c) )); - let t_did = impl_.trait_.def_id().unwrap(); + let t_did = impl_.trait_.def_id(c).unwrap(); for it in &impl_.items { if let clean::TypedefItem(ref tydef, _) = *it.kind { out.push_str(" "); @@ -3713,6 +3714,7 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String { Some(&tydef.type_), AssocItemLink::GotoSource(t_did, &FxHashSet::default()), "", + c, ); out.push_str(";"); } @@ -3750,18 +3752,17 @@ fn render_impl( // This argument is used to reference same type with different paths to avoid duplication // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], - cache: &Cache, ) { - let traits = &cache.traits; - let trait_ = i.trait_did().map(|did| &traits[&did]); + let traits = &cx.cache.traits; + let trait_ = i.trait_did(cx.cache()).map(|did| &traits[&did]); if render_mode == RenderMode::Normal { let id = cx.derive_id(match i.inner_impl().trait_ { Some(ref t) => { if is_on_foreign_type { - get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t) + get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx.cache()) } else { - format!("impl-{}", small_url_encode(&format!("{:#}", t.print()))) + format!("impl-{}", small_url_encode(&format!("{:#}", t.print(cx.cache())))) } } None => "impl".to_string(), @@ -3773,12 +3774,20 @@ fn render_impl( }; if let Some(use_absolute) = use_absolute { write!(w, "

", id, aliases); - fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute); + fmt_impl_for_trait_page(&i.inner_impl(), w, use_absolute, cx.cache()); if show_def_docs { for it in &i.inner_impl().items { if let clean::TypedefItem(ref tydef, _) = *it.kind { write!(w, " "); - assoc_type(w, it, &[], Some(&tydef.type_), AssocItemLink::Anchor(None), ""); + assoc_type( + w, + it, + &[], + Some(&tydef.type_), + AssocItemLink::Anchor(None), + "", + cx.cache(), + ); write!(w, ";"); } } @@ -3790,7 +3799,7 @@ fn render_impl( "

{}", id, aliases, - i.inner_impl().print() + i.inner_impl().print(cx.cache()) ); } write!(w, "", id); @@ -3801,7 +3810,7 @@ fn render_impl( outer_version, outer_const_version, ); - write_srclink(cx, &i.impl_item, w, cache); + write_srclink(cx, &i.impl_item, w); write!(w, "

"); if trait_.is_some() { @@ -3817,7 +3826,7 @@ fn render_impl( "
{}
", Markdown( &*dox, - &i.impl_item.links(), + &i.impl_item.links(&cx.cache), &mut ids, cx.shared.codes, cx.shared.edition, @@ -3840,14 +3849,15 @@ fn render_impl( outer_const_version: Option<&str>, trait_: Option<&clean::Trait>, show_def_docs: bool, - cache: &Cache, ) { let item_type = item.type_(); let name = item.name.as_ref().unwrap(); let render_method_item = match render_mode { RenderMode::Normal => true, - RenderMode::ForDeref { mut_: deref_mut_ } => should_render_item(&item, deref_mut_), + RenderMode::ForDeref { mut_: deref_mut_ } => { + should_render_item(&item, deref_mut_, &cx.cache) + } }; let (is_hidden, extra_class) = @@ -3874,14 +3884,22 @@ fn render_impl( outer_version, outer_const_version, ); - write_srclink(cx, item, w, cache); + write_srclink(cx, item, w); write!(w, "

"); } } clean::TypedefItem(ref tydef, _) => { let id = cx.derive_id(format!("{}.{}", ItemType::AssocType, name)); write!(w, "

", id, item_type, extra_class); - assoc_type(w, item, &Vec::new(), Some(&tydef.type_), link.anchor(&id), ""); + assoc_type( + w, + item, + &Vec::new(), + Some(&tydef.type_), + link.anchor(&id), + "", + cx.cache(), + ); write!(w, "

"); } clean::AssocConstItem(ref ty, ref default) => { @@ -3896,13 +3914,13 @@ fn render_impl( outer_version, outer_const_version, ); - write_srclink(cx, item, w, cache); + write_srclink(cx, item, w); write!(w, ""); } clean::AssocTypeItem(ref bounds, ref default) => { let id = cx.derive_id(format!("{}.{}", item_type, name)); write!(w, "

", id, item_type, extra_class); - assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), ""); + assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "", cx.cache()); write!(w, "

"); } clean::StrippedItem(..) => return, @@ -3961,7 +3979,6 @@ fn render_impl( outer_const_version, trait_, show_def_docs, - cache, ); } @@ -3975,14 +3992,13 @@ fn render_impl( outer_version: Option<&str>, outer_const_version: Option<&str>, show_def_docs: bool, - cache: &Cache, ) { for trait_item in &t.items { let n = trait_item.name; if i.items.iter().any(|m| m.name == n) { continue; } - let did = i.trait_.as_ref().unwrap().def_id().unwrap(); + let did = i.trait_.as_ref().unwrap().def_id(cx.cache()).unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.provided_trait_methods); doc_impl_item( @@ -3997,7 +4013,6 @@ fn render_impl( outer_const_version, None, show_def_docs, - cache, ); } } @@ -4018,29 +4033,23 @@ fn render_impl( outer_version, outer_const_version, show_def_docs, - cache, ); } } write!(w, ""); } -fn item_opaque_ty( - w: &mut Buffer, - cx: &Context<'_>, - it: &clean::Item, - t: &clean::OpaqueTy, - cache: &Cache, -) { +fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { write!(w, "
");
     render_attributes(w, it, false);
     write!(
         w,
         "type {}{}{where_clause} = impl {bounds};
", it.name.as_ref().unwrap(), - t.generics.print(), - where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, - bounds = bounds(&t.bounds, false) + t.generics.print(cx.cache()), + where_clause = + WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()), + bounds = bounds(&t.bounds, false, cx.cache()) ); document(w, cx, it, None); @@ -4049,25 +4058,19 @@ fn item_opaque_ty( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn item_trait_alias( - w: &mut Buffer, - cx: &Context<'_>, - it: &clean::Item, - t: &clean::TraitAlias, - cache: &Cache, -) { +fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) { write!(w, "
");
     render_attributes(w, it, false);
     write!(
         w,
         "trait {}{}{} = {};
", it.name.as_ref().unwrap(), - t.generics.print(), - WhereClause { gens: &t.generics, indent: 0, end_newline: true }, - bounds(&t.bounds, true) + t.generics.print(cx.cache()), + WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()), + bounds(&t.bounds, true, cx.cache()) ); document(w, cx, it, None); @@ -4076,25 +4079,20 @@ fn item_trait_alias( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn item_typedef( - w: &mut Buffer, - cx: &Context<'_>, - it: &clean::Item, - t: &clean::Typedef, - cache: &Cache, -) { +fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { write!(w, "
");
     render_attributes(w, it, false);
     write!(
         w,
         "type {}{}{where_clause} = {type_};
", it.name.as_ref().unwrap(), - t.generics.print(), - where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, - type_ = t.type_.print() + t.generics.print(cx.cache()), + where_clause = + WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()), + type_ = t.type_.print(cx.cache()) ); document(w, cx, it, None); @@ -4103,25 +4101,25 @@ fn item_typedef( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache: &Cache) { +fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { writeln!(w, "
extern {{");
     render_attributes(w, it, false);
     write!(
         w,
         "    {}type {};\n}}
", - it.visibility.print_with_space(cx.tcx(), it.def_id), + it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()), it.name.as_ref().unwrap(), ); document(w, cx, it, None); - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer, cache: &Cache) { +fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) { let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 }; if it.is_struct() @@ -4156,7 +4154,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer, cache: } if it.is_crate() { - if let Some(ref version) = cache.crate_version { + if let Some(ref version) = cx.cache.crate_version { write!( buffer, "
\ @@ -4245,12 +4243,13 @@ fn get_methods( for_deref: bool, used_links: &mut FxHashSet, deref_mut: bool, + cache: &Cache, ) -> Vec { i.items .iter() .filter_map(|item| match item.name { Some(ref name) if !name.is_empty() && item.is_method() => { - if !for_deref || should_render_item(item, deref_mut) { + if !for_deref || should_render_item(item, deref_mut, cache) { Some(format!( "{}", get_next_url(used_links, format!("method.{}", name)), @@ -4283,8 +4282,7 @@ fn small_url_encode(s: &str) -> String { fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String { let mut out = String::new(); - let c = cache(); - if let Some(v) = c.impls.get(&it.def_id) { + if let Some(v) = cx.cache.impls.get(&it.def_id) { let mut used_links = FxHashSet::default(); { @@ -4292,7 +4290,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String { let mut ret = v .iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false)) + .flat_map(move |i| { + get_methods(i.inner_impl(), false, used_links_bor, false, &cx.cache) + }) .collect::>(); if !ret.is_empty() { // We want links' order to be reproducible so we don't use unstable sort. @@ -4309,7 +4309,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String { if let Some(impl_) = v .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did) + .find(|i| i.inner_impl().trait_.def_id(cx.cache()) == cx.cache.deref_trait_did) { out.push_str(&sidebar_deref_methods(cx, impl_, v)); } @@ -4320,9 +4320,9 @@ fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String { .iter() .filter_map(|it| { if let Some(ref i) = it.inner_impl().trait_ { - let i_display = format!("{:#}", i.print()); + let i_display = format!("{:#}", i.print(cx.cache())); let out = Escape(&i_display); - let encoded = small_url_encode(&format!("{:#}", i.print())); + let encoded = small_url_encode(&format!("{:#}", i.print(cx.cache()))); let generated = format!( "{}{}", encoded, @@ -4380,7 +4380,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String { fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> String { let mut out = String::new(); - let c = cache(); + let c = cx.cache(); debug!("found Deref: {:?}", impl_); if let Some((target, real_target)) = @@ -4396,9 +4396,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> Strin let deref_mut = v .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .any(|i| i.inner_impl().trait_.def_id() == c.deref_mut_trait_did); + .any(|i| i.inner_impl().trait_.def_id(cx.cache()) == c.deref_mut_trait_did); let inner_impl = target - .def_id() + .def_id(cx.cache()) .or_else(|| { target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned()) }) @@ -4409,18 +4409,18 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> Strin let mut ret = impls .iter() .filter(|i| i.inner_impl().trait_.is_none()) - .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut)) + .flat_map(|i| get_methods(i.inner_impl(), true, &mut used_links, deref_mut, c)) .collect::>(); if !ret.is_empty() { let deref_id_map = cx.deref_id_map.borrow(); let id = deref_id_map - .get(&real_target.def_id().unwrap()) + .get(&real_target.def_id(cx.cache()).unwrap()) .expect("Deref section without derived id"); out.push_str(&format!( "Methods from {}<Target={}>", id, - Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print())), - Escape(&format!("{:#}", real_target.print())), + Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(c))), + Escape(&format!("{:#}", real_target.print(c))), )); // We want links' order to be reproducible so we don't use unstable sort. ret.sort(); @@ -4429,14 +4429,14 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> Strin } // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id() { + if let Some(target_did) = target.def_id(cx.cache()) { if let Some(target_impls) = c.impls.get(&target_did) { if let Some(target_deref_impl) = target_impls .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did) + .find(|i| i.inner_impl().trait_.def_id(cx.cache()) == c.deref_trait_did) { - if let Some(type_did) = impl_.inner_impl().for_.def_id() { + if let Some(type_did) = impl_.inner_impl().for_.def_id(cx.cache()) { // `impl Deref for S` if target_did == type_did { // Avoid infinite cycles @@ -4473,17 +4473,21 @@ fn sidebar_struct(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, s: &clea } } -fn get_id_for_impl_on_foreign_type(for_: &clean::Type, trait_: &clean::Type) -> String { - small_url_encode(&format!("impl-{:#}-for-{:#}", trait_.print(), for_.print())) +fn get_id_for_impl_on_foreign_type( + for_: &clean::Type, + trait_: &clean::Type, + cache: &Cache, +) -> String { + small_url_encode(&format!("impl-{:#}-for-{:#}", trait_.print(cache), for_.print(cache))) } -fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> { +fn extract_for_impl_name(item: &clean::Item, cache: &Cache) -> Option<(String, String)> { match *item.kind { clean::ItemKind::ImplItem(ref i) => { if let Some(ref trait_) = i.trait_ { Some(( - format!("{:#}", i.for_.print()), - get_id_for_impl_on_foreign_type(&i.for_, trait_), + format!("{:#}", i.for_.print(cache)), + get_id_for_impl_on_foreign_type(&i.for_, trait_, cache), )) } else { None @@ -4570,13 +4574,16 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean )); } - let c = cache(); - - if let Some(implementors) = c.implementors.get(&it.def_id) { + if let Some(implementors) = cx.cache.implementors.get(&it.def_id) { let mut res = implementors .iter() - .filter(|i| i.inner_impl().for_.def_id().map_or(false, |d| !c.paths.contains_key(&d))) - .filter_map(|i| extract_for_impl_name(&i.impl_item)) + .filter(|i| { + i.inner_impl() + .for_ + .def_id(cx.cache()) + .map_or(false, |d| !cx.cache.paths.contains_key(&d)) + }) + .filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache())) .collect::>(); if !res.is_empty() { @@ -4815,9 +4822,9 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean document(w, cx, it, None) } -fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache: &Cache) { +fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { document(w, cx, it, None); - render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache) + render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { @@ -4836,11 +4843,10 @@ fn make_item_keywords(it: &clean::Item) -> String { /// types are re-exported, we don't use the corresponding /// entry from the js file, as inlining will have already /// picked up the impl -fn collect_paths_for_type(first_ty: clean::Type) -> Vec { +fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { let mut out = Vec::new(); let mut visited = FxHashSet::default(); let mut work = VecDeque::new(); - let cache = cache(); work.push_back(first_ty); diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 512c9124727ef..6b19e9885c7a6 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -32,6 +32,7 @@ crate struct JsonRenderer<'tcx> { index: Rc>>, /// The directory where the blob will be written to. out_path: PathBuf, + cache: Rc, } impl JsonRenderer<'_> { @@ -39,12 +40,9 @@ impl JsonRenderer<'_> { self.tcx.sess } - fn get_trait_implementors( - &mut self, - id: rustc_span::def_id::DefId, - cache: &Cache, - ) -> Vec { - cache + fn get_trait_implementors(&mut self, id: rustc_span::def_id::DefId) -> Vec { + self.cache + .clone() .implementors .get(&id) .map(|implementors| { @@ -52,7 +50,7 @@ impl JsonRenderer<'_> { .iter() .map(|i| { let item = &i.impl_item; - self.item(item.clone(), cache).unwrap(); + self.item(item.clone()).unwrap(); item.def_id.into() }) .collect() @@ -60,8 +58,9 @@ impl JsonRenderer<'_> { .unwrap_or_default() } - fn get_impls(&mut self, id: rustc_span::def_id::DefId, cache: &Cache) -> Vec { - cache + fn get_impls(&mut self, id: rustc_span::def_id::DefId) -> Vec { + self.cache + .clone() .impls .get(&id) .map(|impls| { @@ -70,7 +69,7 @@ impl JsonRenderer<'_> { .filter_map(|i| { let item = &i.impl_item; if item.def_id.is_local() { - self.item(item.clone(), cache).unwrap(); + self.item(item.clone()).unwrap(); Some(item.def_id.into()) } else { None @@ -81,24 +80,26 @@ impl JsonRenderer<'_> { .unwrap_or_default() } - fn get_trait_items(&mut self, cache: &Cache) -> Vec<(types::Id, types::Item)> { - cache + fn get_trait_items(&mut self) -> Vec<(types::Id, types::Item)> { + self.cache + .clone() .traits .iter() .filter_map(|(&id, trait_item)| { // only need to synthesize items for external traits 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(( id.into(), types::Item { id: id.into(), crate_id: id.krate.as_u32(), - name: cache + name: self + .cache .paths .get(&id) .unwrap_or_else(|| { - cache + self.cache .external_paths .get(&id) .expect("Trait should either be in local or external paths") @@ -134,8 +135,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { options: RenderOptions, _render_info: RenderInfo, _edition: Edition, - _cache: &mut Cache, - tcx: TyCtxt<'tcx>, + cache: Cache, + tcx: ty::TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error> { debug!("Initializing json renderer"); Ok(( @@ -143,6 +144,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { tcx, index: Rc::new(RefCell::new(FxHashMap::default())), out_path: options.output, + cache: Rc::new(cache), }, krate, )) @@ -151,18 +153,18 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { /// 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 /// 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 - 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; if let Some(mut new_item) = self.convert_item(item) { 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 { - 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 { - 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()); // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check @@ -175,27 +177,20 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { Ok(()) } - fn mod_item_in( - &mut self, - item: &clean::Item, - _module_name: &str, - cache: &Cache, - ) -> Result<(), Error> { + fn mod_item_in(&mut self, item: &clean::Item, _module_name: &str) -> Result<(), Error> { use clean::types::ItemKind::*; if let ModuleItem(m) = &*item.kind { for item in &m.items { match &*item.kind { // These don't have names so they don't get added to the output by default - ImportItem(_) => self.item(item.clone(), cache).unwrap(), - ExternCrateItem(_, _) => self.item(item.clone(), cache).unwrap(), - ImplItem(i) => { - i.items.iter().for_each(|i| self.item(i.clone(), cache).unwrap()) - } + ImportItem(_) => self.item(item.clone()).unwrap(), + ExternCrateItem(_, _) => self.item(item.clone()).unwrap(), + ImplItem(i) => i.items.iter().for_each(|i| self.item(i.clone()).unwrap()), _ => {} } } } - self.item(item.clone(), cache).unwrap(); + self.item(item.clone()).unwrap(); Ok(()) } @@ -206,22 +201,22 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { fn after_krate( &mut self, krate: &clean::Crate, - cache: &Cache, _diag: &rustc_errors::Handler, ) -> Result<(), Error> { debug!("Done with crate"); 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 { root: types::Id(String::from("0:0")), crate_version: krate.version.clone(), - includes_private: cache.document_private, + includes_private: self.cache.document_private, index, - paths: cache + paths: self + .cache .paths .clone() .into_iter() - .chain(cache.external_paths.clone().into_iter()) + .chain(self.cache.external_paths.clone().into_iter()) .map(|(k, (path, kind))| { ( k.into(), @@ -229,7 +224,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), - external_crates: cache + external_crates: self + .cache .extern_locations .iter() .map(|(k, v)| { @@ -254,4 +250,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { serde_json::ser::to_writer(&file, &output).unwrap(); Ok(()) } + + fn cache(&self) -> &Cache { + &self.cache + } } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 05a3a15adac80..61e14c0522277 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -218,7 +218,12 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> { clean::ImplItem(ref impl_) => { let filename = i.source.filename(self.ctx.sess()); 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 // 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 // cases it doesn't make sense, as all methods on a type are in one single // impl block - debug!("impl {:#} in {}", impl_.for_.print(), filename); + debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename); } } _ => { diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 7b5e9e5905f33..9dc12737d6a86 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -2,6 +2,7 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; +use crate::formats::cache::Cache; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -96,12 +97,12 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // Gather all type to `Deref` target edges. for it in &new_items { if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { - if trait_.def_id() == cx.tcx.lang_items().deref_trait() { + if trait_.def_id(&cx.cache) == cx.tcx.lang_items().deref_trait() { let target = items.iter().find_map(|item| match *item.kind { TypedefItem(ref t, true) => Some(&t.type_), _ => None, }); - if let (Some(for_did), Some(target)) = (for_.def_id(), target) { + if let (Some(for_did), Some(target)) = (for_.def_id(&cx.cache), target) { type_did_to_deref_target.insert(for_did, target); } } @@ -112,19 +113,20 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { map: &FxHashMap, cleaner: &mut BadImplStripper, type_did: &DefId, + cache: &Cache, ) { if let Some(target) = map.get(type_did) { debug!("add_deref_target: type {:?}, target {:?}", type_did, target); if let Some(target_prim) = target.primitive_type() { cleaner.prims.insert(target_prim); - } else if let Some(target_did) = target.def_id() { + } else if let Some(target_did) = target.def_id(cache) { // `impl Deref for S` if target_did == *type_did { // Avoid infinite cycles return; } cleaner.items.insert(target_did); - add_deref_target(map, cleaner, &target_did); + add_deref_target(map, cleaner, &target_did, cache); } } } @@ -133,14 +135,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // `Deref` target type and the impl for type positions, this map of types is keyed by // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. if cleaner.keep_impl_with_def_id(type_did) { - add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did); + add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did, &cx.cache); } } new_items.retain(|it| { if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { - cleaner.keep_impl(for_) - || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t)) + cleaner.keep_impl(for_, &cx.cache) + || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t, &cx.cache)) || blanket_impl.is_some() } else { true @@ -216,13 +218,13 @@ struct BadImplStripper { } impl BadImplStripper { - fn keep_impl(&self, ty: &Type) -> bool { + fn keep_impl(&self, ty: &Type, cache: &Cache) -> bool { if let Generic(_) = ty { // keep impls made on generics true } else if let Some(prim) = ty.primitive_type() { self.prims.contains(&prim) - } else if let Some(did) = ty.def_id() { + } else if let Some(did) = ty.def_id(cache) { self.keep_impl_with_def_id(&did) } else { false diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index a276b7a63371b..c67f7869f4baf 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -15,7 +15,7 @@ crate const STRIP_HIDDEN: Pass = Pass { }; /// Strip items marked `#[doc(hidden)]` -crate fn strip_hidden(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { +crate fn strip_hidden(krate: clean::Crate, cx: &DocContext<'_>) -> clean::Crate { let mut retained = DefIdSet::default(); // strip all #[doc(hidden)] items @@ -25,7 +25,7 @@ crate fn strip_hidden(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { }; // strip all impls referencing stripped items - let mut stripper = ImplStripper { retained: &retained }; + let mut stripper = ImplStripper { retained: &retained, cache: &cx.cache }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index e812bcd87fe3c..0ca4db83b7064 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -30,6 +30,6 @@ crate fn strip_private(mut krate: clean::Crate, cx: &DocContext<'_>) -> clean::C } // strip all impls referencing private items - let mut stripper = ImplStripper { retained: &retained }; + let mut stripper = ImplStripper { retained: &retained, cache: &cx.cache }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 162b70973b418..424928e2377b0 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -4,6 +4,7 @@ use std::mem; use crate::clean::{self, GetDefId, Item}; use crate::fold::{DocFolder, StripItem}; +use crate::formats::cache::Cache; crate struct Stripper<'a> { crate retained: &'a mut DefIdSet, @@ -117,6 +118,7 @@ impl<'a> DocFolder for Stripper<'a> { /// This stripper discards all impls which reference stripped items crate struct ImplStripper<'a> { crate retained: &'a DefIdSet, + crate cache: &'a Cache, } impl<'a> DocFolder for ImplStripper<'a> { @@ -126,13 +128,13 @@ impl<'a> DocFolder for ImplStripper<'a> { if imp.trait_.is_none() && imp.items.is_empty() { return None; } - if let Some(did) = imp.for_.def_id() { + if let Some(did) = imp.for_.def_id(&self.cache) { if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) { debug!("ImplStripper: impl item for stripped type; removing"); return None; } } - if let Some(did) = imp.trait_.def_id() { + if let Some(did) = imp.trait_.def_id(&self.cache) { if did.is_local() && !self.retained.contains(&did) { debug!("ImplStripper: impl item for stripped trait; removing"); return None; @@ -140,7 +142,7 @@ impl<'a> DocFolder for ImplStripper<'a> { } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { for typaram in generics { - if let Some(did) = typaram.def_id() { + if let Some(did) = typaram.def_id(&self.cache) { if did.is_local() && !self.retained.contains(&did) { debug!( "ImplStripper: stripped item in trait's generics; removing impl" From c448270099444486cdf3c22bc841a5c673d9da4f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 Jan 2021 22:06:41 +0100 Subject: [PATCH 02/10] Use empty Cache for methods requiring it when filling Cache itself --- src/librustdoc/formats/cache.rs | 118 +++++++++++++++++++------------- 1 file changed, 70 insertions(+), 48 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c4c8145a57d0a..6e42acfe11f7d 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -193,7 +193,11 @@ impl Cache { } cache.stack.push(krate.name.to_string()); - krate = cache.fold_crate(krate); + + krate = { + let mut cache_wrapper = CacheWrapper { cache: &mut cache, tmp_cache: Cache::default() }; + cache_wrapper.fold_crate(krate) + }; for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { if cache.traits.contains_key(&trait_did) { @@ -207,7 +211,15 @@ impl Cache { } } -impl DocFolder for Cache { +/// This struct is needed because we need to use an empty `Cache` for all functions requiring +/// a `Cache`. If we use the already filled one (`cache` in here), it'll provide information +/// about implementations that aren't related to the type being checked. +struct CacheWrapper<'a> { + cache: &'a mut Cache, + tmp_cache: Cache, +} + +impl<'a> DocFolder for CacheWrapper<'a> { fn fold_item(&mut self, item: clean::Item) -> Option { if item.def_id.is_local() { debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); @@ -217,17 +229,21 @@ impl DocFolder for Cache { // we don't want it or its children in the search index. let orig_stripped_mod = match *item.kind { clean::StrippedItem(box clean::ModuleItem(..)) => { - mem::replace(&mut self.stripped_mod, true) + mem::replace(&mut self.cache.stripped_mod, true) } - _ => self.stripped_mod, + _ => self.cache.stripped_mod, }; // If the impl is from a masked crate or references something from a // masked crate then remove it completely. if let clean::ImplItem(ref i) = *item.kind { - if self.masked_crates.contains(&item.def_id.krate) - || i.trait_.def_id(self).map_or(false, |d| self.masked_crates.contains(&d.krate)) - || i.for_.def_id(self).map_or(false, |d| self.masked_crates.contains(&d.krate)) + if self.cache.masked_crates.contains(&item.def_id.krate) + || i.trait_ + .def_id(&self.tmp_cache) + .map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) + || i.for_ + .def_id(&self.tmp_cache) + .map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) { return None; } @@ -236,14 +252,15 @@ impl DocFolder for Cache { // Propagate a trait method's documentation to all implementors of the // trait. if let clean::TraitItem(ref t) = *item.kind { - self.traits.entry(item.def_id).or_insert_with(|| t.clone()); + self.cache.traits.entry(item.def_id).or_insert_with(|| t.clone()); } // Collect all the implementors of traits. if let clean::ImplItem(ref i) = *item.kind { - if let Some(did) = i.trait_.def_id(self) { + if let Some(did) = i.trait_.def_id(&self.tmp_cache) { if i.blanket_impl.is_none() { - self.implementors + self.cache + .implementors .entry(did) .or_default() .push(Impl { impl_item: item.clone() }); @@ -256,7 +273,7 @@ impl DocFolder for Cache { let (parent, is_inherent_impl_item) = match *item.kind { clean::StrippedItem(..) => ((None, None), false), clean::AssocConstItem(..) | clean::TypedefItem(_, true) - if self.parent_is_trait_impl => + if self.cache.parent_is_trait_impl => { // skip associated items in trait impls ((None, None), false) @@ -266,18 +283,18 @@ impl DocFolder for Cache { | clean::StructFieldItem(..) | clean::VariantItem(..) => ( ( - Some(*self.parent_stack.last().expect("parent_stack is empty")), - Some(&self.stack[..self.stack.len() - 1]), + Some(*self.cache.parent_stack.last().expect("parent_stack is empty")), + Some(&self.cache.stack[..self.cache.stack.len() - 1]), ), false, ), clean::MethodItem(..) | clean::AssocConstItem(..) => { - if self.parent_stack.is_empty() { + if self.cache.parent_stack.is_empty() { ((None, None), false) } else { - let last = self.parent_stack.last().expect("parent_stack is empty 2"); + let last = self.cache.parent_stack.last().expect("parent_stack is empty 2"); let did = *last; - let path = match self.paths.get(&did) { + let path = match self.cache.paths.get(&did) { // The current stack not necessarily has correlation // for where the type was defined. On the other // hand, `paths` always has the right @@ -289,24 +306,24 @@ impl DocFolder for Cache { | ItemType::Union | ItemType::Enum, )) => Some(&fqp[..fqp.len() - 1]), - Some(..) => Some(&*self.stack), + Some(..) => Some(&*self.cache.stack), None => None, }; ((Some(*last), path), true) } } - _ => ((None, Some(&*self.stack)), false), + _ => ((None, Some(&*self.cache.stack)), false), }; match parent { - (parent, Some(path)) if is_inherent_impl_item || !self.stripped_mod => { + (parent, Some(path)) if is_inherent_impl_item || !self.cache.stripped_mod => { debug_assert!(!item.is_stripped()); // A crate has a module at its root, containing all items, // which should not be indexed. The crate-item itself is // inserted later on when serializing the search-index. if item.def_id.index != CRATE_DEF_INDEX { - self.search_index.push(IndexItem { + self.cache.search_index.push(IndexItem { ty: item.type_(), name: s.to_string(), path: path.join("::"), @@ -315,21 +332,22 @@ impl DocFolder for Cache { .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())), parent, parent_idx: None, - search_type: get_index_search_type(&item, self), + search_type: get_index_search_type(&item, &self.tmp_cache), }); for alias in item.attrs.get_doc_aliases() { - self.aliases + self.cache + .aliases .entry(alias.to_lowercase()) .or_insert(Vec::new()) - .push(self.search_index.len() - 1); + .push(self.cache.search_index.len() - 1); } } } (Some(parent), None) if is_inherent_impl_item => { // We have a parent, but we don't know where they're // defined yet. Wait for later to index this item. - self.orphan_impl_items.push((parent, item.clone())); + self.cache.orphan_impl_items.push((parent, item.clone())); } _ => {} } @@ -338,7 +356,7 @@ impl DocFolder for Cache { // Keep track of the fully qualified path for this item. let pushed = match item.name { Some(n) if !n.is_empty() => { - self.stack.push(n.to_string()); + self.cache.stack.push(n.to_string()); true } _ => false, @@ -360,7 +378,7 @@ impl DocFolder for Cache { | clean::MacroItem(..) | clean::ProcMacroItem(..) | clean::VariantItem(..) - if !self.stripped_mod => + if !self.cache.stripped_mod => { // Re-exported items mean that the same id can show up twice // in the rustdoc ast that we're looking at. We know, @@ -368,21 +386,21 @@ impl DocFolder for Cache { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if !self.paths.contains_key(&item.def_id) - || self.access_levels.is_public(item.def_id) + if !self.cache.paths.contains_key(&item.def_id) + || self.cache.access_levels.is_public(item.def_id) { - self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); + self.cache.paths.insert(item.def_id, (self.cache.stack.clone(), item.type_())); } } clean::PrimitiveItem(..) => { - self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); + self.cache.paths.insert(item.def_id, (self.cache.stack.clone(), item.type_())); } _ => {} } // Maintain the parent stack - let orig_parent_is_trait_impl = self.parent_is_trait_impl; + let orig_parent_is_trait_impl = self.cache.parent_is_trait_impl; let parent_pushed = match *item.kind { clean::TraitItem(..) | clean::EnumItem(..) @@ -390,24 +408,24 @@ impl DocFolder for Cache { | clean::StructItem(..) | clean::UnionItem(..) | clean::VariantItem(..) => { - self.parent_stack.push(item.def_id); - self.parent_is_trait_impl = false; + self.cache.parent_stack.push(item.def_id); + self.cache.parent_is_trait_impl = false; true } clean::ImplItem(ref i) => { - self.parent_is_trait_impl = i.trait_.is_some(); + self.cache.parent_is_trait_impl = i.trait_.is_some(); match i.for_ { clean::ResolvedPath { did, .. } => { - self.parent_stack.push(did); + self.cache.parent_stack.push(did); true } ref t => { let prim_did = t .primitive_type() - .and_then(|t| self.primitive_locations.get(&t).cloned()); + .and_then(|t| self.cache.primitive_locations.get(&t).cloned()); match prim_did { Some(did) => { - self.parent_stack.push(did); + self.cache.parent_stack.push(did); true } None => false, @@ -432,8 +450,9 @@ impl DocFolder for Cache { dids.insert(did); } ref t => { - let did = - t.primitive_type().and_then(|t| self.primitive_locations.get(&t).cloned()); + let did = t + .primitive_type() + .and_then(|t| self.cache.primitive_locations.get(&t).cloned()); if let Some(did) = did { dids.insert(did); @@ -443,19 +462,22 @@ impl DocFolder for Cache { if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { for bound in generics { - if let Some(did) = bound.def_id(self) { + if let Some(did) = bound.def_id(&self.tmp_cache) { dids.insert(did); } } } let impl_item = Impl { impl_item: item }; - if impl_item.trait_did(self).map_or(true, |d| self.traits.contains_key(&d)) { + if impl_item + .trait_did(&self.tmp_cache) + .map_or(true, |d| self.cache.traits.contains_key(&d)) + { for did in dids { - self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + self.cache.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); } } else { - let trait_did = impl_item.trait_did(self).expect("no trait did"); - self.orphan_trait_impls.push((trait_did, dids, impl_item)); + let trait_did = impl_item.trait_did(&self.tmp_cache).expect("no trait did"); + self.cache.orphan_trait_impls.push((trait_did, dids, impl_item)); } None } else { @@ -463,13 +485,13 @@ impl DocFolder for Cache { }; if pushed { - self.stack.pop().expect("stack already empty"); + self.cache.stack.pop().expect("stack already empty"); } if parent_pushed { - self.parent_stack.pop().expect("parent stack already empty"); + self.cache.parent_stack.pop().expect("parent stack already empty"); } - self.stripped_mod = orig_stripped_mod; - self.parent_is_trait_impl = orig_parent_is_trait_impl; + self.cache.stripped_mod = orig_stripped_mod; + self.cache.parent_is_trait_impl = orig_parent_is_trait_impl; ret } } From 19630ead410873a08b271606b8ac5a27029d70b6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 15 Jan 2021 15:36:15 +0100 Subject: [PATCH 03/10] Remove cache usage wherever possible --- src/librustdoc/clean/inline.rs | 10 +- src/librustdoc/clean/mod.rs | 6 +- src/librustdoc/clean/types.rs | 78 +++++++++---- src/librustdoc/clean/utils.rs | 24 ++-- src/librustdoc/formats/cache.rs | 117 ++++++++----------- src/librustdoc/formats/mod.rs | 8 +- src/librustdoc/html/render/cache.rs | 19 +-- src/librustdoc/html/render/mod.rs | 49 ++++---- src/librustdoc/passes/collect_trait_impls.rs | 20 ++-- src/librustdoc/passes/strip_hidden.rs | 4 +- src/librustdoc/passes/strip_private.rs | 2 +- src/librustdoc/passes/stripper.rs | 8 +- 12 files changed, 179 insertions(+), 166 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 6ef74d6e9920c..1f9e7f8ae5cd4 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -368,7 +368,7 @@ crate fn build_impl( // Only inline impl if the implementing type is // reachable in rustdoc generated documentation if !did.is_local() { - if let Some(did) = for_.def_id(&cx.cache) { + if let Some(did) = for_.def_id() { if !cx.renderinfo.borrow().access_levels.is_public(did) { return; } @@ -410,19 +410,19 @@ crate fn build_impl( clean::GenericBound::TraitBound(polyt, _) => polyt.trait_, clean::GenericBound::Outlives(..) => unreachable!(), }); - if trait_.def_id(&cx.cache) == tcx.lang_items().deref_trait() { + if trait_.def_id() == tcx.lang_items().deref_trait() { super::build_deref_target_impls(cx, &trait_items, ret); } - if let Some(trait_did) = trait_.def_id(&cx.cache) { + if let Some(trait_did) = trait_.def_id() { record_extern_trait(cx, trait_did); } let provided = trait_ - .def_id(&cx.cache) + .def_id() .map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect()) .unwrap_or_default(); - debug!("build_impl: impl {:?} for {:?}", trait_.def_id(&cx.cache), for_.def_id(&cx.cache)); + debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id()); let mut item = clean::Item::from_def_id_and_parts( did, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index dcb0b325b9775..03454bb8b7ff0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2089,17 +2089,17 @@ fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &DocContext<'_>) -> // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. - if trait_.def_id(&cx.cache) == cx.tcx.lang_items().deref_trait() { + if trait_.def_id() == cx.tcx.lang_items().deref_trait() { build_deref_target_impls(cx, &items, &mut ret); } let provided: FxHashSet = trait_ - .def_id(&cx.cache) + .def_id() .map(|did| cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect()) .unwrap_or_default(); let for_ = impl_.self_ty.clean(cx); - let type_alias = for_.def_id(&cx.cache).and_then(|did| match cx.tcx.def_kind(did) { + let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) { DefKind::TyAlias => Some(cx.tcx.type_of(did).clean(cx)), _ => None, }); diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index d03c457c8965c..1e3c3a23c9884 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -958,7 +958,7 @@ impl GenericBound { crate fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool { use rustc_hir::TraitBoundModifier as TBM; if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { - if trait_.def_id(&cx.cache) == cx.tcx.lang_items().sized_trait() { + if trait_.def_id() == cx.tcx.lang_items().sized_trait() { return true; } } @@ -1171,9 +1171,16 @@ crate enum FnRetTy { } impl GetDefId for FnRetTy { - fn def_id(&self, cache: &Cache) -> Option { + fn def_id(&self) -> Option { match *self { - Return(ref ty) => ty.def_id(cache), + Return(ref ty) => ty.def_id(), + DefaultReturn => None, + } + } + + fn def_id_full(&self, cache: &Cache) -> Option { + match *self { + Return(ref ty) => ty.def_id_full(cache), DefaultReturn => None, } } @@ -1299,12 +1306,20 @@ crate enum TypeKind { } crate trait GetDefId { - fn def_id(&self, cache: &Cache) -> Option; + /// Doesn't retrieve primitive types `DefId`. Use `def_id_full` if you want it. + fn def_id(&self) -> Option; + /// Retrieves all types' `DefId` (including primitives). If you're not interested about + /// primitives, use `def_id`. + fn def_id_full(&self, cache: &Cache) -> Option; } impl GetDefId for Option { - fn def_id(&self, cache: &Cache) -> Option { - self.as_ref().and_then(|d| d.def_id(cache)) + fn def_id(&self) -> Option { + self.as_ref().and_then(|d| d.def_id()) + } + + fn def_id_full(&self, cache: &Cache) -> Option { + self.as_ref().and_then(|d| d.def_id_full(cache)) } } @@ -1393,33 +1408,50 @@ impl Type { } } -impl GetDefId for Type { - fn def_id(&self, cache: &Cache) -> Option { +impl Type { + fn inner_def_id(&self, cache: Option<&Cache>) -> Option { + fn inner(t: &T, cache: Option<&Cache>) -> Option { + match cache { + Some(c) => t.def_id_full(c), + None => t.def_id(), + } + } + match *self { ResolvedPath { did, .. } => Some(did), - Primitive(p) => cache.primitive_locations.get(&p).cloned(), + Primitive(p) => cache.and_then(|c| c.primitive_locations.get(&p).cloned()), BorrowedRef { type_: box Generic(..), .. } => { - Primitive(PrimitiveType::Reference).def_id(cache) + inner(&Primitive(PrimitiveType::Reference), cache) } - BorrowedRef { ref type_, .. } => type_.def_id(cache), + BorrowedRef { ref type_, .. } => inner(&**type_, cache), Tuple(ref tys) => { if tys.is_empty() { - Primitive(PrimitiveType::Unit).def_id(cache) + inner(&Primitive(PrimitiveType::Unit), cache) } else { - Primitive(PrimitiveType::Tuple).def_id(cache) + inner(&Primitive(PrimitiveType::Tuple), cache) } } - BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(cache), - Never => Primitive(PrimitiveType::Never).def_id(cache), - Slice(..) => Primitive(PrimitiveType::Slice).def_id(cache), - Array(..) => Primitive(PrimitiveType::Array).def_id(cache), - RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(cache), - QPath { ref self_type, .. } => self_type.def_id(cache), + BareFunction(..) => inner(&Primitive(PrimitiveType::Fn), cache), + Never => inner(&Primitive(PrimitiveType::Never), cache), + Slice(..) => inner(&Primitive(PrimitiveType::Slice), cache), + Array(..) => inner(&Primitive(PrimitiveType::Array), cache), + RawPointer(..) => inner(&Primitive(PrimitiveType::RawPointer), cache), + QPath { ref self_type, .. } => inner(&**self_type, cache), _ => None, } } } +impl GetDefId for Type { + fn def_id(&self) -> Option { + self.inner_def_id(None) + } + + fn def_id_full(&self, cache: &Cache) -> Option { + self.inner_def_id(Some(cache)) + } +} + impl PrimitiveType { crate fn from_hir(prim: hir::PrimTy) -> PrimitiveType { match prim { @@ -1814,8 +1846,12 @@ crate struct Typedef { } impl GetDefId for Typedef { - fn def_id(&self, cache: &Cache) -> Option { - self.type_.def_id(cache) + fn def_id(&self) -> Option { + self.type_.def_id() + } + + fn def_id_full(&self, cache: &Cache) -> Option { + self.type_.def_id_full(cache) } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index e6a94926329b9..869d48fc25e07 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -179,9 +179,7 @@ crate fn get_real_types( if arg.is_full_generic() { let arg_s = Symbol::intern(&arg.print(&cx.cache).to_string()); if let Some(where_pred) = generics.where_predicates.iter().find(|g| match g { - WherePredicate::BoundPredicate { ty, .. } => { - ty.def_id(&cx.cache) == arg.def_id(&cx.cache) - } + WherePredicate::BoundPredicate { ty, .. } => ty.def_id() == arg.def_id(), _ => false, }) { let bounds = where_pred.get_bounds().unwrap_or_else(|| &[]); @@ -197,7 +195,7 @@ crate fn get_real_types( res.extend(adds); } else if !ty.is_full_generic() { if let Some(kind) = - ty.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) + ty.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { res.insert((ty, kind)); } @@ -214,9 +212,7 @@ crate fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - if let Some(kind) = - ty.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) - { + if let Some(kind) = ty.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { res.insert((ty.clone(), kind)); } } @@ -224,7 +220,7 @@ crate fn get_real_types( } } } else { - if let Some(kind) = arg.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) { + if let Some(kind) = arg.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { res.insert((arg.clone(), kind)); } if let Some(gens) = arg.generics() { @@ -234,9 +230,7 @@ crate fn get_real_types( if !adds.is_empty() { res.extend(adds); } - } else if let Some(kind) = - gen.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) - { + } else if let Some(kind) = gen.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { res.insert((gen.clone(), kind)); } } @@ -263,9 +257,7 @@ crate fn get_all_types( if !args.is_empty() { all_types.extend(args); } else { - if let Some(kind) = - arg.type_.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) - { + if let Some(kind) = arg.type_.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { all_types.insert((arg.type_.clone(), kind)); } } @@ -275,9 +267,7 @@ crate fn get_all_types( FnRetTy::Return(ref return_type) => { let mut ret = get_real_types(generics, &return_type, cx, 0); if ret.is_empty() { - if let Some(kind) = - return_type.def_id(&cx.cache).map(|did| cx.tcx.def_kind(did).clean(cx)) - { + if let Some(kind) = return_type.def_id().map(|did| cx.tcx.def_kind(did).clean(cx)) { ret.insert((return_type.clone(), kind)); } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 6e42acfe11f7d..c506f5a37b15b 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -194,10 +194,7 @@ impl Cache { cache.stack.push(krate.name.to_string()); - krate = { - let mut cache_wrapper = CacheWrapper { cache: &mut cache, tmp_cache: Cache::default() }; - cache_wrapper.fold_crate(krate) - }; + krate = cache.fold_crate(krate); for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { if cache.traits.contains_key(&trait_did) { @@ -211,15 +208,7 @@ impl Cache { } } -/// This struct is needed because we need to use an empty `Cache` for all functions requiring -/// a `Cache`. If we use the already filled one (`cache` in here), it'll provide information -/// about implementations that aren't related to the type being checked. -struct CacheWrapper<'a> { - cache: &'a mut Cache, - tmp_cache: Cache, -} - -impl<'a> DocFolder for CacheWrapper<'a> { +impl DocFolder for Cache { fn fold_item(&mut self, item: clean::Item) -> Option { if item.def_id.is_local() { debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); @@ -229,21 +218,17 @@ impl<'a> DocFolder for CacheWrapper<'a> { // we don't want it or its children in the search index. let orig_stripped_mod = match *item.kind { clean::StrippedItem(box clean::ModuleItem(..)) => { - mem::replace(&mut self.cache.stripped_mod, true) + mem::replace(&mut self.stripped_mod, true) } - _ => self.cache.stripped_mod, + _ => self.stripped_mod, }; // If the impl is from a masked crate or references something from a // masked crate then remove it completely. if let clean::ImplItem(ref i) = *item.kind { - if self.cache.masked_crates.contains(&item.def_id.krate) - || i.trait_ - .def_id(&self.tmp_cache) - .map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) - || i.for_ - .def_id(&self.tmp_cache) - .map_or(false, |d| self.cache.masked_crates.contains(&d.krate)) + if self.masked_crates.contains(&item.def_id.krate) + || i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) + || i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) { return None; } @@ -252,15 +237,14 @@ impl<'a> DocFolder for CacheWrapper<'a> { // Propagate a trait method's documentation to all implementors of the // trait. if let clean::TraitItem(ref t) = *item.kind { - self.cache.traits.entry(item.def_id).or_insert_with(|| t.clone()); + self.traits.entry(item.def_id).or_insert_with(|| t.clone()); } // Collect all the implementors of traits. if let clean::ImplItem(ref i) = *item.kind { - if let Some(did) = i.trait_.def_id(&self.tmp_cache) { + if let Some(did) = i.trait_.def_id() { if i.blanket_impl.is_none() { - self.cache - .implementors + self.implementors .entry(did) .or_default() .push(Impl { impl_item: item.clone() }); @@ -273,7 +257,7 @@ impl<'a> DocFolder for CacheWrapper<'a> { let (parent, is_inherent_impl_item) = match *item.kind { clean::StrippedItem(..) => ((None, None), false), clean::AssocConstItem(..) | clean::TypedefItem(_, true) - if self.cache.parent_is_trait_impl => + if self.parent_is_trait_impl => { // skip associated items in trait impls ((None, None), false) @@ -283,18 +267,18 @@ impl<'a> DocFolder for CacheWrapper<'a> { | clean::StructFieldItem(..) | clean::VariantItem(..) => ( ( - Some(*self.cache.parent_stack.last().expect("parent_stack is empty")), - Some(&self.cache.stack[..self.cache.stack.len() - 1]), + Some(*self.parent_stack.last().expect("parent_stack is empty")), + Some(&self.stack[..self.stack.len() - 1]), ), false, ), clean::MethodItem(..) | clean::AssocConstItem(..) => { - if self.cache.parent_stack.is_empty() { + if self.parent_stack.is_empty() { ((None, None), false) } else { - let last = self.cache.parent_stack.last().expect("parent_stack is empty 2"); + let last = self.parent_stack.last().expect("parent_stack is empty 2"); let did = *last; - let path = match self.cache.paths.get(&did) { + let path = match self.paths.get(&did) { // The current stack not necessarily has correlation // for where the type was defined. On the other // hand, `paths` always has the right @@ -306,24 +290,24 @@ impl<'a> DocFolder for CacheWrapper<'a> { | ItemType::Union | ItemType::Enum, )) => Some(&fqp[..fqp.len() - 1]), - Some(..) => Some(&*self.cache.stack), + Some(..) => Some(&*self.stack), None => None, }; ((Some(*last), path), true) } } - _ => ((None, Some(&*self.cache.stack)), false), + _ => ((None, Some(&*self.stack)), false), }; match parent { - (parent, Some(path)) if is_inherent_impl_item || !self.cache.stripped_mod => { + (parent, Some(path)) if is_inherent_impl_item || !self.stripped_mod => { debug_assert!(!item.is_stripped()); // A crate has a module at its root, containing all items, // which should not be indexed. The crate-item itself is // inserted later on when serializing the search-index. if item.def_id.index != CRATE_DEF_INDEX { - self.cache.search_index.push(IndexItem { + self.search_index.push(IndexItem { ty: item.type_(), name: s.to_string(), path: path.join("::"), @@ -332,22 +316,21 @@ impl<'a> DocFolder for CacheWrapper<'a> { .map_or_else(String::new, |x| short_markdown_summary(&x.as_str())), parent, parent_idx: None, - search_type: get_index_search_type(&item, &self.tmp_cache), + search_type: get_index_search_type(&item, None), }); for alias in item.attrs.get_doc_aliases() { - self.cache - .aliases + self.aliases .entry(alias.to_lowercase()) .or_insert(Vec::new()) - .push(self.cache.search_index.len() - 1); + .push(self.search_index.len() - 1); } } } (Some(parent), None) if is_inherent_impl_item => { // We have a parent, but we don't know where they're // defined yet. Wait for later to index this item. - self.cache.orphan_impl_items.push((parent, item.clone())); + self.orphan_impl_items.push((parent, item.clone())); } _ => {} } @@ -356,7 +339,7 @@ impl<'a> DocFolder for CacheWrapper<'a> { // Keep track of the fully qualified path for this item. let pushed = match item.name { Some(n) if !n.is_empty() => { - self.cache.stack.push(n.to_string()); + self.stack.push(n.to_string()); true } _ => false, @@ -378,7 +361,7 @@ impl<'a> DocFolder for CacheWrapper<'a> { | clean::MacroItem(..) | clean::ProcMacroItem(..) | clean::VariantItem(..) - if !self.cache.stripped_mod => + if !self.stripped_mod => { // Re-exported items mean that the same id can show up twice // in the rustdoc ast that we're looking at. We know, @@ -386,21 +369,21 @@ impl<'a> DocFolder for CacheWrapper<'a> { // `public_items` map, so we can skip inserting into the // paths map if there was already an entry present and we're // not a public item. - if !self.cache.paths.contains_key(&item.def_id) - || self.cache.access_levels.is_public(item.def_id) + if !self.paths.contains_key(&item.def_id) + || self.access_levels.is_public(item.def_id) { - self.cache.paths.insert(item.def_id, (self.cache.stack.clone(), item.type_())); + self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } } clean::PrimitiveItem(..) => { - self.cache.paths.insert(item.def_id, (self.cache.stack.clone(), item.type_())); + self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } _ => {} } // Maintain the parent stack - let orig_parent_is_trait_impl = self.cache.parent_is_trait_impl; + let orig_parent_is_trait_impl = self.parent_is_trait_impl; let parent_pushed = match *item.kind { clean::TraitItem(..) | clean::EnumItem(..) @@ -408,24 +391,24 @@ impl<'a> DocFolder for CacheWrapper<'a> { | clean::StructItem(..) | clean::UnionItem(..) | clean::VariantItem(..) => { - self.cache.parent_stack.push(item.def_id); - self.cache.parent_is_trait_impl = false; + self.parent_stack.push(item.def_id); + self.parent_is_trait_impl = false; true } clean::ImplItem(ref i) => { - self.cache.parent_is_trait_impl = i.trait_.is_some(); + self.parent_is_trait_impl = i.trait_.is_some(); match i.for_ { clean::ResolvedPath { did, .. } => { - self.cache.parent_stack.push(did); + self.parent_stack.push(did); true } ref t => { let prim_did = t .primitive_type() - .and_then(|t| self.cache.primitive_locations.get(&t).cloned()); + .and_then(|t| self.primitive_locations.get(&t).cloned()); match prim_did { Some(did) => { - self.cache.parent_stack.push(did); + self.parent_stack.push(did); true } None => false, @@ -450,9 +433,8 @@ impl<'a> DocFolder for CacheWrapper<'a> { dids.insert(did); } ref t => { - let did = t - .primitive_type() - .and_then(|t| self.cache.primitive_locations.get(&t).cloned()); + let did = + t.primitive_type().and_then(|t| self.primitive_locations.get(&t).cloned()); if let Some(did) = did { dids.insert(did); @@ -462,22 +444,19 @@ impl<'a> DocFolder for CacheWrapper<'a> { if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { for bound in generics { - if let Some(did) = bound.def_id(&self.tmp_cache) { + if let Some(did) = bound.def_id() { dids.insert(did); } } } let impl_item = Impl { impl_item: item }; - if impl_item - .trait_did(&self.tmp_cache) - .map_or(true, |d| self.cache.traits.contains_key(&d)) - { + if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { for did in dids { - self.cache.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); } } else { - let trait_did = impl_item.trait_did(&self.tmp_cache).expect("no trait did"); - self.cache.orphan_trait_impls.push((trait_did, dids, impl_item)); + let trait_did = impl_item.trait_did().expect("no trait did"); + self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None } else { @@ -485,13 +464,13 @@ impl<'a> DocFolder for CacheWrapper<'a> { }; if pushed { - self.cache.stack.pop().expect("stack already empty"); + self.stack.pop().expect("stack already empty"); } if parent_pushed { - self.cache.parent_stack.pop().expect("parent stack already empty"); + self.parent_stack.pop().expect("parent stack already empty"); } - self.cache.stripped_mod = orig_stripped_mod; - self.cache.parent_is_trait_impl = orig_parent_is_trait_impl; + self.stripped_mod = orig_stripped_mod; + self.parent_is_trait_impl = orig_parent_is_trait_impl; ret } } diff --git a/src/librustdoc/formats/mod.rs b/src/librustdoc/formats/mod.rs index 4d766af98feaf..1ce6572bbed04 100644 --- a/src/librustdoc/formats/mod.rs +++ b/src/librustdoc/formats/mod.rs @@ -39,7 +39,11 @@ impl Impl { } } - crate fn trait_did(&self, cache: &Cache) -> Option { - self.inner_impl().trait_.def_id(cache) + crate fn trait_did(&self) -> Option { + self.inner_impl().trait_.def_id() + } + + crate fn trait_did_full(&self, cache: &Cache) -> Option { + self.inner_impl().trait_.def_id_full(cache) } } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index a2fae03d87a2d..74a770b954853 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -78,7 +78,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)), parent: Some(did), parent_idx: None, - search_type: get_index_search_type(&item, cache), + search_type: get_index_search_type(&item, Some(cache)), }); for alias in item.attrs.get_doc_aliases() { cache @@ -164,7 +164,10 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { ) } -crate fn get_index_search_type(item: &clean::Item, cache: &Cache) -> Option { +crate fn get_index_search_type( + item: &clean::Item, + cache: Option<&Cache>, +) -> Option { let (all_types, ret_types) = match *item.kind { clean::FunctionItem(ref f) => (&f.all_types, &f.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, cache: &Cache) -> Option>(); let output = if output.is_empty() { None } else { Some(output) }; @@ -187,9 +190,9 @@ crate fn get_index_search_type(item: &clean::Item, cache: &Cache) -> Option RenderType { +fn get_index_type(clean_type: &clean::Type, cache: &Option<&Cache>) -> RenderType { RenderType { - ty: clean_type.def_id(cache), + ty: cache.map_or_else(|| clean_type.def_id(), |cache| clean_type.def_id_full(cache)), idx: None, name: get_index_type_name(clean_type, true).map(|s| s.as_str().to_ascii_lowercase()), 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, cache: &Cache) -> Option> { +fn get_generics(clean_type: &clean::Type, cache: &Option<&Cache>) -> Option> { clean_type.generics().and_then(|types| { let r = types .iter() .filter_map(|t| { get_index_type_name(t, false).map(|name| Generic { name: name.as_str().to_ascii_lowercase(), - defid: t.def_id(cache), + defid: cache.map_or_else(|| t.def_id(), |cache| t.def_id_full(cache)), idx: None, }) }) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 88e61403ddbe6..f4ff1f3b6d55b 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2515,7 +2515,7 @@ fn render_impls( let mut impls = traits .iter() .map(|i| { - let did = i.trait_did(cx.cache()).unwrap(); + let did = i.trait_did_full(cx.cache()).unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods); let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() }; render_impl( @@ -2755,7 +2755,10 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra } let (local, foreign) = implementors.iter().partition::, _>(|i| { - i.inner_impl().for_.def_id(cx.cache()).map_or(true, |d| cx.cache.paths.contains_key(&d)) + i.inner_impl() + .for_ + .def_id_full(cx.cache()) + .map_or(true, |d| cx.cache.paths.contains_key(&d)) }); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = @@ -3518,7 +3521,9 @@ fn render_assoc_items( "deref-methods-{:#}", type_.print(cx.cache()) ))); - cx.deref_id_map.borrow_mut().insert(type_.def_id(cx.cache()).unwrap(), id.clone()); + cx.deref_id_map + .borrow_mut() + .insert(type_.def_id_full(cx.cache()).unwrap(), id.clone()); write!( w, "

\ @@ -3553,11 +3558,11 @@ fn render_assoc_items( if !traits.is_empty() { let deref_impl = traits .iter() - .find(|t| t.inner_impl().trait_.def_id(cx.cache()) == cx.cache.deref_trait_did); + .find(|t| t.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_trait_did); if let Some(impl_) = deref_impl { - let has_deref_mut = traits - .iter() - .any(|t| t.inner_impl().trait_.def_id(cx.cache()) == cx.cache.deref_mut_trait_did); + let has_deref_mut = traits.iter().any(|t| { + t.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_mut_trait_did + }); render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } @@ -3636,8 +3641,8 @@ fn render_deref_methods( .expect("Expected associated type binding"); let what = AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; - if let Some(did) = target.def_id(cx.cache()) { - if let Some(type_did) = impl_.inner_impl().for_.def_id(cx.cache()) { + if let Some(did) = target.def_id_full(cx.cache()) { + if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) { // `impl Deref for S` if did == type_did { // Avoid infinite cycles @@ -3684,11 +3689,11 @@ fn spotlight_decl(decl: &clean::FnDecl, c: &Cache) -> String { let mut out = Buffer::html(); let mut trait_ = String::new(); - if let Some(did) = decl.output.def_id(c) { + if let Some(did) = decl.output.def_id_full(c) { if let Some(impls) = c.impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); - if impl_.trait_.def_id(c).map_or(false, |d| c.traits[&d].is_spotlight) { + if impl_.trait_.def_id_full(c).map_or(false, |d| c.traits[&d].is_spotlight) { if out.is_empty() { out.push_str(&format!( "

Notable traits for {}

\ @@ -3703,7 +3708,7 @@ fn spotlight_decl(decl: &clean::FnDecl, c: &Cache) -> String { "{}", impl_.print(c) )); - let t_did = impl_.trait_.def_id(c).unwrap(); + let t_did = impl_.trait_.def_id_full(c).unwrap(); for it in &impl_.items { if let clean::TypedefItem(ref tydef, _) = *it.kind { out.push_str(" "); @@ -3754,7 +3759,7 @@ fn render_impl( aliases: &[String], ) { let traits = &cx.cache.traits; - let trait_ = i.trait_did(cx.cache()).map(|did| &traits[&did]); + let trait_ = i.trait_did_full(cx.cache()).map(|did| &traits[&did]); if render_mode == RenderMode::Normal { let id = cx.derive_id(match i.inner_impl().trait_ { @@ -3998,7 +4003,7 @@ fn render_impl( if i.items.iter().any(|m| m.name == n) { continue; } - let did = i.trait_.as_ref().unwrap().def_id(cx.cache()).unwrap(); + let did = i.trait_.as_ref().unwrap().def_id_full(cx.cache()).unwrap(); let assoc_link = AssocItemLink::GotoSource(did, &i.provided_trait_methods); doc_impl_item( @@ -4309,7 +4314,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, it: &clean::Item) -> String { if let Some(impl_) = v .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id(cx.cache()) == cx.cache.deref_trait_did) + .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == cx.cache.deref_trait_did) { out.push_str(&sidebar_deref_methods(cx, impl_, v)); } @@ -4396,9 +4401,9 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> Strin let deref_mut = v .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .any(|i| i.inner_impl().trait_.def_id(cx.cache()) == c.deref_mut_trait_did); + .any(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_mut_trait_did); let inner_impl = target - .def_id(cx.cache()) + .def_id_full(cx.cache()) .or_else(|| { target.primitive_type().and_then(|prim| c.primitive_locations.get(&prim).cloned()) }) @@ -4414,7 +4419,7 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> Strin if !ret.is_empty() { let deref_id_map = cx.deref_id_map.borrow(); let id = deref_id_map - .get(&real_target.def_id(cx.cache()).unwrap()) + .get(&real_target.def_id_full(cx.cache()).unwrap()) .expect("Deref section without derived id"); out.push_str(&format!( "Methods from {}<Target={}>", @@ -4429,14 +4434,14 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec) -> Strin } // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id(cx.cache()) { + if let Some(target_did) = target.def_id_full(cx.cache()) { if let Some(target_impls) = c.impls.get(&target_did) { if let Some(target_deref_impl) = target_impls .iter() .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id(cx.cache()) == c.deref_trait_did) + .find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did) { - if let Some(type_did) = impl_.inner_impl().for_.def_id(cx.cache()) { + if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) { // `impl Deref for S` if target_did == type_did { // Avoid infinite cycles @@ -4580,7 +4585,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean .filter(|i| { i.inner_impl() .for_ - .def_id(cx.cache()) + .def_id_full(cx.cache()) .map_or(false, |d| !cx.cache.paths.contains_key(&d)) }) .filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache())) diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 9dc12737d6a86..7b5e9e5905f33 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -2,7 +2,6 @@ use super::Pass; use crate::clean::*; use crate::core::DocContext; use crate::fold::DocFolder; -use crate::formats::cache::Cache; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -97,12 +96,12 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // Gather all type to `Deref` target edges. for it in &new_items { if let ImplItem(Impl { ref for_, ref trait_, ref items, .. }) = *it.kind { - if trait_.def_id(&cx.cache) == cx.tcx.lang_items().deref_trait() { + if trait_.def_id() == cx.tcx.lang_items().deref_trait() { let target = items.iter().find_map(|item| match *item.kind { TypedefItem(ref t, true) => Some(&t.type_), _ => None, }); - if let (Some(for_did), Some(target)) = (for_.def_id(&cx.cache), target) { + if let (Some(for_did), Some(target)) = (for_.def_id(), target) { type_did_to_deref_target.insert(for_did, target); } } @@ -113,20 +112,19 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { map: &FxHashMap, cleaner: &mut BadImplStripper, type_did: &DefId, - cache: &Cache, ) { if let Some(target) = map.get(type_did) { debug!("add_deref_target: type {:?}, target {:?}", type_did, target); if let Some(target_prim) = target.primitive_type() { cleaner.prims.insert(target_prim); - } else if let Some(target_did) = target.def_id(cache) { + } else if let Some(target_did) = target.def_id() { // `impl Deref for S` if target_did == *type_did { // Avoid infinite cycles return; } cleaner.items.insert(target_did); - add_deref_target(map, cleaner, &target_did, cache); + add_deref_target(map, cleaner, &target_did); } } } @@ -135,14 +133,14 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { // `Deref` target type and the impl for type positions, this map of types is keyed by // `DefId` and for convenience uses a special cleaner that accepts `DefId`s directly. if cleaner.keep_impl_with_def_id(type_did) { - add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did, &cx.cache); + add_deref_target(&type_did_to_deref_target, &mut cleaner, type_did); } } new_items.retain(|it| { if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind { - cleaner.keep_impl(for_, &cx.cache) - || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t, &cx.cache)) + cleaner.keep_impl(for_) + || trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t)) || blanket_impl.is_some() } else { true @@ -218,13 +216,13 @@ struct BadImplStripper { } impl BadImplStripper { - fn keep_impl(&self, ty: &Type, cache: &Cache) -> bool { + fn keep_impl(&self, ty: &Type) -> bool { if let Generic(_) = ty { // keep impls made on generics true } else if let Some(prim) = ty.primitive_type() { self.prims.contains(&prim) - } else if let Some(did) = ty.def_id(cache) { + } else if let Some(did) = ty.def_id() { self.keep_impl_with_def_id(&did) } else { false diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index c67f7869f4baf..a276b7a63371b 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -15,7 +15,7 @@ crate const STRIP_HIDDEN: Pass = Pass { }; /// Strip items marked `#[doc(hidden)]` -crate fn strip_hidden(krate: clean::Crate, cx: &DocContext<'_>) -> clean::Crate { +crate fn strip_hidden(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { let mut retained = DefIdSet::default(); // strip all #[doc(hidden)] items @@ -25,7 +25,7 @@ crate fn strip_hidden(krate: clean::Crate, cx: &DocContext<'_>) -> clean::Crate }; // strip all impls referencing stripped items - let mut stripper = ImplStripper { retained: &retained, cache: &cx.cache }; + let mut stripper = ImplStripper { retained: &retained }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs index 0ca4db83b7064..e812bcd87fe3c 100644 --- a/src/librustdoc/passes/strip_private.rs +++ b/src/librustdoc/passes/strip_private.rs @@ -30,6 +30,6 @@ crate fn strip_private(mut krate: clean::Crate, cx: &DocContext<'_>) -> clean::C } // strip all impls referencing private items - let mut stripper = ImplStripper { retained: &retained, cache: &cx.cache }; + let mut stripper = ImplStripper { retained: &retained }; stripper.fold_crate(krate) } diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index 424928e2377b0..162b70973b418 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -4,7 +4,6 @@ use std::mem; use crate::clean::{self, GetDefId, Item}; use crate::fold::{DocFolder, StripItem}; -use crate::formats::cache::Cache; crate struct Stripper<'a> { crate retained: &'a mut DefIdSet, @@ -118,7 +117,6 @@ impl<'a> DocFolder for Stripper<'a> { /// This stripper discards all impls which reference stripped items crate struct ImplStripper<'a> { crate retained: &'a DefIdSet, - crate cache: &'a Cache, } impl<'a> DocFolder for ImplStripper<'a> { @@ -128,13 +126,13 @@ impl<'a> DocFolder for ImplStripper<'a> { if imp.trait_.is_none() && imp.items.is_empty() { return None; } - if let Some(did) = imp.for_.def_id(&self.cache) { + if let Some(did) = imp.for_.def_id() { if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) { debug!("ImplStripper: impl item for stripped type; removing"); return None; } } - if let Some(did) = imp.trait_.def_id(&self.cache) { + if let Some(did) = imp.trait_.def_id() { if did.is_local() && !self.retained.contains(&did) { debug!("ImplStripper: impl item for stripped trait; removing"); return None; @@ -142,7 +140,7 @@ impl<'a> DocFolder for ImplStripper<'a> { } if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) { for typaram in generics { - if let Some(did) = typaram.def_id(&self.cache) { + if let Some(did) = typaram.def_id() { if did.is_local() && !self.retained.contains(&did) { debug!( "ImplStripper: stripped item in trait's generics; removing impl" From 6a36b3f49d209a5321450d934f8a241d5cccbb0e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 21 Jan 2021 21:54:14 +0100 Subject: [PATCH 04/10] Apply review comments and improve code --- src/librustdoc/clean/types.rs | 42 +++++++++++++---------------- src/librustdoc/html/render/cache.rs | 2 +- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1e3c3a23c9884..7f329511c3470 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1410,34 +1410,30 @@ impl Type { impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option { - fn inner(t: &T, cache: Option<&Cache>) -> Option { - match cache { - Some(c) => t.def_id_full(c), - None => t.def_id(), - } - } - - match *self { - ResolvedPath { did, .. } => Some(did), - Primitive(p) => cache.and_then(|c| c.primitive_locations.get(&p).cloned()), - BorrowedRef { type_: box Generic(..), .. } => { - inner(&Primitive(PrimitiveType::Reference), cache) - } - BorrowedRef { ref type_, .. } => inner(&**type_, cache), + let t: &dyn GetDefId = match *self { + ResolvedPath { did, .. } => return Some(did), + Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), + BorrowedRef { type_: box Generic(..), .. } => &Primitive(PrimitiveType::Reference), + BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), Tuple(ref tys) => { if tys.is_empty() { - inner(&Primitive(PrimitiveType::Unit), cache) + &Primitive(PrimitiveType::Unit) } else { - inner(&Primitive(PrimitiveType::Tuple), cache) + &Primitive(PrimitiveType::Tuple) } } - BareFunction(..) => inner(&Primitive(PrimitiveType::Fn), cache), - Never => inner(&Primitive(PrimitiveType::Never), cache), - Slice(..) => inner(&Primitive(PrimitiveType::Slice), cache), - Array(..) => inner(&Primitive(PrimitiveType::Array), cache), - RawPointer(..) => inner(&Primitive(PrimitiveType::RawPointer), cache), - QPath { ref self_type, .. } => inner(&**self_type, cache), - _ => None, + BareFunction(..) => &Primitive(PrimitiveType::Fn), + Never => &Primitive(PrimitiveType::Never), + Slice(..) => &Primitive(PrimitiveType::Slice), + Array(..) => &Primitive(PrimitiveType::Array), + RawPointer(..) => &Primitive(PrimitiveType::RawPointer), + QPath { ref self_type, .. } => return self_type.inner_def_id(cache), + // FIXME: remove this wildcard + _ => return None, + }; + match cache { + Some(c) => t.def_id_full(c), + None => t.def_id(), } } } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 74a770b954853..5c02be14181ed 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -78,7 +78,7 @@ crate fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { desc: item.doc_value().map_or_else(String::new, |s| short_markdown_summary(&s)), parent: Some(did), parent_idx: None, - search_type: get_index_search_type(&item, Some(cache)), + search_type: get_index_search_type(&item, None), }); for alias in item.attrs.get_doc_aliases() { cache From d98a72c77bb4bbc58598a285446bde63b9b372c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 22 Jan 2021 21:17:32 +0100 Subject: [PATCH 05/10] Update to new rustdoc APIs --- src/librustdoc/clean/types.rs | 1 - src/librustdoc/formats/renderer.rs | 7 ++----- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/json/mod.rs | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7f329511c3470..46cdefb5a517f 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -37,7 +37,6 @@ use crate::clean::inline; use crate::clean::types::Type::{QPath, ResolvedPath}; use crate::clean::Clean; use crate::core::DocContext; -use crate::doctree; use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::render::cache::ExternalLocation; diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 65e2187e4aeab..6ecc4695dc8fb 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,4 +1,4 @@ -use rustc_middle::ty; +use rustc_middle::ty::TyCtxt; use rustc_span::edition::Edition; use crate::clean; @@ -21,7 +21,7 @@ crate trait FormatRenderer<'tcx>: Clone { render_info: RenderInfo, edition: Edition, cache: Cache, - tcx: ty::TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error>; /// Renders a single non-module item. This means no recursive sub-item rendering is required. @@ -69,9 +69,6 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( .extra_verbose_generic_activity("create_renderer", T::descr()) .run(|| T::init(krate, options, render_info, edition, cache, tcx))?; - let (mut format_renderer, mut krate) = - T::init(krate, options, render_info, edition, cache, tcx)?; - let mut item = match krate.module.take() { Some(i) => i, None => return Ok(()), diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f4ff1f3b6d55b..187e0ec0106b3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -394,7 +394,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { _render_info: RenderInfo, edition: Edition, mut cache: Cache, - tcx: ty::TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error> { // need to save a copy of the options for rendering the index page let md_opts = options.clone(); diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 6b19e9885c7a6..029e752df9f9d 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -136,7 +136,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { _render_info: RenderInfo, _edition: Edition, cache: Cache, - tcx: ty::TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error> { debug!("Initializing json renderer"); Ok(( From 522f48cb3fc5858a8be12e4c7f6b52829b289851 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 23 Jan 2021 23:45:54 +0100 Subject: [PATCH 06/10] Improve documentation on GetDefId trait's methods --- src/librustdoc/clean/types.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 46cdefb5a517f..f23d3df4a6363 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1305,10 +1305,20 @@ crate enum TypeKind { } crate trait GetDefId { - /// Doesn't retrieve primitive types `DefId`. Use `def_id_full` if you want it. + /// 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 are calling it on a primitive [`clean::Type`]. + /// + /// [`clean`]: crate::clean + /// [`clean::Type`]: Type fn def_id(&self) -> Option; - /// Retrieves all types' `DefId` (including primitives). If you're not interested about - /// primitives, use `def_id`. + + /// Use this method to get the [`DefId`] of a [`clean`] AST node that may be + /// a primitive [`clean::Type`]. + /// + /// See [`Self::def_id`] for more. + /// + /// [`clean::Type`]: Type fn def_id_full(&self, cache: &Cache) -> Option; } From 9a64180f0d51de5cb4aa3fe8b3f3d14be5ee103c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 24 Jan 2021 01:08:34 +0100 Subject: [PATCH 07/10] Unify cache usage and improve naming --- src/librustdoc/html/render/mod.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 187e0ec0106b3..c71b2b549e1f0 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1144,7 +1144,7 @@ themePicker.onblur = handleThemeButtonsBlur; Some(Implementor { text: imp.inner_impl().print(cx.cache()).to_string(), synthetic: imp.inner_impl().synthetic, - types: collect_paths_for_type(imp.inner_impl().for_.clone(), &cx.cache), + types: collect_paths_for_type(imp.inner_impl().for_.clone(), cx.cache()), }) } }) @@ -2466,7 +2466,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean:: WhereClause { gens: &f.generics, indent: 0, end_newline: true }.print(cx.cache()), decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness } .print(cx.cache()), - spotlight = spotlight_decl(&f.decl, &cx.cache), + spotlight = spotlight_decl(&f.decl, cx.cache()), ); document(w, cx, it, None) } @@ -3685,30 +3685,31 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo } } -fn spotlight_decl(decl: &clean::FnDecl, c: &Cache) -> String { +fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String { let mut out = Buffer::html(); let mut trait_ = String::new(); - if let Some(did) = decl.output.def_id_full(c) { - if let Some(impls) = c.impls.get(&did) { + if let Some(did) = decl.output.def_id_full(cache) { + if let Some(impls) = cache.impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); - if impl_.trait_.def_id_full(c).map_or(false, |d| c.traits[&d].is_spotlight) { + if impl_.trait_.def_id_full(cache).map_or(false, |d| cache.traits[&d].is_spotlight) + { if out.is_empty() { out.push_str(&format!( "

Notable traits for {}

\ ", - impl_.for_.print(c) + impl_.for_.print(cache) )); - trait_.push_str(&impl_.for_.print(c).to_string()); + trait_.push_str(&impl_.for_.print(cache).to_string()); } //use the "where" class here to make it small out.push_str(&format!( "{}", - impl_.print(c) + impl_.print(cache) )); - let t_did = impl_.trait_.def_id_full(c).unwrap(); + let t_did = impl_.trait_.def_id_full(cache).unwrap(); for it in &impl_.items { if let clean::TypedefItem(ref tydef, _) = *it.kind { out.push_str(" "); @@ -3719,7 +3720,7 @@ fn spotlight_decl(decl: &clean::FnDecl, c: &Cache) -> String { Some(&tydef.type_), AssocItemLink::GotoSource(t_did, &FxHashSet::default()), "", - c, + cache, ); out.push_str(";"); } From cac238e4a3a838f9379b4c07d7463226929cf424 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 24 Jan 2021 17:41:21 +0100 Subject: [PATCH 08/10] More cleanup --- src/librustdoc/clean/types.rs | 32 +++++++++++++------------------ src/librustdoc/html/render/mod.rs | 7 ++----- src/librustdoc/json/mod.rs | 9 +++------ 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index f23d3df4a6363..7b5abc0335e27 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1307,18 +1307,15 @@ crate enum TypeKind { 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 are calling it on a primitive [`clean::Type`]. + /// Use [`Self::def_id_full`] if you want to include primitives. /// /// [`clean`]: crate::clean - /// [`clean::Type`]: Type + // FIXME: get rid of this function and always use `def_id_full` fn def_id(&self) -> Option; - /// Use this method to get the [`DefId`] of a [`clean`] AST node that may be - /// a primitive [`clean::Type`]. + /// Use this method to get the [DefId] of a [clean] AST node, including [PrimitiveType]s. /// /// See [`Self::def_id`] for more. - /// - /// [`clean::Type`]: Type fn def_id_full(&self, cache: &Cache) -> Option; } @@ -1419,31 +1416,28 @@ impl Type { impl Type { fn inner_def_id(&self, cache: Option<&Cache>) -> Option { - let t: &dyn GetDefId = match *self { + let t: PrimitiveType = match *self { ResolvedPath { did, .. } => return Some(did), Primitive(p) => return cache.and_then(|c| c.primitive_locations.get(&p).cloned()), - BorrowedRef { type_: box Generic(..), .. } => &Primitive(PrimitiveType::Reference), + BorrowedRef { type_: box Generic(..), .. } => PrimitiveType::Reference, BorrowedRef { ref type_, .. } => return type_.inner_def_id(cache), Tuple(ref tys) => { if tys.is_empty() { - &Primitive(PrimitiveType::Unit) + PrimitiveType::Unit } else { - &Primitive(PrimitiveType::Tuple) + PrimitiveType::Tuple } } - BareFunction(..) => &Primitive(PrimitiveType::Fn), - Never => &Primitive(PrimitiveType::Never), - Slice(..) => &Primitive(PrimitiveType::Slice), - Array(..) => &Primitive(PrimitiveType::Array), - RawPointer(..) => &Primitive(PrimitiveType::RawPointer), + BareFunction(..) => PrimitiveType::Fn, + Never => PrimitiveType::Never, + Slice(..) => PrimitiveType::Slice, + Array(..) => PrimitiveType::Array, + RawPointer(..) => PrimitiveType::RawPointer, QPath { ref self_type, .. } => return self_type.inner_def_id(cache), // FIXME: remove this wildcard _ => return None, }; - match cache { - Some(c) => t.def_id_full(c), - None => t.def_id(), - } + cache.and_then(|c| Primitive(t).def_id_full(c)) } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index c71b2b549e1f0..bb9a7be590e87 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2587,11 +2587,8 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra ); if !t.generics.where_predicates.is_empty() { - write!( - w, - "{}", - WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()) - ); + let where_ = WhereClause { gens: &t.generics, indent: 0, end_newline: true }; + write!(w, "{}", where_.print(cx.cache())); } else { write!(w, " "); } diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 029e752df9f9d..a8a4b74b818b6 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -41,8 +41,7 @@ impl JsonRenderer<'_> { } fn get_trait_implementors(&mut self, id: rustc_span::def_id::DefId) -> Vec { - self.cache - .clone() + Rc::clone(&self.cache) .implementors .get(&id) .map(|implementors| { @@ -59,8 +58,7 @@ impl JsonRenderer<'_> { } fn get_impls(&mut self, id: rustc_span::def_id::DefId) -> Vec { - self.cache - .clone() + Rc::clone(&self.cache) .impls .get(&id) .map(|impls| { @@ -81,8 +79,7 @@ impl JsonRenderer<'_> { } fn get_trait_items(&mut self) -> Vec<(types::Id, types::Item)> { - self.cache - .clone() + Rc::clone(&self.cache) .traits .iter() .filter_map(|(&id, trait_item)| { From 5f22b30ca6020720d2934c3ef850ea879a1419e3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 24 Jan 2021 17:41:41 +0100 Subject: [PATCH 09/10] Add search index test for primitive types --- src/test/rustdoc-js-std/primitive.js | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/test/rustdoc-js-std/primitive.js diff --git a/src/test/rustdoc-js-std/primitive.js b/src/test/rustdoc-js-std/primitive.js new file mode 100644 index 0000000000000..e5690383e4f0b --- /dev/null +++ b/src/test/rustdoc-js-std/primitive.js @@ -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', + }, + ] + }, +]; From d78e1ed623d0679f20bd12ae79f41629218ff916 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 26 Jan 2021 11:40:48 +0100 Subject: [PATCH 10/10] Fix clean/types doc links --- src/librustdoc/clean/types.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7b5abc0335e27..86bce8b8707a0 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1310,12 +1310,15 @@ crate trait GetDefId { /// 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; /// 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; }