@@ -8,11 +8,48 @@ use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath};
8
8
use rustc_middle:: hir:: nested_filter;
9
9
use rustc_middle:: ty:: TyCtxt ;
10
10
use rustc_span:: hygiene:: MacroKind ;
11
- use rustc_span:: { BytePos , ExpnKind , Span } ;
11
+ use rustc_span:: { BytePos , ExpnKind } ;
12
12
13
13
use crate :: clean:: { self , PrimitiveType , rustc_span} ;
14
14
use crate :: html:: sources;
15
15
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
+
16
53
/// This enum allows us to store two different kinds of information:
17
54
///
18
55
/// In case the `span` definition comes from the same crate, we can simply get the `span` and use
@@ -96,7 +133,7 @@ impl SpanMapVisitor<'_> {
96
133
} )
97
134
. unwrap_or ( path. span )
98
135
} ;
99
- self . matches . insert ( span, link) ;
136
+ self . matches . insert ( span. into ( ) , link) ;
100
137
}
101
138
Res :: Local ( _) if let Some ( span) = self . tcx . hir_res_span ( path. res ) => {
102
139
let path_span = if only_use_last_segment
@@ -106,11 +143,12 @@ impl SpanMapVisitor<'_> {
106
143
} else {
107
144
path. span
108
145
} ;
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) ) ) ;
110
147
}
111
148
Res :: PrimTy ( p) => {
112
149
// 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) ) ) ;
114
152
}
115
153
Res :: Err => { }
116
154
_ => { }
@@ -127,7 +165,7 @@ impl SpanMapVisitor<'_> {
127
165
if cspan. inner ( ) . is_dummy ( ) || cspan. cnum ( self . tcx . sess ) != LOCAL_CRATE {
128
166
return ;
129
167
}
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 ( ) ) ) ;
131
169
}
132
170
}
133
171
@@ -138,7 +176,7 @@ impl SpanMapVisitor<'_> {
138
176
/// so, we loop until we find the macro definition by using `outer_expn_data` in a loop.
139
177
/// Finally, we get the information about the macro itself (`span` if "local", `DefId`
140
178
/// 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 {
142
180
if !span. from_expansion ( ) {
143
181
return false ;
144
182
}
@@ -176,7 +214,7 @@ impl SpanMapVisitor<'_> {
176
214
// The "call_site" includes the whole macro with its "arguments". We only want
177
215
// the macro name.
178
216
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) ;
180
218
true
181
219
}
182
220
@@ -233,7 +271,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
233
271
intravisit:: walk_path ( self , path) ;
234
272
}
235
273
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 ) {
237
275
match * qpath {
238
276
QPath :: TypeRelative ( qself, path) => {
239
277
if matches ! ( path. res, Res :: Err ) {
@@ -249,7 +287,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
249
287
self . handle_path ( & path, false ) ;
250
288
}
251
289
} 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 ( ) ) ;
253
291
}
254
292
255
293
rustc_ast:: visit:: try_visit!( self . visit_ty_unambig( qself) ) ;
@@ -267,16 +305,18 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
267
305
}
268
306
}
269
307
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 ) {
271
309
// To make the difference between "mod foo {}" and "mod foo;". In case we "import" another
272
310
// file, we want to link to it. Otherwise no need to create a link.
273
311
if !span. overlaps ( m. spans . inner_span ) {
274
312
// Now that we confirmed it's a file import, we want to get the span for the module
275
313
// name only and not all the "mod foo;".
276
314
if let Node :: Item ( item) = self . tcx . hir_node ( id) {
277
315
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
+ ) ;
280
320
}
281
321
} else {
282
322
// 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> {
288
328
fn visit_expr ( & mut self , expr : & ' tcx rustc_hir:: Expr < ' tcx > ) {
289
329
match expr. kind {
290
330
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 ( ) )
292
332
}
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 ( ) ) ,
294
334
_ => {
295
335
if self . handle_macro ( expr. span ) {
296
336
// We don't want to go deeper into the macro.
0 commit comments