@@ -33,6 +33,7 @@ use std::cell::Ref;
33
33
use std:: collections:: BTreeMap ;
34
34
use std:: io;
35
35
use std:: mem;
36
+ use std:: ops:: RangeInclusive ;
36
37
use std:: rc:: Rc ;
37
38
use std:: u32;
38
39
@@ -50,9 +51,6 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
50
51
sess : Option < & ' a Session > ,
51
52
tcx : Option < TyCtxt < ' a , ' tcx , ' tcx > > ,
52
53
53
- // Cache the last used filemap for translating spans as an optimization.
54
- last_filemap_index : usize ,
55
-
56
54
lazy_state : LazyState ,
57
55
}
58
56
@@ -70,7 +68,7 @@ pub trait Metadata<'a, 'tcx>: Copy {
70
68
cdata : self . cdata ( ) ,
71
69
sess : self . sess ( ) . or ( tcx. map ( |tcx| tcx. sess ) ) ,
72
70
tcx,
73
- last_filemap_index : 0 ,
71
+
74
72
lazy_state : LazyState :: NoNode ,
75
73
}
76
74
}
@@ -270,63 +268,46 @@ impl<'a, 'tcx> SpecializedDecoder<DefIndex> for DecodeContext<'a, 'tcx> {
270
268
271
269
impl < ' a , ' tcx > SpecializedDecoder < Span > for DecodeContext < ' a , ' tcx > {
272
270
fn specialized_decode ( & mut self ) -> Result < Span , Self :: Error > {
273
- let tag = u8 :: decode ( self ) ?;
271
+ let cnum_tag = u32 :: decode ( self ) ?;
274
272
275
- if tag == TAG_INVALID_SPAN {
273
+ if cnum_tag == TAG_INVALID_SPAN_CNUM {
276
274
return Ok ( DUMMY_SP )
277
275
}
278
276
279
- debug_assert_eq ! ( tag, TAG_VALID_SPAN ) ;
277
+ let original_cnum = CrateNum :: from_u32 ( cnum_tag - TAG_VALID_SPAN_CNUM_START ) ;
278
+ let cnum = self . map_encoded_cnum_to_current ( original_cnum) ;
280
279
281
280
let lo = BytePos :: decode ( self ) ?;
282
281
let len = BytePos :: decode ( self ) ?;
283
- let hi = lo + len;
284
282
285
283
let sess = if let Some ( sess) = self . sess {
286
284
sess
287
285
} else {
288
286
bug ! ( "Cannot decode Span without Session." )
289
287
} ;
290
288
291
- let imported_filemaps = self . cdata ( ) . imported_filemaps ( & sess. codemap ( ) ) ;
292
- let filemap = {
293
- // Optimize for the case that most spans within a translated item
294
- // originate from the same filemap.
295
- let last_filemap = & imported_filemaps[ self . last_filemap_index ] ;
296
-
297
- if lo >= last_filemap. original_start_pos &&
298
- lo <= last_filemap. original_end_pos {
299
- last_filemap
300
- } else {
301
- let mut a = 0 ;
302
- let mut b = imported_filemaps. len ( ) ;
303
-
304
- while b - a > 1 {
305
- let m = ( a + b) / 2 ;
306
- if imported_filemaps[ m] . original_start_pos > lo {
307
- b = m;
308
- } else {
309
- a = m;
310
- }
311
- }
312
-
313
- self . last_filemap_index = a;
314
- & imported_filemaps[ a]
315
- }
289
+ let span_cdata_rc_any;
290
+ let span_cdata = if original_cnum == LOCAL_CRATE {
291
+ self . cdata ( )
292
+ } else {
293
+ // FIXME(eddyb) this requires the `tcx` which isn't always available.
294
+ // However, currently only MIR inlining can end up producing such
295
+ // cross-crate spans, and decoding MIR always provides a `tcx`.
296
+ span_cdata_rc_any = self . tcx ( ) . crate_data_as_rc_any ( cnum) ;
297
+ span_cdata_rc_any. downcast_ref :: < CrateMetadata > ( )
298
+ . expect ( "CrateStore crate data is not a CrateMetadata" )
316
299
} ;
317
300
318
- // Make sure our binary search above is correct.
319
- debug_assert ! ( lo >= filemap. original_start_pos &&
320
- lo <= filemap . original_end_pos ) ;
301
+ let filemap = span_cdata . imported_filemap_containing ( & sess . codemap ( ) , lo , |filemap| {
302
+ filemap. original_start_pos ..=filemap . original_end_pos
303
+ } ) ;
321
304
322
305
// Make sure we correctly filtered out invalid spans during encoding
323
- debug_assert ! ( hi >= filemap. original_start_pos &&
324
- hi <= filemap. original_end_pos) ;
306
+ debug_assert ! ( lo + len >= filemap. original_start_pos &&
307
+ lo + len <= filemap. original_end_pos) ;
325
308
326
309
let lo = ( lo + filemap. translated_filemap . start_pos ) - filemap. original_start_pos ;
327
- let hi = ( hi + filemap. translated_filemap . start_pos ) - filemap. original_start_pos ;
328
-
329
- Ok ( Span :: new ( lo, hi, NO_EXPANSION ) )
310
+ Ok ( Span :: new ( lo, lo + len, NO_EXPANSION ) )
330
311
}
331
312
}
332
313
@@ -1169,4 +1150,41 @@ impl<'a, 'tcx> CrateMetadata {
1169
1150
* self . codemap_import_info . borrow_mut ( ) = imported_filemaps;
1170
1151
self . codemap_import_info . borrow ( )
1171
1152
}
1153
+
1154
+ pub fn imported_filemap_containing < F > ( & ' a self ,
1155
+ local_codemap : & codemap:: CodeMap ,
1156
+ pos : BytePos ,
1157
+ range_of : F )
1158
+ -> Ref < ' a , cstore:: ImportedFileMap >
1159
+ where F : Fn ( & cstore:: ImportedFileMap ) -> RangeInclusive < BytePos >
1160
+ {
1161
+ Ref :: map ( self . imported_filemaps ( local_codemap) , |imported_filemaps| {
1162
+ // Optimize for the case that most spans within a translated item
1163
+ // originate from the same filemap.
1164
+ let last_filemap = & imported_filemaps[ self . last_filemap_index . get ( ) ] ;
1165
+ if range_of ( last_filemap) . contains ( pos) {
1166
+ last_filemap
1167
+ } else {
1168
+ let mut a = 0 ;
1169
+ let mut b = imported_filemaps. len ( ) ;
1170
+
1171
+ while b - a > 1 {
1172
+ let m = ( a + b) / 2 ;
1173
+ if range_of ( & imported_filemaps[ m] ) . start > pos {
1174
+ b = m;
1175
+ } else {
1176
+ a = m;
1177
+ }
1178
+ }
1179
+
1180
+ self . last_filemap_index . set ( a) ;
1181
+ let filemap = & imported_filemaps[ a] ;
1182
+
1183
+ // Make sure our binary search above is correct.
1184
+ debug_assert ! ( range_of( filemap) . contains( pos) ) ;
1185
+
1186
+ filemap
1187
+ }
1188
+ } )
1189
+ }
1172
1190
}
0 commit comments