From 5407a69aa4a816fdfd9cf6f659643f78659c1f88 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 22 Apr 2021 18:54:48 -0400 Subject: [PATCH 1/4] Remove src field from ExternCrate --- src/librustdoc/clean/mod.rs | 4 +--- src/librustdoc/clean/types.rs | 10 +++++++++- src/librustdoc/clean/utils.rs | 4 +++- src/librustdoc/formats/cache.rs | 2 +- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7d33cf210139c..1b8c82b8323f5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -86,8 +86,6 @@ impl Clean for CrateNum { fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate { let tcx = cx.tcx; let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; - let krate_span = tcx.def_span(root); - let krate_src = cx.sess().source_map().span_to_filename(krate_span); // Collect all inner modules which are tagged as implementations of // primitives. @@ -195,8 +193,8 @@ impl Clean for CrateNum { }; ExternalCrate { + crate_num: *self, name: tcx.crate_name(*self), - src: krate_src, attrs: tcx.get_attrs(root).clean(cx), primitives, keywords, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 2b25c6a26bcc4..b24d441f0f85c 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -72,13 +72,21 @@ crate struct TraitWithExtraInfo { #[derive(Clone, Debug)] crate struct ExternalCrate { + crate crate_num: CrateNum, crate name: Symbol, - crate src: FileName, crate attrs: Attributes, crate primitives: ThinVec<(DefId, PrimitiveType)>, crate keywords: ThinVec<(DefId, Symbol)>, } +impl ExternalCrate { + crate fn src(&self, tcx: TyCtxt<'_>) -> FileName { + let root = DefId { krate: self.crate_num, index: rustc_hir::def_id::CRATE_DEF_INDEX }; + let krate_span = tcx.def_span(root); + tcx.sess.source_map().span_to_filename(krate_span) + } +} + /// Anything with a source location and set of attributes and, optionally, a /// name. That is, anything that can be documented. This doesn't correspond /// directly to the AST's concept of an item; it's a strict superset. diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index c2a971d637513..7d058f9e92c60 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -54,7 +54,9 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { _ => unreachable!(), } - let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx); + let local_crate = LOCAL_CRATE.clean(cx); + let src = local_crate.src(cx.tcx); + let ExternalCrate { name, primitives, keywords, .. } = local_crate; { let m = match *module.kind { ItemKind::ModuleItem(ref mut m) => m, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index b2b895cc6726e..5766ed7497d7f 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -155,7 +155,7 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code for &(n, ref e) in &krate.externs { - let src_root = match e.src { + let src_root = match e.src(tcx) { FileName::Real(ref p) => match p.local_path().parent() { Some(p) => p.to_path_buf(), None => PathBuf::new(), From 3bef65ffaf3ea435fa653bd99c72b3adde93ea95 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 22 Apr 2021 19:02:09 -0400 Subject: [PATCH 2/4] Remove `name` field from ExternalCrate --- src/librustdoc/clean/mod.rs | 1 - src/librustdoc/clean/types.rs | 5 ++++- src/librustdoc/clean/utils.rs | 3 ++- src/librustdoc/formats/cache.rs | 7 ++++--- src/librustdoc/html/render/cache.rs | 3 ++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1b8c82b8323f5..2ea119626fe42 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -194,7 +194,6 @@ impl Clean for CrateNum { ExternalCrate { crate_num: *self, - name: tcx.crate_name(*self), attrs: tcx.get_attrs(root).clean(cx), primitives, keywords, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b24d441f0f85c..a28e94eb2c8c5 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -73,7 +73,6 @@ crate struct TraitWithExtraInfo { #[derive(Clone, Debug)] crate struct ExternalCrate { crate crate_num: CrateNum, - crate name: Symbol, crate attrs: Attributes, crate primitives: ThinVec<(DefId, PrimitiveType)>, crate keywords: ThinVec<(DefId, Symbol)>, @@ -85,6 +84,10 @@ impl ExternalCrate { let krate_span = tcx.def_span(root); tcx.sess.source_map().span_to_filename(krate_span) } + + crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol { + tcx.crate_name(self.crate_num) + } } /// Anything with a source location and set of attributes and, optionally, a diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 7d058f9e92c60..6f230e27534af 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -56,7 +56,8 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { let local_crate = LOCAL_CRATE.clean(cx); let src = local_crate.src(cx.tcx); - let ExternalCrate { name, primitives, keywords, .. } = local_crate; + let name = local_crate.name(cx.tcx); + let ExternalCrate { primitives, keywords, .. } = local_crate; { let m = match *module.kind { ItemKind::ModuleItem(ref mut m) => m, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5766ed7497d7f..5c011c5a13c19 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -162,12 +162,13 @@ impl Cache { }, _ => PathBuf::new(), }; - let extern_url = extern_html_root_urls.get(&*e.name.as_str()).map(|u| &**u); + let name = e.name(tcx); + let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u); self.extern_locations - .insert(n, (e.name, src_root, extern_location(e, extern_url, &dst))); + .insert(n, (name, src_root, extern_location(e, extern_url, &dst, tcx))); let did = DefId { krate: n, index: CRATE_DEF_INDEX }; - self.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); + self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module)); } // Cache where all known primitives have their documentation located. diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 2265905dcbaf4..b8544a0f439a7 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -31,10 +31,11 @@ crate fn extern_location( e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path, + tcx: TyCtxt<'_>, ) -> ExternalLocation { use ExternalLocation::*; // See if there's documentation generated into the local directory - let local_location = dst.join(&*e.name.as_str()); + let local_location = dst.join(&*e.name(tcx).as_str()); if local_location.is_dir() { return Local; } From d1d173967367c4ebc8a824b64a2ba965b89aac47 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 22 Apr 2021 19:10:22 -0400 Subject: [PATCH 3/4] Get rid of ExternCrate::primitives --- src/librustdoc/clean/mod.rs | 75 ++------------------------------- src/librustdoc/clean/types.rs | 74 ++++++++++++++++++++++++++++++-- src/librustdoc/clean/utils.rs | 3 +- src/librustdoc/formats/cache.rs | 2 +- 4 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2ea119626fe42..10ab757c5fce1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -87,73 +87,9 @@ impl Clean for CrateNum { let tcx = cx.tcx; let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; - // Collect all inner modules which are tagged as implementations of - // primitives. - // - // Note that this loop only searches the top-level items of the crate, - // and this is intentional. If we were to search the entire crate for an - // item tagged with `#[doc(primitive)]` then we would also have to - // search the entirety of external modules for items tagged - // `#[doc(primitive)]`, which is a pretty inefficient process (decoding - // all that metadata unconditionally). - // - // In order to keep the metadata load under control, the - // `#[doc(primitive)]` feature is explicitly designed to only allow the - // primitive tags to show up as the top level items in a crate. - // - // Also note that this does not attempt to deal with modules tagged - // duplicately for the same primitive. This is handled later on when - // rendering by delegating everything to a hash map. - let mut as_primitive = |res: Res| { + let as_keyword = |res: Res| { if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = cx.tcx.get_attrs(def_id).clean(cx); - let mut prim = None; - for attr in attrs.lists(sym::doc) { - if let Some(v) = attr.value_str() { - if attr.has_name(sym::primitive) { - prim = PrimitiveType::from_symbol(v); - if prim.is_some() { - break; - } - // FIXME: should warn on unknown primitives? - } - } - } - return prim.map(|p| (def_id, p)); - } - None - }; - let primitives = if root.is_local() { - tcx.hir() - .krate() - .item - .item_ids - .iter() - .filter_map(|&id| { - let item = tcx.hir().item(id); - match item.kind { - hir::ItemKind::Mod(_) => { - as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id())) - } - hir::ItemKind::Use(ref path, hir::UseKind::Single) - if item.vis.node.is_pub() => - { - as_primitive(path.res).map(|(_, prim)| { - // Pretend the primitive is local. - (id.def_id.to_def_id(), prim) - }) - } - _ => None, - } - }) - .collect() - } else { - tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect() - }; - - let mut as_keyword = |res: Res| { - if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = tcx.get_attrs(def_id).clean(cx); + let attrs = tcx.get_attrs(def_id); let mut keyword = None; for attr in attrs.lists(sym::doc) { if attr.has_name(sym::keyword) { @@ -192,12 +128,7 @@ impl Clean for CrateNum { tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect() }; - ExternalCrate { - crate_num: *self, - attrs: tcx.get_attrs(root).clean(cx), - primitives, - keywords, - } + ExternalCrate { crate_num: *self, attrs: tcx.get_attrs(root).clean(cx), keywords } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index a28e94eb2c8c5..1d32db062ee68 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -17,8 +17,8 @@ use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex}; +use rustc_hir::def::{CtorKind, DefKind, Res}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc_hir::lang_items::LangItem; use rustc_hir::{BodyId, Mutability}; use rustc_index::vec::IndexVec; @@ -74,7 +74,6 @@ crate struct TraitWithExtraInfo { crate struct ExternalCrate { crate crate_num: CrateNum, crate attrs: Attributes, - crate primitives: ThinVec<(DefId, PrimitiveType)>, crate keywords: ThinVec<(DefId, Symbol)>, } @@ -88,6 +87,75 @@ impl ExternalCrate { crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol { tcx.crate_name(self.crate_num) } + + crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> { + let root = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }; + + // Collect all inner modules which are tagged as implementations of + // primitives. + // + // Note that this loop only searches the top-level items of the crate, + // and this is intentional. If we were to search the entire crate for an + // item tagged with `#[doc(primitive)]` then we would also have to + // search the entirety of external modules for items tagged + // `#[doc(primitive)]`, which is a pretty inefficient process (decoding + // all that metadata unconditionally). + // + // In order to keep the metadata load under control, the + // `#[doc(primitive)]` feature is explicitly designed to only allow the + // primitive tags to show up as the top level items in a crate. + // + // Also note that this does not attempt to deal with modules tagged + // duplicately for the same primitive. This is handled later on when + // rendering by delegating everything to a hash map. + let as_primitive = |res: Res| { + if let Res::Def(DefKind::Mod, def_id) = res { + let attrs = tcx.get_attrs(def_id); + let mut prim = None; + for attr in attrs.lists(sym::doc) { + if let Some(v) = attr.value_str() { + if attr.has_name(sym::primitive) { + prim = PrimitiveType::from_symbol(v); + if prim.is_some() { + break; + } + // FIXME: should warn on unknown primitives? + } + } + } + return prim.map(|p| (def_id, p)); + } + None + }; + + if root.is_local() { + tcx.hir() + .krate() + .item + .item_ids + .iter() + .filter_map(|&id| { + let item = tcx.hir().item(id); + match item.kind { + hir::ItemKind::Mod(_) => { + as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id())) + } + hir::ItemKind::Use(ref path, hir::UseKind::Single) + if item.vis.node.is_pub() => + { + as_primitive(path.res).map(|(_, prim)| { + // Pretend the primitive is local. + (id.def_id.to_def_id(), prim) + }) + } + _ => None, + } + }) + .collect() + } else { + tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect() + } + } } /// Anything with a source location and set of attributes and, optionally, a diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 6f230e27534af..a066777609d92 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -57,7 +57,8 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { let local_crate = LOCAL_CRATE.clean(cx); let src = local_crate.src(cx.tcx); let name = local_crate.name(cx.tcx); - let ExternalCrate { primitives, keywords, .. } = local_crate; + let primitives = local_crate.primitives(cx.tcx); + let ExternalCrate { keywords, .. } = local_crate; { let m = match *module.kind { ItemKind::ModuleItem(ref mut m) => m, diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 5c011c5a13c19..9a61f963a3ec3 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -176,7 +176,7 @@ impl Cache { // Favor linking to as local extern as possible, so iterate all crates in // reverse topological order. for &(_, ref e) in krate.externs.iter().rev() { - for &(def_id, prim) in &e.primitives { + for &(def_id, prim) in &e.primitives(tcx) { self.primitive_locations.insert(prim, def_id); } } From 6c6bd88ab36593f60e9dcf252a3bd9511374874a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 22 Apr 2021 19:16:41 -0400 Subject: [PATCH 4/4] Remove `keywords` from ExternCrate --- src/librustdoc/clean/mod.rs | 45 +--------------------------- src/librustdoc/clean/types.rs | 56 ++++++++++++++++++++++++++++++++--- src/librustdoc/clean/utils.rs | 8 ++--- 3 files changed, 57 insertions(+), 52 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 10ab757c5fce1..72046645e3a97 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -84,51 +84,8 @@ impl, U> Clean> for Option { impl Clean for CrateNum { fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate { - let tcx = cx.tcx; let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; - - let as_keyword = |res: Res| { - if let Res::Def(DefKind::Mod, def_id) = res { - let attrs = tcx.get_attrs(def_id); - let mut keyword = None; - for attr in attrs.lists(sym::doc) { - if attr.has_name(sym::keyword) { - if let Some(v) = attr.value_str() { - keyword = Some(v); - break; - } - } - } - return keyword.map(|p| (def_id, p)); - } - None - }; - let keywords = if root.is_local() { - tcx.hir() - .krate() - .item - .item_ids - .iter() - .filter_map(|&id| { - let item = tcx.hir().item(id); - match item.kind { - hir::ItemKind::Mod(_) => { - as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id())) - } - hir::ItemKind::Use(ref path, hir::UseKind::Single) - if item.vis.node.is_pub() => - { - as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) - } - _ => None, - } - }) - .collect() - } else { - tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect() - }; - - ExternalCrate { crate_num: *self, attrs: tcx.get_attrs(root).clean(cx), keywords } + ExternalCrate { crate_num: *self, attrs: cx.tcx.get_attrs(root).clean(cx) } } } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1d32db062ee68..9f686d19e3c91 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -74,13 +74,16 @@ crate struct TraitWithExtraInfo { crate struct ExternalCrate { crate crate_num: CrateNum, crate attrs: Attributes, - crate keywords: ThinVec<(DefId, Symbol)>, } impl ExternalCrate { + #[inline] + fn def_id(&self) -> DefId { + DefId { krate: self.crate_num, index: CRATE_DEF_INDEX } + } + crate fn src(&self, tcx: TyCtxt<'_>) -> FileName { - let root = DefId { krate: self.crate_num, index: rustc_hir::def_id::CRATE_DEF_INDEX }; - let krate_span = tcx.def_span(root); + let krate_span = tcx.def_span(self.def_id()); tcx.sess.source_map().span_to_filename(krate_span) } @@ -88,8 +91,53 @@ impl ExternalCrate { tcx.crate_name(self.crate_num) } + crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> { + let root = self.def_id(); + + let as_keyword = |res: Res| { + if let Res::Def(DefKind::Mod, def_id) = res { + let attrs = tcx.get_attrs(def_id); + let mut keyword = None; + for attr in attrs.lists(sym::doc) { + if attr.has_name(sym::keyword) { + if let Some(v) = attr.value_str() { + keyword = Some(v); + break; + } + } + } + return keyword.map(|p| (def_id, p)); + } + None + }; + if root.is_local() { + tcx.hir() + .krate() + .item + .item_ids + .iter() + .filter_map(|&id| { + let item = tcx.hir().item(id); + match item.kind { + hir::ItemKind::Mod(_) => { + as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id())) + } + hir::ItemKind::Use(ref path, hir::UseKind::Single) + if item.vis.node.is_pub() => + { + as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim)) + } + _ => None, + } + }) + .collect() + } else { + tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect() + } + } + crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> { - let root = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }; + let root = self.def_id(); // Collect all inner modules which are tagged as implementations of // primitives. diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index a066777609d92..55a0cb42a2081 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -1,9 +1,9 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ - inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item, - ItemKind, Lifetime, MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, - TypeBinding, TypeKind, + inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime, + MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding, + TypeKind, }; use crate::core::DocContext; @@ -58,7 +58,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate { let src = local_crate.src(cx.tcx); let name = local_crate.name(cx.tcx); let primitives = local_crate.primitives(cx.tcx); - let ExternalCrate { keywords, .. } = local_crate; + let keywords = local_crate.keywords(cx.tcx); { let m = match *module.kind { ItemKind::ModuleItem(ref mut m) => m,