Skip to content

Commit 7b69a13

Browse files
Auto merge of #147189 - yotamofek:pr/rustdoc/highlight-optimizations-2, r=<try>
[PERF] Use small `Span`s in rustdoc's highlighter
2 parents a2db928 + a2250d0 commit 7b69a13

File tree

4 files changed

+59
-17
lines changed

4 files changed

+59
-17
lines changed

src/librustdoc/html/highlight.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use std::iter;
1212

1313
use rustc_data_structures::fx::FxIndexMap;
1414
use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
15+
use rustc_span::BytePos;
1516
use rustc_span::edition::Edition;
1617
use rustc_span::symbol::Symbol;
17-
use rustc_span::{BytePos, DUMMY_SP, Span};
1818

1919
use super::format;
2020
use crate::clean::PrimitiveType;
@@ -23,6 +23,38 @@ use crate::html::escape::EscapeBodyText;
2323
use crate::html::macro_expansion::ExpandedCode;
2424
use crate::html::render::{Context, LinkFromSrc};
2525

26+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27+
pub(crate) struct Span {
28+
lo: BytePos,
29+
hi: BytePos,
30+
}
31+
32+
impl From<rustc_span::Span> for Span {
33+
fn from(value: rustc_span::Span) -> Self {
34+
Self { lo: value.lo(), hi: value.hi() }
35+
}
36+
}
37+
38+
impl Span {
39+
fn lo(self) -> BytePos {
40+
self.lo
41+
}
42+
43+
fn hi(self) -> BytePos {
44+
self.hi
45+
}
46+
47+
fn with_lo(self, lo: BytePos) -> Self {
48+
Self { lo, hi: self.hi() }
49+
}
50+
51+
fn with_hi(self, hi: BytePos) -> Span {
52+
Self { lo: self.lo(), hi }
53+
}
54+
}
55+
56+
const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0) };
57+
2658
/// This type is needed in case we want to render links on items to allow to go to their definition.
2759
pub(crate) struct HrefContext<'a, 'tcx> {
2860
pub(crate) context: &'a Context<'tcx>,

src/librustdoc/html/render/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::formats::FormatRenderer;
2828
use crate::formats::cache::Cache;
2929
use crate::formats::item_type::ItemType;
3030
use crate::html::escape::Escape;
31+
use crate::html::highlight::Span;
3132
use crate::html::macro_expansion::ExpandedCode;
3233
use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
3334
use crate::html::render::write_shared::write_shared;
@@ -139,7 +140,7 @@ pub(crate) struct SharedContext<'tcx> {
139140

140141
/// Correspondence map used to link types used in the source code pages to allow to click on
141142
/// links to jump to the type's definition.
142-
pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
143+
pub(crate) span_correspondence_map: FxHashMap<Span, LinkFromSrc>,
143144
pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
144145
/// The [`Cache`] used during rendering.
145146
pub(crate) cache: Cache,

src/librustdoc/html/render/span_map.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath};
88
use rustc_middle::hir::nested_filter;
99
use rustc_middle::ty::TyCtxt;
1010
use rustc_span::hygiene::MacroKind;
11-
use rustc_span::{BytePos, ExpnKind, Span};
11+
use rustc_span::{BytePos, ExpnKind};
1212

1313
use crate::clean::{self, PrimitiveType, rustc_span};
14+
use crate::html::highlight::Span;
1415
use crate::html::sources;
1516

1617
/// This enum allows us to store two different kinds of information:
@@ -96,7 +97,7 @@ impl SpanMapVisitor<'_> {
9697
})
9798
.unwrap_or(path.span)
9899
};
99-
self.matches.insert(span, link);
100+
self.matches.insert(span.into(), link);
100101
}
101102
Res::Local(_) if let Some(span) = self.tcx.hir_res_span(path.res) => {
102103
let path_span = if only_use_last_segment
@@ -106,11 +107,12 @@ impl SpanMapVisitor<'_> {
106107
} else {
107108
path.span
108109
};
109-
self.matches.insert(path_span, LinkFromSrc::Local(clean::Span::new(span)));
110+
self.matches.insert(path_span.into(), LinkFromSrc::Local(clean::Span::new(span)));
110111
}
111112
Res::PrimTy(p) => {
112113
// FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
113-
self.matches.insert(path.span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
114+
self.matches
115+
.insert(path.span.into(), LinkFromSrc::Primitive(PrimitiveType::from(p)));
114116
}
115117
Res::Err => {}
116118
_ => {}
@@ -127,7 +129,7 @@ impl SpanMapVisitor<'_> {
127129
if cspan.inner().is_dummy() || cspan.cnum(self.tcx.sess) != LOCAL_CRATE {
128130
return;
129131
}
130-
self.matches.insert(span, LinkFromSrc::Doc(item.owner_id.to_def_id()));
132+
self.matches.insert(span.into(), LinkFromSrc::Doc(item.owner_id.to_def_id()));
131133
}
132134
}
133135

@@ -138,7 +140,7 @@ impl SpanMapVisitor<'_> {
138140
/// so, we loop until we find the macro definition by using `outer_expn_data` in a loop.
139141
/// Finally, we get the information about the macro itself (`span` if "local", `DefId`
140142
/// otherwise) and store it inside the span map.
141-
fn handle_macro(&mut self, span: Span) -> bool {
143+
fn handle_macro(&mut self, span: rustc_span::Span) -> bool {
142144
if !span.from_expansion() {
143145
return false;
144146
}
@@ -176,7 +178,7 @@ impl SpanMapVisitor<'_> {
176178
// The "call_site" includes the whole macro with its "arguments". We only want
177179
// the macro name.
178180
let new_span = new_span.with_hi(new_span.lo() + BytePos(macro_name.len() as u32));
179-
self.matches.insert(new_span, link_from_src);
181+
self.matches.insert(new_span.into(), link_from_src);
180182
true
181183
}
182184

@@ -233,7 +235,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
233235
intravisit::walk_path(self, path);
234236
}
235237

236-
fn visit_qpath(&mut self, qpath: &QPath<'tcx>, id: HirId, _span: Span) {
238+
fn visit_qpath(&mut self, qpath: &QPath<'tcx>, id: HirId, _span: rustc_span::Span) {
237239
match *qpath {
238240
QPath::TypeRelative(qself, path) => {
239241
if matches!(path.res, Res::Err) {
@@ -249,7 +251,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
249251
self.handle_path(&path, false);
250252
}
251253
} else {
252-
self.infer_id(path.hir_id, Some(id), path.ident.span);
254+
self.infer_id(path.hir_id, Some(id), path.ident.span.into());
253255
}
254256

255257
rustc_ast::visit::try_visit!(self.visit_ty_unambig(qself));
@@ -267,16 +269,18 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
267269
}
268270
}
269271

270-
fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) {
272+
fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: rustc_span::Span, id: HirId) {
271273
// To make the difference between "mod foo {}" and "mod foo;". In case we "import" another
272274
// file, we want to link to it. Otherwise no need to create a link.
273275
if !span.overlaps(m.spans.inner_span) {
274276
// Now that we confirmed it's a file import, we want to get the span for the module
275277
// name only and not all the "mod foo;".
276278
if let Node::Item(item) = self.tcx.hir_node(id) {
277279
let (ident, _) = item.expect_mod();
278-
self.matches
279-
.insert(ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)));
280+
self.matches.insert(
281+
ident.span.into(),
282+
LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)),
283+
);
280284
}
281285
} else {
282286
// If it's a "mod foo {}", we want to look to its documentation page.
@@ -288,9 +292,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
288292
fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
289293
match expr.kind {
290294
ExprKind::MethodCall(segment, ..) => {
291-
self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span)
295+
self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span.into())
292296
}
293-
ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span),
297+
ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span.into()),
294298
_ => {
295299
if self.handle_macro(expr.span) {
296300
// We don't want to go deeper into the macro.

src/librustdoc/html/sources.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,12 @@ pub(crate) fn print_src(
348348
highlight::write_code(
349349
fmt,
350350
s,
351-
Some(highlight::HrefContext { context, file_span, root_path, current_href }),
351+
Some(highlight::HrefContext {
352+
context,
353+
file_span: file_span.into(),
354+
root_path,
355+
current_href,
356+
}),
352357
Some(decoration_info),
353358
Some(line_info),
354359
);

0 commit comments

Comments
 (0)