Skip to content

Commit e30d952

Browse files
authored
Rollup merge of #84601 - tdelabro:rustdoc-get-rid-of-cache-extern_locations, r=jyn514
rustdoc: Only store locations in Cache::extern_locations and calculate the other info on-demand help #84588
2 parents 3d67e07 + 2cc2639 commit e30d952

File tree

6 files changed

+88
-84
lines changed

6 files changed

+88
-84
lines changed

src/librustdoc/clean/types.rs

+56-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::fmt;
44
use std::hash::{Hash, Hasher};
55
use std::iter::FromIterator;
66
use std::lazy::SyncOnceCell as OnceCell;
7+
use std::path::PathBuf;
78
use std::rc::Rc;
89
use std::sync::Arc;
910
use std::{slice, vec};
@@ -90,6 +91,58 @@ impl ExternalCrate {
9091
tcx.crate_name(self.crate_num)
9192
}
9293

94+
crate fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
95+
match self.src(tcx) {
96+
FileName::Real(ref p) => match p.local_path().parent() {
97+
Some(p) => p.to_path_buf(),
98+
None => PathBuf::new(),
99+
},
100+
_ => PathBuf::new(),
101+
}
102+
}
103+
104+
/// Attempts to find where an external crate is located, given that we're
105+
/// rendering in to the specified source destination.
106+
crate fn location(
107+
&self,
108+
extern_url: Option<&str>,
109+
dst: &std::path::Path,
110+
tcx: TyCtxt<'_>,
111+
) -> ExternalLocation {
112+
use ExternalLocation::*;
113+
114+
fn to_remote(url: impl ToString) -> ExternalLocation {
115+
let mut url = url.to_string();
116+
if !url.ends_with('/') {
117+
url.push('/');
118+
}
119+
Remote(url)
120+
}
121+
122+
// See if there's documentation generated into the local directory
123+
// WARNING: since rustdoc creates these directories as it generates documentation, this check is only accurate before rendering starts.
124+
// Make sure to call `location()` by that time.
125+
let local_location = dst.join(&*self.name(tcx).as_str());
126+
if local_location.is_dir() {
127+
return Local;
128+
}
129+
130+
if let Some(url) = extern_url {
131+
return to_remote(url);
132+
}
133+
134+
// Failing that, see if there's an attribute specifying where to find this
135+
// external crate
136+
let did = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
137+
tcx.get_attrs(did)
138+
.lists(sym::doc)
139+
.filter(|a| a.has_name(sym::html_root_url))
140+
.filter_map(|a| a.value_str())
141+
.map(to_remote)
142+
.next()
143+
.unwrap_or(Unknown) // Well, at least we tried.
144+
}
145+
93146
crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
94147
let root = self.def_id();
95148

@@ -381,7 +434,7 @@ impl Item {
381434
let relative_to = &cx.current;
382435
if let Some(ref fragment) = *fragment {
383436
let url = match cx.cache().extern_locations.get(&self.def_id.krate) {
384-
Some(&(_, _, ExternalLocation::Local)) => {
437+
Some(ExternalLocation::Local) => {
385438
if relative_to[0] == "std" {
386439
let depth = relative_to.len() - 1;
387440
"../".repeat(depth)
@@ -390,10 +443,10 @@ impl Item {
390443
format!("{}std/", "../".repeat(depth))
391444
}
392445
}
393-
Some(&(_, _, ExternalLocation::Remote(ref s))) => {
446+
Some(ExternalLocation::Remote(ref s)) => {
394447
format!("{}/std/", s.trim_end_matches('/'))
395448
}
396-
Some(&(_, _, ExternalLocation::Unknown)) | None => format!(
449+
Some(ExternalLocation::Unknown) | None => format!(
397450
"https://doc.rust-lang.org/{}/std/",
398451
crate::doc_rust_lang_org_channel(),
399452
),

src/librustdoc/formats/cache.rs

+4-17
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
use std::collections::BTreeMap;
22
use std::mem;
3-
use std::path::{Path, PathBuf};
3+
use std::path::Path;
44

55
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
66
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
77
use rustc_middle::middle::privacy::AccessLevels;
88
use rustc_middle::ty::TyCtxt;
9-
use rustc_span::source_map::FileName;
109
use rustc_span::symbol::sym;
11-
use rustc_span::Symbol;
1210

1311
use crate::clean::{self, GetDefId};
1412
use crate::fold::DocFolder;
1513
use crate::formats::item_type::ItemType;
1614
use crate::formats::Impl;
1715
use crate::html::markdown::short_markdown_summary;
18-
use crate::html::render::cache::{extern_location, get_index_search_type, ExternalLocation};
16+
use crate::html::render::cache::{get_index_search_type, ExternalLocation};
1917
use crate::html::render::IndexItem;
2018

2119
/// This cache is used to store information about the [`clean::Crate`] being
@@ -72,7 +70,7 @@ crate struct Cache {
7270
crate implementors: FxHashMap<DefId, Vec<Impl>>,
7371

7472
/// Cache of where external crate documentation can be found.
75-
crate extern_locations: FxHashMap<CrateNum, (Symbol, PathBuf, ExternalLocation)>,
73+
crate extern_locations: FxHashMap<CrateNum, ExternalLocation>,
7674

7775
/// Cache of where documentation for primitives can be found.
7876
crate primitive_locations: FxHashMap<clean::PrimitiveType, DefId>,
@@ -155,21 +153,10 @@ impl Cache {
155153
// Cache where all our extern crates are located
156154
// FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
157155
for &(n, ref e) in &krate.externs {
158-
let src_root = match e.src(tcx) {
159-
FileName::Real(ref p) => match p.local_path().parent() {
160-
Some(p) => p.to_path_buf(),
161-
None => PathBuf::new(),
162-
},
163-
_ => PathBuf::new(),
164-
};
165156
let name = e.name(tcx);
166157
let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
167158
let did = DefId { krate: n, index: CRATE_DEF_INDEX };
168-
self.extern_locations.insert(
169-
n,
170-
(name, src_root, extern_location(e, extern_url, tcx.get_attrs(did), &dst, tcx)),
171-
);
172-
159+
self.extern_locations.insert(n, e.location(extern_url, &dst, tcx));
173160
self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
174161
}
175162

src/librustdoc/html/format.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::ty::TyCtxt;
1616
use rustc_span::def_id::{DefId, CRATE_DEF_INDEX};
1717
use rustc_target::spec::abi::Abi;
1818

19-
use crate::clean::{self, utils::find_nearest_parent_module, PrimitiveType};
19+
use crate::clean::{self, utils::find_nearest_parent_module, ExternalCrate, PrimitiveType};
2020
use crate::formats::item_type::ItemType;
2121
use crate::html::escape::Escape;
2222
use crate::html::render::cache::ExternalLocation;
@@ -465,14 +465,14 @@ crate fn href(did: DefId, cx: &Context<'_>) -> Option<(String, ItemType, Vec<Str
465465
fqp,
466466
shortty,
467467
match cache.extern_locations[&did.krate] {
468-
(.., ExternalLocation::Remote(ref s)) => {
468+
ExternalLocation::Remote(ref s) => {
469469
let s = s.trim_end_matches('/');
470470
let mut s = vec![&s[..]];
471471
s.extend(module_fqp[..].iter().map(String::as_str));
472472
s
473473
}
474-
(.., ExternalLocation::Local) => href_relative_parts(module_fqp, relative_to),
475-
(.., ExternalLocation::Unknown) => return None,
474+
ExternalLocation::Local => href_relative_parts(module_fqp, relative_to),
475+
ExternalLocation::Unknown => return None,
476476
},
477477
)
478478
}
@@ -578,20 +578,22 @@ fn primitive_link(
578578
Some(&def_id) => {
579579
let cname_str;
580580
let loc = match m.extern_locations[&def_id.krate] {
581-
(ref cname, _, ExternalLocation::Remote(ref s)) => {
582-
cname_str = cname.as_str();
581+
ExternalLocation::Remote(ref s) => {
582+
cname_str =
583+
ExternalCrate { crate_num: def_id.krate }.name(cx.tcx()).as_str();
583584
Some(vec![s.trim_end_matches('/'), &cname_str[..]])
584585
}
585-
(ref cname, _, ExternalLocation::Local) => {
586-
cname_str = cname.as_str();
586+
ExternalLocation::Local => {
587+
cname_str =
588+
ExternalCrate { crate_num: def_id.krate }.name(cx.tcx()).as_str();
587589
Some(if cx.current.first().map(|x| &x[..]) == Some(&cname_str[..]) {
588590
iter::repeat("..").take(cx.current.len() - 1).collect()
589591
} else {
590592
let cname = iter::once(&cname_str[..]);
591593
iter::repeat("..").take(cx.current.len()).chain(cname).collect()
592594
})
593595
}
594-
(.., ExternalLocation::Unknown) => None,
596+
ExternalLocation::Unknown => None,
595597
};
596598
if let Some(loc) = loc {
597599
write!(

src/librustdoc/html/render/cache.rs

+2-45
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
use std::collections::BTreeMap;
2-
use std::path::Path;
32

4-
use rustc_ast::ast;
53
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
64
use rustc_middle::ty::TyCtxt;
7-
use rustc_span::symbol::{sym, Symbol};
5+
use rustc_span::symbol::Symbol;
86
use serde::ser::{Serialize, SerializeStruct, Serializer};
97

108
use crate::clean;
119
use crate::clean::types::{
12-
AttributesExt, FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate,
10+
FnDecl, FnRetTy, GenericBound, Generics, GetDefId, Type, WherePredicate,
1311
};
1412
use crate::formats::cache::Cache;
1513
use crate::formats::item_type::ItemType;
@@ -26,47 +24,6 @@ crate enum ExternalLocation {
2624
Unknown,
2725
}
2826

29-
/// Attempts to find where an external crate is located, given that we're
30-
/// rendering in to the specified source destination.
31-
crate fn extern_location(
32-
e: &clean::ExternalCrate,
33-
extern_url: Option<&str>,
34-
ast_attrs: &[ast::Attribute],
35-
dst: &Path,
36-
tcx: TyCtxt<'_>,
37-
) -> ExternalLocation {
38-
use ExternalLocation::*;
39-
// See if there's documentation generated into the local directory
40-
let local_location = dst.join(&*e.name(tcx).as_str());
41-
if local_location.is_dir() {
42-
return Local;
43-
}
44-
45-
if let Some(url) = extern_url {
46-
let mut url = url.to_string();
47-
if !url.ends_with('/') {
48-
url.push('/');
49-
}
50-
return Remote(url);
51-
}
52-
53-
// Failing that, see if there's an attribute specifying where to find this
54-
// external crate
55-
ast_attrs
56-
.lists(sym::doc)
57-
.filter(|a| a.has_name(sym::html_root_url))
58-
.filter_map(|a| a.value_str())
59-
.map(|url| {
60-
let mut url = url.to_string();
61-
if !url.ends_with('/') {
62-
url.push('/')
63-
}
64-
Remote(url)
65-
})
66-
.next()
67-
.unwrap_or(Unknown) // Well, at least we tried.
68-
}
69-
7027
/// Builds the search index from the collected metadata
7128
crate fn build_index<'tcx>(krate: &clean::Crate, cache: &mut Cache, tcx: TyCtxt<'tcx>) -> String {
7229
let mut defid_to_pathid = FxHashMap::default();

src/librustdoc/html/render/context.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use super::print_item::{full_path, item_path, print_item};
1818
use super::write_shared::write_shared;
1919
use super::{print_sidebar, settings, AllTypes, NameDoc, StylePath, BASIC_KEYWORDS};
2020

21-
use crate::clean;
21+
use crate::clean::{self, ExternalCrate};
2222
use crate::config::RenderOptions;
2323
use crate::docfs::{DocFS, PathError};
2424
use crate::error::Error;
@@ -304,12 +304,16 @@ impl<'tcx> Context<'tcx> {
304304
}
305305
} else {
306306
let (krate, src_root) = match *self.cache.extern_locations.get(&cnum)? {
307-
(name, ref src, ExternalLocation::Local) => (name, src),
308-
(name, ref src, ExternalLocation::Remote(ref s)) => {
307+
ExternalLocation::Local => {
308+
let e = ExternalCrate { crate_num: cnum };
309+
(e.name(self.tcx()), e.src_root(self.tcx()))
310+
}
311+
ExternalLocation::Remote(ref s) => {
309312
root = s.to_string();
310-
(name, src)
313+
let e = ExternalCrate { crate_num: cnum };
314+
(e.name(self.tcx()), e.src_root(self.tcx()))
311315
}
312-
(_, _, ExternalLocation::Unknown) => return None,
316+
ExternalLocation::Unknown => return None,
313317
};
314318

315319
sources::clean_path(&src_root, file, false, |component| {

src/librustdoc/json/mod.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_session::Session;
1717

1818
use rustdoc_json_types as types;
1919

20-
use crate::clean;
20+
use crate::clean::{self, ExternalCrate};
2121
use crate::config::RenderOptions;
2222
use crate::error::Error;
2323
use crate::formats::cache::Cache;
@@ -218,12 +218,13 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
218218
.cache
219219
.extern_locations
220220
.iter()
221-
.map(|(k, v)| {
221+
.map(|(crate_num, external_location)| {
222+
let e = ExternalCrate { crate_num: *crate_num };
222223
(
223-
k.as_u32(),
224+
crate_num.as_u32(),
224225
types::ExternalCrate {
225-
name: v.0.to_string(),
226-
html_root_url: match &v.2 {
226+
name: e.name(self.tcx).to_string(),
227+
html_root_url: match external_location {
227228
ExternalLocation::Remote(s) => Some(s.clone()),
228229
_ => None,
229230
},

0 commit comments

Comments
 (0)