diff --git a/src/librustc/util/fs.rs b/src/librustc/util/fs.rs index 3ae78fa7c19..4936e049ef2 100644 --- a/src/librustc/util/fs.rs +++ b/src/librustc/util/fs.rs @@ -11,14 +11,22 @@ use std::path::{self, Path, PathBuf}; use std::ffi::OsString; -// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...` -// (a verbatim path). This form of path is generally pretty rare, but the -// implementation of `fs::canonicalize` currently generates paths of this form, -// meaning that we're going to be passing quite a few of these down to gcc. +// Unfortunately, on windows, it looks like msvcrt.dll is silently translating +// verbatim paths under the hood to non-verbatim paths! This manifests itself as +// gcc looking like it cannot accept paths of the form `\\?\C:\...`, but the +// real bug seems to lie in msvcrt.dll. +// +// Verbatim paths are generally pretty rare, but the implementation of +// `fs::canonicalize` currently generates paths of this form, meaning that we're +// going to be passing quite a few of these down to gcc, so we need to deal with +// this case. // // For now we just strip the "verbatim prefix" of `\\?\` from the path. This // will probably lose information in some cases, but there's not a whole lot -// more we can do with a buggy gcc... +// more we can do with a buggy msvcrt... +// +// For some more information, see this comment: +// https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737 pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { if !cfg!(windows) { return p.to_path_buf() @@ -28,11 +36,20 @@ pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { Some(path::Component::Prefix(p)) => p, _ => return p.to_path_buf(), }; - let disk = match prefix.kind() { - path::Prefix::VerbatimDisk(disk) => disk, - _ => return p.to_path_buf(), - }; - let mut base = OsString::from(format!("{}:", disk as char)); - base.push(components.as_path()); - PathBuf::from(base) + match prefix.kind() { + path::Prefix::VerbatimDisk(disk) => { + let mut base = OsString::from(format!("{}:", disk as char)); + base.push(components.as_path()); + PathBuf::from(base) + } + path::Prefix::VerbatimUNC(server, share) => { + let mut base = OsString::from(r"\\"); + base.push(server); + base.push(r"\"); + base.push(share); + base.push(components.as_path()); + PathBuf::from(base) + } + _ => p.to_path_buf(), + } }