@@ -37,6 +37,7 @@ use rustc_span::symbol::{sym, Ident, Symbol};
3737use rustc_span:: { self , BytePos , ExpnId , Pos , Span , SyntaxContext , DUMMY_SP } ;
3838
3939use proc_macro:: bridge:: client:: ProcMacro ;
40+ use std:: cell:: RefCell ;
4041use std:: io;
4142use std:: iter:: TrustedLen ;
4243use std:: mem;
@@ -99,7 +100,7 @@ pub(crate) struct CrateMetadata {
99100 /// Proc macro descriptions for this crate, if it's a proc macro crate.
100101 raw_proc_macros : Option < & ' static [ ProcMacro ] > ,
101102 /// Source maps for code from the crate.
102- source_map_import_info : OnceCell < Vec < ImportedSourceFile > > ,
103+ source_map_import_info : RefCell < Vec < Option < ImportedSourceFile > > > ,
103104 /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
104105 def_path_hash_map : DefPathHashMapRef < ' static > ,
105106 /// Likewise for ExpnHash.
@@ -143,7 +144,8 @@ pub(crate) struct CrateMetadata {
143144}
144145
145146/// Holds information about a rustc_span::SourceFile imported from another crate.
146- /// See `imported_source_files()` for more information.
147+ /// See `imported_source_file()` for more information.
148+ #[ derive( Clone ) ]
147149struct ImportedSourceFile {
148150 /// This SourceFile's byte-offset within the source_map of its original crate
149151 original_start_pos : rustc_span:: BytePos ,
@@ -528,7 +530,7 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
528530 } ;
529531
530532 // Index of the file in the corresponding crate's list of encoded files.
531- let metadata_index = usize :: decode ( decoder) ;
533+ let metadata_index = u32 :: decode ( decoder) ;
532534
533535 // There are two possibilities here:
534536 // 1. This is a 'local span', which is located inside a `SourceFile`
@@ -556,10 +558,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
556558 // to be based on the *foreign* crate (e.g. crate C), not the crate
557559 // we are writing metadata for (e.g. crate B). This allows us to
558560 // treat the 'local' and 'foreign' cases almost identically during deserialization:
559- // we can call `imported_source_files ` for the proper crate, and binary search
561+ // we can call `imported_source_file ` for the proper crate, and binary search
560562 // through the returned slice using our span.
561- let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
562- decoder. cdata ( ) . imported_source_files ( sess)
563+ let source_file = if tag == TAG_VALID_SPAN_LOCAL {
564+ decoder. cdata ( ) . imported_source_file ( metadata_index , sess)
563565 } else {
564566 // When we encode a proc-macro crate, all `Span`s should be encoded
565567 // with `TAG_VALID_SPAN_LOCAL`
@@ -587,13 +589,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
587589 decoder. last_source_file_index = 0 ;
588590
589591 let foreign_data = decoder. cdata ( ) . cstore . get_crate_data ( cnum) ;
590- foreign_data. imported_source_files ( sess)
592+ foreign_data. imported_source_file ( metadata_index , sess)
591593 } ;
592594
593- // Optimize for the case that most spans within a translated item
594- // originate from the same source_file.
595- let source_file = & imported_source_files[ metadata_index] ;
596-
597595 // Make sure our binary search above is correct.
598596 debug_assert ! (
599597 lo >= source_file. original_start_pos && lo <= source_file. original_end_pos,
@@ -1438,7 +1436,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
14381436 ///
14391437 /// Proc macro crates don't currently export spans, so this function does not have
14401438 /// to work for them.
1441- fn imported_source_files ( self , sess : & Session ) -> & ' a [ ImportedSourceFile ] {
1439+ fn imported_source_file ( self , source_file_index : u32 , sess : & Session ) -> ImportedSourceFile {
14421440 fn filter < ' a > ( sess : & Session , path : Option < & ' a Path > ) -> Option < & ' a Path > {
14431441 path. filter ( |_| {
14441442 // Only spend time on further checks if we have what to translate *to*.
@@ -1526,94 +1524,97 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
15261524 }
15271525 } ;
15281526
1529- self . cdata . source_map_import_info . get_or_init ( || {
1530- let external_source_map = self . root . source_map . decode ( self ) ;
1531-
1532- external_source_map
1533- . enumerate ( )
1534- . map ( |( source_file_index, source_file_to_import) | {
1535- // We can't reuse an existing SourceFile, so allocate a new one
1536- // containing the information we need.
1537- let rustc_span:: SourceFile {
1538- mut name,
1539- src_hash,
1540- start_pos,
1541- end_pos,
1542- lines,
1543- multibyte_chars,
1544- non_narrow_chars,
1545- normalized_pos,
1546- name_hash,
1547- ..
1548- } = source_file_to_import;
1549-
1550- // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
1551- // during rust bootstrapping by `remap-debuginfo = true`, and the user
1552- // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
1553- // then we change `name` to a similar state as if the rust was bootstrapped
1554- // with `remap-debuginfo = true`.
1555- // This is useful for testing so that tests about the effects of
1556- // `try_to_translate_virtual_to_real` don't have to worry about how the
1557- // compiler is bootstrapped.
1558- if let Some ( virtual_dir) =
1559- & sess. opts . unstable_opts . simulate_remapped_rust_src_base
1560- {
1561- if let Some ( real_dir) = & sess. opts . real_rust_source_base_dir {
1562- if let rustc_span:: FileName :: Real ( ref mut old_name) = name {
1563- if let rustc_span:: RealFileName :: LocalPath ( local) = old_name {
1564- if let Ok ( rest) = local. strip_prefix ( real_dir) {
1565- * old_name = rustc_span:: RealFileName :: Remapped {
1566- local_path : None ,
1567- virtual_name : virtual_dir. join ( rest) ,
1568- } ;
1569- }
1527+ let mut import_info = self . cdata . source_map_import_info . borrow_mut ( ) ;
1528+ for _ in import_info. len ( ) ..=( source_file_index as usize ) {
1529+ import_info. push ( None ) ;
1530+ }
1531+ import_info[ source_file_index as usize ]
1532+ . get_or_insert_with ( || {
1533+ let source_file_to_import = self
1534+ . root
1535+ . source_map
1536+ . get ( self , source_file_index)
1537+ . expect ( "missing source file" )
1538+ . decode ( self ) ;
1539+
1540+ // We can't reuse an existing SourceFile, so allocate a new one
1541+ // containing the information we need.
1542+ let rustc_span:: SourceFile {
1543+ mut name,
1544+ src_hash,
1545+ start_pos,
1546+ end_pos,
1547+ lines,
1548+ multibyte_chars,
1549+ non_narrow_chars,
1550+ normalized_pos,
1551+ name_hash,
1552+ ..
1553+ } = source_file_to_import;
1554+
1555+ // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
1556+ // during rust bootstrapping by `remap-debuginfo = true`, and the user
1557+ // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
1558+ // then we change `name` to a similar state as if the rust was bootstrapped
1559+ // with `remap-debuginfo = true`.
1560+ // This is useful for testing so that tests about the effects of
1561+ // `try_to_translate_virtual_to_real` don't have to worry about how the
1562+ // compiler is bootstrapped.
1563+ if let Some ( virtual_dir) = & sess. opts . unstable_opts . simulate_remapped_rust_src_base
1564+ {
1565+ if let Some ( real_dir) = & sess. opts . real_rust_source_base_dir {
1566+ if let rustc_span:: FileName :: Real ( ref mut old_name) = name {
1567+ if let rustc_span:: RealFileName :: LocalPath ( local) = old_name {
1568+ if let Ok ( rest) = local. strip_prefix ( real_dir) {
1569+ * old_name = rustc_span:: RealFileName :: Remapped {
1570+ local_path : None ,
1571+ virtual_name : virtual_dir. join ( rest) ,
1572+ } ;
15701573 }
15711574 }
15721575 }
15731576 }
1577+ }
15741578
1575- // If this file's path has been remapped to `/rustc/$hash`,
1576- // we might be able to reverse that (also see comments above,
1577- // on `try_to_translate_virtual_to_real`).
1578- try_to_translate_virtual_to_real ( & mut name) ;
1579-
1580- let source_length = ( end_pos - start_pos) . to_usize ( ) ;
1581-
1582- let local_version = sess. source_map ( ) . new_imported_source_file (
1583- name,
1584- src_hash,
1585- name_hash,
1586- source_length,
1587- self . cnum ,
1588- lines,
1589- multibyte_chars,
1590- non_narrow_chars,
1591- normalized_pos,
1592- start_pos,
1593- end_pos,
1594- source_file_index
1595- . try_into ( )
1596- . expect ( "cannot import more than U32_MAX files" ) ,
1597- ) ;
1598- debug ! (
1599- "CrateMetaData::imported_source_files alloc \
1579+ // If this file's path has been remapped to `/rustc/$hash`,
1580+ // we might be able to reverse that (also see comments above,
1581+ // on `try_to_translate_virtual_to_real`).
1582+ try_to_translate_virtual_to_real ( & mut name) ;
1583+
1584+ let source_length = ( end_pos - start_pos) . to_usize ( ) ;
1585+
1586+ let local_version = sess. source_map ( ) . new_imported_source_file (
1587+ name,
1588+ src_hash,
1589+ name_hash,
1590+ source_length,
1591+ self . cnum ,
1592+ lines,
1593+ multibyte_chars,
1594+ non_narrow_chars,
1595+ normalized_pos,
1596+ start_pos,
1597+ end_pos,
1598+ source_file_index,
1599+ ) ;
1600+ debug ! (
1601+ "CrateMetaData::imported_source_files alloc \
16001602 source_file {:?} original (start_pos {:?} end_pos {:?}) \
16011603 translated (start_pos {:?} end_pos {:?})",
1602- local_version. name,
1603- start_pos,
1604- end_pos,
1605- local_version. start_pos,
1606- local_version. end_pos
1607- ) ;
1604+ local_version. name,
1605+ start_pos,
1606+ end_pos,
1607+ local_version. start_pos,
1608+ local_version. end_pos
1609+ ) ;
16081610
1609- ImportedSourceFile {
1610- original_start_pos : start_pos,
1611- original_end_pos : end_pos,
1612- translated_source_file : local_version,
1613- }
1614- } )
1615- . collect ( )
1616- } )
1611+ ImportedSourceFile {
1612+ original_start_pos : start_pos,
1613+ original_end_pos : end_pos,
1614+ translated_source_file : local_version,
1615+ }
1616+ } )
1617+ . clone ( )
16171618 }
16181619
16191620 fn get_generator_diagnostic_data (
@@ -1676,7 +1677,7 @@ impl CrateMetadata {
16761677 trait_impls,
16771678 incoherent_impls : Default :: default ( ) ,
16781679 raw_proc_macros,
1679- source_map_import_info : OnceCell :: new ( ) ,
1680+ source_map_import_info : RefCell :: new ( Vec :: new ( ) ) ,
16801681 def_path_hash_map,
16811682 expn_hash_map : Default :: default ( ) ,
16821683 alloc_decoding_state,
0 commit comments