1
Fork 0

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:
bors 2023-10-19 19:09:29 +00:00
commit 94c4e5c411
34 changed files with 580 additions and 92 deletions

View file

@ -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,

View file

@ -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)"),

View file

@ -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()
}
}
}