diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 662bbe6a287..718498f04b9 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -4,6 +4,7 @@ use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; +use rustc_expand::module::DirectoryOwnership; use rustc_expand::panictry; use rustc_parse::{self, new_sub_parser_from_file, parser::Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; @@ -11,6 +12,7 @@ use rustc_span::symbol::Symbol; use rustc_span::{self, Pos, Span}; use smallvec::SmallVec; +use std::rc::Rc; use rustc_data_structures::sync::Lrc; @@ -101,7 +103,7 @@ pub fn expand_include<'cx>( None => return DummyResult::any(sp), }; // The file will be added to the code map by the parser - let file = match cx.resolve_path(file, sp) { + let mut file = match cx.resolve_path(file, sp) { Ok(f) => f, Err(mut err) => { err.emit(); @@ -110,6 +112,15 @@ pub fn expand_include<'cx>( }; let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp); + // If in the included file we have e.g., `mod bar;`, + // then the path of `bar.rs` should be relative to the directory of `file`. + // See https://github.com/rust-lang/rust/pull/69838/files#r395217057 for a discussion. + // `MacroExpander::fully_expand_fragment` later restores, so "stack discipline" is maintained. + file.pop(); + cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; + let mod_path = cx.current_expansion.module.mod_path.clone(); + cx.current_expansion.module = Rc::new(ModuleData { mod_path, directory: file }); + struct ExpandResult<'a> { p: Parser<'a>, } diff --git a/src/test/ui/macros/issue-69838-dir/bar.rs b/src/test/ui/macros/issue-69838-dir/bar.rs new file mode 100644 index 00000000000..ec12f8c5cb4 --- /dev/null +++ b/src/test/ui/macros/issue-69838-dir/bar.rs @@ -0,0 +1,3 @@ +// ignore-test -- this is an auxiliary file as part of another test. + +pub fn i_am_in_bar() {} diff --git a/src/test/ui/macros/issue-69838-dir/included.rs b/src/test/ui/macros/issue-69838-dir/included.rs new file mode 100644 index 00000000000..9900b8fd509 --- /dev/null +++ b/src/test/ui/macros/issue-69838-dir/included.rs @@ -0,0 +1,3 @@ +// ignore-test -- this is an auxiliary file as part of another test. + +pub mod bar; diff --git a/src/test/ui/macros/issue-69838-mods-relative-to-included-path.rs b/src/test/ui/macros/issue-69838-mods-relative-to-included-path.rs new file mode 100644 index 00000000000..2a4e97f0ef5 --- /dev/null +++ b/src/test/ui/macros/issue-69838-mods-relative-to-included-path.rs @@ -0,0 +1,7 @@ +// check-pass + +include!("issue-69838-dir/included.rs"); + +fn main() { + bar::i_am_in_bar(); +}