Overhaul filename handling for cross-compiler consistency
This commit refactors `SourceMap` and most importantly `RealFileName` to make it self-contained in order to achieve cross-compiler consistency. This is achieved: - by making `RealFileName` immutable - by only having `SourceMap::to_real_filename` create `RealFileName` - by also making `RealFileName` holds it's working directory, it's embeddable name and the remapped scopes - by making most `FileName` and `RealFileName` methods take a scope as an argument In order for `SourceMap::to_real_filename` to know which scopes to apply `FilePathMapping` now takes the current remapping scopes to apply, which makes `FileNameDisplayPreference` and company useless and are removed. The scopes type `RemapPathScopeComponents` was moved from `rustc_session::config` to `rustc_span`. The previous system for scoping the local/remapped filenames `RemapFileNameExt::for_scope` is no longer useful as it's replaced by methods on `FileName` and `RealFileName`.
This commit is contained in:
parent
5da3de7527
commit
8cbfb26383
32 changed files with 805 additions and 764 deletions
|
|
@ -4630,7 +4630,6 @@ dependencies = [
|
|||
name = "rustc_session"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
"libc",
|
||||
"rand 0.9.2",
|
||||
|
|
@ -4657,6 +4656,7 @@ dependencies = [
|
|||
name = "rustc_span"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"blake3",
|
||||
"derive-where",
|
||||
"indexmap",
|
||||
|
|
|
|||
|
|
@ -68,13 +68,10 @@ pub(crate) fn expand_file(
|
|||
let topmost = cx.expansion_cause().unwrap_or(sp);
|
||||
let loc = cx.source_map().lookup_char_pos(topmost.lo());
|
||||
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
use rustc_span::RemapPathScopeComponents;
|
||||
ExpandResult::Ready(MacEager::expr(cx.expr_str(
|
||||
topmost,
|
||||
Symbol::intern(
|
||||
&loc.file.name.for_scope(cx.sess, RemapPathScopeComponents::MACRO).to_string_lossy(),
|
||||
),
|
||||
Symbol::intern(&loc.file.name.display(RemapPathScopeComponents::MACRO).to_string_lossy()),
|
||||
)))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_errors::{Applicability, Diag, Level};
|
|||
use rustc_expand::base::*;
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_span::{ErrorGuaranteed, FileNameDisplayPreference, Ident, Span, Symbol, sym};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, RemapPathScopeComponents, Span, Symbol, sym};
|
||||
use thin_vec::{ThinVec, thin_vec};
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -445,7 +445,7 @@ fn get_location_info(cx: &ExtCtxt<'_>, fn_: &ast::Fn) -> (Symbol, usize, usize,
|
|||
cx.sess.source_map().span_to_location_info(span);
|
||||
|
||||
let file_name = match source_file {
|
||||
Some(sf) => sf.name.display(FileNameDisplayPreference::Remapped).to_string(),
|
||||
Some(sf) => sf.name.display(RemapPathScopeComponents::MACRO).to_string(),
|
||||
None => "no-location".to_string(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,8 @@ use rustc_errors::{DiagCtxtHandle, Level};
|
|||
use rustc_fs_util::{link_or_copy, path_to_c_string};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{
|
||||
self, Lto, OutputType, Passes, RemapPathScopeComponents, SplitDwarfKind, SwitchWithOptPath,
|
||||
};
|
||||
use rustc_span::{BytePos, InnerSpan, Pos, SpanData, SyntaxContext, sym};
|
||||
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
|
||||
use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext, sym};
|
||||
use rustc_target::spec::{
|
||||
Arch, CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel,
|
||||
};
|
||||
|
|
@ -248,6 +246,7 @@ pub(crate) fn target_machine_factory(
|
|||
!sess.opts.unstable_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section);
|
||||
|
||||
let path_mapping = sess.source_map().path_mapping().clone();
|
||||
let working_dir = sess.source_map().working_dir().clone();
|
||||
|
||||
let use_emulated_tls = matches!(sess.tls_model(), TlsModel::Emulated);
|
||||
|
||||
|
|
@ -271,9 +270,6 @@ pub(crate) fn target_machine_factory(
|
|||
}
|
||||
};
|
||||
|
||||
let file_name_display_preference =
|
||||
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
let use_wasm_eh = wants_wasm_eh(sess);
|
||||
|
||||
let prof = SelfProfilerRef::clone(&sess.prof);
|
||||
|
|
@ -284,8 +280,9 @@ pub(crate) fn target_machine_factory(
|
|||
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
|
||||
let path = path.unwrap_or_default();
|
||||
let path = path_mapping
|
||||
.to_real_filename(path)
|
||||
.to_string_lossy(file_name_display_preference)
|
||||
.to_real_filename(&working_dir, path)
|
||||
.path(RemapPathScopeComponents::DEBUGINFO)
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
CString::new(path).unwrap()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
|
|||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
use rustc_span::{SourceFile, StableSourceFileId};
|
||||
use rustc_span::{RemapPathScopeComponents, SourceFile, StableSourceFileId};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::common::CodegenCx;
|
||||
|
|
@ -127,10 +125,7 @@ impl GlobalFileTable {
|
|||
|
||||
for file in all_files {
|
||||
raw_file_table.entry(file.stable_id).or_insert_with(|| {
|
||||
file.name
|
||||
.for_scope(tcx.sess, RemapPathScopeComponents::COVERAGE)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
file.name.display(RemapPathScopeComponents::COVERAGE).to_string_lossy().into_owned()
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -145,9 +140,10 @@ impl GlobalFileTable {
|
|||
// resolve any other entries that are stored as relative paths.
|
||||
let base_dir = tcx
|
||||
.sess
|
||||
.opts
|
||||
.working_dir
|
||||
.for_scope(tcx.sess, RemapPathScopeComponents::COVERAGE)
|
||||
.psess
|
||||
.source_map()
|
||||
.working_dir()
|
||||
.path(RemapPathScopeComponents::COVERAGE)
|
||||
.to_string_lossy();
|
||||
table.push(base_dir.as_ref());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::borrow::Cow;
|
||||
use std::fmt::{self, Write};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::{iter, ptr};
|
||||
|
||||
|
|
@ -19,9 +19,7 @@ use rustc_middle::ty::{
|
|||
self, AdtKind, CoroutineArgsExt, ExistentialTraitRef, Instance, Ty, TyCtxt, Visibility,
|
||||
};
|
||||
use rustc_session::config::{self, DebugInfo, Lto};
|
||||
use rustc_span::{
|
||||
DUMMY_SP, FileName, FileNameDisplayPreference, SourceFile, Span, Symbol, hygiene,
|
||||
};
|
||||
use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene};
|
||||
use rustc_symbol_mangling::typeid_for_trait_ref;
|
||||
use rustc_target::spec::DebuginfoKind;
|
||||
use smallvec::smallvec;
|
||||
|
|
@ -555,79 +553,38 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi
|
|||
) -> &'ll DIFile {
|
||||
debug!(?source_file.name);
|
||||
|
||||
let filename_display_preference =
|
||||
cx.sess().filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
let (directory, file_name) = match &source_file.name {
|
||||
FileName::Real(filename) => {
|
||||
let working_directory = &cx.sess().opts.working_dir;
|
||||
debug!(?working_directory);
|
||||
let (working_directory, embeddable_name) =
|
||||
filename.embeddable_name(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
if filename_display_preference == FileNameDisplayPreference::Remapped {
|
||||
let filename = cx
|
||||
.sess()
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_embeddable_absolute_path(filename.clone(), working_directory);
|
||||
debug!(?working_directory, ?embeddable_name);
|
||||
|
||||
// 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(),
|
||||
)
|
||||
} else {
|
||||
("".into(), abs_path.to_string_lossy().into_owned())
|
||||
}
|
||||
if let Ok(rel_path) = embeddable_name.strip_prefix(working_directory) {
|
||||
// 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(), rel_path.to_string_lossy().into_owned())
|
||||
} else {
|
||||
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(),
|
||||
rel_path.to_string_lossy().into_owned(),
|
||||
)
|
||||
} else {
|
||||
("".into(), abs_path.to_string_lossy().into_owned())
|
||||
}
|
||||
("".into(), embeddable_name.to_string_lossy().into_owned())
|
||||
}
|
||||
}
|
||||
other => {
|
||||
debug!(?other);
|
||||
("".into(), other.display(filename_display_preference).to_string())
|
||||
("".into(), other.display(RemapPathScopeComponents::DEBUGINFO).to_string())
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -889,12 +846,10 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
|
|||
codegen_unit_name: &str,
|
||||
debug_context: &CodegenUnitDebugContext<'ll, 'tcx>,
|
||||
) -> &'ll DIDescriptor {
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
let mut name_in_debuginfo = tcx
|
||||
.sess
|
||||
.local_crate_source_file()
|
||||
.map(|src| src.for_scope(&tcx.sess, RemapPathScopeComponents::DEBUGINFO).to_path_buf())
|
||||
.map(|src| src.path(RemapPathScopeComponents::DEBUGINFO).to_path_buf())
|
||||
.unwrap_or_else(|| PathBuf::from(tcx.crate_name(LOCAL_CRATE).as_str()));
|
||||
|
||||
// To avoid breaking split DWARF, we need to ensure that each codegen unit
|
||||
|
|
@ -923,12 +878,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
|
|||
let producer = format!("clang LLVM ({rustc_producer})");
|
||||
|
||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||
let work_dir = tcx
|
||||
.sess
|
||||
.opts
|
||||
.working_dir
|
||||
.for_scope(tcx.sess, RemapPathScopeComponents::DEBUGINFO)
|
||||
.to_string_lossy();
|
||||
let work_dir = tcx.sess.psess.source_map().working_dir();
|
||||
let output_filenames = tcx.output_filenames(());
|
||||
let split_name = if tcx.sess.target_can_use_split_dwarf()
|
||||
&& let Some(f) = output_filenames.split_dwarf_path(
|
||||
|
|
@ -938,14 +888,15 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
|
|||
tcx.sess.invocation_temp.as_deref(),
|
||||
) {
|
||||
// We get a path relative to the working directory from split_dwarf_path
|
||||
Some(tcx.sess.source_map().path_mapping().to_real_filename(f))
|
||||
Some(tcx.sess.source_map().path_mapping().to_real_filename(work_dir, f))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let split_name = split_name
|
||||
.as_ref()
|
||||
.map(|f| f.for_scope(tcx.sess, RemapPathScopeComponents::DEBUGINFO).to_string_lossy())
|
||||
.map(|f| f.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy())
|
||||
.unwrap_or_default();
|
||||
let work_dir = work_dir.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy();
|
||||
let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
|
||||
|
||||
let dwarf_version = tcx.sess.dwarf_version();
|
||||
|
|
|
|||
|
|
@ -208,15 +208,10 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
|
|||
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::RemapFileNameExt;
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
use rustc_span::RemapPathScopeComponents;
|
||||
(
|
||||
Symbol::intern(
|
||||
&caller
|
||||
.file
|
||||
.name
|
||||
.for_scope(self.tcx.sess, RemapPathScopeComponents::DIAGNOSTICS)
|
||||
.to_string_lossy(),
|
||||
&caller.file.name.display(RemapPathScopeComponents::DIAGNOSTICS).to_string_lossy(),
|
||||
),
|
||||
u32::try_from(caller.line).unwrap(),
|
||||
u32::try_from(caller.col_display).unwrap().checked_add(1).unwrap(),
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ impl<'tcx> pprust_hir::PpAnn for HirTypedAnn<'tcx> {
|
|||
}
|
||||
|
||||
fn get_source(sess: &Session) -> (String, FileName) {
|
||||
let src_name = sess.io.input.source_name();
|
||||
let src_name = sess.io.input.file_name(&sess);
|
||||
let src = String::clone(
|
||||
sess.source_map()
|
||||
.get_source_file(&src_name)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
use std::error::Report;
|
||||
use std::io::{self, Write};
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::vec;
|
||||
|
||||
|
|
@ -20,9 +20,9 @@ use derive_setters::Setters;
|
|||
use rustc_data_structures::sync::IntoDynSyncSend;
|
||||
use rustc_error_messages::FluentArgs;
|
||||
use rustc_lint_defs::Applicability;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::hygiene::ExpnData;
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
use rustc_span::{FileName, RealFileName, Span};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
|
||||
|
|
@ -490,8 +490,14 @@ impl DiagnosticSpan {
|
|||
None => {
|
||||
span = rustc_span::DUMMY_SP;
|
||||
empty_source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
empty_source_map
|
||||
.new_source_file(std::path::PathBuf::from("empty.rs").into(), String::new());
|
||||
empty_source_map.new_source_file(
|
||||
FileName::Real(
|
||||
empty_source_map
|
||||
.path_mapping()
|
||||
.to_real_filename(&RealFileName::empty(), PathBuf::from("empty.rs")),
|
||||
),
|
||||
String::new(),
|
||||
);
|
||||
&empty_source_map
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,11 +36,15 @@ impl<T: Write> Write for Shared<T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn filename(sm: &SourceMap, path: &str) -> FileName {
|
||||
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
|
||||
}
|
||||
|
||||
/// Test the span yields correct positions in JSON.
|
||||
fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) {
|
||||
rustc_span::create_default_session_globals_then(|| {
|
||||
let sm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
sm.new_source_file(Path::new("test.rs").to_owned().into(), code.to_owned());
|
||||
sm.new_source_file(filename(&sm, "test.rs"), code.to_owned());
|
||||
let translator =
|
||||
Translator::with_fallback_bundle(vec![crate::DEFAULT_LOCALE_RESOURCE], false);
|
||||
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||
FileName::Real(name) => name
|
||||
.into_local_path()
|
||||
.expect("attempting to resolve a file path in an external file"),
|
||||
other => PathBuf::from(other.prefer_local().to_string()),
|
||||
other => PathBuf::from(other.prefer_local_unconditionally().to_string()),
|
||||
};
|
||||
let dir_path = file_path.parent().unwrap_or(&file_path).to_owned();
|
||||
self.cx.root_path = dir_path.clone();
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@ use rustc_session::output::{collect_crate_types, filename_for_input};
|
|||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_span::{
|
||||
DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span,
|
||||
Symbol, sym,
|
||||
DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym,
|
||||
};
|
||||
use rustc_trait_selection::{solve, traits};
|
||||
use tracing::{info, instrument};
|
||||
|
|
@ -595,7 +594,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
|
|||
.filter(|fmap| !fmap.is_imported())
|
||||
.map(|fmap| {
|
||||
(
|
||||
escape_dep_filename(&fmap.name.prefer_local().to_string()),
|
||||
escape_dep_filename(&fmap.name.prefer_local_unconditionally().to_string()),
|
||||
// This needs to be unnormalized,
|
||||
// as external tools wouldn't know how rustc normalizes them
|
||||
fmap.unnormalized_source_len as u64,
|
||||
|
|
@ -610,10 +609,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P
|
|||
// (e.g. accessed in proc macros).
|
||||
let file_depinfo = sess.psess.file_depinfo.borrow();
|
||||
|
||||
let normalize_path = |path: PathBuf| {
|
||||
let file = FileName::from(path);
|
||||
escape_dep_filename(&file.prefer_local().to_string())
|
||||
};
|
||||
let normalize_path = |path: PathBuf| escape_dep_filename(&path.to_string_lossy());
|
||||
|
||||
// The entries will be used to declare dependencies between files in a
|
||||
// Makefile-like output, so the iteration order does not matter.
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ use rustc_session::config::TargetModifier;
|
|||
use rustc_session::cstore::{CrateSource, ExternCrate};
|
||||
use rustc_span::hygiene::HygieneDecodeContext;
|
||||
use rustc_span::{
|
||||
BlobDecoder, BytePos, ByteSymbol, DUMMY_SP, Pos, SpanData, SpanDecoder, Symbol, SyntaxContext,
|
||||
kw,
|
||||
BlobDecoder, BytePos, ByteSymbol, DUMMY_SP, Pos, RemapPathScopeComponents, SpanData,
|
||||
SpanDecoder, Symbol, SyntaxContext, kw,
|
||||
};
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -1669,15 +1669,15 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
for virtual_dir in virtual_source_base_dir.iter().flatten() {
|
||||
if let Some(real_dir) = &real_source_base_dir
|
||||
&& let rustc_span::FileName::Real(old_name) = name
|
||||
&& let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
|
||||
old_name
|
||||
&& let Ok(rest) = virtual_name.strip_prefix(virtual_dir)
|
||||
&& let (_working_dir, embeddable_name) =
|
||||
old_name.embeddable_name(RemapPathScopeComponents::MACRO)
|
||||
&& let Ok(rest) = embeddable_name.strip_prefix(virtual_dir)
|
||||
{
|
||||
let new_path = real_dir.join(rest);
|
||||
|
||||
debug!(
|
||||
"try_to_translate_virtual_to_real: `{}` -> `{}`",
|
||||
virtual_name.display(),
|
||||
embeddable_name.display(),
|
||||
new_path.display(),
|
||||
);
|
||||
|
||||
|
|
@ -1686,17 +1686,12 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
// Note that this is a special case for imported rust-src paths specified by
|
||||
// https://rust-lang.github.io/rfcs/3127-trim-paths.html#handling-sysroot-paths.
|
||||
// Other imported paths are not currently remapped (see #66251).
|
||||
let (user_remapped, applied) =
|
||||
tcx.sess.source_map().path_mapping().map_prefix(&new_path);
|
||||
let new_name = if applied {
|
||||
rustc_span::RealFileName::Remapped {
|
||||
local_path: Some(new_path.clone()),
|
||||
virtual_name: user_remapped.to_path_buf(),
|
||||
}
|
||||
} else {
|
||||
rustc_span::RealFileName::LocalPath(new_path)
|
||||
};
|
||||
*old_name = new_name;
|
||||
*name = rustc_span::FileName::Real(
|
||||
tcx.sess
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_real_filename(&rustc_span::RealFileName::empty(), new_path),
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1711,15 +1706,12 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
&& let Some(real_dir) = real_source_base_dir
|
||||
&& let rustc_span::FileName::Real(old_name) = name
|
||||
{
|
||||
let relative_path = match old_name {
|
||||
rustc_span::RealFileName::LocalPath(local) => {
|
||||
local.strip_prefix(real_dir).ok()
|
||||
}
|
||||
rustc_span::RealFileName::Remapped { virtual_name, .. } => {
|
||||
virtual_source_base_dir
|
||||
.and_then(|virtual_dir| virtual_name.strip_prefix(virtual_dir).ok())
|
||||
}
|
||||
};
|
||||
let (_working_dir, embeddable_path) =
|
||||
old_name.embeddable_name(RemapPathScopeComponents::MACRO);
|
||||
let relative_path = embeddable_path.strip_prefix(real_dir).ok().or_else(|| {
|
||||
virtual_source_base_dir
|
||||
.and_then(|virtual_dir| embeddable_path.strip_prefix(virtual_dir).ok())
|
||||
});
|
||||
debug!(
|
||||
?relative_path,
|
||||
?virtual_dir,
|
||||
|
|
@ -1727,10 +1719,10 @@ impl<'a> CrateMetadataRef<'a> {
|
|||
"simulate_remapped_rust_src_base"
|
||||
);
|
||||
if let Some(rest) = relative_path.and_then(|p| p.strip_prefix(subdir).ok()) {
|
||||
*old_name = rustc_span::RealFileName::Remapped {
|
||||
local_path: None,
|
||||
virtual_name: virtual_dir.join(subdir).join(rest),
|
||||
};
|
||||
*name =
|
||||
rustc_span::FileName::Real(rustc_span::RealFileName::from_virtual_path(
|
||||
&virtual_dir.join(subdir).join(rest),
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -541,8 +541,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
// is done.
|
||||
let required_source_files = self.required_source_files.take().unwrap();
|
||||
|
||||
let working_directory = &self.tcx.sess.opts.working_dir;
|
||||
|
||||
let mut adapted = TableBuilder::default();
|
||||
|
||||
let local_crate_stable_id = self.tcx.stable_crate_id(LOCAL_CRATE);
|
||||
|
|
@ -567,10 +565,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
|
||||
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 mut adapted_file_name = original_file_name.clone();
|
||||
adapted_file_name.update_for_crate_metadata();
|
||||
adapted_source_file.name = FileName::Real(adapted_file_name);
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@ use std::fmt::{self, Debug, Display, Formatter};
|
|||
use rustc_abi::{HasDataLayout, Size};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol};
|
||||
use rustc_span::{DUMMY_SP, RemapPathScopeComponents, Span, Symbol};
|
||||
use rustc_type_ir::TypeVisitableExt;
|
||||
|
||||
use super::interpret::ReportedErrorInfo;
|
||||
|
|
@ -587,11 +585,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
let caller = self.sess.source_map().lookup_char_pos(topmost.lo());
|
||||
self.const_caller_location(
|
||||
Symbol::intern(
|
||||
&caller
|
||||
.file
|
||||
.name
|
||||
.for_scope(self.sess, RemapPathScopeComponents::MACRO)
|
||||
.to_string_lossy(),
|
||||
&caller.file.name.display(RemapPathScopeComponents::MACRO).to_string_lossy(),
|
||||
),
|
||||
caller.line as u32,
|
||||
caller.col_display as u32 + 1,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ use rustc_hir::definitions::{DefKey, DefPathDataName};
|
|||
use rustc_hir::limit::Limit;
|
||||
use rustc_macros::{Lift, extension};
|
||||
use rustc_session::cstore::{ExternCrate, ExternCrateSource};
|
||||
use rustc_span::{FileNameDisplayPreference, Ident, Symbol, kw, sym};
|
||||
use rustc_span::{Ident, RemapPathScopeComponents, Symbol, kw, sym};
|
||||
use rustc_type_ir::{Upcast as _, elaborate};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
|
@ -890,7 +890,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx().sess.source_map().span_to_embeddable_string(span)
|
||||
self.tcx().sess.source_map().span_to_diagnostic_string(span)
|
||||
)?;
|
||||
} else {
|
||||
write!(self, "@")?;
|
||||
|
|
@ -921,7 +921,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx().sess.source_map().span_to_embeddable_string(span)
|
||||
self.tcx().sess.source_map().span_to_diagnostic_string(span)
|
||||
)?;
|
||||
} else {
|
||||
write!(self, "@")?;
|
||||
|
|
@ -947,10 +947,13 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
self.print_def_path(did.to_def_id(), args)?;
|
||||
} else {
|
||||
let span = self.tcx().def_span(did);
|
||||
let preference = if with_forced_trimmed_paths() {
|
||||
FileNameDisplayPreference::Short
|
||||
let loc = if with_forced_trimmed_paths() {
|
||||
self.tcx().sess.source_map().span_to_short_string(
|
||||
span,
|
||||
RemapPathScopeComponents::DIAGNOSTICS,
|
||||
)
|
||||
} else {
|
||||
FileNameDisplayPreference::Remapped
|
||||
self.tcx().sess.source_map().span_to_diagnostic_string(span)
|
||||
};
|
||||
write!(
|
||||
self,
|
||||
|
|
@ -958,7 +961,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
// This may end up in stderr diagnostics but it may also be
|
||||
// emitted into MIR. Hence we use the remapped path if
|
||||
// available
|
||||
self.tcx().sess.source_map().span_to_string(span, preference)
|
||||
loc
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1004,18 +1007,17 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||
self.print_def_path(did.to_def_id(), args)?;
|
||||
} else {
|
||||
let span = self.tcx().def_span(did);
|
||||
let preference = if with_forced_trimmed_paths() {
|
||||
FileNameDisplayPreference::Short
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
let loc = if with_forced_trimmed_paths() {
|
||||
self.tcx().sess.source_map().span_to_short_string(
|
||||
span,
|
||||
RemapPathScopeComponents::DIAGNOSTICS,
|
||||
)
|
||||
} else {
|
||||
FileNameDisplayPreference::Remapped
|
||||
self.tcx().sess.source_map().span_to_diagnostic_string(span)
|
||||
};
|
||||
write!(
|
||||
self,
|
||||
"@{}",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx().sess.source_map().span_to_string(span, preference)
|
||||
)?;
|
||||
write!(self, "@{loc}")?;
|
||||
}
|
||||
} else {
|
||||
write!(self, "@")?;
|
||||
|
|
@ -2258,7 +2260,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
|
|||
"<impl at {}>",
|
||||
// This may end up in stderr diagnostics but it may also be emitted
|
||||
// into MIR. Hence we use the remapped path if available
|
||||
self.tcx.sess.source_map().span_to_embeddable_string(span)
|
||||
self.tcx.sess.source_map().span_to_diagnostic_string(span)
|
||||
)?;
|
||||
self.empty_path = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,13 @@ pub fn utf8_error<E: EmissionGuarantee>(
|
|||
note.clone()
|
||||
};
|
||||
let contents = String::from_utf8_lossy(contents).to_string();
|
||||
let source = sm.new_source_file(PathBuf::from(path).into(), contents);
|
||||
|
||||
// We only emit this error for files in the current session
|
||||
// so the working directory can only be the current working directory
|
||||
let filename = FileName::Real(
|
||||
sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path).as_path()),
|
||||
);
|
||||
let source = sm.new_source_file(filename, contents);
|
||||
|
||||
// Avoid out-of-bounds span from lossy UTF-8 conversion.
|
||||
if start as u32 > source.normalized_source_len.0 {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
use std::assert_matches::assert_matches;
|
||||
use std::io::prelude::*;
|
||||
use std::iter::Peekable;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{io, str};
|
||||
|
||||
|
|
@ -29,11 +29,15 @@ fn psess() -> ParseSess {
|
|||
ParseSess::new(vec![crate::DEFAULT_LOCALE_RESOURCE])
|
||||
}
|
||||
|
||||
fn filename(sm: &SourceMap, path: &str) -> FileName {
|
||||
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
|
||||
}
|
||||
|
||||
/// Map string to parser (via tts).
|
||||
fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> {
|
||||
unwrap_or_emit_fatal(new_parser_from_source_str(
|
||||
psess,
|
||||
PathBuf::from("bogofile").into(),
|
||||
filename(psess.source_map(), "bogofile"),
|
||||
source_str,
|
||||
StripTokens::Nothing,
|
||||
))
|
||||
|
|
@ -100,7 +104,7 @@ pub(crate) fn string_to_stream(source_str: String) -> TokenStream {
|
|||
let psess = psess();
|
||||
unwrap_or_emit_fatal(source_str_to_stream(
|
||||
&psess,
|
||||
PathBuf::from("bogofile").into(),
|
||||
filename(psess.source_map(), "bogofile"),
|
||||
source_str,
|
||||
None,
|
||||
))
|
||||
|
|
@ -194,8 +198,7 @@ fn test_harness(
|
|||
(OutputTheme::Unicode, expected_output_unicode),
|
||||
] {
|
||||
let (dcx, source_map, output) = create_test_handler(theme);
|
||||
source_map
|
||||
.new_source_file(Path::new("test.rs").to_owned().into(), file_text.to_owned());
|
||||
source_map.new_source_file(filename(&source_map, "test.rs"), file_text.to_owned());
|
||||
|
||||
let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
|
||||
let mut msp = MultiSpan::from_span(primary_span);
|
||||
|
|
@ -2525,7 +2528,7 @@ fn ttdelim_span() {
|
|||
create_default_session_globals_then(|| {
|
||||
let psess = psess();
|
||||
let expr = parse_expr_from_source_str(
|
||||
PathBuf::from("foo").into(),
|
||||
filename(psess.source_map(), "foo"),
|
||||
"foo!( fn main() { body } )".to_string(),
|
||||
&psess,
|
||||
)
|
||||
|
|
@ -2888,10 +2891,11 @@ fn debug_lookahead() {
|
|||
#[test]
|
||||
fn out_of_line_mod() {
|
||||
create_default_session_globals_then(|| {
|
||||
let psess = psess();
|
||||
let item = parse_item_from_source_str(
|
||||
PathBuf::from("foo").into(),
|
||||
filename(psess.source_map(), "foo"),
|
||||
"mod foo { struct S; mod this_does_not_exist; }".to_owned(),
|
||||
&psess(),
|
||||
&psess,
|
||||
)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
|
|||
use rustc_hir::{CRATE_HIR_ID, ItemId, Node, find_attr};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::{CrateType, EntryFnType, RemapPathScopeComponents, sigpipe};
|
||||
use rustc_span::{Span, sym};
|
||||
use rustc_session::config::{CrateType, EntryFnType, sigpipe};
|
||||
use rustc_span::{RemapPathScopeComponents, Span, sym};
|
||||
|
||||
use crate::errors::{ExternMain, MultipleRustcMain, NoMainErr};
|
||||
|
||||
|
|
@ -115,7 +114,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
|
|||
let filename = tcx
|
||||
.sess
|
||||
.local_crate_source_file()
|
||||
.map(|src| src.for_scope(&tcx.sess, RemapPathScopeComponents::DIAGNOSTICS).to_path_buf())
|
||||
.map(|src| src.path(RemapPathScopeComponents::DIAGNOSTICS).to_path_buf())
|
||||
.unwrap_or_else(|| {
|
||||
has_filename = false;
|
||||
Default::default()
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use rustc_middle::ty::{
|
|||
use rustc_middle::{mir, ty};
|
||||
use rustc_session::cstore::ForeignModule;
|
||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_span::{FileNameDisplayPreference, Span, Symbol};
|
||||
use rustc_span::{Span, Symbol};
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use super::{AllocRangeHelpers, CompilerCtxt, TyHelpers, TypingEnvHelpers};
|
||||
|
|
@ -324,12 +324,7 @@ impl<'tcx, B: Bridge> CompilerCtxt<'tcx, B> {
|
|||
|
||||
/// Return filename from given `Span`, for diagnostic purposes.
|
||||
pub fn get_filename(&self, span: Span) -> String {
|
||||
self.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_filename(span)
|
||||
.display(FileNameDisplayPreference::Local)
|
||||
.to_string()
|
||||
self.tcx.sess.source_map().span_to_filename(span).prefer_local_unconditionally().to_string()
|
||||
}
|
||||
|
||||
/// Return lines corresponding to this `Span`.
|
||||
|
|
|
|||
|
|
@ -2,14 +2,18 @@ use std::path::PathBuf;
|
|||
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{BytePos, DUMMY_SP, Span};
|
||||
use rustc_span::{BytePos, DUMMY_SP, FileName, Span};
|
||||
|
||||
use super::{DocFragment, DocFragmentKind, source_span_for_markdown_range_inner};
|
||||
|
||||
fn filename(sm: &SourceMap, path: &str) -> FileName {
|
||||
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_backtick() {
|
||||
let sm = SourceMap::new(FilePathMapping::empty());
|
||||
sm.new_source_file(PathBuf::from("foo.rs").into(), r#"#[doc = "`"] fn foo() {}"#.to_string());
|
||||
sm.new_source_file(filename(&sm, "foo.rs"), r#"#[doc = "`"] fn foo() {}"#.to_string());
|
||||
let (span, _) = source_span_for_markdown_range_inner(
|
||||
&sm,
|
||||
"`",
|
||||
|
|
@ -32,7 +36,7 @@ fn single_backtick() {
|
|||
fn utf8() {
|
||||
// regression test for https://github.com/rust-lang/rust/issues/141665
|
||||
let sm = SourceMap::new(FilePathMapping::empty());
|
||||
sm.new_source_file(PathBuf::from("foo.rs").into(), r#"#[doc = "⚠"] fn foo() {}"#.to_string());
|
||||
sm.new_source_file(filename(&sm, "foo.rs"), r#"#[doc = "⚠"] fn foo() {}"#.to_string());
|
||||
let (span, _) = source_span_for_markdown_range_inner(
|
||||
&sm,
|
||||
"⚠",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
getopts = "0.2"
|
||||
rand = "0.9.0"
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
|
|
|
|||
|
|
@ -24,10 +24,7 @@ use rustc_hashes::Hash64;
|
|||
use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
use rustc_span::{
|
||||
FileName, FileNameDisplayPreference, FileNameEmbeddablePreference, RealFileName,
|
||||
SourceFileHashAlgorithm, Symbol, sym,
|
||||
};
|
||||
use rustc_span::{FileName, SourceFileHashAlgorithm, Symbol, sym};
|
||||
use rustc_target::spec::{
|
||||
FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
|
||||
Target, TargetTuple,
|
||||
|
|
@ -1022,9 +1019,15 @@ impl Input {
|
|||
"rust_out"
|
||||
}
|
||||
|
||||
pub fn source_name(&self) -> FileName {
|
||||
pub fn file_name(&self, session: &Session) -> FileName {
|
||||
match *self {
|
||||
Input::File(ref ifile) => ifile.clone().into(),
|
||||
Input::File(ref ifile) => FileName::Real(
|
||||
session
|
||||
.psess
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_real_filename(session.psess.source_map().working_dir(), ifile.as_path()),
|
||||
),
|
||||
Input::Str { ref name, .. } => name.clone(),
|
||||
}
|
||||
}
|
||||
|
|
@ -1312,25 +1315,6 @@ impl OutputFilenames {
|
|||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Scopes used to determined if it need to apply to --remap-path-prefix
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct RemapPathScopeComponents: u8 {
|
||||
/// Apply remappings to the expansion of std::file!() macro
|
||||
const MACRO = 1 << 0;
|
||||
/// Apply remappings to printed compiler diagnostics
|
||||
const DIAGNOSTICS = 1 << 1;
|
||||
/// Apply remappings to debug information
|
||||
const DEBUGINFO = 1 << 3;
|
||||
/// Apply remappings to coverage information
|
||||
const COVERAGE = 1 << 4;
|
||||
|
||||
/// An alias for `macro`, `debuginfo` and `coverage`. This ensures all paths in compiled
|
||||
/// executables, libraries and objects are remapped but not elsewhere.
|
||||
const OBJECT = Self::MACRO.bits() | Self::DEBUGINFO.bits() | Self::COVERAGE.bits();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Sysroot {
|
||||
pub explicit: Option<PathBuf>,
|
||||
|
|
@ -1369,21 +1353,7 @@ 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
|
||||
},
|
||||
if unstable_opts.remap_path_scope.is_all() {
|
||||
FileNameEmbeddablePreference::RemappedOnly
|
||||
} else {
|
||||
FileNameEmbeddablePreference::LocalAndRemapped
|
||||
},
|
||||
)
|
||||
FilePathMapping::new(remap_path_prefix.clone(), unstable_opts.remap_path_scope)
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
|
|
@ -3115,8 +3085,8 @@ pub(crate) mod dep_tracking {
|
|||
use rustc_errors::LanguageIdentifier;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_hashes::Hash64;
|
||||
use rustc_span::RealFileName;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{RealFileName, RemapPathScopeComponents};
|
||||
use rustc_target::spec::{
|
||||
CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
|
||||
RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
|
||||
|
|
@ -3128,9 +3098,9 @@ pub(crate) mod dep_tracking {
|
|||
CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug,
|
||||
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
|
||||
LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel,
|
||||
OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius,
|
||||
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
|
||||
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
|
||||
OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks,
|
||||
SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
|
||||
WasiExecModel,
|
||||
};
|
||||
use crate::lint;
|
||||
use crate::utils::NativeLib;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use rustc_feature::UnstableFeatures;
|
|||
use rustc_hashes::Hash64;
|
||||
use rustc_macros::{BlobDecodable, Encodable};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{RealFileName, SourceFileHashAlgorithm};
|
||||
use rustc_span::{RemapPathScopeComponents, SourceFileHashAlgorithm};
|
||||
use rustc_target::spec::{
|
||||
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
|
||||
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use std::any::Any;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
|
@ -28,7 +28,7 @@ use rustc_macros::HashStable_Generic;
|
|||
pub use rustc_span::def_id::StableCrateId;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::source_map::{FilePathMapping, SourceMap};
|
||||
use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol};
|
||||
use rustc_span::{RealFileName, Span, Symbol};
|
||||
use rustc_target::asm::InlineAsmArch;
|
||||
use rustc_target::spec::{
|
||||
Arch, CodeModel, DebuginfoKind, Os, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
|
||||
|
|
@ -40,8 +40,7 @@ use crate::code_stats::CodeStats;
|
|||
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
||||
use crate::config::{
|
||||
self, CoverageLevel, CoverageOptions, CrateType, DebugInfo, ErrorOutputType, FunctionReturn,
|
||||
Input, InstrumentCoverage, OptLevel, OutFileName, OutputType, RemapPathScopeComponents,
|
||||
SwitchWithOptPath,
|
||||
Input, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath,
|
||||
};
|
||||
use crate::filesearch::FileSearch;
|
||||
use crate::lint::LintId;
|
||||
|
|
@ -192,7 +191,11 @@ impl Session {
|
|||
}
|
||||
|
||||
pub fn local_crate_source_file(&self) -> Option<RealFileName> {
|
||||
Some(self.source_map().path_mapping().to_real_filename(self.io.input.opt_path()?))
|
||||
Some(
|
||||
self.source_map()
|
||||
.path_mapping()
|
||||
.to_real_filename(self.source_map().working_dir(), self.io.input.opt_path()?),
|
||||
)
|
||||
}
|
||||
|
||||
fn check_miri_unleashed_features(&self) -> Option<ErrorGuaranteed> {
|
||||
|
|
@ -846,21 +849,6 @@ impl Session {
|
|||
self.opts.cg.link_dead_code.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn filename_display_preference(
|
||||
&self,
|
||||
scope: RemapPathScopeComponents,
|
||||
) -> FileNameDisplayPreference {
|
||||
assert!(
|
||||
scope.bits().count_ones() == 1,
|
||||
"one and only one scope should be passed to `Session::filename_display_preference`"
|
||||
);
|
||||
if self.opts.unstable_opts.remap_path_scope.contains(scope) {
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the deployment target on Apple platforms based on the standard environment variables,
|
||||
/// or fall back to the minimum version supported by `rustc`.
|
||||
///
|
||||
|
|
@ -1496,46 +1484,3 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
|||
};
|
||||
emitter
|
||||
}
|
||||
|
||||
pub trait RemapFileNameExt {
|
||||
type Output<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
/// Returns a possibly remapped filename based on the passed scope and remap cli options.
|
||||
///
|
||||
/// One and only one scope should be passed to this method, it will panic otherwise.
|
||||
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_>;
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::FileName {
|
||||
type Output<'a> = rustc_span::FileNameDisplay<'a>;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_> {
|
||||
assert!(
|
||||
scope.bits().count_ones() == 1,
|
||||
"one and only one scope should be passed to for_scope"
|
||||
);
|
||||
if sess.opts.unstable_opts.remap_path_scope.contains(scope) {
|
||||
self.prefer_remapped_unconditionally()
|
||||
} else {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::RealFileName {
|
||||
type Output<'a> = &'a Path;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scope: RemapPathScopeComponents) -> Self::Output<'_> {
|
||||
assert!(
|
||||
scope.bits().count_ones() == 1,
|
||||
"one and only one scope should be passed to for_scope"
|
||||
);
|
||||
if sess.opts.unstable_opts.remap_path_scope.contains(scope) {
|
||||
self.remapped_path_if_available()
|
||||
} else {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
bitflags = "2.4.1"
|
||||
blake3 = "1.5.2"
|
||||
derive-where = "1.2.7"
|
||||
indexmap = { version = "2.0.0" }
|
||||
|
|
|
|||
|
|
@ -221,99 +221,227 @@ pub fn with_metavar_spans<R>(f: impl FnOnce(&MetavarSpansMap) -> R) -> R {
|
|||
with_session_globals(|session_globals| f(&session_globals.metavar_spans))
|
||||
}
|
||||
|
||||
// FIXME: We should use this enum or something like it to get rid of the
|
||||
// use of magic `/rust/1.x/...` paths across the board.
|
||||
bitflags::bitflags! {
|
||||
/// Scopes used to determined if it need to apply to `--remap-path-prefix`
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd, Hash)]
|
||||
pub struct RemapPathScopeComponents: u8 {
|
||||
/// Apply remappings to the expansion of `std::file!()` macro
|
||||
const MACRO = 1 << 0;
|
||||
/// Apply remappings to printed compiler diagnostics
|
||||
const DIAGNOSTICS = 1 << 1;
|
||||
/// Apply remappings to debug information
|
||||
const DEBUGINFO = 1 << 3;
|
||||
/// Apply remappings to coverage information
|
||||
const COVERAGE = 1 << 4;
|
||||
|
||||
/// An alias for `macro`, `debuginfo` and `coverage`. This ensures all paths in compiled
|
||||
/// executables, libraries and objects are remapped but not elsewhere.
|
||||
const OBJECT = Self::MACRO.bits() | Self::DEBUGINFO.bits() | Self::COVERAGE.bits();
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Encoder> Encodable<E> for RemapPathScopeComponents {
|
||||
fn encode(&self, s: &mut E) {
|
||||
s.emit_u8(self.bits());
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: Decoder> Decodable<D> for RemapPathScopeComponents {
|
||||
fn decode(s: &mut D) -> RemapPathScopeComponents {
|
||||
RemapPathScopeComponents::from_bits(s.read_u8())
|
||||
.expect("invalid bits for RemapPathScopeComponents")
|
||||
}
|
||||
}
|
||||
|
||||
/// A self-contained "real" filename.
|
||||
///
|
||||
/// It is produced by `SourceMap::to_real_filename`.
|
||||
///
|
||||
/// `RealFileName` represents a filename that may have been (partly) remapped
|
||||
/// by `--remap-path-prefix` and `-Zremap-path-scope`.
|
||||
///
|
||||
/// It also contains an embedabble component which gives a working directory
|
||||
/// and a maybe-remapped maybe-aboslote name. This is useful for debuginfo where
|
||||
/// some formats and tools highly prefer absolute paths.
|
||||
///
|
||||
/// ## Consistency across compiler sessions
|
||||
///
|
||||
/// The type-system, const-eval and other parts of the compiler rely on `FileName`
|
||||
/// and by extension `RealFileName` to be consistent across compiler sessions.
|
||||
///
|
||||
/// Otherwise unsoudness (like rust-lang/rust#148328) may occur.
|
||||
///
|
||||
/// As such this type is self-sufficient and consistent in it's output.
|
||||
///
|
||||
/// The [`RealFileName::path`] and [`RealFileName::embeddable_name`] methods
|
||||
/// are guaranteed to always return the same output across compiler sessions.
|
||||
///
|
||||
/// ## Usage
|
||||
///
|
||||
/// Creation of a [`RealFileName`] should be done using
|
||||
/// [`FilePathMapping::to_real_filename`][rustc_span::source_map::FilePathMapping::to_real_filename].
|
||||
///
|
||||
/// Retrieving a path can be done in two main ways:
|
||||
/// - by using [`RealFileName::path`] with a given scope (should be preferred)
|
||||
/// - or by using [`RealFileName::embeddable_name`] with a given scope
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable)]
|
||||
pub enum RealFileName {
|
||||
LocalPath(PathBuf),
|
||||
/// For remapped paths (namely paths into libstd that have been mapped
|
||||
/// to the appropriate spot on the local host's file system, and local file
|
||||
/// system paths that have been remapped with `FilePathMapping`),
|
||||
Remapped {
|
||||
/// `local_path` is the (host-dependent) local path to the file. This is
|
||||
/// None if the file was imported from another crate
|
||||
local_path: Option<PathBuf>,
|
||||
/// `virtual_name` is the stable path rustc will store internally within
|
||||
/// build artifacts.
|
||||
virtual_name: PathBuf,
|
||||
},
|
||||
pub struct RealFileName {
|
||||
/// The local name (always present in the original crate)
|
||||
local: Option<InnerRealFileName>,
|
||||
/// The maybe remapped part. Correspond to `local` when no remapped happened.
|
||||
maybe_remapped: InnerRealFileName,
|
||||
/// The remapped scopes. Any active scope MUST use `maybe_virtual`
|
||||
scopes: RemapPathScopeComponents,
|
||||
}
|
||||
|
||||
/// The inner workings of `RealFileName`.
|
||||
///
|
||||
/// It contains the `name`, `working_directory` and `embeddable_name` components.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Decodable, Encodable, Hash)]
|
||||
struct InnerRealFileName {
|
||||
/// The name.
|
||||
name: PathBuf,
|
||||
/// The working directory associated with the embeddable name.
|
||||
working_directory: PathBuf,
|
||||
/// The embeddable name.
|
||||
embeddable_name: PathBuf,
|
||||
}
|
||||
|
||||
impl Hash for RealFileName {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
// To prevent #70924 from happening again we should only hash the
|
||||
// remapped (virtualized) path if that exists. This is because
|
||||
// virtualized paths to sysroot crates (/rust/$hash or /rust/$version)
|
||||
// remain stable even if the corresponding local_path changes
|
||||
self.remapped_path_if_available().hash(state)
|
||||
// remapped path if that exists. This is because remapped paths to
|
||||
// sysroot crates (/rust/$hash or /rust/$version) remain stable even
|
||||
// if the corresponding local path changes.
|
||||
if !self.scopes.is_all() {
|
||||
self.local.hash(state);
|
||||
}
|
||||
self.maybe_remapped.hash(state);
|
||||
self.scopes.bits().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl RealFileName {
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
|
||||
pub fn local_path(&self) -> Option<&Path> {
|
||||
match self {
|
||||
RealFileName::LocalPath(p) => Some(p),
|
||||
RealFileName::Remapped { local_path, virtual_name: _ } => local_path.as_deref(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
|
||||
pub fn into_local_path(self) -> Option<PathBuf> {
|
||||
match self {
|
||||
RealFileName::LocalPath(p) => Some(p),
|
||||
RealFileName::Remapped { local_path: p, virtual_name: _ } => p,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path suitable for embedding into build artifacts. This would still
|
||||
/// be a local path if it has not been remapped. A remapped path will not correspond
|
||||
/// to a valid file system path: see `local_path_if_available()` for something that
|
||||
/// is more likely to return paths into the local host file system.
|
||||
pub fn remapped_path_if_available(&self) -> &Path {
|
||||
match self {
|
||||
RealFileName::LocalPath(p)
|
||||
| RealFileName::Remapped { local_path: _, virtual_name: p } => p,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists. Otherwise returns the remapped name.
|
||||
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
|
||||
pub fn local_path_if_available(&self) -> &Path {
|
||||
match self {
|
||||
RealFileName::LocalPath(path)
|
||||
| RealFileName::Remapped { local_path: None, virtual_name: path }
|
||||
| RealFileName::Remapped { local_path: Some(path), virtual_name: _ } => path,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the path remapped or not depending on the [`FileNameDisplayPreference`].
|
||||
/// Returns the associated path for the given remapping scope.
|
||||
///
|
||||
/// For the purpose of this function, local and short preference are equal.
|
||||
pub fn to_path(&self, display_pref: FileNameDisplayPreference) -> &Path {
|
||||
match display_pref {
|
||||
FileNameDisplayPreference::Local | FileNameDisplayPreference::Short => {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
FileNameDisplayPreference::Remapped => self.remapped_path_if_available(),
|
||||
/// ## Panic
|
||||
///
|
||||
/// Only one scope components can be given to this function.
|
||||
pub fn path(&self, scope: RemapPathScopeComponents) -> &Path {
|
||||
assert!(
|
||||
scope.bits().count_ones() == 1,
|
||||
"one and only one scope should be passed to `RealFileName::path`: {scope:?}"
|
||||
);
|
||||
if !self.scopes.contains(scope)
|
||||
&& let Some(local_name) = &self.local
|
||||
{
|
||||
local_name.name.as_path()
|
||||
} else {
|
||||
self.maybe_remapped.name.as_path()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string_lossy(&self, display_pref: FileNameDisplayPreference) -> Cow<'_, str> {
|
||||
/// Returns the working directory and embeddable path for the given remapping scope.
|
||||
///
|
||||
/// Useful for embedding a mostly abosolute path (modulo remapping) in the compiler outputs.
|
||||
///
|
||||
/// The embedabble path is not guaranteed to be an absolute path, nor is it garuenteed
|
||||
/// that the working directory part is always a prefix of embeddable path.
|
||||
///
|
||||
/// ## Panic
|
||||
///
|
||||
/// Only one scope components can be given to this function.
|
||||
pub fn embeddable_name(&self, scope: RemapPathScopeComponents) -> (&Path, &Path) {
|
||||
assert!(
|
||||
scope.bits().count_ones() == 1,
|
||||
"one and only one scope should be passed to `RealFileName::embeddable_path`: {scope:?}"
|
||||
);
|
||||
if !self.scopes.contains(scope)
|
||||
&& let Some(local_name) = &self.local
|
||||
{
|
||||
(&local_name.working_directory, &local_name.embeddable_name)
|
||||
} else {
|
||||
(&self.maybe_remapped.working_directory, &self.maybe_remapped.embeddable_name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
///
|
||||
/// May not exists if the filename was imported from another crate.
|
||||
pub fn local_path(&self) -> Option<&Path> {
|
||||
self.local.as_ref().map(|lp| lp.name.as_ref())
|
||||
}
|
||||
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
///
|
||||
/// May not exists if the filename was imported from another crate.
|
||||
pub fn into_local_path(self) -> Option<PathBuf> {
|
||||
self.local.map(|lp| lp.name)
|
||||
}
|
||||
|
||||
/// Returns whenever the filename was remapped.
|
||||
pub(crate) fn was_remapped(&self) -> bool {
|
||||
!self.scopes.is_empty()
|
||||
}
|
||||
|
||||
/// Returns an empty `RealFileName`
|
||||
///
|
||||
/// Useful as the working directory input to `SourceMap::to_real_filename`.
|
||||
pub fn empty() -> RealFileName {
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: PathBuf::new(),
|
||||
working_directory: PathBuf::new(),
|
||||
embeddable_name: PathBuf::new(),
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: PathBuf::new(),
|
||||
working_directory: PathBuf::new(),
|
||||
embeddable_name: PathBuf::new(),
|
||||
},
|
||||
scopes: RemapPathScopeComponents::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a `RealFileName` that is completely remapped without any local components.
|
||||
///
|
||||
/// Only exposed for the purpose of `-Zsimulate-remapped-rust-src-base`.
|
||||
pub fn from_virtual_path(path: &Path) -> RealFileName {
|
||||
let name = InnerRealFileName {
|
||||
name: path.to_owned(),
|
||||
embeddable_name: path.to_owned(),
|
||||
working_directory: PathBuf::new(),
|
||||
};
|
||||
RealFileName { local: None, maybe_remapped: name, scopes: RemapPathScopeComponents::all() }
|
||||
}
|
||||
|
||||
/// Update the filename for encoding in the crate metadata.
|
||||
///
|
||||
/// Currently it's about removing the local part when the filename
|
||||
/// is fully remapped.
|
||||
pub fn update_for_crate_metadata(&mut self) {
|
||||
if self.scopes.is_all() {
|
||||
self.local = None;
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal routine to display the filename.
|
||||
///
|
||||
/// Users should always use the `RealFileName::path` method or `FileName` methods instead.
|
||||
fn to_string_lossy<'a>(&'a self, display_pref: FileNameDisplayPreference) -> Cow<'a, str> {
|
||||
match display_pref {
|
||||
FileNameDisplayPreference::Local => self.local_path_if_available().to_string_lossy(),
|
||||
FileNameDisplayPreference::Remapped => {
|
||||
self.remapped_path_if_available().to_string_lossy()
|
||||
FileNameDisplayPreference::Remapped => self.maybe_remapped.name.to_string_lossy(),
|
||||
FileNameDisplayPreference::Local => {
|
||||
self.local.as_ref().unwrap_or(&self.maybe_remapped).name.to_string_lossy()
|
||||
}
|
||||
FileNameDisplayPreference::Short => self
|
||||
.local_path_if_available()
|
||||
.maybe_remapped
|
||||
.name
|
||||
.file_name()
|
||||
.map_or_else(|| "".into(), |f| f.to_string_lossy()),
|
||||
FileNameDisplayPreference::Scope(scope) => self.path(scope).to_string_lossy(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -339,40 +467,20 @@ pub enum FileName {
|
|||
InlineAsm(Hash64),
|
||||
}
|
||||
|
||||
impl From<PathBuf> for FileName {
|
||||
fn from(p: PathBuf) -> Self {
|
||||
FileName::Real(RealFileName::LocalPath(p))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum FileNameEmbeddablePreference {
|
||||
/// If a remapped path is available, only embed the `virtual_path` and omit the `local_path`.
|
||||
///
|
||||
/// Otherwise embed the local-path into the `virtual_path`.
|
||||
RemappedOnly,
|
||||
/// Embed the original path as well as its remapped `virtual_path` component if available.
|
||||
LocalAndRemapped,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum FileNameDisplayPreference {
|
||||
/// Display the path after the application of rewrite rules provided via `--remap-path-prefix`.
|
||||
/// This is appropriate for paths that get embedded into files produced by the compiler.
|
||||
Remapped,
|
||||
/// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
|
||||
/// This is appropriate for use in user-facing output (such as diagnostics).
|
||||
Local,
|
||||
/// Display only the filename, as a way to reduce the verbosity of the output.
|
||||
/// This is appropriate for use in user-facing output (such as diagnostics).
|
||||
Short,
|
||||
}
|
||||
|
||||
pub struct FileNameDisplay<'a> {
|
||||
inner: &'a FileName,
|
||||
display_pref: FileNameDisplayPreference,
|
||||
}
|
||||
|
||||
// Internal enum. Should not be exposed.
|
||||
#[derive(Clone, Copy)]
|
||||
enum FileNameDisplayPreference {
|
||||
Remapped,
|
||||
Local,
|
||||
Short,
|
||||
Scope(RemapPathScopeComponents),
|
||||
}
|
||||
|
||||
impl fmt::Display for FileNameDisplay<'_> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use FileName::*;
|
||||
|
|
@ -417,18 +525,30 @@ impl FileName {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
///
|
||||
/// Avoid embedding this in build artifacts. Prefer using the `display` method.
|
||||
pub fn prefer_remapped_unconditionally(&self) -> FileNameDisplay<'_> {
|
||||
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Remapped }
|
||||
}
|
||||
|
||||
/// This may include transient local filesystem information.
|
||||
/// Must not be embedded in build outputs.
|
||||
pub fn prefer_local(&self) -> FileNameDisplay<'_> {
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
///
|
||||
/// Avoid embedding this in build artifacts. Prefer using the `display` method.
|
||||
pub fn prefer_local_unconditionally(&self) -> FileNameDisplay<'_> {
|
||||
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Local }
|
||||
}
|
||||
|
||||
pub fn display(&self, display_pref: FileNameDisplayPreference) -> FileNameDisplay<'_> {
|
||||
FileNameDisplay { inner: self, display_pref }
|
||||
/// Returns a short (either the filename or an empty string).
|
||||
pub fn short(&self) -> FileNameDisplay<'_> {
|
||||
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Short }
|
||||
}
|
||||
|
||||
/// Returns a `Display`-able path for the given scope.
|
||||
pub fn display(&self, scope: RemapPathScopeComponents) -> FileNameDisplay<'_> {
|
||||
FileNameDisplay { inner: self, display_pref: FileNameDisplayPreference::Scope(scope) }
|
||||
}
|
||||
|
||||
pub fn macro_expansion_source_code(src: &str) -> FileName {
|
||||
|
|
@ -473,7 +593,8 @@ impl FileName {
|
|||
|
||||
/// Returns the path suitable for reading from the file system on the local host,
|
||||
/// if this information exists.
|
||||
/// Avoid embedding this in build artifacts; see `remapped_path_if_available()` for that.
|
||||
///
|
||||
/// Avoid embedding this in build artifacts.
|
||||
pub fn into_local_path(self) -> Option<PathBuf> {
|
||||
match self {
|
||||
FileName::Real(path) => path.into_local_path(),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use std::borrow::Borrow;
|
|||
|
||||
use rustc_data_structures::profiling::EventArgRecorder;
|
||||
|
||||
use crate::RemapPathScopeComponents;
|
||||
use crate::source_map::SourceMap;
|
||||
|
||||
/// Extension trait for self-profiling purposes: allows to record spans within a generic activity's
|
||||
|
|
@ -24,6 +25,6 @@ impl SpannedEventArgRecorder for EventArgRecorder<'_> {
|
|||
A: Borrow<str> + Into<String>,
|
||||
{
|
||||
self.record_arg(event_arg);
|
||||
self.record_arg(source_map.span_to_embeddable_string(span));
|
||||
self.record_arg(source_map.span_to_string(span, RemapPathScopeComponents::DEBUGINFO));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ impl SourceMap {
|
|||
let cwd = file_loader
|
||||
.current_directory()
|
||||
.expect("expecting a current working directory to exist");
|
||||
let working_dir = cwd.to_path_buf().into();
|
||||
let working_dir = path_mapping.to_real_filename(&RealFileName::empty(), &cwd);
|
||||
debug!(?working_dir);
|
||||
SourceMap {
|
||||
files: Default::default(),
|
||||
|
|
@ -260,7 +260,7 @@ impl SourceMap {
|
|||
|
||||
pub fn load_file(&self, path: &Path) -> io::Result<Arc<SourceFile>> {
|
||||
let src = self.file_loader.read_file(path)?;
|
||||
let filename = path.to_owned().into();
|
||||
let filename = FileName::Real(self.path_mapping.to_real_filename(&self.working_dir, path));
|
||||
Ok(self.new_source_file(filename, src))
|
||||
}
|
||||
|
||||
|
|
@ -277,7 +277,8 @@ impl SourceMap {
|
|||
// via `mod`, so we try to use real file contents and not just an
|
||||
// empty string.
|
||||
let text = std::str::from_utf8(&bytes).unwrap_or("").to_string();
|
||||
let file = self.new_source_file(path.to_owned().into(), text);
|
||||
let filename = FileName::Real(self.path_mapping.to_real_filename(&self.working_dir, path));
|
||||
let file = self.new_source_file(filename, text);
|
||||
Ok((
|
||||
bytes,
|
||||
Span::new(
|
||||
|
|
@ -345,7 +346,6 @@ impl SourceMap {
|
|||
// Note that filename may not be a valid path, eg it may be `<anon>` etc,
|
||||
// but this is okay because the directory determined by `path.pop()` will
|
||||
// be empty, so the working directory will be used.
|
||||
let (filename, _) = self.path_mapping.map_filename_prefix(&filename);
|
||||
|
||||
let stable_id = StableSourceFileId::from_filename_in_current_crate(&filename);
|
||||
match self.source_file_by_stable_id(stable_id) {
|
||||
|
|
@ -444,25 +444,36 @@ impl SourceMap {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn span_to_string(
|
||||
pub fn span_to_string(&self, sp: Span, display_scope: RemapPathScopeComponents) -> String {
|
||||
self.span_to_string_ext(sp, display_scope, false)
|
||||
}
|
||||
|
||||
pub fn span_to_short_string(
|
||||
&self,
|
||||
sp: Span,
|
||||
filename_display_pref: FileNameDisplayPreference,
|
||||
display_scope: RemapPathScopeComponents,
|
||||
) -> String {
|
||||
self.span_to_string_ext(sp, display_scope, true)
|
||||
}
|
||||
|
||||
fn span_to_string_ext(
|
||||
&self,
|
||||
sp: Span,
|
||||
display_scope: RemapPathScopeComponents,
|
||||
short: bool,
|
||||
) -> String {
|
||||
let (source_file, lo_line, lo_col, hi_line, hi_col) = self.span_to_location_info(sp);
|
||||
|
||||
let file_name = match source_file {
|
||||
Some(sf) => sf.name.display(filename_display_pref).to_string(),
|
||||
Some(sf) => {
|
||||
if short { sf.name.short() } else { sf.name.display(display_scope) }.to_string()
|
||||
}
|
||||
None => return "no-location".to_string(),
|
||||
};
|
||||
|
||||
format!(
|
||||
"{file_name}:{lo_line}:{lo_col}{}",
|
||||
if let FileNameDisplayPreference::Short = filename_display_pref {
|
||||
String::new()
|
||||
} else {
|
||||
format!(": {hi_line}:{hi_col}")
|
||||
}
|
||||
if short { String::new() } else { format!(": {hi_line}:{hi_col}") }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -479,16 +490,11 @@ impl SourceMap {
|
|||
(Some(lo.file), lo.line, lo.col.to_usize() + 1, hi.line, hi.col.to_usize() + 1)
|
||||
}
|
||||
|
||||
/// Format the span location suitable for embedding in build artifacts
|
||||
pub fn span_to_embeddable_string(&self, sp: Span) -> String {
|
||||
self.span_to_string(sp, FileNameDisplayPreference::Remapped)
|
||||
}
|
||||
|
||||
/// Format the span location to be printed in diagnostics. Must not be emitted
|
||||
/// to build artifacts as this may leak local file paths. Use span_to_embeddable_string
|
||||
/// for string suitable for embedding.
|
||||
pub fn span_to_diagnostic_string(&self, sp: Span) -> String {
|
||||
self.span_to_string(sp, self.path_mapping.filename_display_for_diagnostics)
|
||||
self.span_to_string(sp, RemapPathScopeComponents::DIAGNOSTICS)
|
||||
}
|
||||
|
||||
pub fn span_to_filename(&self, sp: Span) -> FileName {
|
||||
|
|
@ -496,7 +502,7 @@ impl SourceMap {
|
|||
}
|
||||
|
||||
pub fn filename_for_diagnostics<'a>(&self, filename: &'a FileName) -> FileNameDisplay<'a> {
|
||||
filename.display(self.path_mapping.filename_display_for_diagnostics)
|
||||
filename.display(RemapPathScopeComponents::DIAGNOSTICS)
|
||||
}
|
||||
|
||||
pub fn is_multiline(&self, sp: Span) -> bool {
|
||||
|
|
@ -1045,10 +1051,8 @@ impl SourceMap {
|
|||
}
|
||||
|
||||
pub fn get_source_file(&self, filename: &FileName) -> Option<Arc<SourceFile>> {
|
||||
// Remap filename before lookup
|
||||
let filename = self.path_mapping().map_filename_prefix(filename).0;
|
||||
for sf in self.files.borrow().source_files.iter() {
|
||||
if filename == sf.name {
|
||||
if *filename == sf.name {
|
||||
return Some(Arc::clone(&sf));
|
||||
}
|
||||
}
|
||||
|
|
@ -1080,16 +1084,20 @@ impl SourceMap {
|
|||
return None;
|
||||
};
|
||||
|
||||
let local_path: Cow<'_, Path> = match name {
|
||||
RealFileName::LocalPath(local_path) => local_path.into(),
|
||||
RealFileName::Remapped { local_path: Some(local_path), .. } => local_path.into(),
|
||||
RealFileName::Remapped { local_path: None, virtual_name } => {
|
||||
let local_path: Cow<'_, Path> = match name.local_path() {
|
||||
Some(local) => local.into(),
|
||||
None => {
|
||||
// The compiler produces better error messages if the sources of dependencies
|
||||
// are available. Attempt to undo any path mapping so we can find remapped
|
||||
// dependencies.
|
||||
//
|
||||
// We can only use the heuristic because `add_external_src` checks the file
|
||||
// content hash.
|
||||
self.path_mapping.reverse_map_prefix_heuristically(virtual_name)?.into()
|
||||
let maybe_remapped_path = name.path(RemapPathScopeComponents::DIAGNOSTICS);
|
||||
self.path_mapping
|
||||
.reverse_map_prefix_heuristically(maybe_remapped_path)
|
||||
.map(Cow::from)
|
||||
.unwrap_or(maybe_remapped_path.into())
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1135,35 +1143,25 @@ pub fn get_source_map() -> Option<Arc<SourceMap>> {
|
|||
#[derive(Clone)]
|
||||
pub struct FilePathMapping {
|
||||
mapping: Vec<(PathBuf, PathBuf)>,
|
||||
filename_display_for_diagnostics: FileNameDisplayPreference,
|
||||
filename_embeddable_preference: FileNameEmbeddablePreference,
|
||||
filename_remapping_scopes: RemapPathScopeComponents,
|
||||
}
|
||||
|
||||
impl FilePathMapping {
|
||||
pub fn empty() -> FilePathMapping {
|
||||
FilePathMapping::new(
|
||||
Vec::new(),
|
||||
FileNameDisplayPreference::Local,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
)
|
||||
FilePathMapping::new(Vec::new(), RemapPathScopeComponents::empty())
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
mapping: Vec<(PathBuf, PathBuf)>,
|
||||
filename_display_for_diagnostics: FileNameDisplayPreference,
|
||||
filename_embeddable_preference: FileNameEmbeddablePreference,
|
||||
filename_remapping_scopes: RemapPathScopeComponents,
|
||||
) -> FilePathMapping {
|
||||
FilePathMapping {
|
||||
mapping,
|
||||
filename_display_for_diagnostics,
|
||||
filename_embeddable_preference,
|
||||
}
|
||||
FilePathMapping { mapping, filename_remapping_scopes }
|
||||
}
|
||||
|
||||
/// Applies any path prefix substitution as defined by the mapping.
|
||||
/// The return value is the remapped path and a boolean indicating whether
|
||||
/// the path was affected by the mapping.
|
||||
pub fn map_prefix<'a>(&'a self, path: impl Into<Cow<'a, Path>>) -> (Cow<'a, Path>, bool) {
|
||||
fn map_prefix<'a>(&'a self, path: impl Into<Cow<'a, Path>>) -> (Cow<'a, Path>, bool) {
|
||||
let path = path.into();
|
||||
if path.as_os_str().is_empty() {
|
||||
// Exit early if the path is empty and therefore there's nothing to remap.
|
||||
|
|
@ -1209,138 +1207,68 @@ impl FilePathMapping {
|
|||
}
|
||||
}
|
||||
|
||||
fn map_filename_prefix(&self, file: &FileName) -> (FileName, bool) {
|
||||
match file {
|
||||
FileName::Real(realfile) if let RealFileName::LocalPath(local_path) = realfile => {
|
||||
let (mapped_path, mapped) = self.map_prefix(local_path);
|
||||
let realfile = if mapped {
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(local_path.clone()),
|
||||
virtual_name: mapped_path.into_owned(),
|
||||
}
|
||||
} else {
|
||||
realfile.clone()
|
||||
};
|
||||
(FileName::Real(realfile), mapped)
|
||||
}
|
||||
FileName::Real(_) => unreachable!("attempted to remap an already remapped filename"),
|
||||
other => (other.clone(), false),
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies any path prefix substitution as defined by the mapping.
|
||||
/// The return value is the local path with a "virtual path" representing the remapped
|
||||
/// part if any remapping was performed.
|
||||
pub fn to_real_filename<'a>(&self, local_path: impl Into<Cow<'a, Path>>) -> RealFileName {
|
||||
let local_path = local_path.into();
|
||||
if let (remapped_path, true) = self.map_prefix(&*local_path) {
|
||||
RealFileName::Remapped {
|
||||
virtual_name: remapped_path.into_owned(),
|
||||
local_path: Some(local_path.into_owned()),
|
||||
}
|
||||
} else {
|
||||
RealFileName::LocalPath(local_path.into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand a relative path to an absolute path with remapping taken into account.
|
||||
/// Use this when absolute paths are required (e.g. debuginfo or crate metadata).
|
||||
///
|
||||
/// The resulting `RealFileName` will have its `local_path` portion erased if
|
||||
/// possible (i.e. if there's also a remapped path).
|
||||
pub fn to_embeddable_absolute_path(
|
||||
/// The returned filename contains the a remapped path representing the remapped
|
||||
/// part if any remapping was performed.
|
||||
pub fn to_real_filename<'a>(
|
||||
&self,
|
||||
file_path: RealFileName,
|
||||
working_directory: &RealFileName,
|
||||
local_path: impl Into<Cow<'a, Path>>,
|
||||
) -> RealFileName {
|
||||
match file_path {
|
||||
// Anything that's already remapped we don't modify, except for erasing
|
||||
// the `local_path` portion (if desired).
|
||||
RealFileName::Remapped { local_path, virtual_name } => {
|
||||
RealFileName::Remapped {
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => local_path,
|
||||
},
|
||||
// We use the remapped name verbatim, even if it looks like a relative
|
||||
// path. The assumption is that the user doesn't want us to further
|
||||
// process paths that have gone through remapping.
|
||||
virtual_name,
|
||||
}
|
||||
}
|
||||
let local_path = local_path.into();
|
||||
|
||||
RealFileName::LocalPath(unmapped_file_path) => {
|
||||
// If no remapping has been applied yet, try to do so
|
||||
let (new_path, was_remapped) = self.map_prefix(&unmapped_file_path);
|
||||
if was_remapped {
|
||||
// It was remapped, so don't modify further
|
||||
return RealFileName::Remapped {
|
||||
virtual_name: new_path.into_owned(),
|
||||
// But still provide the local path if desired
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => {
|
||||
Some(unmapped_file_path)
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
let (remapped_path, mut was_remapped) = self.map_prefix(&*local_path);
|
||||
debug!(?local_path, ?remapped_path, ?was_remapped, ?self.filename_remapping_scopes);
|
||||
|
||||
if new_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(new_path.into_owned());
|
||||
}
|
||||
// Always populate the local part, even if we just remapped it and the scopes are
|
||||
// total, so that places that load the file from disk still have access to it.
|
||||
let local = InnerRealFileName {
|
||||
name: local_path.to_path_buf(),
|
||||
working_directory: working_directory
|
||||
.local_path()
|
||||
.expect("working directory should be local")
|
||||
.to_path_buf(),
|
||||
embeddable_name: if local_path.is_absolute() {
|
||||
local_path.to_path_buf()
|
||||
} else {
|
||||
working_directory
|
||||
.local_path()
|
||||
.expect("working directory should be local")
|
||||
.to_path_buf()
|
||||
.join(&local_path)
|
||||
},
|
||||
};
|
||||
|
||||
debug_assert!(new_path.is_relative());
|
||||
let unmapped_file_path_rel = new_path;
|
||||
RealFileName {
|
||||
maybe_remapped: InnerRealFileName {
|
||||
working_directory: working_directory.maybe_remapped.name.clone(),
|
||||
embeddable_name: if remapped_path.is_absolute() || was_remapped {
|
||||
// The current directory may have been remapped so we take that
|
||||
// into account, otherwise we'll forget to include the scopes
|
||||
was_remapped = was_remapped || working_directory.was_remapped();
|
||||
|
||||
match working_directory {
|
||||
RealFileName::LocalPath(unmapped_working_dir_abs) => {
|
||||
let unmapped_file_path_abs =
|
||||
unmapped_working_dir_abs.join(unmapped_file_path_rel);
|
||||
remapped_path.to_path_buf()
|
||||
} else {
|
||||
// Create an absolute path and remap it as well.
|
||||
let (abs_path, abs_was_remapped) = self.map_prefix(
|
||||
working_directory.maybe_remapped.name.clone().join(&remapped_path),
|
||||
);
|
||||
|
||||
// Although neither `working_directory` nor the file name were subject
|
||||
// to path remapping, the concatenation between the two may be. Hence
|
||||
// we need to do a remapping here.
|
||||
let (file_path_abs, was_remapped) =
|
||||
self.map_prefix(&unmapped_file_path_abs);
|
||||
if was_remapped {
|
||||
RealFileName::Remapped {
|
||||
virtual_name: file_path_abs.into_owned(),
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => {
|
||||
Some(unmapped_file_path_abs)
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// No kind of remapping applied to this path, so
|
||||
// we leave it as it is.
|
||||
RealFileName::LocalPath(file_path_abs.into_owned())
|
||||
}
|
||||
}
|
||||
RealFileName::Remapped {
|
||||
local_path,
|
||||
virtual_name: remapped_working_dir_abs,
|
||||
} => {
|
||||
// If working_directory has been remapped, then we emit
|
||||
// Remapped variant as the expanded path won't be valid
|
||||
RealFileName::Remapped {
|
||||
virtual_name: Path::new(remapped_working_dir_abs)
|
||||
.join(&unmapped_file_path_rel),
|
||||
local_path: match self.filename_embeddable_preference {
|
||||
FileNameEmbeddablePreference::RemappedOnly => None,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped => local_path
|
||||
.as_ref()
|
||||
.map(|local_path| local_path.join(unmapped_file_path_rel)),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If either the embeddable name or the working directory was
|
||||
// remapped, then the filename was remapped
|
||||
was_remapped = abs_was_remapped || working_directory.was_remapped();
|
||||
|
||||
abs_path.to_path_buf()
|
||||
},
|
||||
name: remapped_path.to_path_buf(),
|
||||
},
|
||||
local: Some(local),
|
||||
scopes: if was_remapped {
|
||||
self.filename_remapping_scopes
|
||||
} else {
|
||||
RemapPathScopeComponents::empty()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
use super::*;
|
||||
|
||||
fn filename(sm: &SourceMap, path: &str) -> FileName {
|
||||
FileName::Real(sm.path_mapping().to_real_filename(sm.working_dir(), PathBuf::from(path)))
|
||||
}
|
||||
|
||||
fn init_source_map() -> SourceMap {
|
||||
let sm = SourceMap::new(FilePathMapping::empty());
|
||||
sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string());
|
||||
sm.new_source_file(PathBuf::from("empty.rs").into(), String::new());
|
||||
sm.new_source_file(PathBuf::from("blork2.rs").into(), "first line.\nsecond line".to_string());
|
||||
sm.new_source_file(filename(&sm, "blork.rs"), "first line.\nsecond line".to_string());
|
||||
sm.new_source_file(filename(&sm, "empty.rs"), String::new());
|
||||
sm.new_source_file(filename(&sm, "blork2.rs"), "first line.\nsecond line".to_string());
|
||||
sm
|
||||
}
|
||||
|
||||
|
|
@ -59,15 +63,15 @@ fn t3() {
|
|||
let sm = init_source_map();
|
||||
|
||||
let srcfbp1 = sm.lookup_byte_offset(BytePos(23));
|
||||
assert_eq!(srcfbp1.sf.name, PathBuf::from("blork.rs").into());
|
||||
assert_eq!(srcfbp1.sf.name, filename(&sm, "blork.rs"));
|
||||
assert_eq!(srcfbp1.pos, BytePos(23));
|
||||
|
||||
let srcfbp1 = sm.lookup_byte_offset(BytePos(24));
|
||||
assert_eq!(srcfbp1.sf.name, PathBuf::from("empty.rs").into());
|
||||
assert_eq!(srcfbp1.sf.name, filename(&sm, "empty.rs"));
|
||||
assert_eq!(srcfbp1.pos, BytePos(0));
|
||||
|
||||
let srcfbp2 = sm.lookup_byte_offset(BytePos(25));
|
||||
assert_eq!(srcfbp2.sf.name, PathBuf::from("blork2.rs").into());
|
||||
assert_eq!(srcfbp2.sf.name, filename(&sm, "blork2.rs"));
|
||||
assert_eq!(srcfbp2.pos, BytePos(0));
|
||||
}
|
||||
|
||||
|
|
@ -89,12 +93,12 @@ fn t5() {
|
|||
let sm = init_source_map();
|
||||
|
||||
let loc1 = sm.lookup_char_pos(BytePos(22));
|
||||
assert_eq!(loc1.file.name, PathBuf::from("blork.rs").into());
|
||||
assert_eq!(loc1.file.name, filename(&sm, "blork.rs"));
|
||||
assert_eq!(loc1.line, 2);
|
||||
assert_eq!(loc1.col, CharPos(10));
|
||||
|
||||
let loc2 = sm.lookup_char_pos(BytePos(25));
|
||||
assert_eq!(loc2.file.name, PathBuf::from("blork2.rs").into());
|
||||
assert_eq!(loc2.file.name, filename(&sm, "blork2.rs"));
|
||||
assert_eq!(loc2.line, 1);
|
||||
assert_eq!(loc2.col, CharPos(0));
|
||||
}
|
||||
|
|
@ -102,14 +106,8 @@ fn t5() {
|
|||
fn init_source_map_mbc() -> SourceMap {
|
||||
let sm = SourceMap::new(FilePathMapping::empty());
|
||||
// "€" is a three-byte UTF8 char.
|
||||
sm.new_source_file(
|
||||
PathBuf::from("blork.rs").into(),
|
||||
"fir€st €€€€ line.\nsecond line".to_string(),
|
||||
);
|
||||
sm.new_source_file(
|
||||
PathBuf::from("blork2.rs").into(),
|
||||
"first line€€.\n€ second line".to_string(),
|
||||
);
|
||||
sm.new_source_file(filename(&sm, "blork.rs"), "fir€st €€€€ line.\nsecond line".to_string());
|
||||
sm.new_source_file(filename(&sm, "blork2.rs"), "first line€€.\n€ second line".to_string());
|
||||
sm
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +136,7 @@ fn t7() {
|
|||
let span = Span::with_root_ctxt(BytePos(12), BytePos(23));
|
||||
let file_lines = sm.span_to_lines(span).unwrap();
|
||||
|
||||
assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
|
||||
assert_eq!(file_lines.file.name, filename(&sm, "blork.rs"));
|
||||
assert_eq!(file_lines.lines.len(), 1);
|
||||
assert_eq!(file_lines.lines[0].line_index, 1);
|
||||
}
|
||||
|
|
@ -161,7 +159,7 @@ fn span_to_snippet_and_lines_spanning_multiple_lines() {
|
|||
let sm = SourceMap::new(FilePathMapping::empty());
|
||||
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
|
||||
let selection = " \n ~~\n~~~\n~~~~~ \n \n";
|
||||
sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_string());
|
||||
sm.new_source_file(filename(&sm, "blork.rs"), inputtext.to_string());
|
||||
let span = span_from_selection(inputtext, selection);
|
||||
|
||||
// Check that we are extracting the text we thought we were extracting.
|
||||
|
|
@ -204,7 +202,7 @@ fn span_merging_fail() {
|
|||
let inputtext = "bbbb BB\ncc CCC\n";
|
||||
let selection1 = " ~~\n \n";
|
||||
let selection2 = " \n ~~~\n";
|
||||
sm.new_source_file(Path::new("blork.rs").to_owned().into(), inputtext.to_owned());
|
||||
sm.new_source_file(filename(&sm, "blork.rs"), inputtext.to_owned());
|
||||
let span1 = span_from_selection(inputtext, selection1);
|
||||
let span2 = span_from_selection(inputtext, selection2);
|
||||
|
||||
|
|
@ -218,7 +216,7 @@ fn t10() {
|
|||
let unnormalized = "first line.\r\nsecond line";
|
||||
let normalized = "first line.\nsecond line";
|
||||
|
||||
let src_file = sm.new_source_file(PathBuf::from("blork.rs").into(), unnormalized.to_string());
|
||||
let src_file = sm.new_source_file(filename(&sm, "blork.rs"), unnormalized.to_string());
|
||||
|
||||
assert_eq!(src_file.src.as_ref().unwrap().as_ref(), normalized);
|
||||
assert!(
|
||||
|
|
@ -306,8 +304,7 @@ fn path_prefix_remapping() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc/def"), path("foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("foo/src/main.rs"));
|
||||
|
|
@ -318,8 +315,7 @@ fn path_prefix_remapping() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc/def"), path("/foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
|
||||
|
|
@ -330,8 +326,7 @@ fn path_prefix_remapping() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/abc/def"), path("foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("foo/src/main.rs"));
|
||||
|
|
@ -342,8 +337,7 @@ fn path_prefix_remapping() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/abc/def"), path("/foo"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(map_path_prefix(mapping, "/abc/def/src/main.rs"), path_str("/foo/src/main.rs"));
|
||||
|
|
@ -352,171 +346,322 @@ fn path_prefix_remapping() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn path_prefix_remapping_expand_to_absolute() {
|
||||
fn to_real_filename_with_full_scopes() {
|
||||
// "virtual" working directory is relative path
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
let working_directory = path("/foo");
|
||||
let working_directory = RealFileName::Remapped {
|
||||
local_path: Some(working_directory.clone()),
|
||||
virtual_name: mapping.map_prefix(working_directory).0.into_owned(),
|
||||
};
|
||||
let working_directory = mapping.to_real_filename(&RealFileName::empty(), working_directory);
|
||||
|
||||
assert_eq!(working_directory.remapped_path_if_available(), path("FOO"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::DIAGNOSTICS), path("FOO"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::MACRO), path("FOO"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::DEBUGINFO), path("FOO"));
|
||||
|
||||
// Unmapped absolute path
|
||||
// Absolute path
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/foo/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("FOO/src/main.rs") }
|
||||
);
|
||||
|
||||
// Unmapped absolute path with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/bar/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("BAR/src/main.rs") }
|
||||
);
|
||||
|
||||
// Unmapped absolute path that does not match any prefix
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/quux/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::LocalPath(path("/quux/src/main.rs")),
|
||||
);
|
||||
|
||||
// Unmapped relative path
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("FOO/src/main.rs") }
|
||||
);
|
||||
|
||||
// Unmapped relative path with `./`
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("./src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("FOO/src/main.rs") }
|
||||
);
|
||||
|
||||
// Unmapped relative path that does not match any prefix
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("quux/src/main.rs")),
|
||||
&RealFileName::LocalPath(path("/abc")),
|
||||
),
|
||||
RealFileName::LocalPath(path("/abc/quux/src/main.rs")),
|
||||
);
|
||||
|
||||
// Already remapped absolute path
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/foo/src/main.rs")),
|
||||
virtual_name: path("FOO/src/main.rs"),
|
||||
mapping.to_real_filename(&working_directory, path("/foo/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/foo/src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/foo/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("FOO/src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("FOO/src/main.rs")
|
||||
},
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("FOO/src/main.rs") }
|
||||
scopes: RemapPathScopeComponents::all()
|
||||
}
|
||||
);
|
||||
|
||||
// Already remapped absolute path, with unrelated working directory
|
||||
// Absolute path with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs"),
|
||||
mapping.to_real_filename(&working_directory, path("/bar/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/bar/src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/bar/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("BAR/src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("BAR/src/main.rs")
|
||||
},
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("BAR/src/main.rs") }
|
||||
scopes: RemapPathScopeComponents::all()
|
||||
}
|
||||
);
|
||||
|
||||
// Already remapped relative path
|
||||
// Absolute path that does not match any prefix
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") },
|
||||
&working_directory
|
||||
mapping.to_real_filename(&working_directory, path("/quux/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/quux/src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/quux/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("/quux/src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("/quux/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::all()
|
||||
}
|
||||
);
|
||||
|
||||
// Relative path
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/foo/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("FOO/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::all()
|
||||
}
|
||||
);
|
||||
|
||||
// Relative path with `./`
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("./src/main.rs"),),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("./src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/foo/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("./src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("FOO/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::all()
|
||||
}
|
||||
);
|
||||
|
||||
// Relative path that does not match any prefix
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(
|
||||
&mapping.to_real_filename(&RealFileName::empty(), path("/abc")),
|
||||
path("quux/src/main.rs"),
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") }
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("quux/src/main.rs"),
|
||||
working_directory: path("/abc"),
|
||||
embeddable_name: path("/abc/quux/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("quux/src/main.rs"),
|
||||
working_directory: path("/abc"),
|
||||
embeddable_name: path("/abc/quux/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::empty()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_prefix_remapping_expand_to_absolute_and_local() {
|
||||
fn to_real_filename_with_mixed_scopes() {
|
||||
// "virtual" working directory is relative path
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/foo"), path("FOO")), (path("/bar"), path("BAR"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::LocalAndRemapped,
|
||||
RemapPathScopeComponents::OBJECT,
|
||||
);
|
||||
let working_directory = path("/foo");
|
||||
let working_directory = RealFileName::Remapped {
|
||||
local_path: Some(working_directory.clone()),
|
||||
virtual_name: mapping.map_prefix(working_directory).0.into_owned(),
|
||||
};
|
||||
let working_directory = mapping.to_real_filename(&RealFileName::empty(), working_directory);
|
||||
|
||||
assert_eq!(working_directory.remapped_path_if_available(), path("FOO"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::DIAGNOSTICS), path("/foo"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::MACRO), path("FOO"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::DEBUGINFO), path("FOO"));
|
||||
|
||||
// Unmapped absolute path
|
||||
// Absolute path
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/foo/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/foo/src/main.rs")),
|
||||
virtual_name: path("FOO/src/main.rs")
|
||||
}
|
||||
);
|
||||
|
||||
// Unmapped absolute path with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::LocalPath(path("/bar/src/main.rs")),
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs")
|
||||
}
|
||||
);
|
||||
|
||||
// Already remapped absolute path, with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs"),
|
||||
mapping.to_real_filename(&working_directory, path("/foo/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/foo/src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/foo/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("FOO/src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("FOO/src/main.rs")
|
||||
},
|
||||
&working_directory
|
||||
),
|
||||
RealFileName::Remapped {
|
||||
local_path: Some(path("/bar/src/main.rs")),
|
||||
virtual_name: path("BAR/src/main.rs")
|
||||
scopes: RemapPathScopeComponents::OBJECT
|
||||
}
|
||||
);
|
||||
|
||||
// Already remapped relative path
|
||||
// Absolute path with unrelated working directory
|
||||
assert_eq!(
|
||||
mapping.to_embeddable_absolute_path(
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") },
|
||||
&working_directory
|
||||
mapping.to_real_filename(&working_directory, path("/bar/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/bar/src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/bar/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("BAR/src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("BAR/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::OBJECT
|
||||
}
|
||||
);
|
||||
|
||||
// Absolute path without remapping
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("/quux/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/quux/src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/quux/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("/quux/src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("/quux/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::OBJECT
|
||||
}
|
||||
);
|
||||
|
||||
// Relative path
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("src/main.rs"),
|
||||
working_directory: path("/foo"),
|
||||
embeddable_name: path("/foo/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("src/main.rs"),
|
||||
working_directory: path("FOO"),
|
||||
embeddable_name: path("FOO/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::OBJECT
|
||||
}
|
||||
);
|
||||
|
||||
// Relative path that does not match any prefix
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(
|
||||
&mapping.to_real_filename(&RealFileName::empty(), path("/abc")),
|
||||
path("quux/src/main.rs"),
|
||||
),
|
||||
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") }
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("quux/src/main.rs"),
|
||||
working_directory: path("/abc"),
|
||||
embeddable_name: path("/abc/quux/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("quux/src/main.rs"),
|
||||
working_directory: path("/abc"),
|
||||
embeddable_name: path("/abc/quux/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::empty()
|
||||
}
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn to_real_filename_without_remapped_cwd() {
|
||||
// "virtual" working directory is relative path
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("/foo"), path("FOO")), (path("/cwd/bar"), path("CWDBAR"))],
|
||||
RemapPathScopeComponents::OBJECT,
|
||||
);
|
||||
let working_directory = path("/cwd");
|
||||
let working_directory = mapping.to_real_filename(&RealFileName::empty(), working_directory);
|
||||
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::DIAGNOSTICS), path("/cwd"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::MACRO), path("/cwd"));
|
||||
assert_eq!(working_directory.path(RemapPathScopeComponents::DEBUGINFO), path("/cwd"));
|
||||
|
||||
// Absolute path
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("/foo/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/foo/src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("/foo/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("FOO/src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("FOO/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::OBJECT
|
||||
}
|
||||
);
|
||||
|
||||
// Absolute path with unrelated root
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("/bar/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/bar/src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("/bar/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("/bar/src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("/bar/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::empty()
|
||||
}
|
||||
);
|
||||
|
||||
// Absolute path with cwd
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("/cwd/bar/src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("/cwd/bar/src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("/cwd/bar/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("CWDBAR/src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("CWDBAR/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::OBJECT
|
||||
}
|
||||
);
|
||||
|
||||
// Relative path
|
||||
assert_eq!(
|
||||
mapping.to_real_filename(&working_directory, path("src/main.rs")),
|
||||
RealFileName {
|
||||
local: Some(InnerRealFileName {
|
||||
name: path("src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("/cwd/src/main.rs")
|
||||
}),
|
||||
maybe_remapped: InnerRealFileName {
|
||||
name: path("src/main.rs"),
|
||||
working_directory: path("/cwd"),
|
||||
embeddable_name: path("/cwd/src/main.rs")
|
||||
},
|
||||
scopes: RemapPathScopeComponents::empty()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -526,8 +671,7 @@ fn path_prefix_remapping_reverse() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/")), (path("def"), path("."))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(reverse_map_prefix(mapping, "/hello.rs"), None);
|
||||
|
|
@ -538,8 +682,7 @@ fn path_prefix_remapping_reverse() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/redacted")), (path("def"), path("/redacted"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(reverse_map_prefix(mapping, "/redacted/hello.rs"), None);
|
||||
|
|
@ -549,8 +692,7 @@ fn path_prefix_remapping_reverse() {
|
|||
{
|
||||
let mapping = &FilePathMapping::new(
|
||||
vec![(path("abc"), path("/redacted")), (path("def/ghi"), path("/fake/dir"))],
|
||||
FileNameDisplayPreference::Remapped,
|
||||
FileNameEmbeddablePreference::RemappedOnly,
|
||||
RemapPathScopeComponents::all(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
|
|
@ -567,7 +709,7 @@ fn path_prefix_remapping_reverse() {
|
|||
#[test]
|
||||
fn test_next_point() {
|
||||
let sm = SourceMap::new(FilePathMapping::empty());
|
||||
sm.new_source_file(PathBuf::from("example.rs").into(), "a…b".to_string());
|
||||
sm.new_source_file(filename(&sm, "example.rs"), "a…b".to_string());
|
||||
|
||||
// Dummy spans don't advance.
|
||||
let span = DUMMY_SP;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ fn rustc_with_common_args() -> Rustc {
|
|||
|
||||
fn main() {
|
||||
rustc_with_common_args()
|
||||
.input("foo-v1.rs")
|
||||
.input(cwd().join("foo-v1.rs"))
|
||||
.crate_type("rlib")
|
||||
.crate_name("foo")
|
||||
.extra_filename("-v1")
|
||||
|
|
@ -19,7 +19,7 @@ fn main() {
|
|||
.run();
|
||||
|
||||
rustc_with_common_args()
|
||||
.input("foo-v2.rs")
|
||||
.input(cwd().join("foo-v2.rs"))
|
||||
.crate_type("rlib")
|
||||
.crate_name("foo")
|
||||
.extra_filename("-v2")
|
||||
|
|
@ -27,7 +27,7 @@ fn main() {
|
|||
.run();
|
||||
|
||||
rustc_with_common_args()
|
||||
.input("re-export-foo.rs")
|
||||
.input(cwd().join("re-export-foo.rs"))
|
||||
.crate_type("rlib")
|
||||
.extern_("foo", rust_lib_name("foo-v2"))
|
||||
.run();
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ help: the trait `std::fmt::Display` is not implemented for `A`
|
|||
LL | struct A;
|
||||
| ^^^^^^^^
|
||||
note: required by a bound in `Trait`
|
||||
--> $DIR/auxiliary/trait-diag.rs:LL:COL
|
||||
--> remapped/errors/auxiliary/trait-diag.rs:LL:COL
|
||||
|
|
||||
LL | pub trait Trait: std::fmt::Display {}
|
||||
| ^^^^^^^^^^^^^^^^^ required by this bound in `Trait`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue