11// Decoding metadata from a single crate's metadata
22
33use std:: iter:: TrustedLen ;
4- use std:: path:: Path ;
4+ use std:: path:: { Path , PathBuf } ;
55use std:: sync:: { Arc , OnceLock } ;
66use std:: { io, iter, mem} ;
77
@@ -1610,10 +1610,14 @@ impl<'a> CrateMetadataRef<'a> {
16101610 /// Proc macro crates don't currently export spans, so this function does not have
16111611 /// to work for them.
16121612 fn imported_source_file ( self , source_file_index : u32 , sess : & Session ) -> ImportedSourceFile {
1613- fn filter < ' a > ( sess : & Session , path : Option < & ' a Path > ) -> Option < & ' a Path > {
1613+ fn filter < ' a > (
1614+ sess : & Session ,
1615+ real_source_base_dir : & Option < PathBuf > ,
1616+ path : Option < & ' a Path > ,
1617+ ) -> Option < & ' a Path > {
16141618 path. filter ( |_| {
16151619 // Only spend time on further checks if we have what to translate *to*.
1616- sess . opts . real_rust_source_base_dir . is_some ( )
1620+ real_source_base_dir . is_some ( )
16171621 // Some tests need the translation to be always skipped.
16181622 && sess. opts . unstable_opts . translate_remapped_path_to_local_path
16191623 } )
@@ -1625,57 +1629,92 @@ impl<'a> CrateMetadataRef<'a> {
16251629 } )
16261630 }
16271631
1628- let try_to_translate_virtual_to_real = |name : & mut rustc_span:: FileName | {
1629- // Translate the virtual `/rustc/$hash` prefix back to a real directory
1630- // that should hold actual sources, where possible.
1631- //
1632- // NOTE: if you update this, you might need to also update bootstrap's code for generating
1633- // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1634- let virtual_rust_source_base_dir = [
1635- filter ( sess, option_env ! ( "CFG_VIRTUAL_RUST_SOURCE_BASE_DIR" ) . map ( Path :: new) ) ,
1636- filter ( sess, sess. opts . unstable_opts . simulate_remapped_rust_src_base . as_deref ( ) ) ,
1637- ] ;
1632+ let try_to_translate_virtual_to_real =
1633+ |virtual_source_base_dir : Option < & str > ,
1634+ real_source_base_dir : & Option < PathBuf > ,
1635+ name : & mut rustc_span:: FileName | {
1636+ let virtual_source_base_dir = [
1637+ filter ( sess, real_source_base_dir, virtual_source_base_dir. map ( Path :: new) ) ,
1638+ filter (
1639+ sess,
1640+ real_source_base_dir,
1641+ sess. opts . unstable_opts . simulate_remapped_rust_src_base . as_deref ( ) ,
1642+ ) ,
1643+ ] ;
16381644
1639- debug ! (
1640- "try_to_translate_virtual_to_real(name={:?}): \
1641- virtual_rust_source_base_dir ={:?}, real_rust_source_base_dir ={:?}",
1642- name, virtual_rust_source_base_dir , sess . opts . real_rust_source_base_dir ,
1643- ) ;
1645+ debug ! (
1646+ "try_to_translate_virtual_to_real(name={:?}): \
1647+ virtual_source_base_dir ={:?}, real_source_base_dir ={:?}",
1648+ name, virtual_source_base_dir , real_source_base_dir ,
1649+ ) ;
16441650
1645- for virtual_dir in virtual_rust_source_base_dir. iter ( ) . flatten ( ) {
1646- if let Some ( real_dir) = & sess. opts . real_rust_source_base_dir
1651+ for virtual_dir in virtual_source_base_dir. iter ( ) . flatten ( ) {
1652+ if let Some ( real_dir) = & real_source_base_dir
1653+ && let rustc_span:: FileName :: Real ( old_name) = name
1654+ && let rustc_span:: RealFileName :: Remapped { local_path : _, virtual_name } =
1655+ old_name
1656+ && let Ok ( rest) = virtual_name. strip_prefix ( virtual_dir)
1657+ {
1658+ let new_path = real_dir. join ( rest) ;
1659+
1660+ debug ! (
1661+ "try_to_translate_virtual_to_real: `{}` -> `{}`" ,
1662+ virtual_name. display( ) ,
1663+ new_path. display( ) ,
1664+ ) ;
1665+
1666+ // Check if the translated real path is affected by any user-requested
1667+ // remaps via --remap-path-prefix. Apply them if so.
1668+ // Note that this is a special case for imported rust-src paths specified by
1669+ // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1670+ // Other imported paths are not currently remapped (see #66251).
1671+ let ( user_remapped, applied) =
1672+ sess. source_map ( ) . path_mapping ( ) . map_prefix ( & new_path) ;
1673+ let new_name = if applied {
1674+ rustc_span:: RealFileName :: Remapped {
1675+ local_path : Some ( new_path. clone ( ) ) ,
1676+ virtual_name : user_remapped. to_path_buf ( ) ,
1677+ }
1678+ } else {
1679+ rustc_span:: RealFileName :: LocalPath ( new_path)
1680+ } ;
1681+ * old_name = new_name;
1682+ }
1683+ }
1684+ } ;
1685+
1686+ let try_to_translate_real_to_virtual =
1687+ |virtual_source_base_dir : Option < & str > ,
1688+ real_source_base_dir : & Option < PathBuf > ,
1689+ subdir : & str ,
1690+ name : & mut rustc_span:: FileName | {
1691+ if let Some ( virtual_dir) = & sess. opts . unstable_opts . simulate_remapped_rust_src_base
1692+ && let Some ( real_dir) = real_source_base_dir
16471693 && let rustc_span:: FileName :: Real ( old_name) = name
1648- && let rustc_span:: RealFileName :: Remapped { local_path : _, virtual_name } =
1649- old_name
1650- && let Ok ( rest) = virtual_name. strip_prefix ( virtual_dir)
16511694 {
1652- let new_path = real_dir. join ( rest) ;
1653-
1654- debug ! (
1655- "try_to_translate_virtual_to_real: `{}` -> `{}`" ,
1656- virtual_name. display( ) ,
1657- new_path. display( ) ,
1658- ) ;
1659-
1660- // Check if the translated real path is affected by any user-requested
1661- // remaps via --remap-path-prefix. Apply them if so.
1662- // Note that this is a special case for imported rust-src paths specified by
1663- // https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
1664- // Other imported paths are not currently remapped (see #66251).
1665- let ( user_remapped, applied) =
1666- sess. source_map ( ) . path_mapping ( ) . map_prefix ( & new_path) ;
1667- let new_name = if applied {
1668- rustc_span:: RealFileName :: Remapped {
1669- local_path : Some ( new_path. clone ( ) ) ,
1670- virtual_name : user_remapped. to_path_buf ( ) ,
1695+ let relative_path = match old_name {
1696+ rustc_span:: RealFileName :: LocalPath ( local) => {
1697+ local. strip_prefix ( real_dir) . ok ( )
1698+ }
1699+ rustc_span:: RealFileName :: Remapped { virtual_name, .. } => {
1700+ virtual_source_base_dir
1701+ . and_then ( |virtual_dir| virtual_name. strip_prefix ( virtual_dir) . ok ( ) )
16711702 }
1672- } else {
1673- rustc_span:: RealFileName :: LocalPath ( new_path)
16741703 } ;
1675- * old_name = new_name;
1704+ debug ! (
1705+ ?relative_path,
1706+ ?virtual_dir,
1707+ ?subdir,
1708+ "simulate_remapped_rust_src_base"
1709+ ) ;
1710+ if let Some ( rest) = relative_path. and_then ( |p| p. strip_prefix ( subdir) . ok ( ) ) {
1711+ * old_name = rustc_span:: RealFileName :: Remapped {
1712+ local_path : None ,
1713+ virtual_name : virtual_dir. join ( subdir) . join ( rest) ,
1714+ } ;
1715+ }
16761716 }
1677- }
1678- } ;
1717+ } ;
16791718
16801719 let mut import_info = self . cdata . source_map_import_info . lock ( ) ;
16811720 for _ in import_info. len ( ) ..=( source_file_index as usize ) {
@@ -1713,36 +1752,45 @@ impl<'a> CrateMetadataRef<'a> {
17131752 // This is useful for testing so that tests about the effects of
17141753 // `try_to_translate_virtual_to_real` don't have to worry about how the
17151754 // compiler is bootstrapped.
1716- if let Some ( virtual_dir) = & sess. opts . unstable_opts . simulate_remapped_rust_src_base
1717- && let Some ( real_dir) = & sess. opts . real_rust_source_base_dir
1718- && let rustc_span:: FileName :: Real ( ref mut old_name) = name
1719- {
1720- let relative_path = match old_name {
1721- rustc_span:: RealFileName :: LocalPath ( local) => {
1722- local. strip_prefix ( real_dir) . ok ( )
1723- }
1724- rustc_span:: RealFileName :: Remapped { virtual_name, .. } => {
1725- option_env ! ( "CFG_VIRTUAL_RUST_SOURCE_BASE_DIR" )
1726- . and_then ( |virtual_dir| virtual_name. strip_prefix ( virtual_dir) . ok ( ) )
1727- }
1728- } ;
1729- debug ! ( ?relative_path, ?virtual_dir, "simulate_remapped_rust_src_base" ) ;
1730- for subdir in [ "library" , "compiler" ] {
1731- if let Some ( rest) = relative_path. and_then ( |p| p. strip_prefix ( subdir) . ok ( ) )
1732- {
1733- * old_name = rustc_span:: RealFileName :: Remapped {
1734- local_path : None , // FIXME: maybe we should preserve this?
1735- virtual_name : virtual_dir. join ( subdir) . join ( rest) ,
1736- } ;
1737- break ;
1738- }
1739- }
1740- }
1755+ try_to_translate_real_to_virtual (
1756+ option_env ! ( "CFG_VIRTUAL_RUST_SOURCE_BASE_DIR" ) ,
1757+ & sess. opts . real_rust_source_base_dir ,
1758+ "library" ,
1759+ & mut name,
1760+ ) ;
1761+
1762+ // If this file is under $sysroot/lib/rustlib/rustc-src/
1763+ // and the user wish to simulate remapping with -Z simulate-remapped-rust-src-base,
1764+ // then we change `name` to a similar state as if the rust was bootstrapped
1765+ // with `remap-debuginfo = true`.
1766+ try_to_translate_real_to_virtual (
1767+ option_env ! ( "CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR" ) ,
1768+ & sess. opts . real_rustc_dev_source_base_dir ,
1769+ "compiler" ,
1770+ & mut name,
1771+ ) ;
17411772
17421773 // If this file's path has been remapped to `/rustc/$hash`,
1743- // we might be able to reverse that (also see comments above,
1744- // on `try_to_translate_virtual_to_real`).
1745- try_to_translate_virtual_to_real ( & mut name) ;
1774+ // we might be able to reverse that.
1775+ //
1776+ // NOTE: if you update this, you might need to also update bootstrap's code for generating
1777+ // the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
1778+ try_to_translate_virtual_to_real (
1779+ option_env ! ( "CFG_VIRTUAL_RUST_SOURCE_BASE_DIR" ) ,
1780+ & sess. opts . real_rust_source_base_dir ,
1781+ & mut name,
1782+ ) ;
1783+
1784+ // If this file's path has been remapped to `/rustc-dev/$hash`,
1785+ // we might be able to reverse that.
1786+ //
1787+ // NOTE: if you update this, you might need to also update bootstrap's code for generating
1788+ // the `rustc-dev` component in `Src::run` in `src/bootstrap/dist.rs`.
1789+ try_to_translate_virtual_to_real (
1790+ option_env ! ( "CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR" ) ,
1791+ & sess. opts . real_rustc_dev_source_base_dir ,
1792+ & mut name,
1793+ ) ;
17461794
17471795 let local_version = sess. source_map ( ) . new_imported_source_file (
17481796 name,
0 commit comments