Skip to content

Commit 374f9b5

Browse files
Move primitive_locations build before the crate.clean
1 parent b419a1d commit 374f9b5

File tree

7 files changed

+135
-69
lines changed

7 files changed

+135
-69
lines changed

Diff for: src/librustdoc/clean/mod.rs

+43-58
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,10 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
2828
use rustc_span::{self, Pos};
2929
use rustc_typeck::hir_ty_to_ty;
3030

31-
use std::cell::RefCell;
3231
use std::collections::hash_map::Entry;
3332
use std::default::Default;
3433
use std::hash::Hash;
3534
use std::rc::Rc;
36-
use std::sync::Arc;
3735
use std::{mem, vec};
3836

3937
use crate::core::{self, DocContext, ImplTraitParam};
@@ -50,13 +48,6 @@ pub use self::types::Type::*;
5048
pub use self::types::Visibility::{Inherited, Public};
5149
pub use self::types::*;
5250

53-
thread_local!(static PRIMITIVES: RefCell<Arc<FxHashMap<PrimitiveType, DefId>>> =
54-
Default::default());
55-
56-
crate fn primitives() -> Arc<FxHashMap<PrimitiveType, DefId>> {
57-
PRIMITIVES.with(|c| c.borrow().clone())
58-
}
59-
6051
const FN_OUTPUT_NAME: &str = "Output";
6152

6253
pub trait Clean<T> {
@@ -93,48 +84,49 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
9384
}
9485
}
9586

87+
/// Collect all inner modules which are tagged as implementations of
88+
/// primitives.
89+
///
90+
/// Note that this loop only searches the top-level items of the crate,
91+
/// and this is intentional. If we were to search the entire crate for an
92+
/// item tagged with `#[doc(primitive)]` then we would also have to
93+
/// search the entirety of external modules for items tagged
94+
/// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
95+
/// all that metadata unconditionally).
96+
///
97+
/// In order to keep the metadata load under control, the
98+
/// `#[doc(primitive)]` feature is explicitly designed to only allow the
99+
/// primitive tags to show up as the top level items in a crate.
100+
///
101+
/// Also note that this does not attempt to deal with modules tagged
102+
/// duplicately for the same primitive. This is handled later on when
103+
/// rendering by delegating everything to a hash map.
104+
crate fn as_primitive(cx: &DocContext<'_>, res: Res) -> Option<(DefId, PrimitiveType, Attributes)> {
105+
if let Res::Def(DefKind::Mod, def_id) = res {
106+
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
107+
let mut prim = None;
108+
for attr in attrs.lists(sym::doc) {
109+
if let Some(v) = attr.value_str() {
110+
if attr.check_name(sym::primitive) {
111+
prim = PrimitiveType::from_symbol(v);
112+
if prim.is_some() {
113+
break;
114+
}
115+
// FIXME: should warn on unknown primitives?
116+
}
117+
}
118+
}
119+
return prim.map(|p| (def_id, p, attrs));
120+
}
121+
None
122+
}
123+
96124
impl Clean<ExternalCrate> for CrateNum {
97125
fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
98126
let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
99127
let krate_span = cx.tcx.def_span(root);
100128
let krate_src = cx.sess().source_map().span_to_filename(krate_span);
101129

102-
// Collect all inner modules which are tagged as implementations of
103-
// primitives.
104-
//
105-
// Note that this loop only searches the top-level items of the crate,
106-
// and this is intentional. If we were to search the entire crate for an
107-
// item tagged with `#[doc(primitive)]` then we would also have to
108-
// search the entirety of external modules for items tagged
109-
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
110-
// all that metadata unconditionally).
111-
//
112-
// In order to keep the metadata load under control, the
113-
// `#[doc(primitive)]` feature is explicitly designed to only allow the
114-
// primitive tags to show up as the top level items in a crate.
115-
//
116-
// Also note that this does not attempt to deal with modules tagged
117-
// duplicately for the same primitive. This is handled later on when
118-
// rendering by delegating everything to a hash map.
119-
let as_primitive = |res: Res| {
120-
if let Res::Def(DefKind::Mod, def_id) = res {
121-
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
122-
let mut prim = None;
123-
for attr in attrs.lists(sym::doc) {
124-
if let Some(v) = attr.value_str() {
125-
if attr.check_name(sym::primitive) {
126-
prim = PrimitiveType::from_symbol(v);
127-
if prim.is_some() {
128-
break;
129-
}
130-
// FIXME: should warn on unknown primitives?
131-
}
132-
}
133-
}
134-
return prim.map(|p| (def_id, p, attrs));
135-
}
136-
None
137-
};
138130
let primitives: Vec<(DefId, PrimitiveType, Attributes)> = if root.is_local() {
139131
cx.tcx
140132
.hir()
@@ -146,14 +138,14 @@ impl Clean<ExternalCrate> for CrateNum {
146138
.filter_map(|&id| {
147139
let item = cx.tcx.hir().expect_item(id.id);
148140
match item.kind {
149-
hir::ItemKind::Mod(_) => as_primitive(Res::Def(
150-
DefKind::Mod,
151-
cx.tcx.hir().local_def_id(id.id).to_def_id(),
152-
)),
141+
hir::ItemKind::Mod(_) => as_primitive(
142+
cx,
143+
Res::Def(DefKind::Mod, cx.tcx.hir().local_def_id(id.id).to_def_id()),
144+
),
153145
hir::ItemKind::Use(ref path, hir::UseKind::Single)
154146
if item.vis.node.is_pub() =>
155147
{
156-
as_primitive(path.res).map(|(_, prim, attrs)| {
148+
as_primitive(cx, path.res).map(|(_, prim, attrs)| {
157149
// Pretend the primitive is local.
158150
(cx.tcx.hir().local_def_id(id.id).to_def_id(), prim, attrs)
159151
})
@@ -167,16 +159,9 @@ impl Clean<ExternalCrate> for CrateNum {
167159
.item_children(root)
168160
.iter()
169161
.map(|item| item.res)
170-
.filter_map(as_primitive)
162+
.filter_map(|res| as_primitive(cx, res))
171163
.collect()
172164
};
173-
PRIMITIVES.with(|v| {
174-
let mut tmp = v.borrow_mut();
175-
let stored_primitives = Arc::make_mut(&mut *tmp);
176-
for (prim, did) in primitives.iter().map(|x| (x.1, x.0)) {
177-
stored_primitives.insert(prim, did);
178-
}
179-
});
180165

181166
let as_keyword = |res: Res| {
182167
if let Res::Def(DefKind::Mod, def_id) = res {

Diff for: src/librustdoc/clean/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ impl GetDefId for Type {
11731173
fn def_id(&self) -> Option<DefId> {
11741174
match *self {
11751175
ResolvedPath { did, .. } => Some(did),
1176-
Primitive(p) => super::primitives().get(&p).cloned(),
1176+
Primitive(p) => crate::core::primitives().get(&p).cloned(),
11771177
BorrowedRef { type_: box Generic(..), .. } => {
11781178
Primitive(PrimitiveType::Reference).def_id()
11791179
}

Diff for: src/librustdoc/core.rs

+71-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use rustc_driver::abort_on_err;
55
use rustc_errors::emitter::{Emitter, EmitterWriter};
66
use rustc_errors::json::JsonEmitter;
77
use rustc_feature::UnstableFeatures;
8-
use rustc_hir::def::{Namespace::TypeNS, Res};
8+
use rustc_hir as hir;
9+
use rustc_hir::def::{DefKind, Namespace::TypeNS, Res};
910
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1011
use rustc_hir::HirId;
1112
use rustc_hir::{
@@ -29,16 +30,25 @@ use rustc_span::DUMMY_SP;
2930
use std::cell::RefCell;
3031
use std::mem;
3132
use std::rc::Rc;
33+
use std::sync::Arc;
3234

3335
use crate::clean;
34-
use crate::clean::{AttributesExt, MAX_DEF_ID};
36+
use crate::clean::types::PrimitiveType;
37+
use crate::clean::{as_primitive, AttributesExt, MAX_DEF_ID};
3538
use crate::config::RenderInfo;
3639
use crate::config::{Options as RustdocOptions, RenderOptions};
3740
use crate::passes::{self, Condition::*, ConditionalPass};
3841

3942
pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options};
4043
pub use rustc_session::search_paths::SearchPath;
4144

45+
thread_local!(static PRIMITIVES: RefCell<Arc<FxHashMap<PrimitiveType, DefId>>> =
46+
Default::default());
47+
48+
crate fn primitives() -> Arc<FxHashMap<PrimitiveType, DefId>> {
49+
PRIMITIVES.with(|c| c.borrow().clone())
50+
}
51+
4252
pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;
4353

4454
pub struct DocContext<'tcx> {
@@ -499,6 +509,65 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
499509
};
500510
debug!("crate: {:?}", tcx.hir().krate());
501511

512+
PRIMITIVES.with(|v| {
513+
let mut tmp = v.borrow_mut();
514+
let stored_primitives = Arc::make_mut(&mut *tmp);
515+
516+
let mut externs = Vec::new();
517+
for &cnum in ctxt.tcx.crates().iter() {
518+
externs.push(cnum);
519+
}
520+
externs.sort_by(|a, b| a.cmp(&b));
521+
522+
for krate in externs.iter().chain([LOCAL_CRATE].iter()) {
523+
let root = DefId { krate: *krate, index: CRATE_DEF_INDEX };
524+
let iter: Vec<(DefId, PrimitiveType)> = if root.is_local() {
525+
ctxt.tcx.hir_crate(*krate).item.module.item_ids.iter().filter_map(
526+
|&id| {
527+
let item = ctxt.tcx.hir().expect_item(id.id);
528+
match item.kind {
529+
hir::ItemKind::Mod(_) => as_primitive(
530+
&ctxt,
531+
Res::Def(
532+
DefKind::Mod,
533+
ctxt.tcx.hir().local_def_id(id.id).to_def_id(),
534+
),
535+
)
536+
.map(|(did, prim, _)| (did, prim)),
537+
hir::ItemKind::Use(ref path, hir::UseKind::Single)
538+
if item.vis.node.is_pub() =>
539+
{
540+
as_primitive(&ctxt, path.res).map(|(_, prim, _)| {
541+
// Pretend the primitive is local.
542+
(
543+
ctxt.tcx
544+
.hir()
545+
.local_def_id(id.id)
546+
.to_def_id(),
547+
prim,
548+
)
549+
})
550+
}
551+
_ => None,
552+
}
553+
},
554+
)
555+
.collect()
556+
} else {
557+
ctxt
558+
.tcx
559+
.item_children(root)
560+
.iter()
561+
.map(|item| item.res)
562+
.filter_map(|res| as_primitive(&ctxt, res).map(|(did, prim, _)| (did, prim)))
563+
.collect()
564+
};
565+
for (did, prim) in iter {
566+
stored_primitives.insert(prim, did);
567+
}
568+
}
569+
});
570+
502571
let mut krate = clean::krate(&mut ctxt);
503572

504573
if let Some(ref m) = krate.module {

Diff for: src/librustdoc/formats/cache.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
99
use rustc_middle::middle::privacy::AccessLevels;
1010
use rustc_span::source_map::FileName;
1111

12-
use crate::clean::{self, primitives, GetDefId};
12+
use crate::clean::{self, GetDefId};
1313
use crate::config::RenderInfo;
14+
use crate::core::primitives;
1415
use crate::fold::DocFolder;
1516
use crate::formats::item_type::ItemType;
1617
use crate::formats::Impl;

Diff for: src/librustdoc/html/format.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use rustc_hir as hir;
1414
use rustc_span::def_id::DefId;
1515
use rustc_target::spec::abi::Abi;
1616

17-
use crate::clean::{self, primitives, PrimitiveType};
17+
use crate::clean::{self, PrimitiveType};
18+
use crate::core::primitives;
1819
use crate::formats::cache::cache;
1920
use crate::formats::item_type::ItemType;
2021
use crate::html::escape::Escape;
@@ -578,13 +579,21 @@ fn primitive_link(
578579
needs_termination = true;
579580
}
580581
Some(&def_id) => {
581-
let loc = match m.extern_locations[&def_id.krate] {
582-
(ref cname, _, ExternalLocation::Remote(ref s)) => Some((cname, s.to_string())),
583-
(ref cname, _, ExternalLocation::Local) => {
582+
let loc = match m.extern_locations.get(&def_id.krate) {
583+
Some((ref cname, _, ExternalLocation::Remote(ref s))) => {
584+
Some((cname.as_str(), s.to_string()))
585+
}
586+
Some((ref cname, _, ExternalLocation::Local)) => {
587+
let len = CURRENT_DEPTH.with(|s| s.get());
588+
Some((cname.as_str(), "../".repeat(len)))
589+
}
590+
Some((.., ExternalLocation::Unknown)) => None,
591+
None => {
592+
// It means we're in core, since the primitive types aren't "accessible"
593+
// from it so we have to simulate it.
584594
let len = CURRENT_DEPTH.with(|s| s.get());
585-
Some((cname, "../".repeat(len)))
595+
Some(("core", "../".repeat(len)))
586596
}
587-
(.., ExternalLocation::Unknown) => None,
588597
};
589598
if let Some((cname, root)) = loc {
590599
write!(

Diff for: src/librustdoc/html/render/cache.rs

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::html::render::{plain_summary_line, shorten};
1313
use crate::html::render::{Generic, IndexItem, IndexItemFunctionType, RenderType, TypeWithKind};
1414

1515
/// Indicates where an external crate can be found.
16+
#[derive(Debug)]
1617
pub enum ExternalLocation {
1718
/// Remote URL root of the external crate
1819
Remote(String),

Diff for: src/librustdoc/html/render/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ use rustc_span::symbol::{sym, Symbol};
6363
use serde::ser::SerializeSeq;
6464
use serde::{Serialize, Serializer};
6565

66-
use crate::clean::{self, primitives, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
66+
use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind};
6767
use crate::config::RenderInfo;
6868
use crate::config::RenderOptions;
69+
use crate::core::primitives;
6970
use crate::docfs::{DocFS, PathError};
7071
use crate::doctree;
7172
use crate::error::Error;

0 commit comments

Comments
 (0)