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. 
16121612fn  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