Skip to content

Commit 0248c6f

Browse files
committedJan 30, 2021
Auto merge of #81398 - bugadani:rustdoc-perf, r=GuillaumeGomez
rustdoc tweaking * Reuse memory * simplify `next_def_id`, avoid multiple hashing and unnecessary lookups * remove `all_fake_def_ids`, use the global map instead (probably not a good step toward parallelization, though...) * convert `add_deref_target` to iterative implementation * use `ArrayVec` where we know the max number of elements * minor touchups here and there * avoid building temporary vectors that get appended to other vectors At most places I may or may not be doing the compiler's job is this PR.
·
1.88.01.51.0
2 parents 9fa9b58 + 4b80687 commit 0248c6f

File tree

16 files changed

+521
-512
lines changed

16 files changed

+521
-512
lines changed
 

‎Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4386,6 +4386,7 @@ dependencies = [
43864386
name = "rustdoc"
43874387
version = "0.0.0"
43884388
dependencies = [
4389+
"arrayvec",
43894390
"expect-test",
43904391
"itertools 0.9.0",
43914392
"minifier",

‎src/librustdoc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edition = "2018"
88
path = "lib.rs"
99

1010
[dependencies]
11+
arrayvec = { version = "0.5.1", default-features = false }
1112
pulldown-cmark = { version = "0.8", default-features = false }
1213
minifier = "0.0.33"
1314
rayon = { version = "0.3.0", package = "rustc-rayon" }

‎src/librustdoc/clean/inline.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ crate fn try_inline(
5656
let kind = match res {
5757
Res::Def(DefKind::Trait, did) => {
5858
record_extern_fqn(cx, did, clean::TypeKind::Trait);
59-
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
59+
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
6060
clean::TraitItem(build_external_trait(cx, did))
6161
}
6262
Res::Def(DefKind::Fn, did) => {
@@ -65,27 +65,27 @@ crate fn try_inline(
6565
}
6666
Res::Def(DefKind::Struct, did) => {
6767
record_extern_fqn(cx, did, clean::TypeKind::Struct);
68-
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
68+
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
6969
clean::StructItem(build_struct(cx, did))
7070
}
7171
Res::Def(DefKind::Union, did) => {
7272
record_extern_fqn(cx, did, clean::TypeKind::Union);
73-
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
73+
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
7474
clean::UnionItem(build_union(cx, did))
7575
}
7676
Res::Def(DefKind::TyAlias, did) => {
7777
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
78-
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
78+
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
7979
clean::TypedefItem(build_type_alias(cx, did), false)
8080
}
8181
Res::Def(DefKind::Enum, did) => {
8282
record_extern_fqn(cx, did, clean::TypeKind::Enum);
83-
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
83+
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
8484
clean::EnumItem(build_enum(cx, did))
8585
}
8686
Res::Def(DefKind::ForeignTy, did) => {
8787
record_extern_fqn(cx, did, clean::TypeKind::Foreign);
88-
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
88+
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
8989
clean::ForeignTypeItem
9090
}
9191
// Never inline enum variants but leave them shown as re-exports.
@@ -133,10 +133,7 @@ crate fn try_inline_glob(
133133
res: Res,
134134
visited: &mut FxHashSet<DefId>,
135135
) -> Option<Vec<clean::Item>> {
136-
if res == Res::Err {
137-
return None;
138-
}
139-
let did = res.def_id();
136+
let did = res.opt_def_id()?;
140137
if did.is_local() {
141138
return None;
142139
}
@@ -280,16 +277,14 @@ crate fn build_impls(
280277
parent_module: Option<DefId>,
281278
did: DefId,
282279
attrs: Option<Attrs<'_>>,
283-
) -> Vec<clean::Item> {
280+
ret: &mut Vec<clean::Item>,
281+
) {
284282
let tcx = cx.tcx;
285-
let mut impls = Vec::new();
286283

287284
// for each implementation of an item represented by `did`, build the clean::Item for that impl
288285
for &did in tcx.inherent_impls(did).iter() {
289-
build_impl(cx, parent_module, did, attrs, &mut impls);
286+
build_impl(cx, parent_module, did, attrs, ret);
290287
}
291-
292-
impls
293288
}
294289

295290
/// `parent_module` refers to the parent of the re-export, not the original item

‎src/librustdoc/clean/types.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::rc::Rc;
88
use std::sync::Arc;
99
use std::{slice, vec};
1010

11+
use arrayvec::ArrayVec;
1112
use rustc_ast::attr;
1213
use rustc_ast::util::comments::beautify_doc_string;
1314
use rustc_ast::{self as ast, AttrStyle};
@@ -16,7 +17,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1617
use rustc_feature::UnstableFeatures;
1718
use rustc_hir as hir;
1819
use rustc_hir::def::{CtorKind, Res};
19-
use rustc_hir::def_id::{CrateNum, DefId};
20+
use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
2021
use rustc_hir::lang_items::LangItem;
2122
use rustc_hir::Mutability;
2223
use rustc_index::vec::IndexVec;
@@ -28,7 +29,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
2829
use rustc_span::{self, FileName, Loc};
2930
use rustc_target::abi::VariantIdx;
3031
use rustc_target::spec::abi::Abi;
31-
use smallvec::{smallvec, SmallVec};
3232

3333
use crate::clean::cfg::Cfg;
3434
use crate::clean::external_path;
@@ -45,7 +45,7 @@ use self::ItemKind::*;
4545
use self::SelfTy::*;
4646
use self::Type::*;
4747

48-
thread_local!(crate static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
48+
thread_local!(crate static MAX_DEF_IDX: RefCell<FxHashMap<CrateNum, DefIndex>> = Default::default());
4949

5050
#[derive(Clone, Debug)]
5151
crate struct Crate {
@@ -293,8 +293,8 @@ impl Item {
293293
///
294294
/// [`next_def_id()`]: DocContext::next_def_id()
295295
crate fn is_fake(&self) -> bool {
296-
MAX_DEF_ID.with(|m| {
297-
m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
296+
MAX_DEF_IDX.with(|m| {
297+
m.borrow().get(&self.def_id.krate).map(|&idx| idx <= self.def_id.index).unwrap_or(false)
298298
})
299299
}
300300
}
@@ -1539,12 +1539,12 @@ impl PrimitiveType {
15391539
}
15401540
}
15411541

1542-
crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
1542+
crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<[DefId; 4]> {
15431543
Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
15441544
}
15451545

1546-
crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
1547-
static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
1546+
crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>> {
1547+
static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>>> = OnceCell::new();
15481548

15491549
CELL.get_or_init(move || {
15501550
use self::PrimitiveType::*;
@@ -1568,7 +1568,7 @@ impl PrimitiveType {
15681568
}
15691569

15701570
let single = |a: Option<DefId>| a.into_iter().collect();
1571-
let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
1571+
let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_> {
15721572
a.into_iter().chain(b).collect()
15731573
};
15741574

@@ -1601,8 +1601,8 @@ impl PrimitiveType {
16011601
.collect()
16021602
},
16031603
Array => single(lang_items.array_impl()),
1604-
Tuple => smallvec![],
1605-
Unit => smallvec![],
1604+
Tuple => ArrayVec::new(),
1605+
Unit => ArrayVec::new(),
16061606
RawPointer => {
16071607
lang_items
16081608
.const_ptr_impl()
@@ -1612,9 +1612,9 @@ impl PrimitiveType {
16121612
.chain(lang_items.mut_slice_ptr_impl())
16131613
.collect()
16141614
},
1615-
Reference => smallvec![],
1616-
Fn => smallvec![],
1617-
Never => smallvec![],
1615+
Reference => ArrayVec::new(),
1616+
Fn => ArrayVec::new(),
1617+
Never => ArrayVec::new(),
16181618
}
16191619
})
16201620
}

‎src/librustdoc/clean/utils.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -322,20 +322,14 @@ crate fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut
322322
ItemKind::TypedefItem(ref t, true) => &t.type_,
323323
_ => continue,
324324
};
325-
let primitive = match *target {
326-
ResolvedPath { did, .. } if did.is_local() => continue,
327-
ResolvedPath { did, .. } => {
328-
ret.extend(inline::build_impls(cx, None, did, None));
329-
continue;
325+
326+
if let Some(prim) = target.primitive_type() {
327+
for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) {
328+
inline::build_impl(cx, None, did, None, ret);
330329
}
331-
_ => match target.primitive_type() {
332-
Some(prim) => prim,
333-
None => continue,
334-
},
335-
};
336-
for &did in primitive.impls(tcx) {
330+
} else if let ResolvedPath { did, .. } = *target {
337331
if !did.is_local() {
338-
inline::build_impl(cx, None, did, None, ret);
332+
inline::build_impls(cx, None, did, None, ret);
339333
}
340334
}
341335
}

‎src/librustdoc/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ impl Options {
474474
};
475475

476476
let mut id_map = html::markdown::IdMap::new();
477-
id_map.populate(html::render::initial_ids());
477+
id_map.populate(&html::render::INITIAL_IDS);
478478
let external_html = match ExternalHtml::load(
479479
&matches.opt_strs("html-in-header"),
480480
&matches.opt_strs("html-before-content"),

‎src/librustdoc/core.rs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,15 @@ use rustc_span::source_map;
2424
use rustc_span::symbol::sym;
2525
use rustc_span::DUMMY_SP;
2626

27-
use std::cell::{Cell, RefCell};
2827
use std::mem;
2928
use std::rc::Rc;
29+
use std::{
30+
cell::{Cell, RefCell},
31+
collections::hash_map::Entry,
32+
};
3033

3134
use crate::clean;
32-
use crate::clean::{AttributesExt, MAX_DEF_ID};
35+
use crate::clean::{AttributesExt, MAX_DEF_IDX};
3336
use crate::config::{Options as RustdocOptions, RenderOptions};
3437
use crate::config::{OutputFormat, RenderInfo};
3538
use crate::formats::cache::Cache;
@@ -63,8 +66,7 @@ crate struct DocContext<'tcx> {
6366
crate ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
6467
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
6568
crate impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
66-
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
67-
crate all_fake_def_ids: RefCell<FxHashSet<DefId>>,
69+
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefIndex>>,
6870
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
6971
// FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
7072
crate generated_synthetics: RefCell<FxHashSet<(Ty<'tcx>, DefId)>>,
@@ -138,37 +140,38 @@ impl<'tcx> DocContext<'tcx> {
138140
/// [`Debug`]: std::fmt::Debug
139141
/// [`clean::Item`]: crate::clean::types::Item
140142
crate fn next_def_id(&self, crate_num: CrateNum) -> DefId {
141-
let start_def_id = {
142-
let num_def_ids = if crate_num == LOCAL_CRATE {
143-
self.tcx.hir().definitions().def_path_table().num_def_ids()
144-
} else {
145-
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
146-
};
147-
148-
DefId { krate: crate_num, index: DefIndex::from_usize(num_def_ids) }
149-
};
150-
151143
let mut fake_ids = self.fake_def_ids.borrow_mut();
152144

153-
let def_id = *fake_ids.entry(crate_num).or_insert(start_def_id);
154-
fake_ids.insert(
155-
crate_num,
156-
DefId { krate: crate_num, index: DefIndex::from(def_id.index.index() + 1) },
157-
);
158-
159-
MAX_DEF_ID.with(|m| {
160-
m.borrow_mut().entry(def_id.krate).or_insert(start_def_id);
161-
});
162-
163-
self.all_fake_def_ids.borrow_mut().insert(def_id);
145+
let def_index = match fake_ids.entry(crate_num) {
146+
Entry::Vacant(e) => {
147+
let num_def_idx = {
148+
let num_def_idx = if crate_num == LOCAL_CRATE {
149+
self.tcx.hir().definitions().def_path_table().num_def_ids()
150+
} else {
151+
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
152+
};
153+
154+
DefIndex::from_usize(num_def_idx)
155+
};
156+
157+
MAX_DEF_IDX.with(|m| {
158+
m.borrow_mut().insert(crate_num, num_def_idx);
159+
});
160+
e.insert(num_def_idx)
161+
}
162+
Entry::Occupied(e) => e.into_mut(),
163+
};
164+
*def_index = DefIndex::from(*def_index + 1);
164165

165-
def_id
166+
DefId { krate: crate_num, index: *def_index }
166167
}
167168

168169
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
169170
/// (This avoids a slice-index-out-of-bounds panic.)
170171
crate fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
171-
if self.all_fake_def_ids.borrow().contains(&def_id) {
172+
if MAX_DEF_IDX.with(|m| {
173+
m.borrow().get(&def_id.krate).map(|&idx| idx <= def_id.index).unwrap_or(false)
174+
}) {
172175
None
173176
} else {
174177
def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
@@ -517,7 +520,6 @@ crate fn run_global_ctxt(
517520
ct_substs: Default::default(),
518521
impl_trait_bounds: Default::default(),
519522
fake_def_ids: Default::default(),
520-
all_fake_def_ids: Default::default(),
521523
generated_synthetics: Default::default(),
522524
auto_traits: tcx
523525
.all_traits(LOCAL_CRATE)

‎src/librustdoc/formats/item_type.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,6 @@ impl ItemType {
158158

159159
impl fmt::Display for ItemType {
160160
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161-
write!(f, "{}", self.as_str())
161+
f.write_str(self.as_str())
162162
}
163163
}

‎src/librustdoc/html/escape.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,20 @@ impl<'a> fmt::Display for Escape<'a> {
1616
let Escape(s) = *self;
1717
let pile_o_bits = s;
1818
let mut last = 0;
19-
for (i, ch) in s.bytes().enumerate() {
20-
match ch as char {
21-
'<' | '>' | '&' | '\'' | '"' => {
22-
fmt.write_str(&pile_o_bits[last..i])?;
23-
let s = match ch as char {
24-
'>' => "&gt;",
25-
'<' => "&lt;",
26-
'&' => "&amp;",
27-
'\'' => "&#39;",
28-
'"' => "&quot;",
29-
_ => unreachable!(),
30-
};
31-
fmt.write_str(s)?;
32-
last = i + 1;
33-
}
34-
_ => {}
35-
}
19+
for (i, ch) in s.char_indices() {
20+
let s = match ch {
21+
'>' => "&gt;",
22+
'<' => "&lt;",
23+
'&' => "&amp;",
24+
'\'' => "&#39;",
25+
'"' => "&quot;",
26+
_ => continue,
27+
};
28+
fmt.write_str(&pile_o_bits[last..i])?;
29+
fmt.write_str(s)?;
30+
// NOTE: we only expect single byte characters here - which is fine as long as we
31+
// only match single byte characters
32+
last = i + 1;
3633
}
3734

3835
if last < s.len() {

‎src/librustdoc/html/highlight.rs

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,26 @@
77
88
use crate::html::escape::Escape;
99

10-
use std::fmt::{Display, Write};
10+
use std::fmt::Display;
1111
use std::iter::Peekable;
1212

1313
use rustc_lexer::{LiteralKind, TokenKind};
1414
use rustc_span::edition::Edition;
1515
use rustc_span::symbol::Symbol;
1616
use rustc_span::with_default_session_globals;
1717

18+
use super::format::Buffer;
19+
1820
/// Highlights `src`, returning the HTML output.
1921
crate fn render_with_highlighting(
20-
src: String,
22+
src: &str,
23+
out: &mut Buffer,
2124
class: Option<&str>,
2225
playground_button: Option<&str>,
2326
tooltip: Option<(Option<Edition>, &str)>,
2427
edition: Edition,
25-
) -> String {
28+
) {
2629
debug!("highlighting: ================\n{}\n==============", src);
27-
let mut out = String::with_capacity(src.len());
2830
if let Some((edition_info, class)) = tooltip {
2931
write!(
3032
out,
@@ -35,23 +37,19 @@ crate fn render_with_highlighting(
3537
} else {
3638
String::new()
3739
},
38-
)
39-
.unwrap();
40+
);
4041
}
4142

42-
write_header(&mut out, class);
43-
write_code(&mut out, &src, edition);
44-
write_footer(&mut out, playground_button);
45-
46-
out
43+
write_header(out, class);
44+
write_code(out, &src, edition);
45+
write_footer(out, playground_button);
4746
}
4847

49-
fn write_header(out: &mut String, class: Option<&str>) {
50-
write!(out, "<div class=\"example-wrap\"><pre class=\"rust {}\">\n", class.unwrap_or_default())
51-
.unwrap()
48+
fn write_header(out: &mut Buffer, class: Option<&str>) {
49+
write!(out, "<div class=\"example-wrap\"><pre class=\"rust {}\">\n", class.unwrap_or_default());
5250
}
5351

54-
fn write_code(out: &mut String, src: &str, edition: Edition) {
52+
fn write_code(out: &mut Buffer, src: &str, edition: Edition) {
5553
// This replace allows to fix how the code source with DOS backline characters is displayed.
5654
let src = src.replace("\r\n", "\n");
5755
Classifier::new(&src, edition).highlight(&mut |highlight| {
@@ -63,8 +61,8 @@ fn write_code(out: &mut String, src: &str, edition: Edition) {
6361
});
6462
}
6563

66-
fn write_footer(out: &mut String, playground_button: Option<&str>) {
67-
write!(out, "</pre>{}</div>\n", playground_button.unwrap_or_default()).unwrap()
64+
fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
65+
write!(out, "</pre>{}</div>\n", playground_button.unwrap_or_default());
6866
}
6967

7068
/// How a span of text is classified. Mostly corresponds to token kinds.
@@ -331,13 +329,13 @@ impl<'a> Classifier<'a> {
331329

332330
/// Called when we start processing a span of text that should be highlighted.
333331
/// The `Class` argument specifies how it should be highlighted.
334-
fn enter_span(out: &mut String, klass: Class) {
335-
write!(out, "<span class=\"{}\">", klass.as_html()).unwrap()
332+
fn enter_span(out: &mut Buffer, klass: Class) {
333+
write!(out, "<span class=\"{}\">", klass.as_html());
336334
}
337335

338336
/// Called at the end of a span of highlighted text.
339-
fn exit_span(out: &mut String) {
340-
write!(out, "</span>").unwrap()
337+
fn exit_span(out: &mut Buffer) {
338+
out.write_str("</span>");
341339
}
342340

343341
/// Called for a span of text. If the text should be highlighted differently
@@ -351,10 +349,10 @@ fn exit_span(out: &mut String) {
351349
/// ```
352350
/// The latter can be thought of as a shorthand for the former, which is more
353351
/// flexible.
354-
fn string<T: Display>(out: &mut String, text: T, klass: Option<Class>) {
352+
fn string<T: Display>(out: &mut Buffer, text: T, klass: Option<Class>) {
355353
match klass {
356-
None => write!(out, "{}", text).unwrap(),
357-
Some(klass) => write!(out, "<span class=\"{}\">{}</span>", klass.as_html(), text).unwrap(),
354+
None => write!(out, "{}", text),
355+
Some(klass) => write!(out, "<span class=\"{}\">{}</span>", klass.as_html(), text),
358356
}
359357
}
360358

‎src/librustdoc/html/highlight/tests.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::write_code;
2+
use crate::html::format::Buffer;
23
use expect_test::expect_file;
34
use rustc_span::edition::Edition;
45

@@ -18,9 +19,9 @@ const STYLE: &str = r#"
1819
fn test_html_highlighting() {
1920
let src = include_str!("fixtures/sample.rs");
2021
let html = {
21-
let mut out = String::new();
22+
let mut out = Buffer::new();
2223
write_code(&mut out, src, Edition::Edition2018);
23-
format!("{}<pre><code>{}</code></pre>\n", STYLE, out)
24+
format!("{}<pre><code>{}</code></pre>\n", STYLE, out.into_inner())
2425
};
2526
expect_file!["fixtures/sample.html"].assert_eq(&html);
2627
}
@@ -30,7 +31,7 @@ fn test_dos_backline() {
3031
let src = "pub fn foo() {\r\n\
3132
println!(\"foo\");\r\n\
3233
}\r\n";
33-
let mut html = String::new();
34+
let mut html = Buffer::new();
3435
write_code(&mut html, src, Edition::Edition2018);
35-
expect_file!["fixtures/dos_line.html"].assert_eq(&html);
36+
expect_file!["fixtures/dos_line.html"].assert_eq(&html.into_inner());
3637
}

‎src/librustdoc/html/layout.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ crate fn render<T: Print, S: Print>(
114114
{after_content}\
115115
<div id=\"rustdoc-vars\" data-root-path=\"{root_path}\" data-current-crate=\"{krate}\"></div>
116116
<script src=\"{static_root_path}main{suffix}.js\"></script>\
117-
{static_extra_scripts}\
118117
{extra_scripts}\
119118
<script defer src=\"{root_path}search-index{suffix}.js\"></script>\
120119
</body>\
@@ -135,22 +134,23 @@ crate fn render<T: Print, S: Print>(
135134
root_path = page.root_path,
136135
css_class = page.css_class,
137136
logo = {
138-
let p = format!("{}{}", page.root_path, layout.krate);
139-
let p = ensure_trailing_slash(&p);
140137
if layout.logo.is_empty() {
141138
format!(
142-
"<a href='{path}index.html'>\
139+
"<a href='{root}{path}index.html'>\
143140
<div class='logo-container rust-logo'>\
144141
<img src='{static_root_path}rust-logo{suffix}.png' alt='logo'></div></a>",
145-
path = p,
142+
root = page.root_path,
143+
path = ensure_trailing_slash(&layout.krate),
146144
static_root_path = static_root_path,
147145
suffix = page.resource_suffix
148146
)
149147
} else {
150148
format!(
151-
"<a href='{}index.html'>\
152-
<div class='logo-container'><img src='{}' alt='logo'></div></a>",
153-
p, layout.logo
149+
"<a href='{root}{path}index.html'>\
150+
<div class='logo-container'><img src='{logo}' alt='logo'></div></a>",
151+
root = page.root_path,
152+
path = ensure_trailing_slash(&layout.krate),
153+
logo = layout.logo
154154
)
155155
}
156156
},
@@ -194,7 +194,7 @@ crate fn render<T: Print, S: Print>(
194194
))
195195
.collect::<String>(),
196196
suffix = page.resource_suffix,
197-
static_extra_scripts = page
197+
extra_scripts = page
198198
.static_extra_scripts
199199
.iter()
200200
.map(|e| {
@@ -204,17 +204,13 @@ crate fn render<T: Print, S: Print>(
204204
extra_script = e
205205
)
206206
})
207-
.collect::<String>(),
208-
extra_scripts = page
209-
.extra_scripts
210-
.iter()
211-
.map(|e| {
207+
.chain(page.extra_scripts.iter().map(|e| {
212208
format!(
213209
"<script src=\"{root_path}{extra_script}.js\"></script>",
214210
root_path = page.root_path,
215211
extra_script = e
216212
)
217-
})
213+
}))
218214
.collect::<String>(),
219215
filter_crates = if layout.generate_search_filter {
220216
"<select id=\"crate-search\">\

‎src/librustdoc/html/markdown.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ use pulldown_cmark::{
4141
html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
4242
};
4343

44+
use super::format::Buffer;
45+
4446
#[cfg(test)]
4547
mod tests;
4648

@@ -235,9 +237,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
235237
}
236238
let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
237239
let text = lines.collect::<Vec<Cow<'_, str>>>().join("\n");
238-
// insert newline to clearly separate it from the
239-
// previous block so we can shorten the html output
240-
let mut s = String::from("\n");
240+
241241
let playground_button = self.playground.as_ref().and_then(|playground| {
242242
let krate = &playground.crate_name;
243243
let url = &playground.url;
@@ -298,17 +298,22 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
298298
None
299299
};
300300

301-
s.push_str(&highlight::render_with_highlighting(
302-
text,
301+
// insert newline to clearly separate it from the
302+
// previous block so we can shorten the html output
303+
let mut s = Buffer::new();
304+
s.push_str("\n");
305+
highlight::render_with_highlighting(
306+
&text,
307+
&mut s,
303308
Some(&format!(
304309
"rust-example-rendered{}",
305310
if let Some((_, class)) = tooltip { format!(" {}", class) } else { String::new() }
306311
)),
307312
playground_button.as_deref(),
308313
tooltip,
309314
edition,
310-
));
311-
Some(Event::Html(s.into()))
315+
);
316+
Some(Event::Html(s.into_inner().into()))
312317
}
313318
}
314319

@@ -1332,7 +1337,7 @@ impl IdMap {
13321337
IdMap { map: init_id_map() }
13331338
}
13341339

1335-
crate fn populate<I: IntoIterator<Item = String>>(&mut self, ids: I) {
1340+
crate fn populate<I: IntoIterator<Item = S>, S: AsRef<str> + ToString>(&mut self, ids: I) {
13361341
for id in ids {
13371342
let _ = self.derive(id);
13381343
}
@@ -1342,11 +1347,11 @@ impl IdMap {
13421347
self.map = init_id_map();
13431348
}
13441349

1345-
crate fn derive(&mut self, candidate: String) -> String {
1346-
let id = match self.map.get_mut(&candidate) {
1347-
None => candidate,
1350+
crate fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
1351+
let id = match self.map.get_mut(candidate.as_ref()) {
1352+
None => candidate.to_string(),
13481353
Some(a) => {
1349-
let id = format!("{}-{}", candidate, *a);
1354+
let id = format!("{}-{}", candidate.as_ref(), *a);
13501355
*a += 1;
13511356
id
13521357
}

‎src/librustdoc/html/render/mod.rs

Lines changed: 361 additions & 338 deletions
Large diffs are not rendered by default.

‎src/librustdoc/html/sources.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,15 @@ impl SourceCollector<'_, '_> {
8686
return Ok(());
8787
}
8888

89-
let mut contents = match fs::read_to_string(&p) {
89+
let contents = match fs::read_to_string(&p) {
9090
Ok(contents) => contents,
9191
Err(e) => {
9292
return Err(Error::new(e, &p));
9393
}
9494
};
9595

9696
// Remove the utf-8 BOM if any
97-
if contents.starts_with('\u{feff}') {
98-
contents.drain(..3);
99-
}
97+
let contents = if contents.starts_with('\u{feff}') { &contents[3..] } else { &contents };
10098

10199
// Create the intermediate directories
102100
let mut cur = self.dst.clone();
@@ -171,18 +169,18 @@ where
171169

172170
/// Wrapper struct to render the source code of a file. This will do things like
173171
/// adding line numbers to the left-hand side.
174-
fn print_src(buf: &mut Buffer, s: String, edition: Edition) {
172+
fn print_src(buf: &mut Buffer, s: &str, edition: Edition) {
175173
let lines = s.lines().count();
176174
let mut cols = 0;
177175
let mut tmp = lines;
178176
while tmp > 0 {
179177
cols += 1;
180178
tmp /= 10;
181179
}
182-
write!(buf, "<pre class=\"line-numbers\">");
180+
buf.write_str("<pre class=\"line-numbers\">");
183181
for i in 1..=lines {
184182
write!(buf, "<span id=\"{0}\">{0:1$}</span>\n", i, cols);
185183
}
186-
write!(buf, "</pre>");
187-
write!(buf, "{}", highlight::render_with_highlighting(s, None, None, None, edition));
184+
buf.write_str("</pre>");
185+
highlight::render_with_highlighting(s, buf, None, None, None, edition);
188186
}

‎src/librustdoc/passes/collect_trait_impls.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
5656

5757
// `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
5858
// doesn't work with it anyway, so pull them from the HIR map instead
59+
let mut extra_attrs = Vec::new();
5960
for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() {
6061
for &impl_node in cx.tcx.hir().trait_impls(trait_did) {
61-
let impl_did = cx.tcx.hir().local_def_id(impl_node);
62+
let impl_did = cx.tcx.hir().local_def_id(impl_node).to_def_id();
6263
cx.tcx.sess.prof.generic_activity("build_local_trait_impl").run(|| {
63-
let mut extra_attrs = Vec::new();
64-
let mut parent = cx.tcx.parent(impl_did.to_def_id());
64+
let mut parent = cx.tcx.parent(impl_did);
6565
while let Some(did) = parent {
6666
extra_attrs.extend(
6767
cx.tcx
@@ -79,13 +79,8 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
7979
);
8080
parent = cx.tcx.parent(did);
8181
}
82-
inline::build_impl(
83-
cx,
84-
None,
85-
impl_did.to_def_id(),
86-
Some(&extra_attrs),
87-
&mut new_items,
88-
);
82+
inline::build_impl(cx, None, impl_did, Some(&extra_attrs), &mut new_items);
83+
extra_attrs.clear();
8984
});
9085
}
9186
}
@@ -137,25 +132,28 @@ crate fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
137132
}
138133
}
139134

140-
new_items.retain(|it| {
141-
if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
142-
cleaner.keep_impl(for_)
143-
|| trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
144-
|| blanket_impl.is_some()
145-
} else {
146-
true
147-
}
148-
});
149-
150-
if let Some(ref mut it) = krate.module {
135+
let items = if let Some(ref mut it) = krate.module {
151136
if let ModuleItem(Module { ref mut items, .. }) = *it.kind {
152-
items.extend(synth.impls);
153-
items.extend(new_items);
137+
items
154138
} else {
155139
panic!("collect-trait-impls can't run");
156140
}
157141
} else {
158142
panic!("collect-trait-impls can't run");
143+
};
144+
145+
items.extend(synth.impls);
146+
for it in new_items.drain(..) {
147+
if let ImplItem(Impl { ref for_, ref trait_, ref blanket_impl, .. }) = *it.kind {
148+
if !(cleaner.keep_impl(for_)
149+
|| trait_.as_ref().map_or(false, |t| cleaner.keep_impl(t))
150+
|| blanket_impl.is_some())
151+
{
152+
continue;
153+
}
154+
}
155+
156+
items.push(it);
159157
}
160158

161159
krate

0 commit comments

Comments
 (0)
Please sign in to comment.