diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 4a6841aedca12..625edc02b7729 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -59,7 +59,7 @@ use syntax::parse::{self, token}; use syntax::symbol::Symbol; use syntax::tokenstream; use syntax_pos::DUMMY_SP; -use syntax_pos::{FileMap, Pos, SyntaxContext}; +use syntax_pos::{FileMap, Pos, SyntaxContext, FileName}; use syntax_pos::hygiene::Mark; /// The main type provided by this crate, representing an abstract stream of @@ -89,7 +89,7 @@ impl FromStr for TokenStream { fn from_str(src: &str) -> Result { __internal::with_sess(|(sess, mark)| { let src = src.to_string(); - let name = "".to_string(); + let name = FileName::ProcMacroSourceCode; let expn_info = mark.expn_info().unwrap(); let call_site = expn_info.call_site; // notify the expansion info that it is unhygienic @@ -279,7 +279,7 @@ pub struct SourceFile { } impl SourceFile { - /// Get the path to this source file as a string. + /// Get the path to this source file. /// /// ### Note /// If the code span associated with this `SourceFile` was generated by an external macro, this @@ -290,7 +290,7 @@ impl SourceFile { /// /// [`is_real`]: #method.is_real # [unstable(feature = "proc_macro", issue = "38356")] - pub fn as_str(&self) -> &str { + pub fn path(&self) -> &FileName { &self.filemap.name } @@ -306,9 +306,9 @@ impl SourceFile { } #[unstable(feature = "proc_macro", issue = "38356")] -impl AsRef for SourceFile { - fn as_ref(&self) -> &str { - self.as_str() +impl AsRef for SourceFile { + fn as_ref(&self) -> &FileName { + self.path() } } @@ -316,7 +316,7 @@ impl AsRef for SourceFile { impl fmt::Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("SourceFile") - .field("path", &self.as_str()) + .field("path", self.path()) .field("is_real", &self.is_real()) .finish() } @@ -333,8 +333,8 @@ impl PartialEq for SourceFile { impl Eq for SourceFile {} #[unstable(feature = "proc_macro", issue = "38356")] -impl PartialEq for SourceFile { - fn eq(&self, other: &str) -> bool { +impl PartialEq for SourceFile { + fn eq(&self, other: &FileName) -> bool { self.as_ref() == other } } diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index d94dd24af3edc..fb502ecb996ae 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -21,7 +21,7 @@ use syntax::print::pprust::PrintState; use syntax::ptr::P; use syntax::symbol::keywords; use syntax::util::parser::{self, AssocOp, Fixity}; -use syntax_pos::{self, BytePos}; +use syntax_pos::{self, BytePos, FileName}; use hir; use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd}; @@ -125,7 +125,7 @@ pub const default_columns: usize = 78; pub fn print_crate<'a>(cm: &'a CodeMap, sess: &ParseSess, krate: &hir::Crate, - filename: String, + filename: FileName, input: &mut Read, out: Box, ann: &'a PpAnn, @@ -144,7 +144,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, impl<'a> State<'a> { pub fn new_from_input(cm: &'a CodeMap, sess: &ParseSess, - filename: String, + filename: FileName, input: &mut Read, out: Box, ann: &'a PpAnn, diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index c414349c8ffd6..c25aa10eb1e73 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -371,6 +371,17 @@ impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind { QuestionMark }); +impl_stable_hash_for!(enum ::syntax_pos::FileName { + Real(pb), + Macros(s), + QuoteExpansion, + Anon, + MacroExpansion, + ProcMacroSourceCode, + CfgSpec, + Custom(s) +}); + impl<'gcx> HashStable> for FileMap { fn hash_stable(&self, hcx: &mut StableHashingContext<'gcx>, diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 2f527413432bc..e80ea16f565ab 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -607,7 +607,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let span_key = msp.primary_span().and_then(|sp: Span| if sp != DUMMY_SP { let file = cm.lookup_char_pos(sp.lo()).file; - if file.name.starts_with("<") && file.name.ends_with(" macros>") { + if file.name.is_macros() { None } else { Some(span) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 0dcd3e8081080..d4d33af1d59e3 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -27,7 +27,7 @@ use lint; use middle::cstore; use syntax::ast::{self, IntTy, UintTy}; -use syntax::codemap::FilePathMapping; +use syntax::codemap::{FilePathMapping, FileName}; use syntax::parse::token; use syntax::parse; use syntax::symbol::Symbol; @@ -440,7 +440,7 @@ pub enum Input { File(PathBuf), Str { /// String that is shown in place of a filename - name: String, + name: FileName, /// Anonymous source string input: String, }, @@ -733,7 +733,9 @@ macro_rules! options { Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`"); pub const parse_string: Option<&'static str> = Some("a string"); pub const parse_string_push: Option<&'static str> = Some("a string"); + pub const parse_pathbuf_push: Option<&'static str> = Some("a path"); pub const parse_opt_string: Option<&'static str> = Some("a string"); + pub const parse_opt_pathbuf: Option<&'static str> = Some("a path"); pub const parse_list: Option<&'static str> = Some("a space-separated list of strings"); pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings"); pub const parse_uint: Option<&'static str> = Some("a number"); @@ -757,6 +759,7 @@ macro_rules! options { mod $mod_set { use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer}; use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel}; + use std::path::PathBuf; $( pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { @@ -797,6 +800,13 @@ macro_rules! options { } } + fn parse_opt_pathbuf(slot: &mut Option, v: Option<&str>) -> bool { + match v { + Some(s) => { *slot = Some(PathBuf::from(s)); true }, + None => false, + } + } + fn parse_string(slot: &mut String, v: Option<&str>) -> bool { match v { Some(s) => { *slot = s.to_string(); true }, @@ -811,6 +821,13 @@ macro_rules! options { } } + fn parse_pathbuf_push(slot: &mut Vec, v: Option<&str>) -> bool { + match v { + Some(s) => { slot.push(PathBuf::from(s)); true }, + None => false, + } + } + fn parse_list(slot: &mut Vec, v: Option<&str>) -> bool { match v { @@ -931,7 +948,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, CG_OPTIONS, cg_type_desc, cgsetters, ar: Option = (None, parse_opt_string, [UNTRACKED], "this option is deprecated and does nothing"), - linker: Option = (None, parse_opt_string, [UNTRACKED], + linker: Option = (None, parse_opt_pathbuf, [UNTRACKED], "system linker to link outputs with"), link_arg: Vec = (vec![], parse_string_push, [UNTRACKED], "a single extra argument to append to the linker invocation (can be used several times)"), @@ -1151,9 +1168,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "set the optimization fuel quota for a crate"), print_fuel: Option = (None, parse_opt_string, [TRACKED], "make Rustc print the total optimization fuel used by a crate"), - remap_path_prefix_from: Vec = (vec![], parse_string_push, [TRACKED], + remap_path_prefix_from: Vec = (vec![], parse_pathbuf_push, [TRACKED], "add a source pattern to the file path remapping config"), - remap_path_prefix_to: Vec = (vec![], parse_string_push, [TRACKED], + remap_path_prefix_to: Vec = (vec![], parse_pathbuf_push, [TRACKED], "add a mapping target to the file path remapping config"), force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED], "force all crates to be `rustc_private` unstable"), @@ -1472,7 +1489,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec ) -> ast::CrateConfig { cfgspecs.into_iter().map(|s| { let sess = parse::ParseSess::new(FilePathMapping::empty()); let mut parser = - parse::new_parser_from_source_str(&sess, "cfgspec".to_string(), s.to_string()); + parse::new_parser_from_source_str(&sess, FileName::CfgSpec, s.to_string()); let meta_item = panictry!(parser.parse_meta_item()); @@ -1594,13 +1611,13 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) 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)) + a corresponding `-Zremap-path-prefix-to`", source.display())) } } 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)) + a corresponding `-Zremap-path-prefix-from`", target.display())) } } @@ -2001,6 +2018,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(usize); impl_dep_tracking_hash_via_hash!(u64); impl_dep_tracking_hash_via_hash!(String); + impl_dep_tracking_hash_via_hash!(PathBuf); impl_dep_tracking_hash_via_hash!(lint::Level); impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_via_hash!(Option); @@ -2025,6 +2043,7 @@ mod dep_tracking { impl_dep_tracking_hash_via_hash!(Option); impl_dep_tracking_hash_for_sortable_vec_of!(String); + impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf); impl_dep_tracking_hash_for_sortable_vec_of!(CrateType); impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level)); impl_dep_tracking_hash_for_sortable_vec_of!((String, Option, @@ -2533,7 +2552,7 @@ mod tests { opts.cg.ar = Some(String::from("abc")); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); - opts.cg.linker = Some(String::from("linker")); + opts.cg.linker = Some(PathBuf::from("linker")); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 36c1966bdc834..d6f72fb116dc0 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -69,10 +69,10 @@ pub struct Session { pub default_sysroot: Option, /// The name of the root source file of the crate, in the local file system. /// `None` means that there is no source file. - pub local_crate_source_file: Option, + pub local_crate_source_file: Option, /// 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 working_dir: (PathBuf, bool), pub lint_store: RefCell, pub buffered_lints: RefCell>, /// Set of (DiagnosticId, Option, message) tuples tracking @@ -864,7 +864,7 @@ pub fn build_session_(sopts: config::Options, let file_path_mapping = sopts.file_path_mapping(); let local_crate_source_file = local_crate_source_file.map(|path| { - file_path_mapping.map_prefix(path.to_string_lossy().into_owned()).0 + file_path_mapping.map_prefix(path).0 }); let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone()); @@ -874,7 +874,7 @@ pub fn build_session_(sopts: config::Options, let print_fuel = Cell::new(0); let working_dir = match env::current_dir() { - Ok(dir) => dir.to_string_lossy().into_owned(), + Ok(dir) => dir, Err(e) => { panic!(p_s.span_diagnostic.fatal(&format!("Current directory is invalid: {}", e))) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 86b05955f1972..a9ad0a591880e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -59,6 +59,7 @@ use syntax::ext::base::ExtCtxt; use syntax::fold::Folder; use syntax::parse::{self, PResult}; use syntax::util::node_count::NodeCounter; +use syntax_pos::FileName; use syntax; use syntax_ext; use arena::DroplessArena; @@ -306,17 +307,9 @@ fn keep_hygiene_data(sess: &Session) -> bool { sess.opts.debugging_opts.keep_hygiene_data } - -/// The name used for source code that doesn't originate in a file -/// (e.g. source from stdin or a string) -pub fn anon_src() -> String { - "".to_string() -} - -pub fn source_name(input: &Input) -> String { +pub fn source_name(input: &Input) -> FileName { match *input { - // FIXME (#9639): This needs to handle non-utf8 paths - Input::File(ref ifile) => ifile.to_str().unwrap().to_string(), + Input::File(ref ifile) => ifile.clone().into(), Input::Str { ref name, .. } => name.clone(), } } @@ -573,7 +566,9 @@ pub fn phase_1_parse_input<'a>(control: &CompileController, parse::parse_crate_from_file(file, &sess.parse_sess) } Input::Str { ref input, ref name } => { - parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess) + parse::parse_crate_from_source_str(name.clone(), + input.clone(), + &sess.parse_sess) } } })?; @@ -1135,10 +1130,10 @@ pub fn phase_5_run_llvm_passes(sess: &Session, (sess.compile_status(), trans) } -fn escape_dep_filename(filename: &str) -> String { +fn escape_dep_filename(filename: &FileName) -> String { // Apparently clang and gcc *only* escape spaces: // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4 - filename.replace(" ", "\\ ") + filename.to_string().replace(" ", "\\ ") } fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index d9b67e2d27f0c..8bfcb0cca05b4 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -98,7 +98,7 @@ use syntax::ast; use syntax::codemap::{CodeMap, FileLoader, RealFileLoader}; use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; -use syntax_pos::{DUMMY_SP, MultiSpan}; +use syntax_pos::{DUMMY_SP, MultiSpan, FileName}; #[cfg(test)] mod test; @@ -274,7 +274,7 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option)> { if ifile == "-" { let mut src = String::new(); io::stdin().read_to_string(&mut src).unwrap(); - Some((Input::Str { name: driver::anon_src(), input: src }, + Some((Input::Str { name: FileName::Anon, input: src }, None)) } else { Some((Input::File(PathBuf::from(ifile)), @@ -1165,7 +1165,9 @@ fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec { - parse::parse_crate_attrs_from_source_str(name.clone(), input.clone(), &sess.parse_sess) + parse::parse_crate_attrs_from_source_str(name.clone(), + input.clone(), + &sess.parse_sess) } } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d930739c9f014..8d99ed858ee0e 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -34,7 +34,7 @@ use syntax::print::{pprust}; use syntax::print::pprust::PrintState; use syntax::ptr::P; use syntax::util::small_vector::SmallVector; -use syntax_pos; +use syntax_pos::{self, FileName}; use graphviz as dot; @@ -841,7 +841,7 @@ pub fn fold_crate(sess: &Session, krate: ast::Crate, ppm: PpMode) -> ast::Crate } } -fn get_source(input: &Input, sess: &Session) -> (Vec, String) { +fn get_source(input: &Input, sess: &Session) -> (Vec, FileName) { let src_name = driver::source_name(input); let src = sess.codemap() .get_filemap(&src_name) @@ -885,7 +885,7 @@ pub fn print_after_parsing(sess: &Session, pprust::print_crate(sess.codemap(), &sess.parse_sess, krate, - src_name.to_string(), + src_name, &mut rdr, box out, annotation.pp_ann(), @@ -944,7 +944,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, pprust::print_crate(sess.codemap(), &sess.parse_sess, krate, - src_name.to_string(), + src_name, &mut rdr, box out, annotation.pp_ann(), @@ -969,7 +969,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, pprust_hir::print_crate(sess.codemap(), &sess.parse_sess, krate, - src_name.to_string(), + src_name, &mut rdr, box out, annotation.pp_ann(), @@ -1011,7 +1011,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session, let hir_map = annotation.hir_map().expect("--unpretty missing HIR map"); let mut pp_state = pprust_hir::State::new_from_input(sess.codemap(), &sess.parse_sess, - src_name.to_string(), + src_name, &mut rdr, box out, annotation.pp_ann(), diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 2f55bee210838..f04e01f3f961d 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -33,7 +33,7 @@ use rustc_trans_utils::trans_crate::TransCrate; use std::rc::Rc; use syntax::ast; use syntax::abi::Abi; -use syntax::codemap::{CodeMap, FilePathMapping}; +use syntax::codemap::{CodeMap, FilePathMapping, FileName}; use errors; use errors::emitter::Emitter; use errors::{Level, DiagnosticBuilder}; @@ -113,7 +113,7 @@ fn test_env(source_string: &str, rustc_trans::init(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let input = config::Input::Str { - name: driver::anon_src(), + name: FileName::Anon, input: source_string.to_string(), }; let krate = driver::phase_1_parse_input(&driver::CompileController::basic(), diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index a9c934e971345..6bba6fbc295c5 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -765,7 +765,7 @@ impl EmitterWriter { }))); } // Check to make sure we're not in any <*macros> - if !cm.span_to_filename(def_site).contains("macros>") && + if !cm.span_to_filename(def_site).is_macros() && !trace.macro_decl_name.starts_with("#[") || always_backtrace { new_labels.push((trace.call_site, @@ -791,7 +791,7 @@ impl EmitterWriter { if sp_label.span == DUMMY_SP { continue; } - if cm.span_to_filename(sp_label.span.clone()).contains("macros>") && + if cm.span_to_filename(sp_label.span.clone()).is_macros() && !always_backtrace { let v = sp_label.span.macro_backtrace(); @@ -987,14 +987,20 @@ impl EmitterWriter { buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber); buffer.append(buffer_msg_line_offset, - &format!("{}:{}:{}", loc.file.name, loc.line, loc.col.0 + 1), + &format!("{}:{}:{}", + loc.file.name, + loc.line, + loc.col.0 + 1), Style::LineAndColumn); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle); } } else { buffer.prepend(0, - &format!("{}:{}:{} - ", loc.file.name, loc.line, loc.col.0 + 1), + &format!("{}:{}:{} - ", + loc.file.name, + loc.line, + loc.col.0 + 1), Style::LineAndColumn); } } else if !self.short_message { @@ -1007,7 +1013,7 @@ impl EmitterWriter { // Then, the secondary file indicator buffer.prepend(buffer_msg_line_offset + 1, "::: ", Style::LineNumber); buffer.append(buffer_msg_line_offset + 1, - &annotated_file.file.name, + &annotated_file.file.name.to_string(), Style::LineAndColumn); for _ in 0..max_line_num_len { buffer.prepend(buffer_msg_line_offset + 1, " ", Style::NoStyle); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 870e9643ef725..90580de07be56 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -37,7 +37,7 @@ use syntax::attr; use syntax::ext::base::SyntaxExtension; use syntax::parse::filemap_to_stream; use syntax::symbol::Symbol; -use syntax_pos::{Span, NO_EXPANSION}; +use syntax_pos::{Span, NO_EXPANSION, FileName}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc::hir; @@ -460,7 +460,7 @@ impl CrateStore for cstore::CStore { } let (name, def) = data.get_macro(id.index); - let source_name = format!("<{} macros>", name); + let source_name = FileName::Macros(name.to_string()); let filemap = sess.parse_sess.codemap().new_filemap(source_name, def.body); let local_span = Span::new(filemap.start_pos, filemap.end_pos, NO_EXPANSION); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7de3b8a4264e3..caeee989283fc 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -39,7 +39,7 @@ use syntax::ast::{self, CRATE_NODE_ID}; use syntax::codemap::Spanned; use syntax::attr; use syntax::symbol::Symbol; -use syntax_pos; +use syntax_pos::{self, FileName}; use rustc::hir::{self, PatKind}; use rustc::hir::itemlikevisit::ItemLikeVisitor; @@ -279,20 +279,22 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // `-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); - 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) + match filemap.name { + FileName::Real(ref name) => { + 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(); + adapted.name = Path::new(&working_dir).join(name).into(); + Rc::new(adapted) + } + }, + // expanded code, not from a file + _ => filemap.clone(), } }) .collect::>(); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 602c70f9a1f4b..7989dba11f7b8 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1359,7 +1359,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc name: String::new(), qualname, span, - value: filename, + value: filename.to_string(), children, parent: None, decl_id: None, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index fddafed11f314..a815c81a6fe0b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -93,7 +93,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { let end = cm.lookup_char_pos(span.hi()); SpanData { - file_name: start.file.name.clone().into(), + file_name: start.file.name.clone().to_string().into(), byte_start: span.lo().0, byte_end: span.hi().0, line_start: Row::new_one_indexed(start.line as u32), @@ -117,6 +117,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { }; let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo()); result.push(ExternalCrateData { + // FIXME: change file_name field to PathBuf in rls-data + // https://github.com/nrc/rls-data/issues/7 file_name: SpanUtils::make_path_string(&lo_loc.file.name), num: n.as_u32(), id: GlobalCrateId { @@ -271,7 +273,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { name: item.ident.to_string(), qualname, span: self.span_from_span(sub_span.unwrap()), - value: filename, + value: filename.to_string(), parent: None, children: m.items .iter() diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index ff1a8541e06a6..25e81e6f326e1 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -14,7 +14,6 @@ use generated_code; use std::cell::Cell; use std::env; -use std::path::Path; use syntax::parse::lexer::{self, StringReader}; use syntax::parse::token::{self, Token}; @@ -37,16 +36,15 @@ impl<'a> SpanUtils<'a> { } } - pub fn make_path_string(file_name: &str) -> String { - let path = Path::new(file_name); - if path.is_absolute() { - path.clone().display().to_string() - } else { - env::current_dir() - .unwrap() - .join(&path) - .display() - .to_string() + pub fn make_path_string(path: &FileName) -> String { + match *path { + FileName::Real(ref path) if !path.is_absolute() => + env::current_dir() + .unwrap() + .join(&path) + .display() + .to_string(), + _ => path.to_string(), } } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index a182d7c6fbe06..ec1c7e16c71f0 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -57,7 +57,7 @@ pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_o // The third parameter is for env vars, used on windows to set up the // path for MSVC to find its DLLs, and gcc to find its bundled // toolchain -pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)>) { +pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)>) { let envs = vec![("PATH".into(), command_path(sess))]; // If our linker looks like a batch script on Windows then to execute this @@ -68,7 +68,7 @@ pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)> // This worked historically but is needed manually since #42436 (regression // was tagged as #42791) and some more info can be found on #44443 for // emscripten itself. - let cmd = |linker: &str| { + let cmd = |linker: &Path| { if cfg!(windows) && linker.ends_with(".bat") { let mut cmd = Command::new("cmd"); cmd.arg("/c").arg(linker); @@ -82,10 +82,11 @@ pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)> (linker.clone(), cmd(linker), envs) } else if sess.target.target.options.is_like_msvc { let (cmd, envs) = msvc_link_exe_cmd(sess); - ("link.exe".to_string(), cmd, envs) + (PathBuf::from("link.exe"), cmd, envs) } else { - let linker = &sess.target.target.options.linker; - (linker.clone(), cmd(linker), envs) + let linker = PathBuf::from(&sess.target.target.options.linker); + let cmd = cmd(&linker); + (linker, cmd, envs) } } @@ -696,7 +697,7 @@ fn link_natively(sess: &Session, let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); sess.struct_err(&format!("linking with `{}` failed: {}", - pname, + pname.display(), prog.status)) .note(&format!("{:?}", &cmd)) .note(&escape_string(&output)) @@ -707,7 +708,7 @@ fn link_natively(sess: &Session, info!("linker stdout:\n{}", escape_string(&prog.stdout)); }, Err(e) => { - sess.struct_err(&format!("could not exec the linker `{}`: {}", pname, e)) + sess.struct_err(&format!("could not exec the linker `{}`: {}", pname.display(), e)) .note(&format!("{:?}", &cmd)) .emit(); if sess.target.target.options.is_like_msvc && e.kind() == io::ErrorKind::NotFound { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index cb883e0349f31..d8e95cd2cf2e0 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1955,7 +1955,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { note.extend_from_slice(&prog.stdout); sess.struct_err(&format!("linking with `{}` failed: {}", - pname, + pname.display(), prog.status)) .note(&format!("{:?}", &cmd)) .note(str::from_utf8(¬e[..]).unwrap()) @@ -1964,7 +1964,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { } }, Err(e) => { - sess.err(&format!("could not exec the linker `{}`: {}", pname, e)); + sess.err(&format!("could not exec the linker `{}`: {}", pname.display(), e)); sess.abort_if_errors(); } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index b2ad538a8ab29..d09272df3451d 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -41,10 +41,10 @@ use libc::{c_uint, c_longlong}; use std::ffi::CString; use std::fmt::Write; use std::ptr; -use std::path::Path; +use std::path::{Path, PathBuf}; use syntax::ast; use syntax::symbol::{Interner, InternedString, Symbol}; -use syntax_pos::{self, Span}; +use syntax_pos::{self, Span, FileName}; // From DWARF 5. @@ -675,21 +675,21 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } pub fn file_metadata(cx: &CrateContext, - file_name: &str, + file_name: &FileName, defining_crate: CrateNum) -> DIFile { debug!("file_metadata: file_name: {}, defining_crate: {}", file_name, defining_crate); let directory = if defining_crate == LOCAL_CRATE { - &cx.sess().working_dir.0[..] + &cx.sess().working_dir.0 } else { // If the path comes from an upstream crate we assume it has been made // independent of the compiler's working directory one way or another. - "" + Path::new("") }; - file_metadata_raw(cx, file_name, directory) + file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy()) } pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile { @@ -792,7 +792,7 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, -> DIDescriptor { let mut name_in_debuginfo = match sess.local_crate_source_file { Some(ref path) => path.clone(), - None => scc.tcx().crate_name(LOCAL_CRATE).to_string(), + None => PathBuf::from(&*scc.tcx().crate_name(LOCAL_CRATE).as_str()), }; // The OSX linker has an idiosyncrasy where it will ignore some debuginfo @@ -800,8 +800,8 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, // As a workaround we generate unique names for each object file. Those do // not correspond to an actual source file but that should be harmless. if scc.sess().target.target.options.is_like_osx { - name_in_debuginfo.push_str("@"); - name_in_debuginfo.push_str(codegen_unit_name); + name_in_debuginfo.push("@"); + name_in_debuginfo.push(codegen_unit_name); } debug!("compile_unit_metadata: {:?}", name_in_debuginfo); @@ -809,8 +809,9 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext, let producer = format!("clang LLVM (rustc version {})", (option_env!("CFG_VERSION")).expect("CFG_VERSION")); + let name_in_debuginfo = name_in_debuginfo.to_string_lossy().into_owned(); let name_in_debuginfo = CString::new(name_in_debuginfo).unwrap(); - let work_dir = CString::new(&sess.working_dir.0[..]).unwrap(); + let work_dir = CString::new(&sess.working_dir.0.to_string_lossy()[..]).unwrap(); let producer = CString::new(producer).unwrap(); let flags = "\0"; let split_name = "\0"; diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index c0df25202d8a9..e9350256c3055 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -469,7 +469,7 @@ pub fn declare_local<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, let file = span_start(cx, span).file; let file_metadata = file_metadata(cx, - &file.name[..], + &file.name, dbg_context.get_ref(span).defining_crate); let loc = span_start(cx, span); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 94c8d469c642d..fd3408676db8c 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Get the location information. let loc = bcx.sess().codemap().lookup_char_pos(span.lo()); - let filename = Symbol::intern(&loc.file.name).as_str(); + let filename = Symbol::intern(&loc.file.name.to_string()).as_str(); let filename = C_str_slice(bcx.ccx, filename); let line = C_u32(bcx.ccx, loc.line as u32); let col = C_u32(bcx.ccx, loc.col.to_usize() as u32 + 1); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0e25d639e45d8..91908de98a65d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -25,7 +25,7 @@ use syntax::attr; use syntax::codemap::Spanned; use syntax::ptr::P; use syntax::symbol::keywords; -use syntax_pos::{self, DUMMY_SP, Pos}; +use syntax_pos::{self, DUMMY_SP, Pos, FileName}; use rustc::middle::const_val::ConstVal; use rustc::middle::privacy::AccessLevels; @@ -45,7 +45,6 @@ use rustc::hir; use rustc_const_math::ConstInt; use std::{mem, slice, vec}; use std::iter::FromIterator; -use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; use std::u32; @@ -114,7 +113,7 @@ impl, U> Clean> for P<[T]> { pub struct Crate { pub name: String, pub version: Option, - pub src: PathBuf, + pub src: FileName, pub module: Option, pub externs: Vec<(CrateNum, ExternalCrate)>, pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, @@ -200,7 +199,7 @@ impl<'a, 'tcx> Clean for visit_ast::RustdocVisitor<'a, 'tcx> { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct ExternalCrate { pub name: String, - pub src: PathBuf, + pub src: FileName, pub attrs: Attributes, pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, } @@ -271,7 +270,7 @@ impl Clean for CrateNum { ExternalCrate { name: cx.tcx.crate_name(*self).to_string(), - src: PathBuf::from(krate_src), + src: krate_src, attrs: cx.tcx.get_attrs(root).clean(cx), primitives, } @@ -2518,7 +2517,7 @@ impl Clean for hir::VariantData { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Span { - pub filename: String, + pub filename: FileName, pub loline: usize, pub locol: usize, pub hiline: usize, @@ -2528,7 +2527,7 @@ pub struct Span { impl Span { pub fn empty() -> Span { Span { - filename: "".to_string(), + filename: FileName::Anon, loline: 0, locol: 0, hiline: 0, hicol: 0, } @@ -2546,7 +2545,7 @@ impl Clean for syntax_pos::Span { let lo = cm.lookup_char_pos(self.lo()); let hi = cm.lookup_char_pos(self.hi()); Span { - filename: filename.to_string(), + filename, loline: lo.line, locol: lo.col.to_usize(), hiline: hi.line, diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 6b0f209c0c454..ef01c3e6bdb0c 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -30,7 +30,7 @@ use syntax::codemap::{CodeMap, FilePathMapping}; use syntax::parse::lexer::{self, TokenAndSpan}; use syntax::parse::token; use syntax::parse; -use syntax_pos::Span; +use syntax_pos::{Span, FileName}; /// Highlights `src`, returning the HTML output. pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>, @@ -38,7 +38,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> tooltip: Option<(&str, &str)>) -> String { debug!("highlighting: ================\n{}\n==============", src); let sess = parse::ParseSess::new(FilePathMapping::empty()); - let fm = sess.codemap().new_filemap("".to_string(), src.to_string()); + let fm = sess.codemap().new_filemap(FileName::Custom("stdin".to_string()), src.to_string()); let mut out = Vec::new(); if let Some((tooltip, class)) = tooltip { @@ -65,7 +65,7 @@ pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str> /// an enclosing `
` block.
 pub fn render_inner_with_highlighting(src: &str) -> io::Result {
     let sess = parse::ParseSess::new(FilePathMapping::empty());
-    let fm = sess.codemap().new_filemap("".to_string(), src.to_string());
+    let fm = sess.codemap().new_filemap(FileName::Custom("stdin".to_string()), src.to_string());
 
     let mut out = Vec::new();
     let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm), sess.codemap());
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 7e5f9b4e31115..8ed35aa8f4396 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -54,6 +54,7 @@ use externalfiles::ExternalHtml;
 
 use serialize::json::{ToJson, Json, as_json};
 use syntax::{abi, ast};
+use syntax::codemap::FileName;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
@@ -491,9 +492,12 @@ pub fn run(mut krate: clean::Crate,
            css_file_extension: Option,
            renderinfo: RenderInfo,
            render_type: RenderType) -> Result<(), Error> {
-    let src_root = match krate.src.parent() {
-        Some(p) => p.to_path_buf(),
-        None => PathBuf::new(),
+    let src_root = match krate.src {
+        FileName::Real(ref p) => match p.parent() {
+            Some(p) => p.to_path_buf(),
+            None => PathBuf::new(),
+        },
+        _ => PathBuf::new(),
     };
     let mut scx = SharedContext {
         src_root,
@@ -596,9 +600,12 @@ pub fn run(mut krate: clean::Crate,
 
     // Cache where all our extern crates are located
     for &(n, ref e) in &krate.externs {
-        let src_root = match Path::new(&e.src).parent() {
-            Some(p) => p.to_path_buf(),
-            None => PathBuf::new(),
+        let src_root = match e.src {
+            FileName::Real(ref p) => match p.parent() {
+                Some(p) => p.to_path_buf(),
+                None => PathBuf::new(),
+            },
+            _ => PathBuf::new(),
         };
         cache.extern_locations.insert(n, (e.name.clone(), src_root,
                                           extern_location(e, &cx.dst)));
@@ -1075,14 +1082,10 @@ impl<'a> DocFolder for SourceCollector<'a> {
         // If we're including source files, and we haven't seen this file yet,
         // then we need to render it out to the filesystem.
         if self.scx.include_sources
-            // skip all invalid spans
-            && item.source.filename != ""
+            // skip all invalid or macro spans
+            && item.source.filename.is_real()
             // skip non-local items
-            && item.def_id.is_local()
-            // Macros from other libraries get special filenames which we can
-            // safely ignore.
-            && !(item.source.filename.starts_with("<")
-                && item.source.filename.ends_with("macros>")) {
+            && item.def_id.is_local() {
 
             // If it turns out that we couldn't read this file, then we probably
             // can't read any of the files (generating html output from json or
@@ -1107,9 +1110,12 @@ impl<'a> DocFolder for SourceCollector<'a> {
 
 impl<'a> SourceCollector<'a> {
     /// Renders the given filename into its corresponding HTML source file.
-    fn emit_source(&mut self, filename: &str) -> io::Result<()> {
-        let p = PathBuf::from(filename);
-        if self.scx.local_sources.contains_key(&p) {
+    fn emit_source(&mut self, filename: &FileName) -> io::Result<()> {
+        let p = match *filename {
+            FileName::Real(ref file) => file,
+            _ => return Ok(()),
+        };
+        if self.scx.local_sources.contains_key(&**p) {
             // We've already emitted this source
             return Ok(());
         }
@@ -1158,7 +1164,7 @@ impl<'a> SourceCollector<'a> {
                        &page, &(""), &Source(contents),
                        self.scx.css_file_extension.is_some())?;
         w.flush()?;
-        self.scx.local_sources.insert(p, href);
+        self.scx.local_sources.insert(p.clone(), href);
         Ok(())
     }
 }
@@ -1670,18 +1676,20 @@ impl<'a> Item<'a> {
 
         let cache = cache();
         let mut path = String::new();
+
+        // We can safely ignore macros from other libraries
+        let file = match self.item.source.filename {
+            FileName::Real(ref path) => path,
+            _ => return None,
+        };
+
         let (krate, path) = if self.item.def_id.is_local() {
-            let path = PathBuf::from(&self.item.source.filename);
-            let path = self.cx.shared.local_sources.get(&path)?;
-            (&self.cx.shared.layout.krate, path)
-        } else {
-            // Macros from other libraries get special filenames which we can
-            // safely ignore.
-            if self.item.source.filename.starts_with("<") &&
-               self.item.source.filename.ends_with("macros>") {
+            if let Some(path) = self.cx.shared.local_sources.get(file) {
+                (&self.cx.shared.layout.krate, path)
+            } else {
                 return None;
             }
-
+        } else {
             let (krate, src_root) = match cache.extern_locations.get(&self.item.def_id.krate) {
                 Some(&(ref name, ref src, Local)) => (name, src),
                 Some(&(ref name, ref src, Remote(ref s))) => {
@@ -1691,7 +1699,6 @@ impl<'a> Item<'a> {
                 Some(&(_, _, Unknown)) | None => return None,
             };
 
-            let file = Path::new(&self.item.source.filename);
             clean_srcpath(&src_root, file, false, |component| {
                 path.push_str(component);
                 path.push('/');
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index f0bb87015f805..1cf71eca84681 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -58,7 +58,7 @@ use std::env;
 use std::fmt::Display;
 use std::io;
 use std::io::Write;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
 use std::process;
 use std::sync::mpsc::channel;
 
@@ -331,7 +331,8 @@ pub fn main_args(args: &[String]) -> isize {
                                           .collect();
 
     let should_test = matches.opt_present("test");
-    let markdown_input = input.ends_with(".md") || input.ends_with(".markdown");
+    let markdown_input = Path::new(input).extension()
+        .map_or(false, |e| e == "md" || e == "markdown");
 
     let output = matches.opt_str("o").map(|s| PathBuf::from(&s));
     let css_file_extension = matches.opt_str("e").map(|s| PathBuf::from(&s));
@@ -367,18 +368,18 @@ pub fn main_args(args: &[String]) -> isize {
     let playground_url = matches.opt_str("playground-url");
     let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
     let display_warnings = matches.opt_present("display-warnings");
-    let linker = matches.opt_str("linker");
+    let linker = matches.opt_str("linker").map(PathBuf::from);
 
     match (should_test, markdown_input) {
         (true, true) => {
-            return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot, render_type,
-                                  display_warnings, linker)
+            return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot,
+                                  render_type, display_warnings, linker)
         }
         (true, false) => {
-            return test::run(input, cfgs, libs, externs, test_args, crate_name, maybe_sysroot,
-                             render_type, display_warnings, linker)
+            return test::run(Path::new(input), cfgs, libs, externs, test_args, crate_name,
+                             maybe_sysroot, render_type, display_warnings, linker)
         }
-        (false, true) => return markdown::render(input,
+        (false, true) => return markdown::render(Path::new(input),
                                                  output.unwrap_or(PathBuf::from("doc")),
                                                  &matches, &external_html,
                                                  !matches.opt_present("markdown-no-toc"),
@@ -387,7 +388,7 @@ pub fn main_args(args: &[String]) -> isize {
     }
 
     let output_format = matches.opt_str("w");
-    let res = acquire_input(input, externs, &matches, move |out| {
+    let res = acquire_input(PathBuf::from(input), externs, &matches, move |out| {
         let Output { krate, passes, renderinfo } = out;
         info!("going to format");
         match output_format.as_ref().map(|s| &**s) {
@@ -424,7 +425,7 @@ fn print_error(error_message: T) where T: Display {
 
 /// Looks inside the command line arguments to extract the relevant input format
 /// and files and then generates the necessary rustdoc output for formatting.
-fn acquire_input(input: &str,
+fn acquire_input(input: PathBuf,
                        externs: Externs,
                        matches: &getopts::Matches,
                        f: F)
@@ -459,7 +460,7 @@ fn parse_externs(matches: &getopts::Matches) -> Result {
 /// generated from the cleaned AST of the crate.
 ///
 /// This form of input will run all of the plug/cleaning passes
-fn rust_input(cratefile: &str, externs: Externs, matches: &getopts::Matches, f: F) -> R
+fn rust_input(cratefile: PathBuf, externs: Externs, matches: &getopts::Matches, f: F) -> R
 where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
     let mut default_passes = !matches.opt_present("no-defaults");
     let mut passes = matches.opt_strs("passes");
@@ -488,7 +489,6 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
     let crate_version = matches.opt_str("crate-version");
     let plugin_path = matches.opt_str("plugin-path");
 
-    let cr = PathBuf::from(cratefile);
     info!("starting to run rustc");
     let display_warnings = matches.opt_present("display-warnings");
 
@@ -501,7 +501,7 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
         use rustc::session::config::Input;
 
         let (mut krate, renderinfo) =
-            core::run_core(paths, cfgs, externs, Input::File(cr), triple, maybe_sysroot,
+            core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
                            display_warnings, force_unstable_if_unmarked);
 
         info!("finished with rustc");
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 9b94e9918f850..af93505293cef 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -17,7 +17,7 @@ use getopts;
 use testing;
 use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::Externs;
-use syntax::codemap::DUMMY_SP;
+use syntax::codemap::{DUMMY_SP, FileName};
 
 use clean::Span;
 
@@ -54,15 +54,14 @@ fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
 
 /// Render `input` (e.g. "foo.md") into an HTML file in `output`
 /// (e.g. output = "bar" => "bar/foo.html").
-pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
+pub fn render(input: &Path, mut output: PathBuf, matches: &getopts::Matches,
               external_html: &ExternalHtml, include_toc: bool,
               render_type: RenderType) -> isize {
     // Span used for markdown hoedown/pulldown differences.
     let mut span = Span::empty();
-    span.filename = input.to_owned();
+    span.filename = FileName::Real(input.to_owned());
 
-    let input_p = Path::new(input);
-    output.push(input_p.file_stem().unwrap());
+    output.push(input.file_stem().unwrap());
     output.set_extension("html");
 
     let mut css = String::new();
@@ -175,7 +174,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
 /// Run any tests/code examples in the markdown file `input`.
 pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs,
             mut test_args: Vec, maybe_sysroot: Option,
-            render_type: RenderType, display_warnings: bool, linker: Option) -> isize {
+            render_type: RenderType, display_warnings: bool, linker: Option) -> isize {
     let input_str = match load_string(input) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
@@ -184,9 +183,9 @@ pub fn test(input: &str, cfgs: Vec, libs: SearchPaths, externs: Externs,
 
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
-    let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
+    let mut collector = Collector::new(input.to_owned(), cfgs, libs, externs,
                                        true, opts, maybe_sysroot, None,
-                                       Some(input.to_owned()),
+                                       Some(PathBuf::from(input)),
                                        render_type, linker);
     if render_type == RenderType::Pulldown {
         old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 74a16cb867d74..abb902003706c 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -38,7 +38,7 @@ use rustc_trans::back::link;
 use syntax::ast;
 use syntax::codemap::CodeMap;
 use syntax::feature_gate::UnstableFeatures;
-use syntax_pos::{BytePos, DUMMY_SP, Pos, Span};
+use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName};
 use errors;
 use errors::emitter::ColorConfig;
 
@@ -51,7 +51,7 @@ pub struct TestOptions {
     pub attrs: Vec,
 }
 
-pub fn run(input: &str,
+pub fn run(input_path: &Path,
            cfgs: Vec,
            libs: SearchPaths,
            externs: Externs,
@@ -60,10 +60,9 @@ pub fn run(input: &str,
            maybe_sysroot: Option,
            render_type: RenderType,
            display_warnings: bool,
-           linker: Option)
+           linker: Option)
            -> isize {
-    let input_path = PathBuf::from(input);
-    let input = config::Input::File(input_path.clone());
+    let input = config::Input::File(input_path.to_owned());
 
     let sessopts = config::Options {
         maybe_sysroot: maybe_sysroot.clone().or_else(
@@ -85,7 +84,7 @@ pub fn run(input: &str,
 
     let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
-        sessopts, Some(input_path.clone()), handler, codemap.clone(),
+        sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
     );
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@@ -177,12 +176,12 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
     opts
 }
 
-fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec, libs: SearchPaths,
+fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec, libs: SearchPaths,
             externs: Externs,
             should_panic: bool, no_run: bool, as_test_harness: bool,
             compile_fail: bool, mut error_codes: Vec, opts: &TestOptions,
             maybe_sysroot: Option,
-            linker: Option) {
+            linker: Option) {
     // the test harness wants its own `main` & top level functions, so
     // never wrap the test in `fn main() { ... }`
     let test = make_test(test, Some(cratename), as_test_harness, opts);
@@ -451,17 +450,17 @@ pub struct Collector {
     maybe_sysroot: Option,
     position: Span,
     codemap: Option>,
-    filename: Option,
+    filename: Option,
     // to be removed when hoedown will be removed as well
     pub render_type: RenderType,
-    linker: Option,
+    linker: Option,
 }
 
 impl Collector {
     pub fn new(cratename: String, cfgs: Vec, libs: SearchPaths, externs: Externs,
                use_headers: bool, opts: TestOptions, maybe_sysroot: Option,
-               codemap: Option>, filename: Option,
-               render_type: RenderType, linker: Option) -> Collector {
+               codemap: Option>, filename: Option,
+               render_type: RenderType, linker: Option) -> Collector {
         Collector {
             tests: Vec::new(),
             old_tests: HashMap::new(),
@@ -481,16 +480,16 @@ impl Collector {
         }
     }
 
-    fn generate_name(&self, line: usize, filename: &str) -> String {
+    fn generate_name(&self, line: usize, filename: &FileName) -> String {
         format!("{} - {} (line {})", filename, self.names.join("::"), line)
     }
 
     // to be removed once hoedown is gone
-    fn generate_name_beginning(&self, filename: &str) -> String {
+    fn generate_name_beginning(&self, filename: &FileName) -> String {
         format!("{} - {} (line", filename, self.names.join("::"))
     }
 
-    pub fn add_old_test(&mut self, test: String, filename: String) {
+    pub fn add_old_test(&mut self, test: String, filename: FileName) {
         let name_beg = self.generate_name_beginning(&filename);
         let entry = self.old_tests.entry(name_beg)
                                   .or_insert(Vec::new());
@@ -500,7 +499,7 @@ impl Collector {
     pub fn add_test(&mut self, test: String,
                     should_panic: bool, no_run: bool, should_ignore: bool,
                     as_test_harness: bool, compile_fail: bool, error_codes: Vec,
-                    line: usize, filename: String, allow_fail: bool) {
+                    line: usize, filename: FileName, allow_fail: bool) {
         let name = self.generate_name(line, &filename);
         // to be removed when hoedown is removed
         if self.render_type == RenderType::Pulldown {
@@ -578,21 +577,21 @@ impl Collector {
         self.position = position;
     }
 
-    pub fn get_filename(&self) -> String {
+    pub fn get_filename(&self) -> FileName {
         if let Some(ref codemap) = self.codemap {
             let filename = codemap.span_to_filename(self.position);
-            if let Ok(cur_dir) = env::current_dir() {
-                if let Ok(path) = Path::new(&filename).strip_prefix(&cur_dir) {
-                    if let Some(path) = path.to_str() {
-                        return path.to_owned();
+            if let FileName::Real(ref filename) = filename {
+                if let Ok(cur_dir) = env::current_dir() {
+                    if let Ok(path) = filename.strip_prefix(&cur_dir) {
+                        return path.to_owned().into();
                     }
                 }
             }
             filename
         } else if let Some(ref filename) = self.filename {
-            filename.clone()
+            filename.clone().into()
         } else {
-            "".to_owned()
+            FileName::Custom("input".to_owned())
         }
     }
 
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 3906ed431ce20..2c91d60ce9d59 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -164,7 +164,7 @@ impl CodeMap {
 
     pub fn load_file(&self, path: &Path) -> io::Result> {
         let src = self.file_loader.read_file(path)?;
-        Ok(self.new_filemap(path.to_str().unwrap().to_string(), src))
+        Ok(self.new_filemap(path.to_owned().into(), src))
     }
 
     pub fn files(&self) -> Ref>> {
@@ -196,9 +196,15 @@ impl CodeMap {
         // Note that filename may not be a valid path, eg it may be `` etc,
         // but this is okay because the directory determined by `path.pop()` will
         // be empty, so the working directory will be used.
-        let unmapped_path = PathBuf::from(filename.clone());
-
-        let (filename, was_remapped) = self.path_mapping.map_prefix(filename);
+        let unmapped_path = filename.clone();
+
+        let (filename, was_remapped) = match filename {
+            FileName::Real(filename) => {
+                let (filename, was_remapped) = self.path_mapping.map_prefix(filename);
+                (FileName::Real(filename), was_remapped)
+            },
+            other => (other, false),
+        };
         let filemap = Rc::new(FileMap::new(
             filename,
             was_remapped,
@@ -217,8 +223,8 @@ impl CodeMap {
     }
 
     /// Creates a new filemap and sets its line information.
-    pub fn new_filemap_and_lines(&self, filename: &str, src: &str) -> Rc {
-        let fm = self.new_filemap(filename.to_string(), src.to_owned());
+    pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Rc {
+        let fm = self.new_filemap(filename.to_owned().into(), src.to_owned());
         let mut byte_pos: u32 = fm.start_pos.0;
         for line in src.lines() {
             // register the start of this line
@@ -373,7 +379,7 @@ impl CodeMap {
     pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
         let loc = self.lookup_char_pos(pos);
         LocWithOpt {
-            filename: loc.file.name.to_string(),
+            filename: loc.file.name.clone(),
             line: loc.line,
             col: loc.col,
             file: Some(loc.file)
@@ -433,7 +439,7 @@ impl CodeMap {
         self.lookup_char_pos(sp.lo()).file.name.clone()
     }
 
-    pub fn span_to_unmapped_path(&self, sp: Span) -> PathBuf {
+    pub fn span_to_unmapped_path(&self, sp: Span) -> FileName {
         self.lookup_char_pos(sp.lo()).file.unmapped_path.clone()
             .expect("CodeMap::span_to_unmapped_path called for imported FileMap?")
     }
@@ -561,9 +567,9 @@ impl CodeMap {
         self.span_until_char(sp, '{')
     }
 
-    pub fn get_filemap(&self, filename: &str) -> Option> {
+    pub fn get_filemap(&self, filename: &FileName) -> Option> {
         for fm in self.files.borrow().iter() {
-            if filename == fm.name {
+            if *filename == fm.name {
                 return Some(fm.clone());
             }
         }
@@ -650,7 +656,7 @@ impl CodeMapper for CodeMap {
         self.merge_spans(sp_lhs, sp_rhs)
     }
     fn call_span_if_macro(&self, sp: Span) -> Span {
-        if self.span_to_filename(sp.clone()).contains("macros>") {
+        if self.span_to_filename(sp.clone()).is_macros() {
             let v = sp.macro_backtrace();
             if let Some(use_site) = v.last() {
                 return use_site.call_site;
@@ -660,14 +666,17 @@ impl CodeMapper for CodeMap {
     }
     fn ensure_filemap_source_present(&self, file_map: Rc) -> bool {
         file_map.add_external_src(
-            || self.file_loader.read_file(Path::new(&file_map.name)).ok()
+            || match file_map.name {
+                FileName::Real(ref name) => self.file_loader.read_file(name).ok(),
+                _ => None,
+            }
         )
     }
 }
 
 #[derive(Clone)]
 pub struct FilePathMapping {
-    mapping: Vec<(String, String)>,
+    mapping: Vec<(PathBuf, PathBuf)>,
 }
 
 impl FilePathMapping {
@@ -677,7 +686,7 @@ impl FilePathMapping {
         }
     }
 
-    pub fn new(mapping: Vec<(String, String)>) -> FilePathMapping {
+    pub fn new(mapping: Vec<(PathBuf, PathBuf)>) -> FilePathMapping {
         FilePathMapping {
             mapping,
         }
@@ -686,14 +695,13 @@ impl FilePathMapping {
     /// 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(&self, path: String) -> (String, bool) {
+    pub fn map_prefix(&self, path: PathBuf) -> (PathBuf, bool) {
         // NOTE: We are iterating over the mapping entries from last to first
         //       because entries specified later on the command line should
         //       take precedence.
         for &(ref from, ref to) in self.mapping.iter().rev() {
-            if path.starts_with(from) {
-                let mapped = path.replacen(from, to, 1);
-                return (mapped, true);
+            if let Ok(rest) = path.strip_prefix(from) {
+                return (to.join(rest), true);
             }
         }
 
@@ -714,7 +722,7 @@ mod tests {
     #[test]
     fn t1 () {
         let cm = CodeMap::new(FilePathMapping::empty());
-        let fm = cm.new_filemap("blork.rs".to_string(),
+        let fm = cm.new_filemap(PathBuf::from("blork.rs").into(),
                                 "first line.\nsecond line".to_string());
         fm.next_line(BytePos(0));
         // Test we can get lines with partial line info.
@@ -730,7 +738,7 @@ mod tests {
     #[should_panic]
     fn t2 () {
         let cm = CodeMap::new(FilePathMapping::empty());
-        let fm = cm.new_filemap("blork.rs".to_string(),
+        let fm = cm.new_filemap(PathBuf::from("blork.rs").into(),
                                 "first line.\nsecond line".to_string());
         // TESTING *REALLY* BROKEN BEHAVIOR:
         fm.next_line(BytePos(0));
@@ -740,11 +748,11 @@ mod tests {
 
     fn init_code_map() -> CodeMap {
         let cm = CodeMap::new(FilePathMapping::empty());
-        let fm1 = cm.new_filemap("blork.rs".to_string(),
+        let fm1 = cm.new_filemap(PathBuf::from("blork.rs").into(),
                                  "first line.\nsecond line".to_string());
-        let fm2 = cm.new_filemap("empty.rs".to_string(),
+        let fm2 = cm.new_filemap(PathBuf::from("empty.rs").into(),
                                  "".to_string());
-        let fm3 = cm.new_filemap("blork2.rs".to_string(),
+        let fm3 = cm.new_filemap(PathBuf::from("blork2.rs").into(),
                                  "first line.\nsecond line".to_string());
 
         fm1.next_line(BytePos(0));
@@ -762,15 +770,15 @@ mod tests {
         let cm = init_code_map();
 
         let fmabp1 = cm.lookup_byte_offset(BytePos(23));
-        assert_eq!(fmabp1.fm.name, "blork.rs");
+        assert_eq!(fmabp1.fm.name, PathBuf::from("blork.rs").into());
         assert_eq!(fmabp1.pos, BytePos(23));
 
         let fmabp1 = cm.lookup_byte_offset(BytePos(24));
-        assert_eq!(fmabp1.fm.name, "empty.rs");
+        assert_eq!(fmabp1.fm.name, PathBuf::from("empty.rs").into());
         assert_eq!(fmabp1.pos, BytePos(0));
 
         let fmabp2 = cm.lookup_byte_offset(BytePos(25));
-        assert_eq!(fmabp2.fm.name, "blork2.rs");
+        assert_eq!(fmabp2.fm.name, PathBuf::from("blork2.rs").into());
         assert_eq!(fmabp2.pos, BytePos(0));
     }
 
@@ -792,12 +800,12 @@ mod tests {
         let cm = init_code_map();
 
         let loc1 = cm.lookup_char_pos(BytePos(22));
-        assert_eq!(loc1.file.name, "blork.rs");
+        assert_eq!(loc1.file.name, PathBuf::from("blork.rs").into());
         assert_eq!(loc1.line, 2);
         assert_eq!(loc1.col, CharPos(10));
 
         let loc2 = cm.lookup_char_pos(BytePos(25));
-        assert_eq!(loc2.file.name, "blork2.rs");
+        assert_eq!(loc2.file.name, PathBuf::from("blork2.rs").into());
         assert_eq!(loc2.line, 1);
         assert_eq!(loc2.col, CharPos(0));
     }
@@ -806,9 +814,9 @@ mod tests {
         let cm = CodeMap::new(FilePathMapping::empty());
         // € is a three byte utf8 char.
         let fm1 =
-            cm.new_filemap("blork.rs".to_string(),
+            cm.new_filemap(PathBuf::from("blork.rs").into(),
                            "fir€st €€€€ line.\nsecond line".to_string());
-        let fm2 = cm.new_filemap("blork2.rs".to_string(),
+        let fm2 = cm.new_filemap(PathBuf::from("blork2.rs").into(),
                                  "first line€€.\n€ second line".to_string());
 
         fm1.next_line(BytePos(0));
@@ -853,7 +861,7 @@ mod tests {
         let span = Span::new(BytePos(12), BytePos(23), NO_EXPANSION);
         let file_lines = cm.span_to_lines(span).unwrap();
 
-        assert_eq!(file_lines.file.name, "blork.rs");
+        assert_eq!(file_lines.file.name, PathBuf::from("blork.rs").into());
         assert_eq!(file_lines.lines.len(), 1);
         assert_eq!(file_lines.lines[0].line_index, 1);
     }
@@ -876,7 +884,7 @@ mod tests {
         let cm = CodeMap::new(FilePathMapping::empty());
         let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
         let selection = "     \n    ~~\n~~~\n~~~~~     \n   \n";
-        cm.new_filemap_and_lines("blork.rs", inputtext);
+        cm.new_filemap_and_lines(Path::new("blork.rs"), inputtext);
         let span = span_from_selection(inputtext, selection);
 
         // check that we are extracting the text we thought we were extracting
@@ -919,7 +927,7 @@ mod tests {
         let inputtext  = "bbbb BB\ncc CCC\n";
         let selection1 = "     ~~\n      \n";
         let selection2 = "       \n   ~~~\n";
-        cm.new_filemap_and_lines("blork.rs", inputtext);
+        cm.new_filemap_and_lines(Path::new("blork.rs"), inputtext);
         let span1 = span_from_selection(inputtext, selection1);
         let span2 = span_from_selection(inputtext, selection2);
 
diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs
index daa7112235f47..5f06475919fec 100644
--- a/src/libsyntax/diagnostics/metadata.rs
+++ b/src/libsyntax/diagnostics/metadata.rs
@@ -20,7 +20,7 @@ use std::io::Write;
 use std::error::Error;
 use rustc_serialize::json::as_json;
 
-use syntax_pos::Span;
+use syntax_pos::{Span, FileName};
 use ext::base::ExtCtxt;
 use diagnostics::plugin::{ErrorMap, ErrorInfo};
 
@@ -40,7 +40,7 @@ pub type ErrorMetadataMap = BTreeMap;
 /// JSON encodable error location type with filename and line number.
 #[derive(PartialEq, RustcDecodable, RustcEncodable)]
 pub struct ErrorLocation {
-    pub filename: String,
+    pub filename: FileName,
     pub line: usize
 }
 
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 82e7747b01461..9a96432f11d4e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -759,7 +759,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
 
     fn expr_fail(&self, span: Span, msg: Symbol) -> P {
         let loc = self.codemap().lookup_char_pos(span.lo());
-        let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name));
+        let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name.to_string()));
         let expr_line = self.expr_u32(span, loc.line as u32);
         let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1);
         let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]);
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index ecb396f259f73..edf3d40be94a6 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -27,7 +27,7 @@ use parse::parser::Parser;
 use ptr::P;
 use symbol::Symbol;
 use symbol::keywords;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Span, DUMMY_SP, FileName};
 use syntax_pos::hygiene::ExpnFormat;
 use tokenstream::{TokenStream, TokenTree};
 use util::small_vector::SmallVector;
@@ -38,6 +38,7 @@ use std::fs::File;
 use std::io::Read;
 use std::mem;
 use std::rc::Rc;
+use std::path::PathBuf;
 
 macro_rules! expansions {
     ($($kind:ident: $ty:ty [$($vec:ident, $ty_elt:ty)*], $kind_name:expr, .$make:ident,
@@ -220,7 +221,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
         let mut module = ModuleData {
             mod_path: vec![Ident::from_str(&self.cx.ecfg.crate_name)],
-            directory: self.cx.codemap().span_to_unmapped_path(krate.span),
+            directory: match self.cx.codemap().span_to_unmapped_path(krate.span) {
+                FileName::Real(path) => path,
+                other => PathBuf::from(other.to_string()),
+            },
         };
         module.directory.pop();
         self.cx.root_path = module.directory.clone();
@@ -978,7 +982,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
                         module.directory.push(&*item.ident.name.as_str());
                     }
                 } else {
-                    let mut path = self.cx.parse_sess.codemap().span_to_unmapped_path(inner);
+                    let path = self.cx.parse_sess.codemap().span_to_unmapped_path(inner);
+                    let mut path = match path {
+                        FileName::Real(path) => path,
+                        other => PathBuf::from(other.to_string()),
+                    };
                     let directory_ownership = match path.file_name().unwrap().to_str() {
                         Some("mod.rs") => DirectoryOwnership::Owned,
                         _ => DirectoryOwnership::UnownedViaMod(false),
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index bd8c9a0ed40b2..426dde4f2a763 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -18,7 +18,6 @@ use parse::token;
 use ptr::P;
 use tokenstream::{TokenStream, TokenTree};
 
-
 /// Quasiquoting works via token trees.
 ///
 /// This is registered as a set of expression syntax extension called quote!
@@ -38,7 +37,7 @@ pub mod rt {
     use tokenstream::{self, TokenTree, TokenStream};
 
     pub use parse::new_parser_from_tts;
-    pub use syntax_pos::{BytePos, Span, DUMMY_SP};
+    pub use syntax_pos::{BytePos, Span, DUMMY_SP, FileName};
     pub use codemap::{dummy_spanned};
 
     pub trait ToTokens {
@@ -343,27 +342,27 @@ pub mod rt {
     impl<'a> ExtParseUtils for ExtCtxt<'a> {
         fn parse_item(&self, s: String) -> P {
             panictry!(parse::parse_item_from_source_str(
-                "".to_string(),
+                FileName::QuoteExpansion,
                 s,
                 self.parse_sess())).expect("parse error")
         }
 
         fn parse_stmt(&self, s: String) -> ast::Stmt {
             panictry!(parse::parse_stmt_from_source_str(
-                "".to_string(),
+                FileName::QuoteExpansion,
                 s,
                 self.parse_sess())).expect("parse error")
         }
 
         fn parse_expr(&self, s: String) -> P {
             panictry!(parse::parse_expr_from_source_str(
-                "".to_string(),
+                FileName::QuoteExpansion,
                 s,
                 self.parse_sess()))
         }
 
         fn parse_tts(&self, s: String) -> Vec {
-            let source_name = "".to_owned();
+            let source_name = FileName::QuoteExpansion;
             parse::parse_stream_from_source_str(source_name, s, self.parse_sess(), None)
                 .into_trees().collect()
         }
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 86657e675b2de..2a80686aa0f30 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use ast;
-use syntax_pos::{self, Pos, Span};
+use syntax_pos::{self, Pos, Span, FileName};
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
@@ -23,7 +23,7 @@ use util::small_vector::SmallVector;
 
 use std::fs::File;
 use std::io::prelude::*;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::rc::Rc;
 
 // These macros all relate to the file system; they either return
@@ -71,7 +71,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
 
     let topmost = cx.expansion_cause().unwrap_or(sp);
     let loc = cx.codemap().lookup_char_pos(topmost.lo());
-    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name)))
+    base::MacEager::expr(cx.expr_str(topmost, Symbol::intern(&loc.file.name.to_string())))
 }
 
 pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
@@ -99,7 +99,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
         None => return DummyResult::expr(sp),
     };
     // The file will be added to the code map by the parser
-    let path = res_rel_file(cx, sp, Path::new(&file));
+    let path = res_rel_file(cx, sp, file);
     let directory_ownership = DirectoryOwnership::Owned;
     let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
 
@@ -135,7 +135,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT
         Some(f) => f,
         None => return DummyResult::expr(sp)
     };
-    let file = res_rel_file(cx, sp, Path::new(&file));
+    let file = res_rel_file(cx, sp, file);
     let mut bytes = Vec::new();
     match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) {
         Ok(..) => {}
@@ -151,8 +151,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenT
         Ok(src) => {
             // Add this input file to the code map to make it available as
             // dependency information
-            let filename = format!("{}", file.display());
-            cx.codemap().new_filemap_and_lines(&filename, &src);
+            cx.codemap().new_filemap_and_lines(&file, &src);
 
             base::MacEager::expr(cx.expr_str(sp, Symbol::intern(&src)))
         }
@@ -171,7 +170,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke
         Some(f) => f,
         None => return DummyResult::expr(sp)
     };
-    let file = res_rel_file(cx, sp, Path::new(&file));
+    let file = res_rel_file(cx, sp, file);
     let mut bytes = Vec::new();
     match File::open(&file).and_then(|mut f| f.read_to_end(&mut bytes)) {
         Err(e) => {
@@ -182,8 +181,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke
         Ok(..) => {
             // Add this input file to the code map to make it available as
             // dependency information, but don't enter it's contents
-            let filename = format!("{}", file.display());
-            cx.codemap().new_filemap_and_lines(&filename, "");
+            cx.codemap().new_filemap_and_lines(&file, "");
 
             base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Rc::new(bytes))))
         }
@@ -192,16 +190,20 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::Toke
 
 // resolve a file-system path to an absolute file-system path (if it
 // isn't already)
-fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: &Path) -> PathBuf {
+fn res_rel_file(cx: &mut ExtCtxt, sp: syntax_pos::Span, arg: String) -> PathBuf {
+    let arg = PathBuf::from(arg);
     // Relative paths are resolved relative to the file in which they are found
     // after macro expansion (that is, they are unhygienic).
     if !arg.is_absolute() {
         let callsite = sp.source_callsite();
-        let mut path = cx.codemap().span_to_unmapped_path(callsite);
+        let mut path = match cx.codemap().span_to_unmapped_path(callsite) {
+            FileName::Real(path) => path,
+            other => panic!("cannot resolve relative path in non-file source `{}`", other),
+        };
         path.pop();
         path.push(arg);
         path
     } else {
-        arg.to_path_buf()
+        arg
     }
 }
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index 80ac0cb4faf7d..54c726d84621f 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -282,7 +282,7 @@ impl DiagnosticSpan {
             })
         });
         DiagnosticSpan {
-            file_name: start.file.name.clone(),
+            file_name: start.file.name.to_string(),
             byte_start: span.lo().0 - start.file.start_pos.0,
             byte_end: span.hi().0 - start.file.start_pos.0,
             line_start: start.line,
diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs
index fb558d1a58f85..23449ee69abb3 100644
--- a/src/libsyntax/parse/lexer/comments.rs
+++ b/src/libsyntax/parse/lexer/comments.rs
@@ -12,7 +12,7 @@ pub use self::CommentStyle::*;
 
 use ast;
 use codemap::CodeMap;
-use syntax_pos::{BytePos, CharPos, Pos};
+use syntax_pos::{BytePos, CharPos, Pos, FileName};
 use parse::lexer::{is_block_doc_comment, is_pattern_whitespace};
 use parse::lexer::{self, ParseSess, StringReader, TokenAndSpan};
 use print::pprust;
@@ -343,7 +343,7 @@ pub struct Literal {
 
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
-pub fn gather_comments_and_literals(sess: &ParseSess, path: String, srdr: &mut Read)
+pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut Read)
                                     -> (Vec, Vec) {
     let mut src = Vec::new();
     srdr.read_to_end(&mut src).unwrap();
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index d9c33fa50bd89..798dfc6d20974 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1714,6 +1714,7 @@ mod tests {
     use std::cell::RefCell;
     use std::collections::HashSet;
     use std::io;
+    use std::path::PathBuf;
     use std::rc::Rc;
 
     fn mk_sess(cm: Rc) -> ParseSess {
@@ -1735,7 +1736,7 @@ mod tests {
                  sess: &'a ParseSess,
                  teststr: String)
                  -> StringReader<'a> {
-        let fm = cm.new_filemap("zebra.rs".to_string(), teststr);
+        let fm = cm.new_filemap(PathBuf::from("zebra.rs").into(), teststr);
         StringReader::new(sess, fm)
     }
 
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index c679efd41ea46..4d435665d3ca9 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -12,7 +12,7 @@
 
 use ast::{self, CrateConfig};
 use codemap::{CodeMap, FilePathMapping};
-use syntax_pos::{self, Span, FileMap, NO_EXPANSION};
+use syntax_pos::{self, Span, FileMap, NO_EXPANSION, FileName};
 use errors::{Handler, ColorConfig, DiagnosticBuilder};
 use feature_gate::UnstableFeatures;
 use parse::parser::Parser;
@@ -107,17 +107,17 @@ pub fn parse_crate_attrs_from_file<'a>(input: &Path, sess: &'a ParseSess)
     parser.parse_inner_attributes()
 }
 
-pub fn parse_crate_from_source_str(name: String, source: String, sess: &ParseSess)
+pub fn parse_crate_from_source_str(name: FileName, source: String, sess: &ParseSess)
                                        -> PResult {
     new_parser_from_source_str(sess, name, source).parse_crate_mod()
 }
 
-pub fn parse_crate_attrs_from_source_str(name: String, source: String, sess: &ParseSess)
+pub fn parse_crate_attrs_from_source_str(name: FileName, source: String, sess: &ParseSess)
                                              -> PResult> {
     new_parser_from_source_str(sess, name, source).parse_inner_attributes()
 }
 
-pub fn parse_expr_from_source_str(name: String, source: String, sess: &ParseSess)
+pub fn parse_expr_from_source_str(name: FileName, source: String, sess: &ParseSess)
                                       -> PResult> {
     new_parser_from_source_str(sess, name, source).parse_expr()
 }
@@ -126,29 +126,29 @@ pub fn parse_expr_from_source_str(name: String, source: String, sess: &ParseSess
 ///
 /// Returns `Ok(Some(item))` when successful, `Ok(None)` when no item was found, and `Err`
 /// when a syntax error occurred.
-pub fn parse_item_from_source_str(name: String, source: String, sess: &ParseSess)
+pub fn parse_item_from_source_str(name: FileName, source: String, sess: &ParseSess)
                                       -> PResult>> {
     new_parser_from_source_str(sess, name, source).parse_item()
 }
 
-pub fn parse_meta_from_source_str(name: String, source: String, sess: &ParseSess)
+pub fn parse_meta_from_source_str(name: FileName, source: String, sess: &ParseSess)
                                       -> PResult {
     new_parser_from_source_str(sess, name, source).parse_meta_item()
 }
 
-pub fn parse_stmt_from_source_str(name: String, source: String, sess: &ParseSess)
+pub fn parse_stmt_from_source_str(name: FileName, source: String, sess: &ParseSess)
                                       -> PResult> {
     new_parser_from_source_str(sess, name, source).parse_stmt()
 }
 
-pub fn parse_stream_from_source_str(name: String, source: String, sess: &ParseSess,
+pub fn parse_stream_from_source_str(name: FileName, source: String, sess: &ParseSess,
                                     override_span: Option)
                                     -> TokenStream {
     filemap_to_stream(sess, sess.codemap().new_filemap(name, source), override_span)
 }
 
 // Create a new parser from a source string
-pub fn new_parser_from_source_str(sess: &ParseSess, name: String, source: String)
+pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String)
                                       -> Parser {
     let mut parser = filemap_to_parser(sess, sess.codemap().new_filemap(name, source));
     parser.recurse_into_file_modules = false;
@@ -1018,7 +1018,7 @@ mod tests {
     #[test] fn crlf_doc_comments() {
         let sess = ParseSess::new(FilePathMapping::empty());
 
-        let name = "".to_string();
+        let name = FileName::Custom("source".to_string());
         let source = "/// doc comment\r\nfn foo() {}".to_string();
         let item = parse_item_from_source_str(name.clone(), source, &sess)
             .unwrap().unwrap();
@@ -1042,7 +1042,7 @@ mod tests {
     #[test]
     fn ttdelim_span() {
         let sess = ParseSess::new(FilePathMapping::empty());
-        let expr = parse::parse_expr_from_source_str("foo".to_string(),
+        let expr = parse::parse_expr_from_source_str(PathBuf::from("foo").into(),
             "foo!( fn main() { body } )".to_string(), &sess).unwrap();
 
         let tts: Vec<_> = match expr.node {
@@ -1065,7 +1065,7 @@ mod tests {
     fn out_of_line_mod() {
         let sess = ParseSess::new(FilePathMapping::empty());
         let item = parse_item_from_source_str(
-            "foo".to_owned(),
+            PathBuf::from("foo").into(),
             "mod foo { struct S; mod this_does_not_exist; }".to_owned(),
             &sess,
         ).unwrap().unwrap();
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 726db7334824e..b3ef70fd18eb9 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -41,7 +41,7 @@ use ast::{BinOpKind, UnOp};
 use ast::{RangeEnd, RangeSyntax};
 use {ast, attr};
 use codemap::{self, CodeMap, Spanned, respan};
-use syntax_pos::{self, Span, BytePos};
+use syntax_pos::{self, Span, BytePos, FileName, DUMMY_SP};
 use errors::{self, DiagnosticBuilder};
 use parse::{self, classify, token};
 use parse::common::SeqSep;
@@ -527,9 +527,11 @@ impl<'a> Parser<'a> {
 
         if let Some(directory) = directory {
             parser.directory = directory;
-        } else if parser.span != syntax_pos::DUMMY_SP {
-            parser.directory.path = sess.codemap().span_to_unmapped_path(parser.span);
-            parser.directory.path.pop();
+        } else if !parser.span.source_equal(&DUMMY_SP) {
+            if let FileName::Real(path) = sess.codemap().span_to_unmapped_path(parser.span) {
+                parser.directory.path = path;
+                parser.directory.path.pop();
+            }
         }
 
         parser.process_potential_macro_variable();
@@ -5764,15 +5766,17 @@ impl<'a> Parser<'a> {
             let mut err = self.diagnostic().struct_span_err(id_sp,
                 "cannot declare a new module at this location");
             if id_sp != syntax_pos::DUMMY_SP {
-                let src_path = PathBuf::from(self.sess.codemap().span_to_filename(id_sp));
-                if let Some(stem) = src_path.file_stem() {
-                    let mut dest_path = src_path.clone();
-                    dest_path.set_file_name(stem);
-                    dest_path.push("mod.rs");
-                    err.span_note(id_sp,
-                                  &format!("maybe move this module `{}` to its own \
-                                            directory via `{}`", src_path.to_string_lossy(),
-                                           dest_path.to_string_lossy()));
+                let src_path = self.sess.codemap().span_to_filename(id_sp);
+                if let FileName::Real(src_path) = src_path {
+                    if let Some(stem) = src_path.file_stem() {
+                        let mut dest_path = src_path.clone();
+                        dest_path.set_file_name(stem);
+                        dest_path.push("mod.rs");
+                        err.span_note(id_sp,
+                                    &format!("maybe move this module `{}` to its own \
+                                                directory via `{}`", src_path.display(),
+                                            dest_path.display()));
+                    }
                 }
             }
             if paths.path_exists {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 26f39f608807d..05368c52d2c32 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -21,7 +21,7 @@ use ptr::P;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use symbol::keywords;
 use syntax::parse::parse_stream_from_source_str;
-use syntax_pos::{self, Span};
+use syntax_pos::{self, Span, FileName};
 use tokenstream::{TokenStream, TokenTree};
 use tokenstream;
 
@@ -495,9 +495,8 @@ impl Token {
         tokens.unwrap_or_else(|| {
             nt.1.force(|| {
                 // FIXME(jseyfried): Avoid this pretty-print + reparse hack
-                let name = "".to_owned();
                 let source = pprust::token_to_string(self);
-                parse_stream_from_source_str(name, source, sess, Some(span))
+                parse_stream_from_source_str(FileName::MacroExpansion, source, sess, Some(span))
             })
         })
     }
@@ -629,7 +628,7 @@ fn prepend_attrs(sess: &ParseSess,
         assert_eq!(attr.style, ast::AttrStyle::Outer,
                    "inner attributes should prevent cached tokens from existing");
         // FIXME: Avoid this pretty-print + reparse hack as bove
-        let name = "".to_owned();
+        let name = FileName::MacroExpansion;
         let source = pprust::attr_to_string(attr);
         let stream = parse_stream_from_source_str(name, source, sess, Some(span));
         builder.push(stream);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 17f37d0f2c0ee..e4b7dc26d3261 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -27,7 +27,7 @@ use print::pp::Breaks::{Consistent, Inconsistent};
 use ptr::P;
 use std_inject;
 use symbol::{Symbol, keywords};
-use syntax_pos::DUMMY_SP;
+use syntax_pos::{DUMMY_SP, FileName};
 use tokenstream::{self, TokenStream, TokenTree};
 
 use std::ascii;
@@ -87,7 +87,7 @@ pub const DEFAULT_COLUMNS: usize = 78;
 pub fn print_crate<'a>(cm: &'a CodeMap,
                        sess: &ParseSess,
                        krate: &ast::Crate,
-                       filename: String,
+                       filename: FileName,
                        input: &mut Read,
                        out: Box,
                        ann: &'a PpAnn,
@@ -120,7 +120,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
 impl<'a> State<'a> {
     pub fn new_from_input(cm: &'a CodeMap,
                           sess: &ParseSess,
-                          filename: String,
+                          filename: FileName,
                           input: &mut Read,
                           out: Box,
                           ann: &'a PpAnn,
diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs
index a29250ea5f19f..5072f2e2793f1 100644
--- a/src/libsyntax/test_snippet.rs
+++ b/src/libsyntax/test_snippet.rs
@@ -16,6 +16,7 @@ use std::io::prelude::*;
 use std::rc::Rc;
 use std::str;
 use std::sync::{Arc, Mutex};
+use std::path::Path;
 use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan};
 
 /// Identify a position in the text by the Nth occurrence of a string.
@@ -48,7 +49,7 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: &
     let output = Arc::new(Mutex::new(Vec::new()));
 
     let code_map = Rc::new(CodeMap::new(FilePathMapping::empty()));
-    code_map.new_filemap_and_lines("test.rs", &file_text);
+    code_map.new_filemap_and_lines(Path::new("test.rs"), &file_text);
 
     let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
     let mut msp = MultiSpan::from_span(primary_span);
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index d993ba14a4ab5..42cd7c8faa532 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -16,16 +16,18 @@ use parse::parser::Parser;
 use ptr::P;
 use tokenstream::TokenStream;
 use std::iter::Peekable;
+use std::path::PathBuf;
 
 /// Map a string to tts, using a made-up filename:
 pub fn string_to_stream(source_str: String) -> TokenStream {
     let ps = ParseSess::new(FilePathMapping::empty());
-    filemap_to_stream(&ps, ps.codemap().new_filemap("bogofile".to_string(), source_str), None)
+    filemap_to_stream(&ps, ps.codemap()
+                             .new_filemap(PathBuf::from("bogofile").into(), source_str), None)
 }
 
 /// Map string to parser (via tts)
 pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
-    new_parser_from_source_str(ps, "bogofile".to_string(), source_str)
+    new_parser_from_source_str(ps, PathBuf::from("bogofile").into(), source_str)
 }
 
 fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> T where
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index ec652b5607ec4..2a3812516632a 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -54,7 +54,78 @@ pub use span_encoding::{Span, DUMMY_SP};
 
 pub mod symbol;
 
-pub type FileName = String;
+/// Differentiates between real files and common virtual files
+#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
+pub enum FileName {
+    Real(PathBuf),
+    /// e.g. "std" macros
+    Macros(String),
+    /// call to `quote!`
+    QuoteExpansion,
+    /// Command line
+    Anon,
+    /// Hack in src/libsyntax/parse.rs
+    /// FIXME(jseyfried)
+    MacroExpansion,
+    ProcMacroSourceCode,
+    /// Strings provided as --cfg [cfgspec] stored in a crate_cfg
+    CfgSpec,
+    /// Custom sources for explicit parser calls from plugins and drivers
+    Custom(String),
+}
+
+impl std::fmt::Display for FileName {
+    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
+        use self::FileName::*;
+        match *self {
+            Real(ref path) => write!(fmt, "{}", path.display()),
+            Macros(ref name) => write!(fmt, "<{} macros>", name),
+            QuoteExpansion => write!(fmt, ""),
+            MacroExpansion => write!(fmt, ""),
+            Anon => write!(fmt, ""),
+            ProcMacroSourceCode => write!(fmt, ""),
+            CfgSpec => write!(fmt, "cfgspec"),
+            Custom(ref s) => write!(fmt, "<{}>", s),
+        }
+    }
+}
+
+impl From for FileName {
+    fn from(p: PathBuf) -> Self {
+        assert!(!p.to_string_lossy().ends_with('>'));
+        FileName::Real(p)
+    }
+}
+
+impl FileName {
+    pub fn is_real(&self) -> bool {
+        use self::FileName::*;
+        match *self {
+            Real(_) => true,
+            Macros(_) |
+            Anon |
+            MacroExpansion |
+            ProcMacroSourceCode |
+            CfgSpec |
+            Custom(_) |
+            QuoteExpansion => false,
+        }
+    }
+
+    pub fn is_macros(&self) -> bool {
+        use self::FileName::*;
+        match *self {
+            Real(_) |
+            Anon |
+            MacroExpansion |
+            ProcMacroSourceCode |
+            CfgSpec |
+            Custom(_) |
+            QuoteExpansion => false,
+            Macros(_) => true,
+        }
+    }
+}
 
 /// Spans represent a region of code, used for error reporting. Positions in spans
 /// are *absolute* positions from the beginning of the codemap, not positions
@@ -600,7 +671,7 @@ pub struct FileMap {
     pub name_was_remapped: bool,
     /// The unmapped path of the file that the source came from.
     /// Set to `None` if the FileMap was imported from an external crate.
-    pub unmapped_path: Option,
+    pub unmapped_path: Option,
     /// Indicates which crate this FileMap was imported from.
     pub crate_of_origin: u32,
     /// The complete source code
@@ -690,7 +761,7 @@ impl Decodable for FileMap {
     fn decode(d: &mut D) -> Result {
 
         d.read_struct("FileMap", 8, |d| {
-            let name: String = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
+            let name: FileName = d.read_struct_field("name", 0, |d| Decodable::decode(d))?;
             let name_was_remapped: bool =
                 d.read_struct_field("name_was_remapped", 1, |d| Decodable::decode(d))?;
             let src_hash: u128 =
@@ -760,7 +831,7 @@ impl fmt::Debug for FileMap {
 impl FileMap {
     pub fn new(name: FileName,
                name_was_remapped: bool,
-               unmapped_path: PathBuf,
+               unmapped_path: FileName,
                mut src: String,
                start_pos: BytePos) -> FileMap {
         remove_bom(&mut src);
@@ -893,8 +964,7 @@ impl FileMap {
     }
 
     pub fn is_real_file(&self) -> bool {
-        !(self.name.starts_with("<") &&
-          self.name.ends_with(">"))
+        self.name.is_real()
     }
 
     pub fn is_imported(&self) -> bool {
@@ -1114,18 +1184,18 @@ pub enum SpanSnippetError {
     IllFormedSpan(Span),
     DistinctSources(DistinctSources),
     MalformedForCodemap(MalformedCodemapPositions),
-    SourceNotAvailable { filename: String }
+    SourceNotAvailable { filename: FileName }
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct DistinctSources {
-    pub begin: (String, BytePos),
-    pub end: (String, BytePos)
+    pub begin: (FileName, BytePos),
+    pub end: (FileName, BytePos)
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct MalformedCodemapPositions {
-    pub name: String,
+    pub name: FileName,
     pub source_len: usize,
     pub begin_pos: BytePos,
     pub end_pos: BytePos
diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs
index c73739bb76543..ea0c9ad2b8324 100644
--- a/src/test/codegen/remap_path_prefix/main.rs
+++ b/src/test/codegen/remap_path_prefix/main.rs
@@ -32,7 +32,7 @@ fn main() {
 }
 
 // Here we check that local debuginfo is mapped correctly.
-// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd")
+// CHECK: !DIFile(filename: "/the/src/remap_path_prefix/main.rs", directory: "/the/cwd/")
 
 // And here that debuginfo from other crates are expanded to absolute paths.
 // CHECK: !DIFile(filename: "/the/aux-src/remap_path_prefix_aux.rs", directory: "")
diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs
index 4db027aaeef71..cfe8048638a86 100644
--- a/src/test/run-make/issue-19371/foo.rs
+++ b/src/test/run-make/issue-19371/foo.rs
@@ -19,13 +19,13 @@ extern crate rustc_trans;
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
-use rustc::session::config::{basic_options, build_configuration, Input,
+use rustc::session::config::{basic_options, Input,
                              OutputType, OutputTypes};
-use rustc_driver::driver::{compile_input, CompileController, anon_src};
+use rustc_driver::driver::{compile_input, CompileController};
 use rustc_metadata::cstore::CStore;
 use rustc_errors::registry::Registry;
+use syntax::codemap::FileName;
 
-use std::collections::HashSet;
 use std::path::PathBuf;
 use std::rc::Rc;
 
@@ -56,7 +56,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc) {
     opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
     opts.maybe_sysroot = Some(sysroot);
     if let Ok(linker) = std::env::var("RUSTC_LINKER") {
-        opts.cg.linker = Some(linker);
+        opts.cg.linker = Some(linker.into());
     }
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
@@ -70,6 +70,6 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc) {
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     let (sess, cstore) = basic_sess(sysroot);
     let control = CompileController::basic();
-    let input = Input::Str { name: anon_src(), input: code };
+    let input = Input::Str { name: FileName::Anon, input: code };
     let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
 }
diff --git a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
index fc031f4a310c2..9f9ef47722424 100644
--- a/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
+++ b/src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs
@@ -17,7 +17,7 @@ extern crate syntax;
 use syntax::ast::*;
 use syntax::attr::*;
 use syntax::ast;
-use syntax::codemap::FilePathMapping;
+use syntax::codemap::{FilePathMapping, FileName};
 use syntax::parse;
 use syntax::parse::{ParseSess, PResult};
 use syntax::parse::new_parser_from_source_str;
@@ -32,7 +32,7 @@ use std::fmt;
 // Copied out of syntax::util::parser_testing
 
 pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> {
-    new_parser_from_source_str(ps, "bogofile".to_string(), source_str)
+    new_parser_from_source_str(ps, FileName::Custom("bogofile".to_owned()), source_str)
 }
 
 fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) -> PResult<'a, T> where
diff --git a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
index 456088b2c5285..e84a982f7b326 100644
--- a/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs
@@ -33,7 +33,7 @@
 extern crate syntax;
 
 use syntax::ast::*;
-use syntax::codemap::{Spanned, DUMMY_SP};
+use syntax::codemap::{Spanned, DUMMY_SP, FileName};
 use syntax::codemap::FilePathMapping;
 use syntax::fold::{self, Folder};
 use syntax::parse::{self, ParseSess};
@@ -44,7 +44,7 @@ use syntax::util::ThinVec;
 
 fn parse_expr(ps: &ParseSess, src: &str) -> P {
     let mut p = parse::new_parser_from_source_str(ps,
-                                                  "".to_owned(),
+                                                  FileName::Custom("expr".to_owned()),
                                                   src.to_owned());
     p.parse_expr().unwrap()
 }
diff --git a/src/tools/toolstate.toml b/src/tools/toolstate.toml
index 744a0f96ad734..3f0d13b585c40 100644
--- a/src/tools/toolstate.toml
+++ b/src/tools/toolstate.toml
@@ -29,7 +29,7 @@ miri = "Broken"
 clippy = "Testing"
 
 # ping @nrc
-rls = "Testing"
+rls = "Broken"
 
 # ping @nrc
-rustfmt = "Testing"
+rustfmt = "Broken"