Auto merge of #84457 - jyn514:cleanup-crate, r=GuillaumeGomez
rustdoc: Remove most fields from ExternalCrate Once https://github.com/rust-lang/rust/issues/84304 is fixed, I can get rid of ExternCrate altogether in favor of CrateNum, but in the meantime, this shrinks ExternalCrate quite a lot. This might hurt compile-times; if it does, I can add `primitive` and `keyword` queries. I expect this to improve compilemem. Helps with https://github.com/rust-lang/rust/issues/76382. r? GuillaumeGomez
This commit is contained in:
commit
484c61943f
5 changed files with 150 additions and 132 deletions
|
@ -84,123 +84,8 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
|
|||
|
||||
impl Clean<ExternalCrate> 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.
|
||||
//
|
||||
// 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| {
|
||||
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 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 {
|
||||
name: tcx.crate_name(*self),
|
||||
src: krate_src,
|
||||
attrs: tcx.get_attrs(root).clean(cx),
|
||||
primitives,
|
||||
keywords,
|
||||
}
|
||||
ExternalCrate { crate_num: *self, attrs: cx.tcx.get_attrs(root).clean(cx) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -72,11 +72,138 @@ crate struct TraitWithExtraInfo {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
crate struct ExternalCrate {
|
||||
crate name: Symbol,
|
||||
crate src: FileName,
|
||||
crate crate_num: CrateNum,
|
||||
crate attrs: Attributes,
|
||||
crate primitives: ThinVec<(DefId, PrimitiveType)>,
|
||||
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 krate_span = tcx.def_span(self.def_id());
|
||||
tcx.sess.source_map().span_to_filename(krate_span)
|
||||
}
|
||||
|
||||
crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
|
||||
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 = self.def_id();
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -54,7 +54,11 @@ 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 name = local_crate.name(cx.tcx);
|
||||
let primitives = local_crate.primitives(cx.tcx);
|
||||
let keywords = local_crate.keywords(cx.tcx);
|
||||
{
|
||||
let m = match *module.kind {
|
||||
ItemKind::ModuleItem(ref mut m) => m,
|
||||
|
|
|
@ -155,19 +155,20 @@ 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(),
|
||||
},
|
||||
_ => 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.
|
||||
|
@ -175,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue