Auto merge of #115214 - Urgau:rfc-3127-trim-paths, r=compiler-errors
Implement rustc part of RFC 3127 trim-paths This PR implements (or at least tries to) [RFC 3127 trim-paths](https://github.com/rust-lang/rust/issues/111540), the rustc part. That is `-Zremap-path-scope` with all of it's components/scopes. `@rustbot` label: +F-trim-paths
This commit is contained in:
commit
94c4e5c411
34 changed files with 580 additions and 92 deletions
|
@ -21,8 +21,8 @@ use rustc_feature::UnstableFeatures;
|
|||
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
|
||||
use rustc_span::source_map::{FileName, FilePathMapping};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::RealFileName;
|
||||
use rustc_span::SourceFileHashAlgorithm;
|
||||
use rustc_span::{FileNameDisplayPreference, RealFileName};
|
||||
|
||||
use rustc_errors::emitter::HumanReadableErrorType;
|
||||
use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
|
||||
|
@ -1018,6 +1018,32 @@ impl OutputFilenames {
|
|||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
/// Scopes used to determined if it need to apply to --remap-path-prefix
|
||||
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 only when they are written to
|
||||
/// compiled executables or libraries, but not when they are in split
|
||||
/// debuginfo files
|
||||
const UNSPLIT_DEBUGINFO = 1 << 2;
|
||||
/// Apply remappings to debug information only when they are written to
|
||||
/// split debug information files, but not in compiled executables or
|
||||
/// libraries
|
||||
const SPLIT_DEBUGINFO = 1 << 3;
|
||||
/// Apply remappings to the paths pointing to split debug information
|
||||
/// files. Does nothing when these files are not generated.
|
||||
const SPLIT_DEBUGINFO_PATH = 1 << 4;
|
||||
|
||||
/// An alias for macro,unsplit-debuginfo,split-debuginfo-path. This
|
||||
/// ensures all paths in compiled executables or libraries are remapped
|
||||
/// but not elsewhere.
|
||||
const OBJECT = Self::MACRO.bits | Self::UNSPLIT_DEBUGINFO.bits | Self::SPLIT_DEBUGINFO_PATH.bits;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn host_triple() -> &'static str {
|
||||
// Get the host triple out of the build environment. This ensures that our
|
||||
// idea of the host triple is the same as for the set of libraries we've
|
||||
|
@ -1030,6 +1056,22 @@ pub fn host_triple() -> &'static str {
|
|||
(option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
|
||||
}
|
||||
|
||||
fn file_path_mapping(
|
||||
remap_path_prefix: Vec<(PathBuf, PathBuf)>,
|
||||
unstable_opts: &UnstableOptions,
|
||||
) -> FilePathMapping {
|
||||
FilePathMapping::new(
|
||||
remap_path_prefix.clone(),
|
||||
if unstable_opts.remap_path_scope.contains(RemapPathScopeComponents::DIAGNOSTICS)
|
||||
&& !remap_path_prefix.is_empty()
|
||||
{
|
||||
FileNameDisplayPreference::Remapped
|
||||
} else {
|
||||
FileNameDisplayPreference::Local
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
fn default() -> Options {
|
||||
Options {
|
||||
|
@ -1085,7 +1127,7 @@ impl Options {
|
|||
}
|
||||
|
||||
pub fn file_path_mapping(&self) -> FilePathMapping {
|
||||
FilePathMapping::new(self.remap_path_prefix.clone())
|
||||
file_path_mapping(self.remap_path_prefix.clone(), &self.unstable_opts)
|
||||
}
|
||||
|
||||
/// Returns `true` if there will be an output file generated.
|
||||
|
@ -2867,7 +2909,7 @@ pub fn build_session_options(
|
|||
handler.early_error(format!("Current directory is invalid: {e}"));
|
||||
});
|
||||
|
||||
let remap = FilePathMapping::new(remap_path_prefix.clone());
|
||||
let remap = file_path_mapping(remap_path_prefix.clone(), &unstable_opts);
|
||||
let (path, remapped) = remap.map_prefix(&working_dir);
|
||||
let working_dir = if remapped {
|
||||
RealFileName::Remapped { virtual_name: path.into_owned(), local_path: Some(working_dir) }
|
||||
|
@ -3173,8 +3215,8 @@ pub(crate) mod dep_tracking {
|
|||
BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression,
|
||||
ErrorOutputType, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
|
||||
LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius,
|
||||
ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath,
|
||||
SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
|
||||
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
|
||||
SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
|
||||
};
|
||||
use crate::lint;
|
||||
use crate::options::WasiExecModel;
|
||||
|
@ -3268,6 +3310,7 @@ pub(crate) mod dep_tracking {
|
|||
StackProtector,
|
||||
SwitchWithOptPath,
|
||||
SymbolManglingVersion,
|
||||
RemapPathScopeComponents,
|
||||
SourceFileHashAlgorithm,
|
||||
TrimmedDefPaths,
|
||||
OutFileName,
|
||||
|
|
|
@ -427,6 +427,7 @@ mod desc {
|
|||
pub const parse_proc_macro_execution_strategy: &str =
|
||||
"one of supported execution strategies (`same-thread`, or `cross-thread`)";
|
||||
pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";
|
||||
pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
|
||||
}
|
||||
|
||||
mod parse {
|
||||
|
@ -1095,6 +1096,30 @@ mod parse {
|
|||
true
|
||||
}
|
||||
|
||||
pub(crate) fn parse_remap_path_scope(
|
||||
slot: &mut RemapPathScopeComponents,
|
||||
v: Option<&str>,
|
||||
) -> bool {
|
||||
if let Some(v) = v {
|
||||
*slot = RemapPathScopeComponents::empty();
|
||||
for s in v.split(',') {
|
||||
*slot |= match s {
|
||||
"macro" => RemapPathScopeComponents::MACRO,
|
||||
"diagnostics" => RemapPathScopeComponents::DIAGNOSTICS,
|
||||
"unsplit-debuginfo" => RemapPathScopeComponents::UNSPLIT_DEBUGINFO,
|
||||
"split-debuginfo" => RemapPathScopeComponents::SPLIT_DEBUGINFO,
|
||||
"split-debuginfo-path" => RemapPathScopeComponents::SPLIT_DEBUGINFO_PATH,
|
||||
"object" => RemapPathScopeComponents::OBJECT,
|
||||
"all" => RemapPathScopeComponents::all(),
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parse_relocation_model(slot: &mut Option<RelocModel>, v: Option<&str>) -> bool {
|
||||
match v.and_then(|s| RelocModel::from_str(s).ok()) {
|
||||
Some(relocation_model) => *slot = Some(relocation_model),
|
||||
|
@ -1733,6 +1758,8 @@ options! {
|
|||
"choose which RELRO level to use"),
|
||||
remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
|
||||
"remap paths under the current working directory to this path prefix"),
|
||||
remap_path_scope: RemapPathScopeComponents = (RemapPathScopeComponents::all(), parse_remap_path_scope, [TRACKED],
|
||||
"remap path scope (default: all)"),
|
||||
remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
|
||||
"directory into which to write optimization remarks (if not specified, they will be \
|
||||
written to standard error output)"),
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::code_stats::CodeStats;
|
||||
pub use crate::code_stats::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
|
||||
use crate::config::{
|
||||
self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath,
|
||||
self, CrateType, InstrumentCoverage, OptLevel, OutFileName, OutputType,
|
||||
RemapPathScopeComponents, SwitchWithOptPath,
|
||||
};
|
||||
use crate::config::{ErrorOutputType, Input};
|
||||
use crate::errors;
|
||||
|
@ -254,7 +255,11 @@ impl Session {
|
|||
|
||||
pub fn local_crate_source_file(&self) -> Option<PathBuf> {
|
||||
let path = self.io.input.opt_path()?;
|
||||
Some(self.opts.file_path_mapping().map_prefix(path).0.into_owned())
|
||||
if self.should_prefer_remapped_for_codegen() {
|
||||
Some(self.opts.file_path_mapping().map_prefix(path).0.into_owned())
|
||||
} else {
|
||||
Some(path.to_path_buf())
|
||||
}
|
||||
}
|
||||
|
||||
fn check_miri_unleashed_features(&self) {
|
||||
|
@ -1243,6 +1248,53 @@ impl Session {
|
|||
pub fn link_dead_code(&self) -> bool {
|
||||
self.opts.cg.link_dead_code.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn should_prefer_remapped_for_codegen(&self) -> bool {
|
||||
// bail out, if any of the requested crate types aren't:
|
||||
// "compiled executables or libraries"
|
||||
for crate_type in &self.opts.crate_types {
|
||||
match crate_type {
|
||||
CrateType::Executable
|
||||
| CrateType::Dylib
|
||||
| CrateType::Rlib
|
||||
| CrateType::Staticlib
|
||||
| CrateType::Cdylib => continue,
|
||||
CrateType::ProcMacro => return false,
|
||||
}
|
||||
}
|
||||
|
||||
let has_split_debuginfo = match self.split_debuginfo() {
|
||||
SplitDebuginfo::Off => false,
|
||||
SplitDebuginfo::Packed => true,
|
||||
SplitDebuginfo::Unpacked => true,
|
||||
};
|
||||
|
||||
let remap_path_scopes = &self.opts.unstable_opts.remap_path_scope;
|
||||
let mut prefer_remapped = false;
|
||||
|
||||
if remap_path_scopes.contains(RemapPathScopeComponents::UNSPLIT_DEBUGINFO) {
|
||||
prefer_remapped |= !has_split_debuginfo;
|
||||
}
|
||||
|
||||
if remap_path_scopes.contains(RemapPathScopeComponents::SPLIT_DEBUGINFO) {
|
||||
prefer_remapped |= has_split_debuginfo;
|
||||
}
|
||||
|
||||
prefer_remapped
|
||||
}
|
||||
|
||||
pub fn should_prefer_remapped_for_split_debuginfo_paths(&self) -> bool {
|
||||
let has_split_debuginfo = match self.split_debuginfo() {
|
||||
SplitDebuginfo::Off => false,
|
||||
SplitDebuginfo::Packed | SplitDebuginfo::Unpacked => true,
|
||||
};
|
||||
|
||||
self.opts
|
||||
.unstable_opts
|
||||
.remap_path_scope
|
||||
.contains(RemapPathScopeComponents::SPLIT_DEBUGINFO_PATH)
|
||||
&& has_split_debuginfo
|
||||
}
|
||||
}
|
||||
|
||||
// JUSTIFICATION: part of session construction
|
||||
|
@ -1752,3 +1804,53 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> {
|
|||
};
|
||||
emitter
|
||||
}
|
||||
|
||||
pub trait RemapFileNameExt {
|
||||
type Output<'a>
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scopes: RemapPathScopeComponents) -> Self::Output<'_>;
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_>;
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::FileName {
|
||||
type Output<'a> = rustc_span::FileNameDisplay<'a>;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scopes: RemapPathScopeComponents) -> Self::Output<'_> {
|
||||
if sess.opts.unstable_opts.remap_path_scope.contains(scopes) {
|
||||
self.prefer_remapped_unconditionaly()
|
||||
} else {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_> {
|
||||
if sess.should_prefer_remapped_for_codegen() {
|
||||
self.prefer_remapped_unconditionaly()
|
||||
} else {
|
||||
self.prefer_local()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RemapFileNameExt for rustc_span::RealFileName {
|
||||
type Output<'a> = &'a Path;
|
||||
|
||||
fn for_scope(&self, sess: &Session, scopes: RemapPathScopeComponents) -> Self::Output<'_> {
|
||||
if sess.opts.unstable_opts.remap_path_scope.contains(scopes) {
|
||||
self.remapped_path_if_available()
|
||||
} else {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
|
||||
fn for_codegen(&self, sess: &Session) -> Self::Output<'_> {
|
||||
if sess.should_prefer_remapped_for_codegen() {
|
||||
self.remapped_path_if_available()
|
||||
} else {
|
||||
self.local_path_if_available()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue