Skip to content

Commit 484c619

Browse files
committed
Auto merge of rust-lang#84457 - jyn514:cleanup-crate, r=GuillaumeGomez
rustdoc: Remove most fields from ExternalCrate Once rust-lang#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 rust-lang#76382. r? GuillaumeGomez
2 parents 9a35232 + 6c6bd88 commit 484c619

File tree

5 files changed

+150
-132
lines changed

5 files changed

+150
-132
lines changed

src/librustdoc/clean/mod.rs

+1-116
Original file line numberDiff line numberDiff line change
@@ -84,123 +84,8 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
8484

8585
impl Clean<ExternalCrate> for CrateNum {
8686
fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate {
87-
let tcx = cx.tcx;
8887
let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
89-
let krate_span = tcx.def_span(root);
90-
let krate_src = cx.sess().source_map().span_to_filename(krate_span);
91-
92-
// Collect all inner modules which are tagged as implementations of
93-
// primitives.
94-
//
95-
// Note that this loop only searches the top-level items of the crate,
96-
// and this is intentional. If we were to search the entire crate for an
97-
// item tagged with `#[doc(primitive)]` then we would also have to
98-
// search the entirety of external modules for items tagged
99-
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
100-
// all that metadata unconditionally).
101-
//
102-
// In order to keep the metadata load under control, the
103-
// `#[doc(primitive)]` feature is explicitly designed to only allow the
104-
// primitive tags to show up as the top level items in a crate.
105-
//
106-
// Also note that this does not attempt to deal with modules tagged
107-
// duplicately for the same primitive. This is handled later on when
108-
// rendering by delegating everything to a hash map.
109-
let mut as_primitive = |res: Res| {
110-
if let Res::Def(DefKind::Mod, def_id) = res {
111-
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
112-
let mut prim = None;
113-
for attr in attrs.lists(sym::doc) {
114-
if let Some(v) = attr.value_str() {
115-
if attr.has_name(sym::primitive) {
116-
prim = PrimitiveType::from_symbol(v);
117-
if prim.is_some() {
118-
break;
119-
}
120-
// FIXME: should warn on unknown primitives?
121-
}
122-
}
123-
}
124-
return prim.map(|p| (def_id, p));
125-
}
126-
None
127-
};
128-
let primitives = if root.is_local() {
129-
tcx.hir()
130-
.krate()
131-
.item
132-
.item_ids
133-
.iter()
134-
.filter_map(|&id| {
135-
let item = tcx.hir().item(id);
136-
match item.kind {
137-
hir::ItemKind::Mod(_) => {
138-
as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
139-
}
140-
hir::ItemKind::Use(ref path, hir::UseKind::Single)
141-
if item.vis.node.is_pub() =>
142-
{
143-
as_primitive(path.res).map(|(_, prim)| {
144-
// Pretend the primitive is local.
145-
(id.def_id.to_def_id(), prim)
146-
})
147-
}
148-
_ => None,
149-
}
150-
})
151-
.collect()
152-
} else {
153-
tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
154-
};
155-
156-
let mut as_keyword = |res: Res| {
157-
if let Res::Def(DefKind::Mod, def_id) = res {
158-
let attrs = tcx.get_attrs(def_id).clean(cx);
159-
let mut keyword = None;
160-
for attr in attrs.lists(sym::doc) {
161-
if attr.has_name(sym::keyword) {
162-
if let Some(v) = attr.value_str() {
163-
keyword = Some(v);
164-
break;
165-
}
166-
}
167-
}
168-
return keyword.map(|p| (def_id, p));
169-
}
170-
None
171-
};
172-
let keywords = if root.is_local() {
173-
tcx.hir()
174-
.krate()
175-
.item
176-
.item_ids
177-
.iter()
178-
.filter_map(|&id| {
179-
let item = tcx.hir().item(id);
180-
match item.kind {
181-
hir::ItemKind::Mod(_) => {
182-
as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
183-
}
184-
hir::ItemKind::Use(ref path, hir::UseKind::Single)
185-
if item.vis.node.is_pub() =>
186-
{
187-
as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
188-
}
189-
_ => None,
190-
}
191-
})
192-
.collect()
193-
} else {
194-
tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
195-
};
196-
197-
ExternalCrate {
198-
name: tcx.crate_name(*self),
199-
src: krate_src,
200-
attrs: tcx.get_attrs(root).clean(cx),
201-
primitives,
202-
keywords,
203-
}
88+
ExternalCrate { crate_num: *self, attrs: cx.tcx.get_attrs(root).clean(cx) }
20489
}
20590
}
20691

src/librustdoc/clean/types.rs

+133-6
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
1717
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1818
use rustc_data_structures::thin_vec::ThinVec;
1919
use rustc_hir as hir;
20-
use rustc_hir::def::{CtorKind, Res};
21-
use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
20+
use rustc_hir::def::{CtorKind, DefKind, Res};
21+
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
2222
use rustc_hir::lang_items::LangItem;
2323
use rustc_hir::{BodyId, Mutability};
2424
use rustc_index::vec::IndexVec;
@@ -72,11 +72,138 @@ crate struct TraitWithExtraInfo {
7272

7373
#[derive(Clone, Debug)]
7474
crate struct ExternalCrate {
75-
crate name: Symbol,
76-
crate src: FileName,
75+
crate crate_num: CrateNum,
7776
crate attrs: Attributes,
78-
crate primitives: ThinVec<(DefId, PrimitiveType)>,
79-
crate keywords: ThinVec<(DefId, Symbol)>,
77+
}
78+
79+
impl ExternalCrate {
80+
#[inline]
81+
fn def_id(&self) -> DefId {
82+
DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
83+
}
84+
85+
crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
86+
let krate_span = tcx.def_span(self.def_id());
87+
tcx.sess.source_map().span_to_filename(krate_span)
88+
}
89+
90+
crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
91+
tcx.crate_name(self.crate_num)
92+
}
93+
94+
crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
95+
let root = self.def_id();
96+
97+
let as_keyword = |res: Res| {
98+
if let Res::Def(DefKind::Mod, def_id) = res {
99+
let attrs = tcx.get_attrs(def_id);
100+
let mut keyword = None;
101+
for attr in attrs.lists(sym::doc) {
102+
if attr.has_name(sym::keyword) {
103+
if let Some(v) = attr.value_str() {
104+
keyword = Some(v);
105+
break;
106+
}
107+
}
108+
}
109+
return keyword.map(|p| (def_id, p));
110+
}
111+
None
112+
};
113+
if root.is_local() {
114+
tcx.hir()
115+
.krate()
116+
.item
117+
.item_ids
118+
.iter()
119+
.filter_map(|&id| {
120+
let item = tcx.hir().item(id);
121+
match item.kind {
122+
hir::ItemKind::Mod(_) => {
123+
as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
124+
}
125+
hir::ItemKind::Use(ref path, hir::UseKind::Single)
126+
if item.vis.node.is_pub() =>
127+
{
128+
as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
129+
}
130+
_ => None,
131+
}
132+
})
133+
.collect()
134+
} else {
135+
tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
136+
}
137+
}
138+
139+
crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
140+
let root = self.def_id();
141+
142+
// Collect all inner modules which are tagged as implementations of
143+
// primitives.
144+
//
145+
// Note that this loop only searches the top-level items of the crate,
146+
// and this is intentional. If we were to search the entire crate for an
147+
// item tagged with `#[doc(primitive)]` then we would also have to
148+
// search the entirety of external modules for items tagged
149+
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
150+
// all that metadata unconditionally).
151+
//
152+
// In order to keep the metadata load under control, the
153+
// `#[doc(primitive)]` feature is explicitly designed to only allow the
154+
// primitive tags to show up as the top level items in a crate.
155+
//
156+
// Also note that this does not attempt to deal with modules tagged
157+
// duplicately for the same primitive. This is handled later on when
158+
// rendering by delegating everything to a hash map.
159+
let as_primitive = |res: Res| {
160+
if let Res::Def(DefKind::Mod, def_id) = res {
161+
let attrs = tcx.get_attrs(def_id);
162+
let mut prim = None;
163+
for attr in attrs.lists(sym::doc) {
164+
if let Some(v) = attr.value_str() {
165+
if attr.has_name(sym::primitive) {
166+
prim = PrimitiveType::from_symbol(v);
167+
if prim.is_some() {
168+
break;
169+
}
170+
// FIXME: should warn on unknown primitives?
171+
}
172+
}
173+
}
174+
return prim.map(|p| (def_id, p));
175+
}
176+
None
177+
};
178+
179+
if root.is_local() {
180+
tcx.hir()
181+
.krate()
182+
.item
183+
.item_ids
184+
.iter()
185+
.filter_map(|&id| {
186+
let item = tcx.hir().item(id);
187+
match item.kind {
188+
hir::ItemKind::Mod(_) => {
189+
as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
190+
}
191+
hir::ItemKind::Use(ref path, hir::UseKind::Single)
192+
if item.vis.node.is_pub() =>
193+
{
194+
as_primitive(path.res).map(|(_, prim)| {
195+
// Pretend the primitive is local.
196+
(id.def_id.to_def_id(), prim)
197+
})
198+
}
199+
_ => None,
200+
}
201+
})
202+
.collect()
203+
} else {
204+
tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
205+
}
206+
}
80207
}
81208

82209
/// Anything with a source location and set of attributes and, optionally, a

src/librustdoc/clean/utils.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::clean::auto_trait::AutoTraitFinder;
22
use crate::clean::blanket_impl::BlanketImplFinder;
33
use crate::clean::{
4-
inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
5-
ItemKind, Lifetime, MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type,
6-
TypeBinding, TypeKind,
4+
inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
5+
MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
6+
TypeKind,
77
};
88
use crate::core::DocContext;
99

@@ -54,7 +54,11 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
5454
_ => unreachable!(),
5555
}
5656

57-
let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
57+
let local_crate = LOCAL_CRATE.clean(cx);
58+
let src = local_crate.src(cx.tcx);
59+
let name = local_crate.name(cx.tcx);
60+
let primitives = local_crate.primitives(cx.tcx);
61+
let keywords = local_crate.keywords(cx.tcx);
5862
{
5963
let m = match *module.kind {
6064
ItemKind::ModuleItem(ref mut m) => m,

src/librustdoc/formats/cache.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -155,27 +155,28 @@ impl Cache {
155155
// Cache where all our extern crates are located
156156
// FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
157157
for &(n, ref e) in &krate.externs {
158-
let src_root = match e.src {
158+
let src_root = match e.src(tcx) {
159159
FileName::Real(ref p) => match p.local_path().parent() {
160160
Some(p) => p.to_path_buf(),
161161
None => PathBuf::new(),
162162
},
163163
_ => PathBuf::new(),
164164
};
165-
let extern_url = extern_html_root_urls.get(&*e.name.as_str()).map(|u| &**u);
165+
let name = e.name(tcx);
166+
let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
166167
self.extern_locations
167-
.insert(n, (e.name, src_root, extern_location(e, extern_url, &dst)));
168+
.insert(n, (name, src_root, extern_location(e, extern_url, &dst, tcx)));
168169

169170
let did = DefId { krate: n, index: CRATE_DEF_INDEX };
170-
self.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
171+
self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
171172
}
172173

173174
// Cache where all known primitives have their documentation located.
174175
//
175176
// Favor linking to as local extern as possible, so iterate all crates in
176177
// reverse topological order.
177178
for &(_, ref e) in krate.externs.iter().rev() {
178-
for &(def_id, prim) in &e.primitives {
179+
for &(def_id, prim) in &e.primitives(tcx) {
179180
self.primitive_locations.insert(prim, def_id);
180181
}
181182
}

src/librustdoc/html/render/cache.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ crate fn extern_location(
3131
e: &clean::ExternalCrate,
3232
extern_url: Option<&str>,
3333
dst: &Path,
34+
tcx: TyCtxt<'_>,
3435
) -> ExternalLocation {
3536
use ExternalLocation::*;
3637
// See if there's documentation generated into the local directory
37-
let local_location = dst.join(&*e.name.as_str());
38+
let local_location = dst.join(&*e.name(tcx).as_str());
3839
if local_location.is_dir() {
3940
return Local;
4041
}

0 commit comments

Comments
 (0)