Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 4 pull requests #41573

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/doc/unstable-book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- [Compiler flags](compiler-flags.md)
- [linker_flavor](compiler-flags/linker-flavor.md)
- [remap_path_prefix](compiler-flags/remap-path-prefix.md)
- [Language features](language-features.md)
- [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md)
- [abi_ptx](language-features/abi-ptx.md)
Expand Down
37 changes: 37 additions & 0 deletions src/doc/unstable-book/src/compiler-flags/remap-path-prefix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# `remap-path-prefix`

The tracking issue for this feature is: [#41555](https://github.com/rust-lang/rust/issues/41555)

------------------------

The `-Z remap-path-prefix-from`, `-Z remap-path-prefix-to` commandline option
pair allows to replace prefixes of any file paths the compiler emits in various
places. This is useful for bringing debuginfo paths into a well-known form and
for achieving reproducible builds independent of the directory the compiler was
executed in. All paths emitted by the compiler are affected, including those in
error messages.

In order to map all paths starting with `/home/foo/my-project/src` to
`/sources/my-project`, one would invoke the compiler as follows:

```text
rustc -Zremap-path-prefix-from="/home/foo/my-project/src" -Zremap-path-prefix-to="/sources/my-project"
```

Debuginfo for code from the file `/home/foo/my-project/src/foo/mod.rs`,
for example, would then point debuggers to `/sources/my-project/foo/mod.rs`
instead of the original file.

The options can be specified multiple times when multiple prefixes should be
mapped:

```text
rustc -Zremap-path-prefix-from="/home/foo/my-project/src" \
-Zremap-path-prefix-to="/sources/my-project" \
-Zremap-path-prefix-from="/home/foo/my-project/build-dir" \
-Zremap-path-prefix-to="/stable-build-dir"
```

When the options are given multiple times, the nth `-from` will be matched up
with the nth `-to` and they can appear anywhere on the commandline. Mappings
specified later on the line will take precedence over earlier ones.
2 changes: 1 addition & 1 deletion src/grammar/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ fn main() {
syntax::errors::registry::Registry::new(&[]),
Rc::new(DummyCrateStore));
let filemap = session.parse_sess.codemap()
.new_filemap("<n/a>".to_string(), None, code);
.new_filemap("<n/a>".to_string(), code);
let mut lexer = lexer::StringReader::new(session.diagnostic(), filemap);
let cm = session.codemap();

Expand Down
15 changes: 7 additions & 8 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,14 +475,13 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
// This is done to handle the case where, for example, the static
// method of a private type is used, but the type itself is never
// called directly.
if let Some(impl_list) =
self.tcx.maps.inherent_impls.borrow().get(&self.tcx.hir.local_def_id(id)) {
for &impl_did in impl_list.iter() {
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) {
if self.live_symbols.contains(&item_node_id) {
return true;
}
let def_id = self.tcx.hir.local_def_id(id);
let inherent_impls = self.tcx.inherent_impls(def_id);
for &impl_did in inherent_impls.iter() {
for &item_did in &self.tcx.associated_item_def_ids(impl_did)[..] {
if let Some(item_node_id) = self.tcx.hir.as_local_node_id(item_did) {
if self.live_symbols.contains(&item_node_id) {
return true;
}
}
}
Expand Down
32 changes: 31 additions & 1 deletion src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use lint;
use middle::cstore;

use syntax::ast::{self, IntTy, UintTy};
use syntax::codemap::FilePathMapping;
use syntax::parse::token;
use syntax::parse;
use syntax::symbol::Symbol;
Expand Down Expand Up @@ -492,6 +493,14 @@ impl Options {
self.incremental.is_none() ||
self.cg.codegen_units == 1
}

pub fn file_path_mapping(&self) -> FilePathMapping {
FilePathMapping::new(
self.debugging_opts.remap_path_prefix_from.iter().zip(
self.debugging_opts.remap_path_prefix_to.iter()
).map(|(src, dst)| (src.clone(), dst.clone())).collect()
)
}
}

// The type of entry function, so
Expand Down Expand Up @@ -1012,6 +1021,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"Set the optimization fuel quota for a crate."),
print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
"Make Rustc print the total optimization fuel used by a crate."),
remap_path_prefix_from: Vec<String> = (vec![], parse_string_push, [TRACKED],
"add a source pattern to the file path remapping config"),
remap_path_prefix_to: Vec<String> = (vec![], parse_string_push, [TRACKED],
"add a mapping target to the file path remapping config"),
}

pub fn default_lib_output() -> CrateType {
Expand Down Expand Up @@ -1319,7 +1332,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
cfgspecs.into_iter().map(|s| {
let sess = parse::ParseSess::new();
let sess = parse::ParseSess::new(FilePathMapping::empty());
let mut parser =
parse::new_parser_from_source_str(&sess, "cfgspec".to_string(), s.to_string());

Expand Down Expand Up @@ -1430,6 +1443,23 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
output_types.insert(OutputType::Exe, None);
}

let remap_path_prefix_sources = debugging_opts.remap_path_prefix_from.len();
let remap_path_prefix_targets = debugging_opts.remap_path_prefix_from.len();

if remap_path_prefix_targets < remap_path_prefix_sources {
for source in &debugging_opts.remap_path_prefix_from[remap_path_prefix_targets..] {
early_error(error_format,
&format!("option `-Zremap-path-prefix-from='{}'` does not have \
a corresponding `-Zremap-path-prefix-to`", source))
}
} else if remap_path_prefix_targets > remap_path_prefix_sources {
for target in &debugging_opts.remap_path_prefix_to[remap_path_prefix_sources..] {
early_error(error_format,
&format!("option `-Zremap-path-prefix-to='{}'` does not have \
a corresponding `-Zremap-path-prefix-from`", target))
}
}

let mut cg = build_codegen_options(matches, error_format);

// Issue #30063: if user requests llvm-related output to one
Expand Down
29 changes: 17 additions & 12 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,10 @@ pub struct Session {
// The name of the root source file of the crate, in the local file system.
// The path is always expected to be absolute. `None` means that there is no
// source file.
pub local_crate_source_file: Option<PathBuf>,
pub working_dir: PathBuf,
pub local_crate_source_file: Option<String>,
// The directory the compiler has been executed in plus a flag indicating
// if the value stored here has been affected by path remapping.
pub working_dir: (String, bool),
pub lint_store: RefCell<lint::LintStore>,
pub lints: RefCell<lint::LintTable>,
/// Set of (LintId, span, message) tuples tracking lint (sub)diagnostics
Expand Down Expand Up @@ -553,12 +555,14 @@ pub fn build_session(sopts: config::Options,
registry: errors::registry::Registry,
cstore: Rc<CrateStore>)
-> Session {
let file_path_mapping = sopts.file_path_mapping();

build_session_with_codemap(sopts,
dep_graph,
local_crate_source_file,
registry,
cstore,
Rc::new(codemap::CodeMap::new()),
Rc::new(codemap::CodeMap::new(file_path_mapping)),
None)
}

Expand Down Expand Up @@ -622,7 +626,7 @@ pub fn build_session_(sopts: config::Options,
Ok(t) => t,
Err(e) => {
panic!(span_diagnostic.fatal(&format!("Error loading host specification: {}", e)));
}
}
};
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
let p_s = parse::ParseSess::with_span_handler(span_diagnostic, codemap);
Expand All @@ -631,21 +635,22 @@ pub fn build_session_(sopts: config::Options,
None => Some(filesearch::get_or_default_sysroot())
};

let file_path_mapping = sopts.file_path_mapping();

// Make the path absolute, if necessary
let local_crate_source_file = local_crate_source_file.map(|path|
if path.is_absolute() {
path.clone()
} else {
env::current_dir().unwrap().join(&path)
}
);
let local_crate_source_file = local_crate_source_file.map(|path| {
file_path_mapping.map_prefix(path.to_string_lossy().into_owned()).0
});

let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
let optimization_fuel_limit = Cell::new(sopts.debugging_opts.fuel.as_ref()
.map(|i| i.1).unwrap_or(0));
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
let print_fuel = Cell::new(0);

let working_dir = env::current_dir().unwrap().to_string_lossy().into_owned();
let working_dir = file_path_mapping.map_prefix(working_dir);

let sess = Session {
dep_graph: dep_graph.clone(),
target: target_cfg,
Expand All @@ -660,7 +665,7 @@ pub fn build_session_(sopts: config::Options,
derive_registrar_fn: Cell::new(None),
default_sysroot: default_sysroot,
local_crate_source_file: local_crate_source_file,
working_dir: env::current_dir().unwrap(),
working_dir: working_dir,
lint_store: RefCell::new(lint::LintStore::new()),
lints: RefCell::new(lint::LintTable::new()),
one_time_diagnostics: RefCell::new(FxHashSet()),
Expand Down
43 changes: 31 additions & 12 deletions src/librustc/ty/item_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use ty::{self, Ty, TyCtxt};
use syntax::ast;
use syntax::symbol::Symbol;
use syntax_pos::DUMMY_SP;

use std::cell::Cell;

thread_local! {
static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false)
static FORCE_ABSOLUTE: Cell<bool> = Cell::new(false);
static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
}

/// Enforces that item_path_str always returns an absolute path.
/// This is useful when building symbols that contain types,
/// where we want the crate name to be part of the symbol.
/// Enforces that item_path_str always returns an absolute path and
/// also enables "type-based" impl paths. This is used when building
/// symbols that contain types, where we want the crate name to be
/// part of the symbol.
pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
FORCE_ABSOLUTE.with(|force| {
let old = force.get();
Expand All @@ -33,6 +36,20 @@ pub fn with_forced_absolute_paths<F: FnOnce() -> R, R>(f: F) -> R {
})
}

/// Force us to name impls with just the filename/line number. We
/// normally try to use types. But at some points, notably while printing
/// cycle errors, this can result in extra or suboptimal error output,
/// so this variable disables that check.
pub fn with_forced_impl_filename_line<F: FnOnce() -> R, R>(f: F) -> R {
FORCE_IMPL_FILENAME_LINE.with(|force| {
let old = force.get();
force.set(true);
let result = f();
force.set(old);
result
})
}

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Returns a string identifying this def-id. This string is
/// suitable for user output. It is relative to the current crate
Expand Down Expand Up @@ -196,14 +213,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
{
let parent_def_id = self.parent_def_id(impl_def_id).unwrap();

let use_types = if !impl_def_id.is_local() {
// always have full types available for extern crates
true
} else {
// for local crates, check whether type info is
// available; typeck might not have completed yet
self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id) &&
self.maps.type_of.borrow().contains_key(&impl_def_id)
// Always use types for non-local impls, where types are always
// available, and filename/line-number is mostly uninteresting.
let use_types = !impl_def_id.is_local() || {
// Otherwise, use filename/line-number if forced.
let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
!force_no_types && {
// Otherwise, use types if we can query them without inducing a cycle.
ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
}
};

if !use_types {
Expand Down
Loading