@@ -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