Auto merge of #149709 - Urgau:overhaul-filenames, r=davidtwco
Overhaul filename handling for cross-compiler consistency This PR overhauls the way we handle filenames in the compiler and `rmeta` in order to achieve achieve cross-compiler consistency (ie. having the same path no matter if the filename was created in the current compiler session or is coming from `rmeta`). This is required as some parts of the compiler rely on consistent paths for the soundness of generated code (see rust-lang/rust#148328). In order to achieved consistency multiple steps are being taken by this PR: - by making `RealFileName` immutable - by only having `SourceMap::to_real_filename` create `RealFileName` - currently `RealFileName` can be created from any `Path` and are remapped afterwards, which creates consistency issue - by also making `RealFileName` holds it's working directory, embeddable name and the remapped scopes - this removes the need for a `Session`, to know the current(!) scopes and cwd, which is invalid as they may not be equal to the scopes used when creating the filename 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. This PR is split-up in multiple commits (unfortunately not atomic), but should help review the changes. Unblocks https://github.com/rust-lang/rust/pull/147611 Fixes https://github.com/rust-lang/rust/issues/148328
This commit is contained in:
commit
8188f6c808
60 changed files with 1129 additions and 924 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",
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
|
||||
let (name, arg) = match locations {
|
||||
Locations::All(span) => {
|
||||
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
|
||||
("All", tcx.sess.source_map().span_to_diagnostic_string(*span))
|
||||
}
|
||||
Locations::Single(loc) => ("Single", format!("{loc:?}")),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,10 @@ use std::path::{Component, Path};
|
|||
use cranelift_codegen::MachSrcLoc;
|
||||
use cranelift_codegen::binemit::CodeOffset;
|
||||
use gimli::write::{FileId, FileInfo, LineProgram, LineString, LineStringTable};
|
||||
use rustc_span::{FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHashAlgorithm, hygiene};
|
||||
use rustc_span::{
|
||||
FileName, Pos, RemapPathScopeComponents, SourceFile, SourceFileAndLine,
|
||||
SourceFileHashAlgorithm, hygiene,
|
||||
};
|
||||
|
||||
use crate::debuginfo::FunctionDebugContext;
|
||||
use crate::debuginfo::emit::address_for_func;
|
||||
|
|
@ -95,7 +98,7 @@ impl DebugContext {
|
|||
match &source_file.name {
|
||||
FileName::Real(path) => {
|
||||
let (dir_path, file_name) =
|
||||
split_path_dir_and_file(path.to_path(self.filename_display_preference));
|
||||
split_path_dir_and_file(path.path(RemapPathScopeComponents::DEBUGINFO));
|
||||
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
|
||||
let file_name = osstr_as_utf8_bytes(file_name);
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use rustc_hir::def::DefKind;
|
|||
use rustc_hir::def_id::DefIdMap;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::{FileNameDisplayPreference, SourceFileHash, StableSourceFileId};
|
||||
use rustc_span::{RemapPathScopeComponents, SourceFileHash, StableSourceFileId};
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
pub(crate) use self::emit::{DebugReloc, DebugRelocName};
|
||||
|
|
@ -44,7 +44,6 @@ pub(crate) struct DebugContext {
|
|||
namespace_map: DefIdMap<UnitEntryId>,
|
||||
array_size_type: Option<UnitEntryId>,
|
||||
|
||||
filename_display_preference: FileNameDisplayPreference,
|
||||
embed_source: bool,
|
||||
}
|
||||
|
||||
|
|
@ -102,18 +101,18 @@ impl DebugContext {
|
|||
|
||||
let mut dwarf = DwarfUnit::new(encoding);
|
||||
|
||||
use rustc_session::config::RemapPathScopeComponents;
|
||||
|
||||
let filename_display_preference =
|
||||
tcx.sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
|
||||
|
||||
let producer = producer(tcx.sess);
|
||||
let comp_dir =
|
||||
tcx.sess.opts.working_dir.to_string_lossy(filename_display_preference).to_string();
|
||||
let comp_dir = tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.working_dir()
|
||||
.path(RemapPathScopeComponents::DEBUGINFO)
|
||||
.to_string_lossy();
|
||||
|
||||
let (name, file_info) = match tcx.sess.local_crate_source_file() {
|
||||
Some(path) => {
|
||||
let name = path.to_string_lossy(filename_display_preference).to_string();
|
||||
let name =
|
||||
path.path(RemapPathScopeComponents::DEBUGINFO).to_string_lossy().into_owned();
|
||||
(name, None)
|
||||
}
|
||||
None => (tcx.crate_name(LOCAL_CRATE).to_string(), None),
|
||||
|
|
@ -137,7 +136,7 @@ impl DebugContext {
|
|||
|
||||
{
|
||||
let name = dwarf.strings.add(format!("{name}/@/{cgu_name}"));
|
||||
let comp_dir = dwarf.strings.add(comp_dir);
|
||||
let comp_dir = dwarf.strings.add(&*comp_dir);
|
||||
|
||||
let root = dwarf.unit.root();
|
||||
let root = dwarf.unit.get_mut(root);
|
||||
|
|
@ -180,7 +179,6 @@ impl DebugContext {
|
|||
stack_pointer_register,
|
||||
namespace_map: DefIdMap::default(),
|
||||
array_size_type,
|
||||
filename_display_preference,
|
||||
embed_source,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,29 +297,11 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
let pos = span.lo();
|
||||
let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
|
||||
match file.name {
|
||||
rustc_span::FileName::Real(ref name) => match *name {
|
||||
rustc_span::RealFileName::LocalPath(ref name) => {
|
||||
if let Some(name) = name.to_str() {
|
||||
self.context.new_location(name, line as i32, col as i32)
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
}
|
||||
rustc_span::RealFileName::Remapped {
|
||||
ref local_path,
|
||||
virtual_name: ref _unused,
|
||||
} => {
|
||||
if let Some(name) = local_path.as_ref() {
|
||||
if let Some(name) = name.to_str() {
|
||||
self.context.new_location(name, line as i32, col as i32)
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
} else {
|
||||
Location::null()
|
||||
}
|
||||
}
|
||||
},
|
||||
rustc_span::FileName::Real(ref name) => self.context.new_location(
|
||||
name.path(rustc_span::RemapPathScopeComponents::DEBUGINFO).to_string_lossy(),
|
||||
line as i32,
|
||||
col as i32,
|
||||
),
|
||||
_ => Location::null(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -138,10 +138,7 @@ pub(crate) fn update_macro_stats(
|
|||
if false {
|
||||
let name = ExpnKind::Macro(macro_kind, name).descr();
|
||||
let crate_name = &ecx.ecfg.crate_name;
|
||||
let span = ecx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_string(span, rustc_span::FileNameDisplayPreference::Local);
|
||||
let span = ecx.sess.source_map().span_to_diagnostic_string(span);
|
||||
eprint!(
|
||||
"\
|
||||
-------------------------------\n\
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -504,7 +504,7 @@ fn write_scope_tree(
|
|||
"{0:1$} // at {2}",
|
||||
indented_header,
|
||||
ALIGN,
|
||||
tcx.sess.source_map().span_to_embeddable_string(span),
|
||||
tcx.sess.source_map().span_to_diagnostic_string(span),
|
||||
)?;
|
||||
} else {
|
||||
writeln!(w, "{indented_header}")?;
|
||||
|
|
@ -688,7 +688,7 @@ fn write_user_type_annotations(
|
|||
"| {:?}: user_ty: {}, span: {}, inferred_ty: {}",
|
||||
index.index(),
|
||||
annotation.user_ty,
|
||||
tcx.sess.source_map().span_to_embeddable_string(annotation.span),
|
||||
tcx.sess.source_map().span_to_diagnostic_string(annotation.span),
|
||||
with_no_trimmed_paths!(format!("{}", annotation.inferred_ty)),
|
||||
)?;
|
||||
}
|
||||
|
|
@ -1420,7 +1420,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
|||
self.push("mir::ConstOperand");
|
||||
self.push(&format!(
|
||||
"+ span: {}",
|
||||
self.tcx.sess.source_map().span_to_embeddable_string(*span)
|
||||
self.tcx.sess.source_map().span_to_diagnostic_string(*span)
|
||||
));
|
||||
if let Some(user_ty) = user_ty {
|
||||
self.push(&format!("+ user_ty: {user_ty:?}"));
|
||||
|
|
@ -1503,7 +1503,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
|
|||
}
|
||||
|
||||
fn comment(tcx: TyCtxt<'_>, SourceInfo { span, scope }: SourceInfo) -> String {
|
||||
let location = tcx.sess.source_map().span_to_embeddable_string(span);
|
||||
let location = tcx.sess.source_map().span_to_diagnostic_string(span);
|
||||
format!("scope {} at {}", scope.index(), location,)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
|
|||
.unwrap_or_else(|e| format!("Failed {e:?}"));
|
||||
|
||||
let closure_span = tcx.def_span(closure_def_id);
|
||||
let src_file = tcx.sess.source_map().span_to_filename(closure_span);
|
||||
let src_file = tcx.sess.source_map().span_to_diagnostic_string(closure_span);
|
||||
let line_nos = tcx
|
||||
.sess
|
||||
.source_map()
|
||||
|
|
@ -57,14 +57,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In
|
|||
.map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last()))
|
||||
.unwrap_or_else(|e| format!("{e:?}"));
|
||||
|
||||
if let Err(e) = writeln!(
|
||||
file,
|
||||
"{}, {}, {}, {:?}",
|
||||
old_size,
|
||||
new_size,
|
||||
src_file.prefer_local(),
|
||||
line_nos
|
||||
) {
|
||||
if let Err(e) = writeln!(file, "{}, {}, {}, {:?}", old_size, new_size, src_file, line_nos) {
|
||||
eprintln!("Error writing to file {e}")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, RealFileName, 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,25 +1353,22 @@ 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 {
|
||||
fn default() -> Options {
|
||||
let unstable_opts = UnstableOptions::default();
|
||||
|
||||
// FIXME(Urgau): This is a hack that ideally shouldn't exist, but rustdoc
|
||||
// currently uses this `Default` implementation, so we have no choice but
|
||||
// to create a default working directory.
|
||||
let working_dir = {
|
||||
let working_dir = std::env::current_dir().unwrap();
|
||||
let file_mapping = file_path_mapping(Vec::new(), &unstable_opts);
|
||||
file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
|
||||
};
|
||||
|
||||
Options {
|
||||
assert_incr_state: None,
|
||||
crate_types: Vec::new(),
|
||||
|
|
@ -1404,7 +1385,7 @@ impl Default for Options {
|
|||
test: false,
|
||||
incremental: None,
|
||||
untracked_state_hash: Default::default(),
|
||||
unstable_opts: Default::default(),
|
||||
unstable_opts,
|
||||
prints: Vec::new(),
|
||||
cg: Default::default(),
|
||||
error_format: ErrorOutputType::default(),
|
||||
|
|
@ -1428,7 +1409,7 @@ impl Default for Options {
|
|||
json_unused_externs: JsonUnusedExterns::No,
|
||||
json_future_incompat: false,
|
||||
pretty: None,
|
||||
working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
|
||||
working_dir,
|
||||
color: ColorConfig::Auto,
|
||||
logical_env: FxIndexMap::default(),
|
||||
verbose: false,
|
||||
|
|
@ -2782,12 +2763,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
|||
.collect()
|
||||
};
|
||||
|
||||
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
|
||||
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
|
||||
});
|
||||
// Ideally we would use `SourceMap::working_dir` instead, but we don't have access to it
|
||||
// so we manually create the potentially-remapped working directory
|
||||
let working_dir = {
|
||||
let working_dir = std::env::current_dir().unwrap_or_else(|e| {
|
||||
early_dcx.early_fatal(format!("Current directory is invalid: {e}"));
|
||||
});
|
||||
|
||||
let file_mapping = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
|
||||
let working_dir = file_mapping.to_real_filename(&working_dir);
|
||||
let file_mapping = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
|
||||
file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
|
||||
};
|
||||
|
||||
let verbose = matches.opt_present("verbose") || unstable_opts.verbose_internals;
|
||||
|
||||
|
|
@ -3115,8 +3100,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 +3113,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::{RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm};
|
||||
use rustc_target::spec::{
|
||||
CodeModel, FramePointer, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy,
|
||||
RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility,
|
||||
|
|
@ -492,7 +492,9 @@ top_level_options!(
|
|||
pretty: Option<PpMode> [UNTRACKED],
|
||||
|
||||
/// The (potentially remapped) working directory
|
||||
#[rustc_lint_opt_deny_field_access("use `SourceMap::working_dir` instead of this field")]
|
||||
working_dir: RealFileName [TRACKED],
|
||||
|
||||
color: ColorConfig [UNTRACKED],
|
||||
|
||||
verbose: bool [TRACKED_NO_CRATE_HASH],
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@ pub trait FileLoader {
|
|||
/// Read the contents of a potentially non-UTF-8 file into memory.
|
||||
/// We don't normalize binary files, so we can start in an Arc.
|
||||
fn read_binary_file(&self, path: &Path) -> io::Result<Arc<[u8]>>;
|
||||
|
||||
/// Current working directory
|
||||
fn current_directory(&self) -> io::Result<PathBuf>;
|
||||
}
|
||||
|
||||
/// A FileLoader that uses std::fs to load real files.
|
||||
|
|
@ -170,6 +173,10 @@ impl FileLoader for RealFileLoader {
|
|||
file.read_to_end(&mut bytes)?;
|
||||
Ok(bytes.into())
|
||||
}
|
||||
|
||||
fn current_directory(&self) -> io::Result<PathBuf> {
|
||||
std::env::current_dir()
|
||||
}
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
|
|
@ -198,6 +205,9 @@ pub struct SourceMap {
|
|||
// `--remap-path-prefix` to all `SourceFile`s allocated within this `SourceMap`.
|
||||
path_mapping: FilePathMapping,
|
||||
|
||||
/// Current working directory
|
||||
working_dir: RealFileName,
|
||||
|
||||
/// The algorithm used for hashing the contents of each source file.
|
||||
hash_kind: SourceFileHashAlgorithm,
|
||||
|
||||
|
|
@ -221,8 +231,14 @@ impl SourceMap {
|
|||
pub fn with_inputs(
|
||||
SourceMapInputs { file_loader, path_mapping, hash_kind, checksum_hash_kind }: SourceMapInputs,
|
||||
) -> SourceMap {
|
||||
let cwd = file_loader
|
||||
.current_directory()
|
||||
.expect("expecting a current working directory to exist");
|
||||
let working_dir = path_mapping.to_real_filename(&RealFileName::empty(), &cwd);
|
||||
debug!(?working_dir);
|
||||
SourceMap {
|
||||
files: Default::default(),
|
||||
working_dir,
|
||||
file_loader: IntoDynSyncSend(file_loader),
|
||||
path_mapping,
|
||||
hash_kind,
|
||||
|
|
@ -234,13 +250,17 @@ impl SourceMap {
|
|||
&self.path_mapping
|
||||
}
|
||||
|
||||
pub fn working_dir(&self) -> &RealFileName {
|
||||
&self.working_dir
|
||||
}
|
||||
|
||||
pub fn file_exists(&self, path: &Path) -> bool {
|
||||
self.file_loader.file_exists(path)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
|
|
@ -257,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(
|
||||
|
|
@ -325,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) {
|
||||
|
|
@ -424,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}") }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -459,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 {
|
||||
|
|
@ -476,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 {
|
||||
|
|
@ -1025,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));
|
||||
}
|
||||
}
|
||||
|
|
@ -1060,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())
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1115,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.
|
||||
|
|
@ -1189,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;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ use rustc_resolve::rustdoc::{
|
|||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::MacroKind;
|
||||
use rustc_span::symbol::{Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, FileName, Loc};
|
||||
use rustc_span::{DUMMY_SP, FileName, Loc, RemapPathScopeComponents};
|
||||
use tracing::{debug, trace};
|
||||
use {rustc_ast as ast, rustc_hir as hir};
|
||||
|
||||
|
|
@ -148,10 +148,17 @@ impl ExternalCrate {
|
|||
|
||||
pub(crate) fn src_root(&self, tcx: TyCtxt<'_>) -> PathBuf {
|
||||
match self.src(tcx) {
|
||||
FileName::Real(ref p) => match p.local_path_if_available().parent() {
|
||||
Some(p) => p.to_path_buf(),
|
||||
None => PathBuf::new(),
|
||||
},
|
||||
FileName::Real(ref p) => {
|
||||
match p
|
||||
.local_path()
|
||||
.or(Some(p.path(RemapPathScopeComponents::MACRO)))
|
||||
.unwrap()
|
||||
.parent()
|
||||
{
|
||||
Some(p) => p.to_path_buf(),
|
||||
None => PathBuf::new(),
|
||||
}
|
||||
}
|
||||
_ => PathBuf::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_session::config::{self, CrateType, ErrorOutputType, Input};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{FileName, Span};
|
||||
use rustc_span::{FileName, RemapPathScopeComponents, Span};
|
||||
use rustc_target::spec::{Target, TargetTuple};
|
||||
use tempfile::{Builder as TempFileBuilder, TempDir};
|
||||
use tracing::debug;
|
||||
|
|
@ -971,14 +971,7 @@ impl ScrapedDocTest {
|
|||
}
|
||||
fn path(&self) -> PathBuf {
|
||||
match &self.filename {
|
||||
FileName::Real(path) => {
|
||||
if let Some(local_path) = path.local_path() {
|
||||
local_path.to_path_buf()
|
||||
} else {
|
||||
// Somehow we got the filename from the metadata of another crate, should never happen
|
||||
unreachable!("doctest from a different crate");
|
||||
}
|
||||
}
|
||||
FileName::Real(name) => name.path(RemapPathScopeComponents::DIAGNOSTICS).to_path_buf(),
|
||||
_ => PathBuf::from(r"doctest.rs"),
|
||||
}
|
||||
}
|
||||
|
|
@ -1025,7 +1018,7 @@ impl CreateRunnableDocTests {
|
|||
// For example `module/file.rs` would become `module_file_rs`
|
||||
let file = scraped_test
|
||||
.filename
|
||||
.prefer_local()
|
||||
.prefer_local_unconditionally()
|
||||
.to_string_lossy()
|
||||
.chars()
|
||||
.map(|c| if c.is_ascii_alphanumeric() { c } else { '_' })
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ use std::sync::{Arc, Mutex};
|
|||
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_session::config::Input;
|
||||
use rustc_span::{DUMMY_SP, FileName};
|
||||
use rustc_span::source_map::FilePathMapping;
|
||||
use rustc_span::{DUMMY_SP, FileName, RealFileName};
|
||||
use tempfile::tempdir;
|
||||
|
||||
use super::{
|
||||
|
|
@ -106,8 +107,12 @@ pub(crate) fn test(input: &Input, options: Options, dcx: DiagCtxtHandle<'_>) ->
|
|||
cur_path: vec![],
|
||||
filename: input
|
||||
.opt_path()
|
||||
.map(ToOwned::to_owned)
|
||||
.map(FileName::from)
|
||||
.map(|f| {
|
||||
// We don't have access to a rustc Session so let's just use a dummy
|
||||
// filepath mapping to create a real filename.
|
||||
let file_mapping = FilePathMapping::empty();
|
||||
FileName::Real(file_mapping.to_real_filename(&RealFileName::empty(), f))
|
||||
})
|
||||
.unwrap_or(FileName::Custom("input".to_owned())),
|
||||
};
|
||||
let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! Doctest functionality used only for doctests in `.rs` source files.
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::env;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -31,15 +30,6 @@ struct RustCollector {
|
|||
impl RustCollector {
|
||||
fn get_filename(&self) -> FileName {
|
||||
let filename = self.source_map.span_to_filename(self.position);
|
||||
if let FileName::Real(ref filename) = filename {
|
||||
let path = filename.remapped_path_if_available();
|
||||
// Strip the cwd prefix from the path. This will likely exist if
|
||||
// the path was not remapped.
|
||||
let path = env::current_dir()
|
||||
.map(|cur_dir| path.strip_prefix(&cur_dir).unwrap_or(path))
|
||||
.unwrap_or(path);
|
||||
return path.to_owned().into();
|
||||
}
|
||||
filename
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -365,7 +365,7 @@ impl<'tcx> Context<'tcx> {
|
|||
|
||||
// We can safely ignore synthetic `SourceFile`s.
|
||||
let file = match span.filename(self.sess()) {
|
||||
FileName::Real(ref path) => path.local_path_if_available().to_path_buf(),
|
||||
FileName::Real(ref path) => path.local_path()?.to_path_buf(),
|
||||
_ => return None,
|
||||
};
|
||||
let file = &file;
|
||||
|
|
@ -499,7 +499,7 @@ impl<'tcx> Context<'tcx> {
|
|||
} = options;
|
||||
|
||||
let src_root = match krate.src(tcx) {
|
||||
FileName::Real(ref p) => match p.local_path_if_available().parent() {
|
||||
FileName::Real(ref p) => match p.local_path().map(|p| p.parent()).flatten() {
|
||||
Some(p) => p.to_path_buf(),
|
||||
None => PathBuf::new(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ use rustc_hir::{ConstStability, Mutability, RustcVersion, StabilityLevel, Stable
|
|||
use rustc_middle::ty::print::PrintTraitRefExt;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::symbol::{Symbol, sym};
|
||||
use rustc_span::{BytePos, DUMMY_SP, FileName, RealFileName};
|
||||
use rustc_span::{BytePos, DUMMY_SP, FileName};
|
||||
use tracing::{debug, info};
|
||||
|
||||
pub(crate) use self::context::*;
|
||||
|
|
@ -2772,7 +2772,7 @@ fn render_call_locations<W: fmt::Write>(
|
|||
files
|
||||
.iter()
|
||||
.find(|file| match &file.name {
|
||||
FileName::Real(RealFileName::LocalPath(other_path)) => rel_path == other_path,
|
||||
FileName::Real(real) => real.local_path().map_or(false, |p| p == rel_path),
|
||||
_ => false,
|
||||
})
|
||||
.map(|file| file.start_pos)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
|||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName};
|
||||
use rustc_span::{FileName, RealFileName, RemapPathScopeComponents};
|
||||
use tracing::info;
|
||||
|
||||
use super::render::Context;
|
||||
|
|
@ -148,7 +148,10 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
|
|||
span,
|
||||
format!(
|
||||
"failed to render source code for `{filename}`: {e}",
|
||||
filename = filename.to_string_lossy(FileNameDisplayPreference::Local),
|
||||
filename = filename
|
||||
.path(RemapPathScopeComponents::DIAGNOSTICS)
|
||||
.to_string_lossy()
|
||||
.into_owned(),
|
||||
),
|
||||
);
|
||||
false
|
||||
|
|
@ -224,10 +227,7 @@ impl SourceCollector<'_, '_> {
|
|||
cur.push(&fname);
|
||||
|
||||
let title = format!("{} - source", src_fname.to_string_lossy());
|
||||
let desc = format!(
|
||||
"Source of the Rust file `{}`.",
|
||||
file.to_string_lossy(FileNameDisplayPreference::Remapped)
|
||||
);
|
||||
let desc = format!("Source of the Rust file `{}`.", p.to_string_lossy());
|
||||
let page = layout::Page {
|
||||
title: &title,
|
||||
short_title: &src_fname.to_string_lossy(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_hir as hir;
|
|||
use rustc_lint::builtin::MISSING_DOCS;
|
||||
use rustc_middle::lint::{LevelAndSource, LintLevelSource};
|
||||
use rustc_session::lint;
|
||||
use rustc_span::FileName;
|
||||
use rustc_span::{FileName, RemapPathScopeComponents};
|
||||
use serde::Serialize;
|
||||
use tracing::debug;
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ impl CoverageCalculator<'_, '_> {
|
|||
&self
|
||||
.items
|
||||
.iter()
|
||||
.map(|(k, v)| (k.prefer_local().to_string(), v))
|
||||
.map(|(k, v)| (k.prefer_local_unconditionally().to_string(), v))
|
||||
.collect::<BTreeMap<String, &ItemCount>>(),
|
||||
)
|
||||
.expect("failed to convert JSON data to string")
|
||||
|
|
@ -167,7 +167,11 @@ impl CoverageCalculator<'_, '_> {
|
|||
for (file, &count) in &self.items {
|
||||
if let Some(percentage) = count.percentage() {
|
||||
print_table_record(
|
||||
&limit_filename_len(file.prefer_local().to_string_lossy().into()),
|
||||
&limit_filename_len(
|
||||
file.display(RemapPathScopeComponents::DIAGNOSTICS)
|
||||
.to_string_lossy()
|
||||
.into(),
|
||||
),
|
||||
count,
|
||||
percentage,
|
||||
count.examples_percentage().unwrap_or(0.),
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub struct ModStyle {
|
|||
|
||||
impl EarlyLintPass for ModStyle {
|
||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, _: &ast::Crate) {
|
||||
self.working_dir = cx.sess().opts.working_dir.local_path().map(Path::to_path_buf);
|
||||
self.working_dir = cx.sess().source_map().working_dir().local_path().map(Path::to_path_buf);
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc_middle::ty::TyCtxt;
|
|||
use rustc_session::Session;
|
||||
use rustc_span::source_map::{SourceMap, original_sp};
|
||||
use rustc_span::{
|
||||
BytePos, DUMMY_SP, DesugaringKind, FileNameDisplayPreference, Pos, RelativeBytePos, SourceFile, SourceFileAndLine,
|
||||
BytePos, DUMMY_SP, DesugaringKind, Pos, RelativeBytePos, SourceFile, SourceFileAndLine,
|
||||
Span, SpanData, SyntaxContext, hygiene,
|
||||
};
|
||||
use std::borrow::Cow;
|
||||
|
|
@ -268,7 +268,7 @@ fn map_range(
|
|||
debug_assert!(
|
||||
range.start <= text.len() && range.end <= text.len(),
|
||||
"Range `{range:?}` is outside the source file (file `{}`, length `{}`)",
|
||||
src.sf.name.display(FileNameDisplayPreference::Local),
|
||||
src.sf.name.prefer_local_unconditionally(),
|
||||
text.len(),
|
||||
);
|
||||
debug_assert!(range.start <= range.end, "Range `{range:?}` has overlapping bounds");
|
||||
|
|
|
|||
|
|
@ -627,7 +627,7 @@ pub fn report_msg<'tcx>(
|
|||
err.subdiagnostic(frame_info.as_note(machine.tcx));
|
||||
} else {
|
||||
let sm = sess.source_map();
|
||||
let span = sm.span_to_embeddable_string(frame_info.span);
|
||||
let span = sm.span_to_diagnostic_string(frame_info.span);
|
||||
err.note(format!("{frame_info} at {span}"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,15 @@ pub enum FileName {
|
|||
impl From<rustc_span::FileName> for FileName {
|
||||
fn from(name: rustc_span::FileName) -> FileName {
|
||||
match name {
|
||||
rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(p)) => FileName::Real(p),
|
||||
rustc_span::FileName::Real(real) => {
|
||||
if let Some(p) = real.into_local_path() {
|
||||
FileName::Real(p)
|
||||
} else {
|
||||
// rustfmt does not remap filenames; the local path should always
|
||||
// remain accessible.
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
rustc_span::FileName::Custom(ref f) if f == "stdin" => FileName::Stdin,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,19 +58,19 @@ impl Emitter for SilentOnIgnoredFilesEmitter {
|
|||
}
|
||||
if let Some(primary_span) = &diag.span.primary_span() {
|
||||
let file_name = self.source_map.span_to_filename(*primary_span);
|
||||
if let rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(ref path)) =
|
||||
file_name
|
||||
{
|
||||
if self
|
||||
.ignore_path_set
|
||||
.is_match(&FileName::Real(path.to_path_buf()))
|
||||
{
|
||||
if !self.has_non_ignorable_parser_errors {
|
||||
self.can_reset.store(true, Ordering::Release);
|
||||
if let rustc_span::FileName::Real(real) = file_name {
|
||||
if let Some(path) = real.local_path() {
|
||||
if self
|
||||
.ignore_path_set
|
||||
.is_match(&FileName::Real(path.to_path_buf()))
|
||||
{
|
||||
if !self.has_non_ignorable_parser_errors {
|
||||
self.can_reset.store(true, Ordering::Release);
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
self.handle_non_ignoreable_error(diag, registry);
|
||||
}
|
||||
|
|
@ -181,7 +181,10 @@ impl ParseSess {
|
|||
self.raw_psess
|
||||
.source_map()
|
||||
.get_source_file(&rustc_span::FileName::Real(
|
||||
rustc_span::RealFileName::LocalPath(path.to_path_buf()),
|
||||
self.raw_psess
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_real_filename(self.raw_psess.source_map().working_dir(), path),
|
||||
))
|
||||
.is_some()
|
||||
}
|
||||
|
|
@ -246,10 +249,20 @@ impl ParseSess {
|
|||
)
|
||||
}
|
||||
|
||||
pub(crate) fn get_original_snippet(&self, file_name: &FileName) -> Option<Arc<String>> {
|
||||
pub(crate) fn get_original_snippet(&self, filename: &FileName) -> Option<Arc<String>> {
|
||||
let rustc_filename = match filename {
|
||||
FileName::Real(path) => rustc_span::FileName::Real(
|
||||
self.raw_psess
|
||||
.source_map()
|
||||
.path_mapping()
|
||||
.to_real_filename(self.raw_psess.source_map().working_dir(), path),
|
||||
),
|
||||
FileName::Stdin => rustc_span::FileName::Custom("stdin".to_owned()),
|
||||
};
|
||||
|
||||
self.raw_psess
|
||||
.source_map()
|
||||
.get_source_file(&file_name.into())
|
||||
.get_source_file(&rustc_filename)
|
||||
.and_then(|source_file| source_file.src.clone())
|
||||
}
|
||||
}
|
||||
|
|
@ -313,7 +326,7 @@ mod tests {
|
|||
use crate::config::IgnoreList;
|
||||
use crate::utils::mk_sp;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_span::{FileName as SourceMapFileName, RealFileName};
|
||||
use rustc_span::FileName as SourceMapFileName;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
|
||||
|
|
@ -372,6 +385,13 @@ mod tests {
|
|||
.ignore()
|
||||
}
|
||||
|
||||
fn filename(sm: &SourceMap, path: &str) -> SourceMapFileName {
|
||||
SourceMapFileName::Real(
|
||||
sm.path_mapping()
|
||||
.to_real_filename(sm.working_dir(), PathBuf::from(path)),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn handles_fatal_parse_error_in_ignored_file() {
|
||||
let num_emitted_errors = Arc::new(AtomicU32::new(0));
|
||||
|
|
@ -380,10 +400,7 @@ mod tests {
|
|||
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let source =
|
||||
String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#);
|
||||
source_map.new_source_file(
|
||||
SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
|
||||
source,
|
||||
);
|
||||
source_map.new_source_file(filename(&source_map, "foo.rs"), source);
|
||||
let registry = Registry::new(&[]);
|
||||
let mut emitter = build_emitter(
|
||||
Arc::clone(&num_emitted_errors),
|
||||
|
|
@ -406,10 +423,7 @@ mod tests {
|
|||
let ignore_list = get_ignore_list(r#"ignore = ["foo.rs"]"#);
|
||||
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let source = String::from(r#"pub fn bar() { 1x; }"#);
|
||||
source_map.new_source_file(
|
||||
SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
|
||||
source,
|
||||
);
|
||||
source_map.new_source_file(filename(&source_map, "foo.rs"), source);
|
||||
let registry = Registry::new(&[]);
|
||||
let mut emitter = build_emitter(
|
||||
Arc::clone(&num_emitted_errors),
|
||||
|
|
@ -431,10 +445,7 @@ mod tests {
|
|||
let can_reset_errors = Arc::new(AtomicBool::new(false));
|
||||
let source_map = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||
let source = String::from(r#"pub fn bar() { 1x; }"#);
|
||||
source_map.new_source_file(
|
||||
SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
|
||||
source,
|
||||
);
|
||||
source_map.new_source_file(filename(&source_map, "foo.rs"), source);
|
||||
let registry = Registry::new(&[]);
|
||||
let mut emitter = build_emitter(
|
||||
Arc::clone(&num_emitted_errors),
|
||||
|
|
@ -460,18 +471,9 @@ mod tests {
|
|||
let foo_source = String::from(r#"pub fn foo() { 1x; }"#);
|
||||
let fatal_source =
|
||||
String::from(r#"extern "system" fn jni_symbol!( funcName ) ( ... ) -> {} "#);
|
||||
source_map.new_source_file(
|
||||
SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("bar.rs"))),
|
||||
bar_source,
|
||||
);
|
||||
source_map.new_source_file(
|
||||
SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("foo.rs"))),
|
||||
foo_source,
|
||||
);
|
||||
source_map.new_source_file(
|
||||
SourceMapFileName::Real(RealFileName::LocalPath(PathBuf::from("fatal.rs"))),
|
||||
fatal_source,
|
||||
);
|
||||
source_map.new_source_file(filename(&source_map, "bar.rs"), bar_source);
|
||||
source_map.new_source_file(filename(&source_map, "foo.rs"), foo_source);
|
||||
source_map.new_source_file(filename(&source_map, "fatal.rs"), fatal_source);
|
||||
let registry = Registry::new(&[]);
|
||||
let mut emitter = build_emitter(
|
||||
Arc::clone(&num_emitted_errors),
|
||||
|
|
|
|||
|
|
@ -65,18 +65,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(non_local_definitions)]
|
||||
impl From<&FileName> for rustc_span::FileName {
|
||||
fn from(filename: &FileName) -> rustc_span::FileName {
|
||||
match filename {
|
||||
FileName::Real(path) => {
|
||||
rustc_span::FileName::Real(rustc_span::RealFileName::LocalPath(path.to_owned()))
|
||||
}
|
||||
FileName::Stdin => rustc_span::FileName::Custom("stdin".to_owned()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SourceFile's in the SourceMap will always have Unix-style line endings
|
||||
// See: https://github.com/rust-lang/rustfmt/issues/3850
|
||||
// So if the user has explicitly overridden the rustfmt `newline_style`
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
21
tests/run-make/remap-path-prefix-consts/location-caller.rs
Normal file
21
tests/run-make/remap-path-prefix-consts/location-caller.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Reproducer from https://github.com/rust-lang/rust/issues/148328#issuecomment-3473688412
|
||||
#[inline(always)]
|
||||
pub const fn the_path() -> &'static str {
|
||||
std::panic::Location::caller().file()
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn the_path2() -> &'static str {
|
||||
const { std::panic::Location::caller().file() }
|
||||
}
|
||||
|
||||
// Reproducer from https://github.com/rust-lang/rust/issues/148328#issuecomment-3473761194
|
||||
pub const fn the_path_len() -> usize {
|
||||
std::panic::Location::caller().file().len()
|
||||
}
|
||||
|
||||
pub type Array = [u8; the_path_len()];
|
||||
|
||||
pub fn the_zeroed_path_len_array() -> Array {
|
||||
[0; _]
|
||||
}
|
||||
115
tests/run-make/remap-path-prefix-consts/rmake.rs
Normal file
115
tests/run-make/remap-path-prefix-consts/rmake.rs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`)
|
||||
//@ needs-target-std
|
||||
|
||||
use run_make_support::{bin_name, cwd, run, rustc};
|
||||
|
||||
fn main() {
|
||||
// No remapping - relative paths
|
||||
{
|
||||
let runner_bin = bin_name("runner-no-remap-rel-paths");
|
||||
|
||||
let mut location_caller = rustc();
|
||||
location_caller.crate_type("lib").input("location-caller.rs");
|
||||
location_caller.run();
|
||||
|
||||
let mut runner = rustc();
|
||||
runner.crate_type("bin").input("runner.rs").output(&runner_bin);
|
||||
runner.run();
|
||||
|
||||
run(&runner_bin);
|
||||
}
|
||||
|
||||
// No remapping - absolute paths
|
||||
{
|
||||
let runner_bin = bin_name("runner-no-remap-abs-paths");
|
||||
|
||||
let mut location_caller = rustc();
|
||||
location_caller.crate_type("lib").input(cwd().join("location-caller.rs"));
|
||||
location_caller.run();
|
||||
|
||||
let mut runner = rustc();
|
||||
runner.crate_type("bin").input(cwd().join("runner.rs")).output(&runner_bin);
|
||||
runner.run();
|
||||
|
||||
run(&runner_bin);
|
||||
}
|
||||
|
||||
// No remapping - mixed paths
|
||||
{
|
||||
let runner_bin = bin_name("runner-no-remap-mixed-paths");
|
||||
|
||||
let mut location_caller = rustc();
|
||||
location_caller.crate_type("lib").input(cwd().join("location-caller.rs"));
|
||||
location_caller.run();
|
||||
|
||||
let mut runner = rustc();
|
||||
runner.crate_type("bin").input("runner.rs").output(&runner_bin);
|
||||
runner.run();
|
||||
|
||||
run(&runner_bin);
|
||||
}
|
||||
|
||||
// Remapping current working directory
|
||||
{
|
||||
let runner_bin = bin_name("runner-remap-cwd");
|
||||
|
||||
let mut location_caller = rustc();
|
||||
location_caller
|
||||
.crate_type("lib")
|
||||
.remap_path_prefix(cwd(), "/remapped")
|
||||
.input(cwd().join("location-caller.rs"));
|
||||
location_caller.run();
|
||||
|
||||
let mut runner = rustc();
|
||||
runner
|
||||
.crate_type("bin")
|
||||
.remap_path_prefix(cwd(), "/remapped")
|
||||
.input(cwd().join("runner.rs"))
|
||||
.output(&runner_bin);
|
||||
runner.run();
|
||||
|
||||
run(&runner_bin);
|
||||
}
|
||||
|
||||
// Remapping current working directory - only in the dependency
|
||||
{
|
||||
let runner_bin = bin_name("runner-remap-cwd-only-dep");
|
||||
|
||||
let mut location_caller = rustc();
|
||||
location_caller
|
||||
.crate_type("lib")
|
||||
.remap_path_prefix(cwd(), "/remapped")
|
||||
.input(cwd().join("location-caller.rs"));
|
||||
location_caller.run();
|
||||
|
||||
let mut runner = rustc();
|
||||
runner.crate_type("bin").input(cwd().join("runner.rs")).output(&runner_bin);
|
||||
runner.run();
|
||||
|
||||
run(&runner_bin);
|
||||
}
|
||||
|
||||
// Remapping current working directory - different scopes
|
||||
{
|
||||
let runner_bin = bin_name("runner-remap-cwd-diff-scope");
|
||||
|
||||
let mut location_caller = rustc();
|
||||
location_caller
|
||||
.crate_type("lib")
|
||||
.remap_path_prefix(cwd(), "/remapped")
|
||||
.arg("-Zremap-path-scope=object")
|
||||
.input(cwd().join("location-caller.rs"));
|
||||
location_caller.run();
|
||||
|
||||
let mut runner = rustc();
|
||||
runner
|
||||
.crate_type("bin")
|
||||
.remap_path_prefix(cwd(), "/remapped")
|
||||
.arg("-Zremap-path-scope=diagnostics")
|
||||
.input(cwd().join("runner.rs"))
|
||||
.output(&runner_bin);
|
||||
runner.run();
|
||||
|
||||
run(&runner_bin);
|
||||
}
|
||||
}
|
||||
19
tests/run-make/remap-path-prefix-consts/runner.rs
Normal file
19
tests/run-make/remap-path-prefix-consts/runner.rs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Verifies that the paths are the same and consistent between this crate and location_caller crate.
|
||||
//
|
||||
// https://github.com/rust-lang/rust/issues/148328
|
||||
|
||||
extern crate location_caller;
|
||||
|
||||
fn main() {
|
||||
{
|
||||
// Assert both paths are the same
|
||||
let the_path = location_caller::the_path();
|
||||
let the_path2 = location_caller::the_path2();
|
||||
assert_eq!(the_path, the_path2);
|
||||
}
|
||||
|
||||
{
|
||||
// Let's make sure we don't read OOB memory
|
||||
println!("{:?}", location_caller::the_zeroed_path_len_array());
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
//@ compile-flags:-Z unstable-options --output-format=doctest
|
||||
//@ normalize-stdout: "tests/rustdoc-ui" -> "$$DIR"
|
||||
//@ normalize-stdout: "[A-Z]:[\\/](?:[^\\/]+[\\/])*?\$DIR" -> "$$DIR"
|
||||
//@ check-pass
|
||||
|
||||
//! ```
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"format_version":2,"doctests":[{"file":"$DIR/extract-doctests-result.rs","line":8,"doctest_attributes":{"original":"","should_panic":false,"no_run":false,"ignore":"None","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nOk(())","doctest_code":{"crate_level":"#![allow(unused)]\n","code":"let x = 12;\nOk(())","wrapper":{"before":"fn main() { fn _inner() -> core::result::Result<(), impl core::fmt::Debug> {\n","after":"\n} _inner().unwrap() }","returns_result":true}},"name":"$DIR/extract-doctests-result.rs - (line 8)"}]}
|
||||
{"format_version":2,"doctests":[{"file":"$DIR/extract-doctests-result.rs","line":9,"doctest_attributes":{"original":"","should_panic":false,"no_run":false,"ignore":"None","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nOk(())","doctest_code":{"crate_level":"#![allow(unused)]\n","code":"let x = 12;\nOk(())","wrapper":{"before":"fn main() { fn _inner() -> core::result::Result<(), impl core::fmt::Debug> {\n","after":"\n} _inner().unwrap() }","returns_result":true}},"name":"$DIR/extract-doctests-result.rs - (line 9)"}]}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
//@ compile-flags:-Z unstable-options --output-format=doctest
|
||||
//@ normalize-stdout: "tests/rustdoc-ui" -> "$$DIR"
|
||||
//@ normalize-stdout: "[A-Z]:[\\/](?:[^\\/]+[\\/])*?\$DIR" -> "$$DIR"
|
||||
//@ check-pass
|
||||
|
||||
//! ```ignore (checking attributes)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"format_version":2,"doctests":[{"file":"$DIR/extract-doctests.rs","line":8,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":{"crate_level":"#![allow(unused)]\n","code":"let x = 12;\nlet y = 14;","wrapper":{"before":"fn main() {\n","after":"\n}","returns_result":false}},"name":"$DIR/extract-doctests.rs - (line 8)"},{"file":"$DIR/extract-doctests.rs","line":13,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 13)"}]}
|
||||
{"format_version":2,"doctests":[{"file":"$DIR/extract-doctests.rs","line":9,"doctest_attributes":{"original":"ignore (checking attributes)","should_panic":false,"no_run":false,"ignore":"All","rust":true,"test_harness":false,"compile_fail":false,"standalone_crate":false,"error_codes":[],"edition":null,"added_css_classes":[],"unknown":[]},"original_code":"let x = 12;\nlet y = 14;","doctest_code":{"crate_level":"#![allow(unused)]\n","code":"let x = 12;\nlet y = 14;","wrapper":{"before":"fn main() {\n","after":"\n}","returns_result":false}},"name":"$DIR/extract-doctests.rs - (line 9)"},{"file":"$DIR/extract-doctests.rs","line":14,"doctest_attributes":{"original":"edition2018,compile_fail","should_panic":false,"no_run":true,"ignore":"None","rust":true,"test_harness":false,"compile_fail":true,"standalone_crate":false,"error_codes":[],"edition":"2018","added_css_classes":[],"unknown":[]},"original_code":"let","doctest_code":null,"name":"$DIR/extract-doctests.rs - (line 14)"}]}
|
||||
|
|
@ -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