Skip to content

Commit 3af441b

Browse files
committed
Auto merge of #55560 - cramertj:current-dir-path, r=<try>
Make #[path] always relative to the current directory Previously, #[path] would be relative to the current directory plus an offset for any inline modules. However, it did not respect the module offset based on a non-"mod.rs" filename unless there was *also* a nested module. After this commit, #[path] ignores inline modules and is only ever relative to the current directory. This means that the old #[path = ...] mod x { ... } (#[path] applied to inline modules) no longer has any effect. This is a [breaking change]. Opening to see what a crater run says. r? @petrochenkov
2 parents bdfeace + 561642c commit 3af441b

File tree

13 files changed

+80
-86
lines changed

13 files changed

+80
-86
lines changed

src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ impl<'a> ExtCtxt<'a> {
828828
mark: Mark::root(),
829829
depth: 0,
830830
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
831-
directory_ownership: DirectoryOwnership::Owned { relative: None },
831+
directory_ownership: DirectoryOwnership::Owned { relative: vec![] },
832832
crate_span: None,
833833
},
834834
expansions: FxHashMap::default(),

src/libsyntax/ext/expand.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -1311,8 +1311,9 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13111311
}
13121312

13131313
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1314-
let old_directory_ownership = self.cx.current_expansion.directory_ownership;
1315-
self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
1314+
let old_directory_ownership =
1315+
mem::replace(&mut self.cx.current_expansion.directory_ownership,
1316+
DirectoryOwnership::UnownedViaBlock);
13161317
let result = noop_fold_block(block, self);
13171318
self.cx.current_expansion.directory_ownership = old_directory_ownership;
13181319
result
@@ -1346,7 +1347,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13461347
return noop_fold_item(item, self);
13471348
}
13481349

1349-
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1350+
// If the directory ownership is replaced, this var
1351+
// holds the original so that it can be swapped back in.
1352+
let mut orig_directory_ownership = None;
1353+
// If the directory ownership `relative` field was appended to,
1354+
// this bool is `true` so that it can be popped at the end.
1355+
let mut directory_ownership_needs_pop = false;
1356+
13501357
let mut module = (*self.cx.current_expansion.module).clone();
13511358
module.mod_path.push(item.ident);
13521359

@@ -1356,12 +1363,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13561363
let inline_module = item.span.contains(inner) || inner.is_dummy();
13571364

13581365
if inline_module {
1359-
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
1360-
self.cx.current_expansion.directory_ownership =
1361-
DirectoryOwnership::Owned { relative: None };
1362-
module.directory.push(&*path.as_str());
1363-
} else {
1364-
module.directory.push(&*item.ident.as_str());
1366+
if let DirectoryOwnership::Owned { relative } =
1367+
&mut self.cx.current_expansion.directory_ownership
1368+
{
1369+
relative.push(item.ident);
1370+
directory_ownership_needs_pop = true;
13651371
}
13661372
} else {
13671373
let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner);
@@ -1370,22 +1376,37 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13701376
other => PathBuf::from(other.to_string()),
13711377
};
13721378
let directory_ownership = match path.file_name().unwrap().to_str() {
1373-
Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
1379+
Some("mod.rs") => DirectoryOwnership::Owned { relative: vec![] },
13741380
Some(_) => DirectoryOwnership::Owned {
1375-
relative: Some(item.ident),
1381+
relative: vec![item.ident],
13761382
},
13771383
None => DirectoryOwnership::UnownedViaMod(false),
13781384
};
13791385
path.pop();
13801386
module.directory = path;
1381-
self.cx.current_expansion.directory_ownership = directory_ownership;
1387+
orig_directory_ownership =
1388+
Some(mem::replace(
1389+
&mut self.cx.current_expansion.directory_ownership,
1390+
directory_ownership));
13821391
}
13831392

13841393
let orig_module =
13851394
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1395+
13861396
let result = noop_fold_item(item, self);
1397+
1398+
// Clean up, restoring all replaced or mutated expansion state.
13871399
self.cx.current_expansion.module = orig_module;
1388-
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1400+
if let Some(orig_directory_ownership) = orig_directory_ownership {
1401+
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1402+
}
1403+
if directory_ownership_needs_pop {
1404+
if let DirectoryOwnership::Owned { relative } =
1405+
&mut self.cx.current_expansion.directory_ownership
1406+
{
1407+
relative.pop();
1408+
}
1409+
}
13891410
result
13901411
}
13911412

src/libsyntax/ext/source_util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
100100
};
101101
// The file will be added to the code map by the parser
102102
let path = res_rel_file(cx, sp, file);
103-
let directory_ownership = DirectoryOwnership::Owned { relative: None };
103+
let directory_ownership = DirectoryOwnership::Owned { relative: vec![] };
104104
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
105105

106106
struct ExpandResult<'a> {

src/libsyntax/ext/tt/macro_rules.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
156156

157157
let directory = Directory {
158158
path: Cow::from(cx.current_expansion.module.directory.as_path()),
159-
ownership: cx.current_expansion.directory_ownership,
159+
ownership: cx.current_expansion.directory_ownership.clone(),
160160
};
161161
let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false);
162162
p.root_module_name = cx.current_expansion.module.mod_path.last()

src/libsyntax/parse/lexer/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1890,7 +1890,6 @@ mod tests {
18901890
missing_fragment_specifiers: Lock::new(FxHashSet::default()),
18911891
raw_identifier_spans: Lock::new(Vec::new()),
18921892
registered_diagnostics: Lock::new(ErrorMap::new()),
1893-
non_modrs_mods: Lock::new(vec![]),
18941893
buffered_lints: Lock::new(vec![]),
18951894
}
18961895
}

src/libsyntax/parse/mod.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ pub struct ParseSess {
5252
pub raw_identifier_spans: Lock<Vec<Span>>,
5353
/// The registered diagnostics codes
5454
crate registered_diagnostics: Lock<ErrorMap>,
55-
// Spans where a `mod foo;` statement was included in a non-mod.rs file.
56-
// These are used to issue errors if the non_modrs_mods feature is not enabled.
57-
pub non_modrs_mods: Lock<Vec<(ast::Ident, Span)>>,
5855
/// Used to determine and report recursive mod inclusions
5956
included_mod_stack: Lock<Vec<PathBuf>>,
6057
source_map: Lrc<SourceMap>,
@@ -81,7 +78,6 @@ impl ParseSess {
8178
registered_diagnostics: Lock::new(ErrorMap::new()),
8279
included_mod_stack: Lock::new(vec![]),
8380
source_map,
84-
non_modrs_mods: Lock::new(vec![]),
8581
buffered_lints: Lock::new(vec![]),
8682
}
8783
}
@@ -113,11 +109,14 @@ pub struct Directory<'a> {
113109
pub ownership: DirectoryOwnership,
114110
}
115111

116-
#[derive(Copy, Clone)]
112+
#[derive(Clone)]
117113
pub enum DirectoryOwnership {
118114
Owned {
119-
// None if `mod.rs`, `Some("foo")` if we're in `foo.rs`
120-
relative: Option<ast::Ident>,
115+
// Module offset from the current directory.
116+
// Starts out as empty in `mod.rs`, starts as `["foo"]` in `foo.rs`.
117+
// Contains one additional element for every inline nested module we've entered.
118+
// e.g. `mod y { mod z { ... } }` in `x.rs` would have `["x", "y", "z"]`
119+
relative: Vec<ast::Ident>,
121120
},
122121
UnownedViaBlock,
123122
UnownedViaMod(bool /* legacy warnings? */),

src/libsyntax/parse/parser.rs

+24-50
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ impl<'a> Parser<'a> {
556556
recurse_into_file_modules,
557557
directory: Directory {
558558
path: Cow::from(PathBuf::new()),
559-
ownership: DirectoryOwnership::Owned { relative: None }
559+
ownership: DirectoryOwnership::Owned { relative: vec![] }
560560
},
561561
root_module_name: None,
562562
expected_tokens: Vec::new(),
@@ -6456,8 +6456,12 @@ impl<'a> Parser<'a> {
64566456
}
64576457
} else {
64586458
let old_directory = self.directory.clone();
6459-
self.push_directory(id, &outer_attrs);
6460-
6459+
// Push inline `mod x { ... }`'s `x` onto the `relative` offset of the module
6460+
// from the current directory's location. This ensures that `mod x { mod y; }`
6461+
// corresponds to `x/y.rs`, not `y.rs`
6462+
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
6463+
relative.push(id);
6464+
}
64616465
self.expect(&token::OpenDelim(token::Brace))?;
64626466
let mod_inner_lo = self.span;
64636467
let attrs = self.parse_inner_attributes()?;
@@ -6468,26 +6472,6 @@ impl<'a> Parser<'a> {
64686472
}
64696473
}
64706474

6471-
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
6472-
if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
6473-
self.directory.path.to_mut().push(&path.as_str());
6474-
self.directory.ownership = DirectoryOwnership::Owned { relative: None };
6475-
} else {
6476-
// We have to push on the current module name in the case of relative
6477-
// paths in order to ensure that any additional module paths from inline
6478-
// `mod x { ... }` come after the relative extension.
6479-
//
6480-
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
6481-
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
6482-
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
6483-
if let Some(ident) = relative.take() { // remove the relative offset
6484-
self.directory.path.to_mut().push(ident.as_str());
6485-
}
6486-
}
6487-
self.directory.path.to_mut().push(&id.as_str());
6488-
}
6489-
}
6490-
64916475
pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
64926476
if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") {
64936477
let s = s.as_str();
@@ -6507,21 +6491,20 @@ impl<'a> Parser<'a> {
65076491
/// Returns either a path to a module, or .
65086492
pub fn default_submod_path(
65096493
id: ast::Ident,
6510-
relative: Option<ast::Ident>,
6494+
relative: &[ast::Ident],
65116495
dir_path: &Path,
65126496
source_map: &SourceMap) -> ModulePath
65136497
{
6514-
// If we're in a foo.rs file instead of a mod.rs file,
6515-
// we need to look for submodules in
6516-
// `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
6517-
// `./<id>.rs` and `./<id>/mod.rs`.
6518-
let relative_prefix_string;
6519-
let relative_prefix = if let Some(ident) = relative {
6520-
relative_prefix_string = format!("{}{}", ident.as_str(), path::MAIN_SEPARATOR);
6521-
&relative_prefix_string
6522-
} else {
6523-
""
6524-
};
6498+
// Offset the current directory first by the name of
6499+
// the file if not `mod.rs`, then by any nested modules.
6500+
// e.g. `mod y { mod z; }` in `x.rs` should look for
6501+
// `./x/y/z.rs` and `./x/y/z/mod.rs` rather than
6502+
// `./z.rs` and `./z/mod.rs`.
6503+
let mut relative_prefix = String::new();
6504+
for ident in relative {
6505+
relative_prefix.push_str(&ident.as_str());
6506+
relative_prefix.push(path::MAIN_SEPARATOR);
6507+
}
65256508

65266509
let mod_name = id.to_string();
65276510
let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
@@ -6536,14 +6519,14 @@ impl<'a> Parser<'a> {
65366519
(true, false) => Ok(ModulePathSuccess {
65376520
path: default_path,
65386521
directory_ownership: DirectoryOwnership::Owned {
6539-
relative: Some(id),
6522+
relative: vec![id],
65406523
},
65416524
warn: false,
65426525
}),
65436526
(false, true) => Ok(ModulePathSuccess {
65446527
path: secondary_path,
65456528
directory_ownership: DirectoryOwnership::Owned {
6546-
relative: None,
6529+
relative: vec![],
65476530
},
65486531
warn: false,
65496532
}),
@@ -6582,27 +6565,18 @@ impl<'a> Parser<'a> {
65826565
// Note that this will produce weirdness when a file named `foo.rs` is
65836566
// `#[path]` included and contains a `mod foo;` declaration.
65846567
// If you encounter this, it's your own darn fault :P
6585-
Some(_) => DirectoryOwnership::Owned { relative: None },
6568+
Some(_) => DirectoryOwnership::Owned { relative: vec![] },
65866569
_ => DirectoryOwnership::UnownedViaMod(true),
65876570
},
65886571
path,
65896572
warn: false,
65906573
});
65916574
}
65926575

6593-
let relative = match self.directory.ownership {
6594-
DirectoryOwnership::Owned { relative } => {
6595-
// Push the usage onto the list of non-mod.rs mod uses.
6596-
// This is used later for feature-gate error reporting.
6597-
if let Some(cur_file_ident) = relative {
6598-
self.sess
6599-
.non_modrs_mods.borrow_mut()
6600-
.push((cur_file_ident, id_sp));
6601-
}
6602-
relative
6603-
},
6576+
let relative = match &self.directory.ownership {
6577+
DirectoryOwnership::Owned { relative } => &**relative,
66046578
DirectoryOwnership::UnownedViaBlock |
6605-
DirectoryOwnership::UnownedViaMod(_) => None,
6579+
DirectoryOwnership::UnownedViaMod(_) => &[],
66066580
};
66076581
let paths = Parser::default_submod_path(
66086582
id, relative, &self.directory.path, self.sess.source_map());

src/libsyntax/tokenstream.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl TokenTree {
107107
// `None` is because we're not interpolating
108108
let directory = Directory {
109109
path: Cow::from(cx.current_expansion.module.directory.as_path()),
110-
ownership: cx.current_expansion.directory_ownership,
110+
ownership: cx.current_expansion.directory_ownership.clone(),
111111
};
112112
macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true)
113113
}

src/test/run-pass/modules/mod_dir_path.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,23 @@
1313
// ignore-pretty issue #37195
1414

1515
mod mod_dir_simple {
16-
#[path = "test.rs"]
16+
#[path = "mod_dir_simple/test.rs"]
1717
pub mod syrup;
1818
}
1919

2020
pub fn main() {
2121
assert_eq!(mod_dir_simple::syrup::foo(), 10);
2222

23-
#[path = "auxiliary"]
2423
mod foo {
24+
#[path = "auxiliary/two_macros_2.rs"]
2525
mod two_macros_2;
2626
}
2727

28-
#[path = "auxiliary"]
2928
mod bar {
30-
macro_rules! m { () => { mod two_macros_2; } }
29+
macro_rules! m { () => {
30+
#[path = "auxiliary/two_macros_2.rs"]
31+
mod two_macros_2;
32+
} }
3133
m!();
3234
}
3335
}

src/test/run-pass/modules/mod_dir_path2.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
// run-pass
1212
// ignore-pretty issue #37195
1313

14-
#[path = "mod_dir_simple"]
1514
mod pancakes {
16-
#[path = "test.rs"]
15+
#[path = "mod_dir_simple/test.rs"]
1716
pub mod syrup;
1817
}
1918

src/test/run-pass/modules/mod_dir_path3.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
// run-pass
1212
// ignore-pretty issue #37195
1313

14-
#[path = "mod_dir_simple"]
1514
mod pancakes {
15+
#[path = "mod_dir_simple/test.rs"]
1616
pub mod test;
1717
}
1818

src/test/run-pass/modules/mod_dir_path_multi.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
// run-pass
1212
// ignore-pretty issue #37195
1313

14-
#[path = "mod_dir_simple"]
1514
mod biscuits {
15+
#[path = "mod_dir_simple/test.rs"]
1616
pub mod test;
1717
}
1818

19-
#[path = "mod_dir_simple"]
2019
mod gravy {
20+
#[path = "mod_dir_simple/test.rs"]
2121
pub mod test;
2222
}
2323

src/test/ui/conditional-compilation/cfg_attr_path.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
#![deny(unused_attributes)] // c.f #35584
1414

1515
mod auxiliary {
16-
#[cfg_attr(any(), path = "nonexistent_file.rs")] pub mod namespaced_enums;
17-
#[cfg_attr(all(), path = "namespaced_enums.rs")] pub mod nonexistent_file;
16+
#[cfg_attr(any(), path = "auxiliary/nonexistent_file.rs")] pub mod namespaced_enums;
17+
#[cfg_attr(all(), path = "auxiliary/namespaced_enums.rs")] pub mod nonexistent_file;
1818
}
1919

2020
#[rustc_error]

0 commit comments

Comments
 (0)