diff --git a/Cargo.lock b/Cargo.lock index 0e12e81904c..88bce36d9a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -553,6 +553,12 @@ version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +[[package]] +name = "relative-path" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a479d53d7eed831f3c92ca79c61002d5987e21417d528296832f802bca532380" + [[package]] name = "rust-argon2" version = "0.5.1" @@ -603,6 +609,7 @@ dependencies = [ "lazy_static", "log", "regex", + "relative-path", "rustc-workspace-hack", "rustfmt-config_proc_macro", "serde", diff --git a/Cargo.toml b/Cargo.toml index 24b3b79343b..19a35c62067 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,6 +58,7 @@ rustfmt-config_proc_macro = { version = "0.2", path = "config_proc_macro" } lazy_static = "1.0.0" anyhow = "1.0" thiserror = "1.0" +relative-path = "1.4.0" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/rust-toolchain b/rust-toolchain index b7d71e79b1b..d0654ca157b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2021-05-04" +channel = "nightly-2021-05-01" components = ["rustc-dev"] diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 0b94749f3c6..a0ba8814d4d 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -1,6 +1,7 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; +use relative_path::RelativePath; use rustc_ast::token::{DelimToken, TokenKind}; use rustc_ast::{ast, ptr}; use rustc_errors::Diagnostic; @@ -94,16 +95,21 @@ pub(crate) enum ParserError { } impl<'a> Parser<'a> { + // On windows, if the base path is specified with the windows path separator + // replace it with the expected '//' so that path traversal works as + // expected. + #[cfg(windows)] pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { - let path_string = first_attr_value_str_by_name(attrs, sym::path)?.as_str(); - // On windows, the base path might have the form - // `\\?\foo\bar` in which case it does not tolerate - // mixed `/` and `\` separators, so canonicalize - // `/` to `\`. - #[cfg(windows)] - let path_string = path_string.replace("/", "\\"); - - Some(path.join(&*path_string)) + let mod_path = first_attr_value_str_by_name(attrs, sym::path)? + .as_str() + .replace(std::path::MAIN_SEPARATOR, "/"); + Some(RelativePath::new(&mod_path).to_logical_path(&path)) + } + + #[cfg(not(windows))] + pub(crate) fn submod_path_from_attr(attrs: &[ast::Attribute], path: &Path) -> Option { + let mod_path = first_attr_value_str_by_name(attrs, sym::path)?.as_str(); + Some(RelativePath::new(&mod_path).to_logical_path(&path)) } pub(crate) fn parse_file_as_module(