[RFC 3127 - Trim Paths]: Condition remapped filepath on remap scopes
This commit is contained in:
parent
30f94717ca
commit
eccc9e6628
16 changed files with 328 additions and 82 deletions
|
@ -61,9 +61,14 @@ pub fn expand_file(
|
|||
|
||||
let topmost = cx.expansion_cause().unwrap_or(sp);
|
||||
let loc = cx.source_map().lookup_char_pos(topmost.lo());
|
||||
base::MacEager::expr(
|
||||
cx.expr_str(topmost, Symbol::intern(&loc.file.name.prefer_remapped().to_string_lossy())),
|
||||
)
|
||||
|
||||
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
|
||||
base::MacEager::expr(cx.expr_str(
|
||||
topmost,
|
||||
Symbol::intern(
|
||||
&loc.file.name.for_scope(cx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn expand_stringify(
|
||||
|
|
|
@ -414,11 +414,12 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
// Note: must be kept in sync with get_caller_location from cg_ssa
|
||||
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
|
||||
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
|
||||
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
let const_loc = fx.tcx.const_caller_location((
|
||||
rustc_span::symbol::Symbol::intern(
|
||||
&caller.file.name.prefer_remapped().to_string_lossy(),
|
||||
&caller.file.name.for_codegen(&fx.tcx.sess).to_string_lossy(),
|
||||
),
|
||||
caller.line as u32,
|
||||
caller.col_display as u32 + 1,
|
||||
|
|
|
@ -95,7 +95,11 @@ impl DebugContext {
|
|||
match &source_file.name {
|
||||
FileName::Real(path) => {
|
||||
let (dir_path, file_name) =
|
||||
split_path_dir_and_file(path.remapped_path_if_available());
|
||||
split_path_dir_and_file(if self.should_remap_filepaths {
|
||||
path.remapped_path_if_available()
|
||||
} else {
|
||||
path.local_path_if_available()
|
||||
});
|
||||
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
|
||||
let file_name = osstr_as_utf8_bytes(file_name);
|
||||
|
||||
|
@ -116,7 +120,14 @@ impl DebugContext {
|
|||
filename => {
|
||||
let dir_id = line_program.default_directory();
|
||||
let dummy_file_name = LineString::new(
|
||||
filename.prefer_remapped().to_string().into_bytes(),
|
||||
filename
|
||||
.display(if self.should_remap_filepaths {
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
})
|
||||
.to_string()
|
||||
.into_bytes(),
|
||||
line_program.encoding(),
|
||||
line_strings,
|
||||
);
|
||||
|
|
|
@ -31,6 +31,8 @@ pub(crate) struct DebugContext {
|
|||
|
||||
dwarf: DwarfUnit,
|
||||
unit_range_list: RangeList,
|
||||
|
||||
should_remap_filepaths: bool,
|
||||
}
|
||||
|
||||
pub(crate) struct FunctionDebugContext {
|
||||
|
@ -63,12 +65,18 @@ impl DebugContext {
|
|||
|
||||
let mut dwarf = DwarfUnit::new(encoding);
|
||||
|
||||
let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen();
|
||||
|
||||
let producer = producer();
|
||||
let comp_dir = tcx
|
||||
.sess
|
||||
.opts
|
||||
.working_dir
|
||||
.to_string_lossy(FileNameDisplayPreference::Remapped)
|
||||
.to_string_lossy(if should_remap_filepaths {
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
})
|
||||
.into_owned();
|
||||
let (name, file_info) = match tcx.sess.local_crate_source_file() {
|
||||
Some(path) => {
|
||||
|
@ -102,7 +110,12 @@ impl DebugContext {
|
|||
root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0)));
|
||||
}
|
||||
|
||||
DebugContext { endian, dwarf, unit_range_list: RangeList(Vec::new()) }
|
||||
DebugContext {
|
||||
endian,
|
||||
dwarf,
|
||||
unit_range_list: RangeList(Vec::new()),
|
||||
should_remap_filepaths,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn define_function(
|
||||
|
|
|
@ -259,9 +259,17 @@ pub fn target_machine_factory(
|
|||
};
|
||||
let debuginfo_compression = SmallCStr::new(&debuginfo_compression);
|
||||
|
||||
let should_prefer_remapped_for_split_debuginfo_paths =
|
||||
sess.should_prefer_remapped_for_split_debuginfo_paths();
|
||||
|
||||
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
|
||||
let path = path_mapping.map_prefix(path.unwrap_or_default()).0;
|
||||
let path = path.unwrap_or_default();
|
||||
let path = if should_prefer_remapped_for_split_debuginfo_paths {
|
||||
path_mapping.map_prefix(path).0
|
||||
} else {
|
||||
path.into()
|
||||
};
|
||||
CString::new(path.to_str().unwrap()).unwrap()
|
||||
};
|
||||
|
||||
|
|
|
@ -126,9 +126,9 @@ impl GlobalFileTable {
|
|||
// Since rustc generates coverage maps with relative paths, the
|
||||
// compilation directory can be combined with the relative paths
|
||||
// to get absolute paths, if needed.
|
||||
let working_dir = Symbol::intern(
|
||||
&tcx.sess.opts.working_dir.remapped_path_if_available().to_string_lossy(),
|
||||
);
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let working_dir =
|
||||
Symbol::intern(&tcx.sess.opts.working_dir.for_codegen(&tcx.sess).to_string_lossy());
|
||||
global_file_table.insert(working_dir);
|
||||
Self { global_file_table }
|
||||
}
|
||||
|
|
|
@ -547,48 +547,77 @@ pub fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) ->
|
|||
) -> &'ll DIFile {
|
||||
debug!(?source_file.name);
|
||||
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let (directory, file_name) = match &source_file.name {
|
||||
FileName::Real(filename) => {
|
||||
let working_directory = &cx.sess().opts.working_dir;
|
||||
debug!(?working_directory);
|
||||
|
||||
let filename = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_embeddable_absolute_path(filename.clone(), working_directory);
|
||||
if cx.sess().should_prefer_remapped_for_codegen() {
|
||||
let filename = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_embeddable_absolute_path(filename.clone(), working_directory);
|
||||
|
||||
// Construct the absolute path of the file
|
||||
let abs_path = filename.remapped_path_if_available();
|
||||
debug!(?abs_path);
|
||||
// Construct the absolute path of the file
|
||||
let abs_path = filename.remapped_path_if_available();
|
||||
debug!(?abs_path);
|
||||
|
||||
if let Ok(rel_path) =
|
||||
abs_path.strip_prefix(working_directory.remapped_path_if_available())
|
||||
{
|
||||
// If the compiler's working directory (which also is the DW_AT_comp_dir of
|
||||
// the compilation unit) is a prefix of the path we are about to emit, then
|
||||
// only emit the part relative to the working directory.
|
||||
// Because of path remapping we sometimes see strange things here: `abs_path`
|
||||
// might actually look like a relative path
|
||||
// (e.g. `<crate-name-and-version>/src/lib.rs`), so if we emit it without
|
||||
// taking the working directory into account, downstream tooling will
|
||||
// interpret it as `<working-directory>/<crate-name-and-version>/src/lib.rs`,
|
||||
// which makes no sense. Usually in such cases the working directory will also
|
||||
// be remapped to `<crate-name-and-version>` or some other prefix of the path
|
||||
// we are remapping, so we end up with
|
||||
// `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
|
||||
// By moving the working directory portion into the `directory` part of the
|
||||
// DIFile, we allow LLVM to emit just the relative path for DWARF, while
|
||||
// still emitting the correct absolute path for CodeView.
|
||||
(
|
||||
working_directory.to_string_lossy(FileNameDisplayPreference::Remapped),
|
||||
rel_path.to_string_lossy().into_owned(),
|
||||
)
|
||||
if let Ok(rel_path) =
|
||||
abs_path.strip_prefix(working_directory.remapped_path_if_available())
|
||||
{
|
||||
// If the compiler's working directory (which also is the DW_AT_comp_dir of
|
||||
// the compilation unit) is a prefix of the path we are about to emit, then
|
||||
// only emit the part relative to the working directory.
|
||||
// Because of path remapping we sometimes see strange things here: `abs_path`
|
||||
// might actually look like a relative path
|
||||
// (e.g. `<crate-name-and-version>/src/lib.rs`), so if we emit it without
|
||||
// taking the working directory into account, downstream tooling will
|
||||
// interpret it as `<working-directory>/<crate-name-and-version>/src/lib.rs`,
|
||||
// which makes no sense. Usually in such cases the working directory will also
|
||||
// be remapped to `<crate-name-and-version>` or some other prefix of the path
|
||||
// we are remapping, so we end up with
|
||||
// `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
|
||||
// By moving the working directory portion into the `directory` part of the
|
||||
// DIFile, we allow LLVM to emit just the relative path for DWARF, while
|
||||
// still emitting the correct absolute path for CodeView.
|
||||
(
|
||||
working_directory.to_string_lossy(FileNameDisplayPreference::Remapped),
|
||||
rel_path.to_string_lossy().into_owned(),
|
||||
)
|
||||
} else {
|
||||
("".into(), abs_path.to_string_lossy().into_owned())
|
||||
}
|
||||
} else {
|
||||
("".into(), abs_path.to_string_lossy().into_owned())
|
||||
let working_directory = working_directory.local_path_if_available();
|
||||
let filename = filename.local_path_if_available();
|
||||
|
||||
debug!(?working_directory, ?filename);
|
||||
|
||||
let abs_path: Cow<'_, Path> = if filename.is_absolute() {
|
||||
filename.into()
|
||||
} else {
|
||||
let mut p = PathBuf::new();
|
||||
p.push(working_directory);
|
||||
p.push(filename);
|
||||
p.into()
|
||||
};
|
||||
|
||||
if let Ok(rel_path) = abs_path.strip_prefix(working_directory) {
|
||||
(
|
||||
working_directory.to_string_lossy().into(),
|
||||
rel_path.to_string_lossy().into_owned(),
|
||||
)
|
||||
} else {
|
||||
("".into(), abs_path.to_string_lossy().into_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
other => ("".into(), other.prefer_remapped().to_string_lossy().into_owned()),
|
||||
other => {
|
||||
debug!(?other);
|
||||
("".into(), other.for_codegen(cx.sess()).to_string_lossy().into_owned())
|
||||
}
|
||||
};
|
||||
|
||||
let hash_kind = match source_file.src_hash.kind {
|
||||
|
@ -822,8 +851,9 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
|||
// FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
|
||||
let producer = format!("clang LLVM ({rustc_producer})");
|
||||
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||
let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped);
|
||||
let work_dir = tcx.sess.opts.working_dir.for_codegen(&tcx.sess).to_string_lossy();
|
||||
let flags = "\0";
|
||||
let output_filenames = tcx.output_filenames(());
|
||||
let split_name = if tcx.sess.target_can_use_split_dwarf() {
|
||||
|
@ -834,7 +864,13 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
|
|||
Some(codegen_unit_name),
|
||||
)
|
||||
// We get a path relative to the working directory from split_dwarf_path
|
||||
.map(|f| tcx.sess.source_map().path_mapping().map_prefix(f).0)
|
||||
.map(|f| {
|
||||
if tcx.sess.should_prefer_remapped_for_split_debuginfo_paths() {
|
||||
tcx.sess.source_map().path_mapping().map_prefix(f).0
|
||||
} else {
|
||||
f.into()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -1454,10 +1454,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let tcx = bx.tcx();
|
||||
|
||||
let mut span_to_caller_location = |span: Span| {
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
|
||||
let caller = tcx.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
let const_loc = tcx.const_caller_location((
|
||||
Symbol::intern(&caller.file.name.prefer_remapped().to_string_lossy()),
|
||||
Symbol::intern(&caller.file.name.for_codegen(self.cx.sess()).to_string_lossy()),
|
||||
caller.line as u32,
|
||||
caller.col_display as u32 + 1,
|
||||
));
|
||||
|
|
|
@ -114,8 +114,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
pub(crate) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
|
||||
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
|
||||
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
|
||||
use rustc_session::{config::RemapPathScopeComponents, RemapFileNameExt};
|
||||
(
|
||||
Symbol::intern(&caller.file.name.prefer_remapped().to_string_lossy()),
|
||||
Symbol::intern(
|
||||
&caller
|
||||
.file
|
||||
.name
|
||||
.for_scope(&self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
|
||||
.to_string_lossy(),
|
||||
),
|
||||
u32::try_from(caller.line).unwrap(),
|
||||
u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
|
||||
)
|
||||
|
|
|
@ -525,9 +525,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
// the remapped version -- as is necessary for reproducible builds.
|
||||
let mut source_file = match source_file.name {
|
||||
FileName::Real(ref original_file_name) => {
|
||||
let adapted_file_name = source_map
|
||||
.path_mapping()
|
||||
.to_embeddable_absolute_path(original_file_name.clone(), working_directory);
|
||||
let adapted_file_name = if self.tcx.sess.should_prefer_remapped_for_codegen() {
|
||||
source_map.path_mapping().to_embeddable_absolute_path(
|
||||
original_file_name.clone(),
|
||||
working_directory,
|
||||
)
|
||||
} else {
|
||||
source_map.path_mapping().to_local_embeddable_absolute_path(
|
||||
original_file_name.clone(),
|
||||
working_directory,
|
||||
)
|
||||
};
|
||||
|
||||
if adapted_file_name != *original_file_name {
|
||||
let mut adapted: SourceFile = (**source_file).clone();
|
||||
|
|
|
@ -219,7 +219,10 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
|
|||
let tcx = self.tcx;
|
||||
let source_map = tcx.sess.source_map();
|
||||
let body_span = self.body_span;
|
||||
let file_name = Symbol::intern(&self.source_file.name.prefer_remapped().to_string_lossy());
|
||||
|
||||
use rustc_session::RemapFileNameExt;
|
||||
let file_name =
|
||||
Symbol::intern(&self.source_file.name.for_codegen(self.tcx.sess).to_string_lossy());
|
||||
|
||||
for (bcb, spans) in coverage_spans.bcbs_with_coverage_spans() {
|
||||
let counter_kind = self.coverage_counters.take_bcb_counter(bcb).unwrap_or_else(|| {
|
||||
|
|
|
@ -21,8 +21,8 @@ use rustc_feature::UnstableFeatures;
|
|||
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
|
||||
use rustc_span::source_map::{FileName, FilePathMapping};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::RealFileName;
|
||||
use rustc_span::SourceFileHashAlgorithm;
|
||||
use rustc_span::{FileNameDisplayPreference, RealFileName};
|
||||
|
||||
use rustc_errors::emitter::HumanReadableErrorType;
|
||||
use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
|
||||
|
@ -1056,6 +1056,22 @@ pub fn host_triple() -> &'static str {
|
|||
(option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
|
||||
}
|
||||
|
||||
fn file_path_mapping(
|
||||
remap_path_prefix: Vec<(PathBuf, PathBuf)>,
|
||||
unstable_opts: &UnstableOptions,
|
||||
) -> FilePathMapping {
|
||||
FilePathMapping::new(
|
||||
remap_path_prefix.clone(),
|
||||
if unstable_opts.remap_path_scope.contains(RemapPathScopeComponents::DIAGNOSTICS)
|
||||
&& !remap_path_prefix.is_empty()
|
||||
{
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
fn default() -> Options {
|
||||
Options {
|
||||
|
@ -1111,7 +1127,7 @@ impl Options {
|
|||
}
|
||||
|
||||
pub fn file_path_mapping(&self) -> FilePathMapping {
|
||||
FilePathMapping::new(self.remap_path_prefix.clone())
|
||||
file_path_mapping(self.remap_path_prefix.clone(), &self.unstable_opts)
|
||||
}
|
||||
|
||||
/// Returns `true` if there will be an output file generated.
|
||||
|
@ -2893,7 +2909,7 @@ pub fn build_session_options(
|
|||
handler.early_error(format!("Current directory is invalid: {e}"));
|
||||
});
|
||||
|
||||
let remap = FilePathMapping::new(remap_path_prefix.clone());
|
||||
let remap = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
|
||||
let (path, remapped) = remap.map_prefix(&working_dir);
|
||||
let working_dir = if remapped {
|
||||
RealFileName::Remapped { virtual_name: path.into_owned(), local_path: Some(working_dir) }
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::code_stats::CodeStats;
|
||||
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
||||
use crate::config::{
|
||||
self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath,
|
||||
self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType,
|
||||
RemapPathScopeComponents, SwitchWithOptPath,
|
||||
};
|
||||
use crate::config::{ErrorOutputType, Input};
|
||||
use crate::errors;
|
||||
|
@ -254,7 +255,11 @@ impl Session {
|
|||
|
||||
pub fn local_crate_source_file(&self) -> Option<PathBuf> {
|
||||
let path = self.io.input.opt_path()?;
|
||||
Some(self.opts.file_path_mapping().map_prefix(path).0.into_owned())
|
||||
if self.should_prefer_remapped_for_codegen() {
|
||||
Some(self.opts.file_path_mapping().map_prefix(path).0.into_owned())
|
||||
} else {
|
||||
Some(path.to_path_buf())
|
||||
}
|
||||
}
|
||||
|
||||
fn check_miri_unleashed_features(&self) {
|
||||
|
@ -1243,6 +1248,53 @@ impl Session {
|
|||
pub fn link_dead_code(&self) -> bool {
|
||||
self.opts.cg.link_dead_code.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn should_prefer_remapped_for_codegen(&self) -> bool {
|
||||
// bail out, if any of the requested crate types aren't:
|
||||
// "compiled executables or libraries"
|
||||
for crate_type in &self.opts.crate_types {
|
||||
match crate_type {
|
||||
CrateType::Executable
|
||||
| CrateType::Dylib
|
||||
| CrateType::Rlib
|
||||
| CrateType::Staticlib
|
||||
| CrateType::Cdylib => continue,
|
||||
CrateType::ProcMacro => return false,
|
||||
}
|
||||
}
|
||||
|
||||
let has_split_debuginfo = match self.split_debuginfo() {
|
||||
SplitDebuginfo::Off => false,
|
||||
SplitDebuginfo::Packed => true,
|
||||
SplitDebuginfo::Unpacked => true,
|
||||
};
|
||||
|
||||
let remap_path_scopes = &self.opts.unstable_opts.remap_path_scope;
|
||||
let mut prefer_remapped = false;
|
||||
|
||||
if remap_path_scopes.contains(RemapPathScopeComponents::UNSPLIT_DEBUGINFO) {
|
||||
prefer_remapped |= !has_split_debuginfo;
|
||||
}
|
||||
|
||||
if remap_path_scopes.contains(RemapPathScopeComponents::SPLIT_DEBUGINFO) {
|
||||
prefer_remapped |= has_split_debuginfo;
|
||||
}
|
||||
|
||||
prefer_remapped
|
||||
}
|
||||
|
||||
pub fn should_prefer_remapped_for_split_debuginfo_paths(&self) -> bool {
|
||||
let has_split_debuginfo = match self.split_debuginfo() {
|
||||
SplitDebuginfo::Off => false,
|
||||
SplitDebuginfo::Packed | SplitDebuginfo::Unpacked => true,
|
||||
};
|
||||
|
||||
self.opts
|
||||
.unstable_opts
|
||||
.remap_path_scope
|
||||
.contains(RemapPathScopeComponents::SPLIT_DEBUGINFO_PATH)
|
||||
&& has_split_debuginfo
|
||||
}
|
||||
}
|
||||
|
||||
// JUSTIFICATION: part of session construction
|
||||
|
@ -1752,3 +1804,53 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
|||
};
|
||||
emitter
|
||||
}
|
||||
|
||||
pub trait RemapFileNameExt {
|
||||
type Output<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scopes: RemapPathScopeComponents) -> Self::Output<'_>;
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_>;
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::FileName {
|
||||
type Output<'a> = rustc_span::FileNameDisplay<'a>;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scopes: RemapPathScopeComponents) -> Self::Output<'_> {
|
||||
if sess.opts.unstable_opts.remap_path_scope.contains(scopes) {
|
||||
self.prefer_remapped_unconditionaly()
|
||||
} else {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_> {
|
||||
if sess.should_prefer_remapped_for_codegen() {
|
||||
self.prefer_remapped_unconditionaly()
|
||||
} else {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::RealFileName {
|
||||
type Output<'a> = &'a Path;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scopes: RemapPathScopeComponents) -> Self::Output<'_> {
|
||||
if sess.opts.unstable_opts.remap_path_scope.contains(scopes) {
|
||||
self.remapped_path_if_available()
|
||||
} else {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_> {
|
||||
if sess.should_prefer_remapped_for_codegen() {
|
||||
self.remapped_path_if_available()
|
||||
} else {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,7 +370,7 @@ impl FileName {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn prefer_remapped(&self) -> FileNameDisplay<'_> {
|
||||
pub fn prefer_remapped_unconditionaly(&self) -> FileNameDisplay<'_> {
|
||||
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
|
||||
}
|
||||
|
||||
|
|
|
@ -1124,16 +1124,13 @@ pub struct FilePathMapping {
|
|||
|
||||
impl FilePathMapping {
|
||||
pub fn empty() -> FilePathMapping {
|
||||
FilePathMapping::new(Vec::new())
|
||||
FilePathMapping::new(Vec::new(), FileNameDisplayPreference::Local)
|
||||
}
|
||||
|
||||
pub fn new(mapping: Vec<(PathBuf, PathBuf)>) -> FilePathMapping {
|
||||
let filename_display_for_diagnostics = if mapping.is_empty() {
|
||||
FileNameDisplayPreference::Local
|
||||
} else {
|
||||
FileNameDisplayPreference::Remapped
|
||||
};
|
||||
|
||||
pub fn new(
|
||||
mapping: Vec<(PathBuf, PathBuf)>,
|
||||
filename_display_for_diagnostics: FileNameDisplayPreference,
|
||||
) -> FilePathMapping {
|
||||
FilePathMapping { mapping, filename_display_for_diagnostics }
|
||||
}
|
||||
|
||||
|
@ -1287,6 +1284,27 @@ impl FilePathMapping {
|
|||
}
|
||||
}
|
||||
|
||||
/// Expand a relative path to an absolute path **without** remapping taken into account.
|
||||
///
|
||||
/// The resulting `RealFileName` will have its `virtual_path` portion erased if
|
||||
/// possible (i.e. if there's also a remapped path).
|
||||
pub fn to_local_embeddable_absolute_path(
|
||||
&self,
|
||||
file_path: RealFileName,
|
||||
working_directory: &RealFileName,
|
||||
) -> RealFileName {
|
||||
let file_path = file_path.local_path_if_available();
|
||||
if file_path.is_absolute() {
|
||||
// No remapping has applied to this path and it is absolute,
|
||||
// so the working directory cannot influence it either, so
|
||||
// we are done.
|
||||
return RealFileName::LocalPath(file_path.to_path_buf());
|
||||
}
|
||||
debug_assert!(file_path.is_relative());
|
||||
let working_directory = working_directory.local_path_if_available();
|
||||
RealFileName::LocalPath(Path::new(working_directory).join(file_path))
|
||||
}
|
||||
|
||||
/// Attempts to (heuristically) reverse a prefix mapping.
|
||||
///
|
||||
/// Returns [`Some`] if there is exactly one mapping where the "to" part is
|
||||
|
|
|
@ -351,7 +351,10 @@ fn reverse_map_prefix(mapping: &FilePathMapping, p: &str) -> Option<String> {
|
|||
fn path_prefix_remapping() {
|
||||
// Relative to relative
|
||||
{
|
||||
let mapping = &FilePathMapping::new(vec![(path("abc/def"), path("foo"))]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc/def"), path("foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("foo/src/main.rs"));
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def"), path_str("foo"));
|
||||
|
@ -359,7 +362,10 @@ fn path_prefix_remapping() {
|
|||
|
||||
// Relative to absolute
|
||||
{
|
||||
let mapping = &FilePathMapping::new(vec![(path("abc/def"), path("/foo"))]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc/def"), path("/foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def"), path_str("/foo"));
|
||||
|
@ -367,7 +373,10 @@ fn path_prefix_remapping() {
|
|||
|
||||
// Absolute to relative
|
||||
{
|
||||
let mapping = &FilePathMapping::new(vec![(path("/abc/def"), path("foo"))]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/abc/def"), path("foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("foo/src/main.rs"));
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def"), path_str("foo"));
|
||||
|
@ -375,7 +384,10 @@ fn path_prefix_remapping() {
|
|||
|
||||
// Absolute to absolute
|
||||
{
|
||||
let mapping = &FilePathMapping::new(vec![(path("/abc/def"), path("/foo"))]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/abc/def"), path("/foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def"), path_str("/foo"));
|
||||
|
@ -385,8 +397,10 @@ fn path_prefix_remapping() {
|
|||
#[test]
|
||||
fn path_prefix_remapping_expand_to_absolute() {
|
||||
// "virtual" working directory is relative path
|
||||
let mapping =
|
||||
&FilePathMapping::new(vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
let working_directory = path("/foo");
|
||||
let working_directory = RealFileName::Remapped {
|
||||
local_path: Some(working_directory.clone()),
|
||||
|
@ -487,8 +501,10 @@ fn path_prefix_remapping_expand_to_absolute() {
|
|||
fn path_prefix_remapping_reverse() {
|
||||
// Ignores options without alphanumeric chars.
|
||||
{
|
||||
let mapping =
|
||||
&FilePathMapping::new(vec![(path("abc"), path("/")), (path("def"), path("."))]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/")), (path("def"), path("."))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(reverse_map_prefix(mapping, "/hello.rs"), None);
|
||||
assert_eq!(reverse_map_prefix(mapping, "./hello.rs"), None);
|
||||
|
@ -496,20 +512,20 @@ fn path_prefix_remapping_reverse() {
|
|||
|
||||
// Returns `None` if multiple options match.
|
||||
{
|
||||
let mapping = &FilePathMapping::new(vec![
|
||||
(path("abc"), path("/redacted")),
|
||||
(path("def"), path("/redacted")),
|
||||
]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/redacted")), (path("def"), path("/redacted"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(reverse_map_prefix(mapping, "/redacted/hello.rs"), None);
|
||||
}
|
||||
|
||||
// Distinct reverse mappings.
|
||||
{
|
||||
let mapping = &FilePathMapping::new(vec![
|
||||
(path("abc"), path("/redacted")),
|
||||
(path("def/ghi"), path("/fake/dir")),
|
||||
]);
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/redacted")), (path("def/ghi"), path("/fake/dir"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
reverse_map_prefix(mapping, "/redacted/path/hello.rs"),
|
||||
|
|
Loading…
Add table
Reference in a new issue