@@ -8,11 +8,48 @@ use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath};
88use rustc_middle::hir::nested_filter;
99use rustc_middle::ty::TyCtxt;
1010use rustc_span::hygiene::MacroKind;
11- use rustc_span::{BytePos, ExpnKind, Span };
11+ use rustc_span::{BytePos, ExpnKind};
1212
1313use crate::clean::{self, PrimitiveType, rustc_span};
1414use crate::html::sources;
1515
16+ /// This is a stripped down version of [`rustc_span::Span`] that only contains the start and end byte positions of the span.
17+ ///
18+ /// Profiling showed that the `Span` interner was taking up a lot of the run-time when highlighting, and since we
19+ /// never actually use the context and parent that are stored in a normal `Span`, we can replace its usages with this
20+ /// one, which is much cheaper to construct.
21+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22+ pub(crate) struct Span {
23+ lo: BytePos,
24+ hi: BytePos,
25+ }
26+
27+ impl From<rustc_span::Span> for Span {
28+ fn from(value: rustc_span::Span) -> Self {
29+ Self { lo: value.lo(), hi: value.hi() }
30+ }
31+ }
32+
33+ impl Span {
34+ pub(crate) fn lo(self) -> BytePos {
35+ self.lo
36+ }
37+
38+ pub(crate) fn hi(self) -> BytePos {
39+ self.hi
40+ }
41+
42+ pub(crate) fn with_lo(self, lo: BytePos) -> Self {
43+ Self { lo, hi: self.hi() }
44+ }
45+
46+ pub(crate) fn with_hi(self, hi: BytePos) -> Self {
47+ Self { lo: self.lo(), hi }
48+ }
49+ }
50+
51+ pub(crate) const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0) };
52+
1653/// This enum allows us to store two different kinds of information:
1754///
1855/// In case the `span` definition comes from the same crate, we can simply get the `span` and use
@@ -96,7 +133,7 @@ impl SpanMapVisitor<'_> {
96133 })
97134 .unwrap_or(path.span)
98135 };
99- self.matches.insert(span, link);
136+ self.matches.insert(span.into() , link);
100137 }
101138 Res::Local(_) if let Some(span) = self.tcx.hir_res_span(path.res) => {
102139 let path_span = if only_use_last_segment
@@ -106,11 +143,12 @@ impl SpanMapVisitor<'_> {
106143 } else {
107144 path.span
108145 };
109- self.matches.insert(path_span, LinkFromSrc::Local(clean::Span::new(span)));
146+ self.matches.insert(path_span.into() , LinkFromSrc::Local(clean::Span::new(span)));
110147 }
111148 Res::PrimTy(p) => {
112149 // FIXME: Doesn't handle "path-like" primitives like arrays or tuples.
113- self.matches.insert(path.span, LinkFromSrc::Primitive(PrimitiveType::from(p)));
150+ self.matches
151+ .insert(path.span.into(), LinkFromSrc::Primitive(PrimitiveType::from(p)));
114152 }
115153 Res::Err => {}
116154 _ => {}
@@ -127,7 +165,7 @@ impl SpanMapVisitor<'_> {
127165 if cspan.inner().is_dummy() || cspan.cnum(self.tcx.sess) != LOCAL_CRATE {
128166 return;
129167 }
130- self.matches.insert(span, LinkFromSrc::Doc(item.owner_id.to_def_id()));
168+ self.matches.insert(span.into() , LinkFromSrc::Doc(item.owner_id.to_def_id()));
131169 }
132170 }
133171
@@ -138,7 +176,7 @@ impl SpanMapVisitor<'_> {
138176 /// so, we loop until we find the macro definition by using `outer_expn_data` in a loop.
139177 /// Finally, we get the information about the macro itself (`span` if "local", `DefId`
140178 /// otherwise) and store it inside the span map.
141- fn handle_macro(&mut self, span: Span) -> bool {
179+ fn handle_macro(&mut self, span: rustc_span:: Span) -> bool {
142180 if !span.from_expansion() {
143181 return false;
144182 }
@@ -176,7 +214,7 @@ impl SpanMapVisitor<'_> {
176214 // The "call_site" includes the whole macro with its "arguments". We only want
177215 // the macro name.
178216 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);
217+ self.matches.insert(new_span.into() , link_from_src);
180218 true
181219 }
182220
@@ -233,7 +271,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
233271 intravisit::walk_path(self, path);
234272 }
235273
236- fn visit_qpath(&mut self, qpath: &QPath<'tcx>, id: HirId, _span: Span) {
274+ fn visit_qpath(&mut self, qpath: &QPath<'tcx>, id: HirId, _span: rustc_span:: Span) {
237275 match *qpath {
238276 QPath::TypeRelative(qself, path) => {
239277 if matches!(path.res, Res::Err) {
@@ -249,7 +287,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
249287 self.handle_path(&path, false);
250288 }
251289 } else {
252- self.infer_id(path.hir_id, Some(id), path.ident.span);
290+ self.infer_id(path.hir_id, Some(id), path.ident.span.into() );
253291 }
254292
255293 rustc_ast::visit::try_visit!(self.visit_ty_unambig(qself));
@@ -267,16 +305,18 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
267305 }
268306 }
269307
270- fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: Span, id: HirId) {
308+ fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: rustc_span:: Span, id: HirId) {
271309 // To make the difference between "mod foo {}" and "mod foo;". In case we "import" another
272310 // file, we want to link to it. Otherwise no need to create a link.
273311 if !span.overlaps(m.spans.inner_span) {
274312 // Now that we confirmed it's a file import, we want to get the span for the module
275313 // name only and not all the "mod foo;".
276314 if let Node::Item(item) = self.tcx.hir_node(id) {
277315 let (ident, _) = item.expect_mod();
278- self.matches
279- .insert(ident.span, LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)));
316+ self.matches.insert(
317+ ident.span.into(),
318+ LinkFromSrc::Local(clean::Span::new(m.spans.inner_span)),
319+ );
280320 }
281321 } else {
282322 // If it's a "mod foo {}", we want to look to its documentation page.
@@ -288,9 +328,9 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
288328 fn visit_expr(&mut self, expr: &'tcx rustc_hir::Expr<'tcx>) {
289329 match expr.kind {
290330 ExprKind::MethodCall(segment, ..) => {
291- self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span)
331+ self.infer_id(segment.hir_id, Some(expr.hir_id), segment.ident.span.into() )
292332 }
293- ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span),
333+ ExprKind::Call(call, ..) => self.infer_id(call.hir_id, None, call.span.into() ),
294334 _ => {
295335 if self.handle_macro(expr.span) {
296336 // We don't want to go deeper into the macro.
0 commit comments