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

Implement a file-path remapping feature in support of debuginfo and reproducible builds #41508

Merged
merged 5 commits into from
Apr 28, 2017
Merged
Show file tree
Hide file tree
Changes from 4 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"
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unclear from this how the remapping is actually operating. It should also answer:

  • Is it delimited by path element boundaries, or is it operating on literal strings?
  • Is there any normalization performed before/after doing the transformation? (Redundant / elimination?)
  • Are the input paths absolute, relative, or whatever was provided to the compiler?
  • In this example, if the input path were /home/foo/my-project/src-orig, would this remap to /sources/my-project-orig? Should there be a trailing / to prevent this if its undesirable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points. I'll provide some more documentation in a follow-up PR. The implementation as it is does as little as possible: (1) Take each string as it is provided to the compiler, (2) don't do any normalization, (3) do a simple string-level prefix replacement.

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does

Mappings specified later on the line will take precedence over earlier ones.

actually mean? Do you mean that if the -Zremap-path-prefix-from is identical it is replaced? Or does it more generally apply, such that a more specific path overrides a more general one?

For example, what's the mapping for:

rustc -Zremap-path-prefix-from=my-project/src -Zremap-path-prefix-to=/sources/my-project \
      -Zremap-path-prefix-from=my-project/src/vendored/otherproject -Zremap-path-prefix-to=/sources/otherproject

when applied to my-project/src/vendored/otherproject/src/lib.rs?

In other words, does the ordering of the -from options matter when multiple mappings could apply? Or is there some other way to disambiguate multiple matching mappings?

Is it guaranteed that at most a single mapping can be applied, or is there some notion of repeated application of mappings until nothing matches?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if defining the matching as:

  1. later remap-path-prefix-from replaces a previous identical one
  2. mappings are matched from longest from prefix to shortest

would be better.

I think this would make it deterministically always select more specific mappings over more general ones, rather than relying purely on ordering.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would differ from the current behaviour in the example a/b -> y, a -> x. I'm not sure which is better, but without a concrete argument that the new one is better I'd suggest to stick with the current behaviour which is simple to describe and implement. The other behaviour would require a trie-like data structure or other more complex thing.

I'm trying to standardise this behaviour across multiple compilers and GCC is already doing something very similar based on the ordering of command-line flags (and I have a patch pending to make it exactly match the behaviour being proposed in this PR). Changing this in the suggested way would make the spec for this standard even more complex. :(

In real-world cases I don't think the issue will crop up, in rustc or anywhere else - it's unlikely that a child process inheriting a prefix-map from a parent process would want to add a less-specific mapping for a higher-level directory.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation is very simple: Walk all from/to pairs as provided on the commandline, starting at the last, and just stop at the first match.

In my opinion, relying only on ordering is a good approach, since the rules are clear and without surprises.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current behaviour allows you to specify useless mappings (by putting more general before more specific in the reverse ordering), which might be inadvertent or unexpected.

I don't think it would require very fancy structures; I think you could implement it pretty simply using BTreeMap<String, String> instead of Vec<String, String>. It would be nice to have an algorithm that can have more efficient implementations (ie, not linear search), to cope with the case where there are lots of mappings (but that's definitely not a requirement for the first implementation).

Copy link
Contributor

@jsgf jsgf Apr 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelwoerister

In my opinion, relying only on ordering is a good approach, since the rules are clear and without surprises

I think that's fine - I think the wording could do with clarification (ie, I managed to misinterpret what it meant until I looked at the source).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. I'll provide an update in a subsequent PR and make sure to ping the usual suspects for review.

Copy link
Contributor

@codyps codyps Apr 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the ordering of flags for the lookup allows easy overriding of previous flags without needing to have a way to remove items from an accumulated list of flags (ex: presuming a variable in some higher level build env is accumulating RUST_FLAGS, using ordering means there is no need to parse all the accumulated flags to figure out which ones to remove when adding a higher priority remapping).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, that might be useful to have anyway, since an identity mapping is semantically different from no mapping at all.

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
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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a potentially confusing CLUI to me. At this point I would simply make -Z remap-path take two arguments… obviously not something our argument parser can do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I know, it's not perfect. There's been quite some discussion about the CLUI in the initial issue (#38322). This seemed to be an acceptable compromise. It's an unstable feature at the moment. If our parser had some improvements before this is stabilized, we could certainly revisit this.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the values are paths, and most file systems do not like colon ':' in path names, can't a single argument be bifurcated on a colon? Example: -Z remap-path="original_path_from:preferred_path_to".

)
}
}

// 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
2 changes: 1 addition & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ pub fn run_compiler<'a>(args: &[String],
let cstore = Rc::new(CStore::new(&dep_graph));

let loader = file_loader.unwrap_or(box RealFileLoader);
let codemap = Rc::new(CodeMap::with_file_loader(loader));
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
let mut sess = session::build_session_with_codemap(
sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest,
);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_driver/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use rustc::session::{self, config};
use std::rc::Rc;
use syntax::ast;
use syntax::abi::Abi;
use syntax::codemap::CodeMap;
use syntax::codemap::{CodeMap, FilePathMapping};
use errors;
use errors::emitter::Emitter;
use errors::{Level, DiagnosticBuilder};
Expand Down Expand Up @@ -108,7 +108,7 @@ fn test_env<F>(source_string: &str,
&dep_graph,
None,
diagnostic_handler,
Rc::new(CodeMap::new()),
Rc::new(CodeMap::new(FilePathMapping::empty())),
cstore.clone());
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let input = config::Input::Str {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ impl CrateStore for cstore::CStore {
let (name, def) = data.get_macro(id.index);
let source_name = format!("<{} macros>", name);

let filemap = sess.parse_sess.codemap().new_filemap(source_name, None, def.body);
let filemap = sess.parse_sess.codemap().new_filemap(source_name, def.body);
let local_span = Span { lo: filemap.start_pos, hi: filemap.end_pos, ctxt: NO_EXPANSION };
let body = filemap_to_stream(&sess.parse_sess, filemap);

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1134,7 +1134,7 @@ impl<'a, 'tcx> CrateMetadata {
// We can't reuse an existing FileMap, so allocate a new one
// containing the information we need.
let syntax_pos::FileMap { name,
abs_path,
name_was_remapped,
start_pos,
end_pos,
lines,
Expand All @@ -1158,7 +1158,7 @@ impl<'a, 'tcx> CrateMetadata {
}

let local_version = local_codemap.new_imported_filemap(name,
abs_path,
name_was_remapped,
source_length,
lines,
multibyte_chars);
Expand Down
32 changes: 30 additions & 2 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use std::hash::Hash;
use std::intrinsics;
use std::io::prelude::*;
use std::io::Cursor;
use std::path::Path;
use std::rc::Rc;
use std::u32;
use syntax::ast::{self, CRATE_NODE_ID};
Expand Down Expand Up @@ -1268,13 +1269,40 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_codemap(&mut self) -> LazySeq<syntax_pos::FileMap> {
let codemap = self.tcx.sess.codemap();
let all_filemaps = codemap.files.borrow();
self.lazy_seq_ref(all_filemaps.iter()
let adapted = all_filemaps.iter()
.filter(|filemap| {
// No need to re-export imported filemaps, as any downstream
// crate will import them from their original source.
!filemap.is_imported()
})
.map(|filemap| &**filemap))
.map(|filemap| {
// When exporting FileMaps, we expand all paths to absolute
// paths because any relative paths are potentially relative to
// a wrong directory.
// However, if a path has been modified via
// `-Zremap-path-prefix` we assume the user has already set
// things up the way they want and don't touch the path values
// anymore.
let name = Path::new(&filemap.name);
let (ref working_dir, working_dir_was_remapped) = self.tcx.sess.working_dir;
if filemap.name_was_remapped ||
(name.is_relative() && working_dir_was_remapped) {
// This path of this FileMap has been modified by
// path-remapping, so we use it verbatim (and avoid cloning
// the whole map in the process).
filemap.clone()
} else {
let mut adapted = (**filemap).clone();
let abs_path = Path::new(working_dir).join(name)
.to_string_lossy()
.into_owned();
adapted.name = abs_path;
Rc::new(adapted)
}
})
.collect::<Vec<_>>();

self.lazy_seq_ref(adapted.iter().map(|fm| &**fm))
}

fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use rustc::ty::{self, TyCtxt, AssociatedItemContainer};
use std::collections::HashSet;
use std::collections::hash_map::DefaultHasher;
use std::hash::*;
use std::path::Path;

use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID};
use syntax::parse::token;
Expand Down Expand Up @@ -128,6 +129,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
let source_file = self.tcx.sess.local_crate_source_file.as_ref();
let crate_root = source_file.map(|source_file| {
let source_file = Path::new(source_file);
match source_file.file_name() {
Some(_) => source_file.parent().unwrap().display().to_string(),
None => source_file.display().to_string(),
Expand Down
23 changes: 13 additions & 10 deletions src/librustc_trans/debuginfo/create_scope_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::FunctionDebugContext;
use super::{FunctionDebugContext, FunctionDebugContextData};
use super::metadata::file_metadata;
use super::utils::{DIB, span_start};

use llvm;
use llvm::debuginfo::{DIScope, DISubprogram};
use llvm::debuginfo::DIScope;
use common::CrateContext;
use rustc::mir::{Mir, VisibilityScope};

Expand Down Expand Up @@ -53,8 +53,8 @@ pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &Function
};
let mut scopes = IndexVec::from_elem(null_scope, &mir.visibility_scopes);

let fn_metadata = match *debug_context {
FunctionDebugContext::RegularContext(ref data) => data.fn_metadata,
let debug_context = match *debug_context {
FunctionDebugContext::RegularContext(ref data) => data,
FunctionDebugContext::DebugInfoDisabled |
FunctionDebugContext::FunctionWithoutDebugInfo => {
return scopes;
Expand All @@ -71,7 +71,7 @@ pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &Function
// Instantiate all scopes.
for idx in 0..mir.visibility_scopes.len() {
let scope = VisibilityScope::new(idx);
make_mir_scope(ccx, &mir, &has_variables, fn_metadata, scope, &mut scopes);
make_mir_scope(ccx, &mir, &has_variables, debug_context, scope, &mut scopes);
}

scopes
Expand All @@ -80,7 +80,7 @@ pub fn create_mir_scopes(ccx: &CrateContext, mir: &Mir, debug_context: &Function
fn make_mir_scope(ccx: &CrateContext,
mir: &Mir,
has_variables: &BitVector,
fn_metadata: DISubprogram,
debug_context: &FunctionDebugContextData,
scope: VisibilityScope,
scopes: &mut IndexVec<VisibilityScope, MirDebugScope>) {
if scopes[scope].is_valid() {
Expand All @@ -89,13 +89,13 @@ fn make_mir_scope(ccx: &CrateContext,

let scope_data = &mir.visibility_scopes[scope];
let parent_scope = if let Some(parent) = scope_data.parent_scope {
make_mir_scope(ccx, mir, has_variables, fn_metadata, parent, scopes);
make_mir_scope(ccx, mir, has_variables, debug_context, parent, scopes);
scopes[parent]
} else {
// The root is the function itself.
let loc = span_start(ccx, mir.span);
scopes[scope] = MirDebugScope {
scope_metadata: fn_metadata,
scope_metadata: debug_context.fn_metadata,
file_start_pos: loc.file.start_pos,
file_end_pos: loc.file.end_pos,
};
Expand All @@ -109,14 +109,17 @@ fn make_mir_scope(ccx: &CrateContext,
// However, we don't skip creating a nested scope if
// our parent is the root, because we might want to
// put arguments in the root and not have shadowing.
if parent_scope.scope_metadata != fn_metadata {
if parent_scope.scope_metadata != debug_context.fn_metadata {
scopes[scope] = parent_scope;
return;
}
}

let loc = span_start(ccx, scope_data.span);
let file_metadata = file_metadata(ccx, &loc.file.name, &loc.file.abs_path);
let file_metadata = file_metadata(ccx,
&loc.file.name,
debug_context.defining_crate);

let scope_metadata = unsafe {
llvm::LLVMRustDIBuilderCreateLexicalBlock(
DIB(ccx),
Expand Down
Loading