@@ -99,7 +99,7 @@ pub(crate) struct CrateMetadata {
99
99
/// Proc macro descriptions for this crate, if it's a proc macro crate.
100
100
raw_proc_macros : Option < & ' static [ ProcMacro ] > ,
101
101
/// Source maps for code from the crate.
102
- source_map_import_info : OnceCell < Vec < ImportedSourceFile > > ,
102
+ source_map_import_info : Lock < Vec < Option < ImportedSourceFile > > > ,
103
103
/// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
104
104
def_path_hash_map : DefPathHashMapRef < ' static > ,
105
105
/// Likewise for ExpnHash.
@@ -143,7 +143,8 @@ pub(crate) struct CrateMetadata {
143
143
}
144
144
145
145
/// Holds information about a rustc_span::SourceFile imported from another crate.
146
- /// See `imported_source_files()` for more information.
146
+ /// See `imported_source_file()` for more information.
147
+ #[ derive( Clone ) ]
147
148
struct ImportedSourceFile {
148
149
/// This SourceFile's byte-offset within the source_map of its original crate
149
150
original_start_pos : rustc_span:: BytePos ,
@@ -160,9 +161,6 @@ pub(super) struct DecodeContext<'a, 'tcx> {
160
161
sess : Option < & ' tcx Session > ,
161
162
tcx : Option < TyCtxt < ' tcx > > ,
162
163
163
- // Cache the last used source_file for translating spans as an optimization.
164
- last_source_file_index : usize ,
165
-
166
164
lazy_state : LazyState ,
167
165
168
166
// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
@@ -191,7 +189,6 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
191
189
blob : self . blob ( ) ,
192
190
sess : self . sess ( ) . or ( tcx. map ( |tcx| tcx. sess ) ) ,
193
191
tcx,
194
- last_source_file_index : 0 ,
195
192
lazy_state : LazyState :: NoNode ,
196
193
alloc_decoding_session : self
197
194
. cdata ( )
@@ -527,6 +524,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
527
524
bug ! ( "Cannot decode Span without Session." )
528
525
} ;
529
526
527
+ // Index of the file in the corresponding crate's list of encoded files.
528
+ let metadata_index = u32:: decode ( decoder) ;
529
+
530
530
// There are two possibilities here:
531
531
// 1. This is a 'local span', which is located inside a `SourceFile`
532
532
// that came from this crate. In this case, we use the source map data
@@ -553,10 +553,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
553
553
// to be based on the *foreign* crate (e.g. crate C), not the crate
554
554
// we are writing metadata for (e.g. crate B). This allows us to
555
555
// treat the 'local' and 'foreign' cases almost identically during deserialization:
556
- // we can call `imported_source_files ` for the proper crate, and binary search
556
+ // we can call `imported_source_file ` for the proper crate, and binary search
557
557
// through the returned slice using our span.
558
- let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
559
- decoder. cdata ( ) . imported_source_files ( sess)
558
+ let source_file = if tag == TAG_VALID_SPAN_LOCAL {
559
+ decoder. cdata ( ) . imported_source_file ( metadata_index , sess)
560
560
} else {
561
561
// When we encode a proc-macro crate, all `Span`s should be encoded
562
562
// with `TAG_VALID_SPAN_LOCAL`
@@ -577,60 +577,30 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
577
577
cnum
578
578
) ;
579
579
580
- // Decoding 'foreign' spans should be rare enough that it's
581
- // not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
582
- // We just set it to 0, to ensure that we don't try to access something out
583
- // of bounds for our initial 'guess'
584
- decoder. last_source_file_index = 0 ;
585
-
586
580
let foreign_data = decoder. cdata ( ) . cstore . get_crate_data ( cnum) ;
587
- foreign_data. imported_source_files ( sess)
581
+ foreign_data. imported_source_file ( metadata_index , sess)
588
582
} ;
589
583
590
- let source_file = {
591
- // Optimize for the case that most spans within a translated item
592
- // originate from the same source_file.
593
- let last_source_file = & imported_source_files[ decoder. last_source_file_index ] ;
594
-
595
- if lo >= last_source_file. original_start_pos && lo <= last_source_file. original_end_pos
596
- {
597
- last_source_file
598
- } else {
599
- let index = imported_source_files
600
- . binary_search_by_key ( & lo, |source_file| source_file. original_start_pos )
601
- . unwrap_or_else ( |index| index - 1 ) ;
602
-
603
- // Don't try to cache the index for foreign spans,
604
- // as this would require a map from CrateNums to indices
605
- if tag == TAG_VALID_SPAN_LOCAL {
606
- decoder. last_source_file_index = index;
607
- }
608
- & imported_source_files[ index]
609
- }
610
- } ;
611
-
612
- // Make sure our binary search above is correct.
584
+ // Make sure our span is well-formed.
613
585
debug_assert ! (
614
- lo >= source_file. original_start_pos && lo <= source_file. original_end_pos,
615
- "Bad binary search : lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}" ,
586
+ lo + source_file. original_start_pos <= source_file. original_end_pos,
587
+ "Malformed encoded span : lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}" ,
616
588
lo,
617
589
source_file. original_start_pos,
618
590
source_file. original_end_pos
619
591
) ;
620
592
621
- // Make sure we correctly filtered out invalid spans during encoding
593
+ // Make sure we correctly filtered out invalid spans during encoding.
622
594
debug_assert ! (
623
- hi >= source_file. original_start_pos && hi <= source_file. original_end_pos,
624
- "Bad binary search : hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}" ,
595
+ hi + source_file. original_start_pos <= source_file. original_end_pos,
596
+ "Malformed encoded span : hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}" ,
625
597
hi,
626
598
source_file. original_start_pos,
627
599
source_file. original_end_pos
628
600
) ;
629
601
630
- let lo =
631
- ( lo + source_file. translated_source_file . start_pos ) - source_file. original_start_pos ;
632
- let hi =
633
- ( hi + source_file. translated_source_file . start_pos ) - source_file. original_start_pos ;
602
+ let lo = lo + source_file. translated_source_file . start_pos ;
603
+ let hi = hi + source_file. translated_source_file . start_pos ;
634
604
635
605
// Do not try to decode parent for foreign spans.
636
606
Span :: new ( lo, hi, ctxt, None )
@@ -1482,7 +1452,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
1482
1452
///
1483
1453
/// Proc macro crates don't currently export spans, so this function does not have
1484
1454
/// to work for them.
1485
- fn imported_source_files ( self , sess : & Session ) -> & ' a [ ImportedSourceFile ] {
1455
+ fn imported_source_file ( self , source_file_index : u32 , sess : & Session ) -> ImportedSourceFile {
1486
1456
fn filter < ' a > ( sess : & Session , path : Option < & ' a Path > ) -> Option < & ' a Path > {
1487
1457
path. filter ( |_| {
1488
1458
// Only spend time on further checks if we have what to translate *to*.
@@ -1570,90 +1540,96 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
1570
1540
}
1571
1541
} ;
1572
1542
1573
- self . cdata . source_map_import_info . get_or_init ( || {
1574
- let external_source_map = self . root . source_map . decode ( self ) ;
1575
-
1576
- external_source_map
1577
- . map ( |source_file_to_import| {
1578
- // We can't reuse an existing SourceFile, so allocate a new one
1579
- // containing the information we need.
1580
- let rustc_span:: SourceFile {
1581
- mut name,
1582
- src_hash,
1583
- start_pos,
1584
- end_pos,
1585
- lines,
1586
- multibyte_chars,
1587
- non_narrow_chars,
1588
- normalized_pos,
1589
- name_hash,
1590
- ..
1591
- } = source_file_to_import;
1592
-
1593
- // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
1594
- // during rust bootstrapping by `remap-debuginfo = true`, and the user
1595
- // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
1596
- // then we change `name` to a similar state as if the rust was bootstrapped
1597
- // with `remap-debuginfo = true`.
1598
- // This is useful for testing so that tests about the effects of
1599
- // `try_to_translate_virtual_to_real` don't have to worry about how the
1600
- // compiler is bootstrapped.
1601
- if let Some ( virtual_dir) =
1602
- & sess. opts . unstable_opts . simulate_remapped_rust_src_base
1603
- {
1604
- if let Some ( real_dir) = & sess. opts . real_rust_source_base_dir {
1605
- if let rustc_span:: FileName :: Real ( ref mut old_name) = name {
1606
- if let rustc_span:: RealFileName :: LocalPath ( local) = old_name {
1607
- if let Ok ( rest) = local. strip_prefix ( real_dir) {
1608
- * old_name = rustc_span:: RealFileName :: Remapped {
1609
- local_path : None ,
1610
- virtual_name : virtual_dir. join ( rest) ,
1611
- } ;
1612
- }
1543
+ let mut import_info = self . cdata . source_map_import_info . lock ( ) ;
1544
+ for _ in import_info. len ( ) ..=( source_file_index as usize ) {
1545
+ import_info. push ( None ) ;
1546
+ }
1547
+ import_info[ source_file_index as usize ]
1548
+ . get_or_insert_with ( || {
1549
+ let source_file_to_import = self
1550
+ . root
1551
+ . source_map
1552
+ . get ( self , source_file_index)
1553
+ . expect ( "missing source file" )
1554
+ . decode ( self ) ;
1555
+
1556
+ // We can't reuse an existing SourceFile, so allocate a new one
1557
+ // containing the information we need.
1558
+ let rustc_span:: SourceFile {
1559
+ mut name,
1560
+ src_hash,
1561
+ start_pos,
1562
+ end_pos,
1563
+ lines,
1564
+ multibyte_chars,
1565
+ non_narrow_chars,
1566
+ normalized_pos,
1567
+ name_hash,
1568
+ ..
1569
+ } = source_file_to_import;
1570
+
1571
+ // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
1572
+ // during rust bootstrapping by `remap-debuginfo = true`, and the user
1573
+ // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
1574
+ // then we change `name` to a similar state as if the rust was bootstrapped
1575
+ // with `remap-debuginfo = true`.
1576
+ // This is useful for testing so that tests about the effects of
1577
+ // `try_to_translate_virtual_to_real` don't have to worry about how the
1578
+ // compiler is bootstrapped.
1579
+ if let Some ( virtual_dir) = & sess. opts . unstable_opts . simulate_remapped_rust_src_base
1580
+ {
1581
+ if let Some ( real_dir) = & sess. opts . real_rust_source_base_dir {
1582
+ if let rustc_span:: FileName :: Real ( ref mut old_name) = name {
1583
+ if let rustc_span:: RealFileName :: LocalPath ( local) = old_name {
1584
+ if let Ok ( rest) = local. strip_prefix ( real_dir) {
1585
+ * old_name = rustc_span:: RealFileName :: Remapped {
1586
+ local_path : None ,
1587
+ virtual_name : virtual_dir. join ( rest) ,
1588
+ } ;
1613
1589
}
1614
1590
}
1615
1591
}
1616
1592
}
1593
+ }
1617
1594
1618
- // If this file's path has been remapped to `/rustc/$hash`,
1619
- // we might be able to reverse that (also see comments above,
1620
- // on `try_to_translate_virtual_to_real`).
1621
- try_to_translate_virtual_to_real ( & mut name) ;
1622
-
1623
- let source_length = ( end_pos - start_pos) . to_usize ( ) ;
1624
-
1625
- let local_version = sess. source_map ( ) . new_imported_source_file (
1626
- name,
1627
- src_hash,
1628
- name_hash,
1629
- source_length,
1630
- self . cnum ,
1631
- lines,
1632
- multibyte_chars,
1633
- non_narrow_chars,
1634
- normalized_pos,
1635
- start_pos,
1636
- end_pos ,
1637
- ) ;
1638
- debug ! (
1639
- "CrateMetaData::imported_source_files alloc \
1595
+ // If this file's path has been remapped to `/rustc/$hash`,
1596
+ // we might be able to reverse that (also see comments above,
1597
+ // on `try_to_translate_virtual_to_real`).
1598
+ try_to_translate_virtual_to_real ( & mut name) ;
1599
+
1600
+ let source_length = ( end_pos - start_pos) . to_usize ( ) ;
1601
+
1602
+ let local_version = sess. source_map ( ) . new_imported_source_file (
1603
+ name,
1604
+ src_hash,
1605
+ name_hash,
1606
+ source_length,
1607
+ self . cnum ,
1608
+ lines,
1609
+ multibyte_chars,
1610
+ non_narrow_chars,
1611
+ normalized_pos,
1612
+ start_pos,
1613
+ source_file_index ,
1614
+ ) ;
1615
+ debug ! (
1616
+ "CrateMetaData::imported_source_files alloc \
1640
1617
source_file {:?} original (start_pos {:?} end_pos {:?}) \
1641
1618
translated (start_pos {:?} end_pos {:?})",
1642
- local_version. name,
1643
- start_pos,
1644
- end_pos,
1645
- local_version. start_pos,
1646
- local_version. end_pos
1647
- ) ;
1619
+ local_version. name,
1620
+ start_pos,
1621
+ end_pos,
1622
+ local_version. start_pos,
1623
+ local_version. end_pos
1624
+ ) ;
1648
1625
1649
- ImportedSourceFile {
1650
- original_start_pos : start_pos,
1651
- original_end_pos : end_pos,
1652
- translated_source_file : local_version,
1653
- }
1654
- } )
1655
- . collect ( )
1656
- } )
1626
+ ImportedSourceFile {
1627
+ original_start_pos : start_pos,
1628
+ original_end_pos : end_pos,
1629
+ translated_source_file : local_version,
1630
+ }
1631
+ } )
1632
+ . clone ( )
1657
1633
}
1658
1634
1659
1635
fn get_generator_diagnostic_data (
@@ -1716,7 +1692,7 @@ impl CrateMetadata {
1716
1692
trait_impls,
1717
1693
incoherent_impls : Default :: default ( ) ,
1718
1694
raw_proc_macros,
1719
- source_map_import_info : OnceCell :: new ( ) ,
1695
+ source_map_import_info : Lock :: new ( Vec :: new ( ) ) ,
1720
1696
def_path_hash_map,
1721
1697
expn_hash_map : Default :: default ( ) ,
1722
1698
alloc_decoding_state,
0 commit comments