Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 32eec18

Browse files
committedNov 1, 2018
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.
1 parent de9666f commit 32eec18

File tree

9 files changed

+53
-73
lines changed

9 files changed

+53
-73
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

+17-9
Original file line numberDiff line numberDiff line change
@@ -1309,8 +1309,9 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13091309
}
13101310

13111311
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
1312-
let old_directory_ownership = self.cx.current_expansion.directory_ownership;
1313-
self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
1312+
let old_directory_ownership =
1313+
mem::replace(&mut self.cx.current_expansion.directory_ownership,
1314+
DirectoryOwnership::UnownedViaBlock);
13141315
let result = noop_fold_block(block, self);
13151316
self.cx.current_expansion.directory_ownership = old_directory_ownership;
13161317
result
@@ -1344,7 +1345,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13441345
return noop_fold_item(item, self);
13451346
}
13461347

1347-
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
1348+
let mut orig_directory_ownership = None;
13481349
let mut module = (*self.cx.current_expansion.module).clone();
13491350
module.mod_path.push(item.ident);
13501351

@@ -1355,8 +1356,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13551356

13561357
if inline_module {
13571358
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
1358-
self.cx.current_expansion.directory_ownership =
1359-
DirectoryOwnership::Owned { relative: None };
1359+
orig_directory_ownership =
1360+
Some(mem::replace(
1361+
&mut self.cx.current_expansion.directory_ownership,
1362+
DirectoryOwnership::Owned { relative: vec![] }));
13601363
module.directory.push(&*path.as_str());
13611364
} else {
13621365
module.directory.push(&*item.ident.as_str());
@@ -1368,22 +1371,27 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13681371
other => PathBuf::from(other.to_string()),
13691372
};
13701373
let directory_ownership = match path.file_name().unwrap().to_str() {
1371-
Some("mod.rs") => DirectoryOwnership::Owned { relative: None },
1374+
Some("mod.rs") => DirectoryOwnership::Owned { relative: vec![] },
13721375
Some(_) => DirectoryOwnership::Owned {
1373-
relative: Some(item.ident),
1376+
relative: vec![item.ident],
13741377
},
13751378
None => DirectoryOwnership::UnownedViaMod(false),
13761379
};
13771380
path.pop();
13781381
module.directory = path;
1379-
self.cx.current_expansion.directory_ownership = directory_ownership;
1382+
orig_directory_ownership =
1383+
Some(mem::replace(
1384+
&mut self.cx.current_expansion.directory_ownership,
1385+
directory_ownership));
13801386
}
13811387

13821388
let orig_module =
13831389
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
13841390
let result = noop_fold_item(item, self);
13851391
self.cx.current_expansion.module = orig_module;
1386-
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1392+
if let Some(orig_directory_ownership) = orig_directory_ownership {
1393+
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
1394+
}
13871395
result
13881396
}
13891397

‎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
@@ -1869,7 +1869,6 @@ mod tests {
18691869
missing_fragment_specifiers: Lock::new(FxHashSet::default()),
18701870
raw_identifier_spans: Lock::new(Vec::new()),
18711871
registered_diagnostics: Lock::new(ErrorMap::new()),
1872-
non_modrs_mods: Lock::new(vec![]),
18731872
buffered_lints: Lock::new(vec![]),
18741873
}
18751874
}

‎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(),
@@ -6409,8 +6409,12 @@ impl<'a> Parser<'a> {
64096409
}
64106410
} else {
64116411
let old_directory = self.directory.clone();
6412-
self.push_directory(id, &outer_attrs);
6413-
6412+
// Push inline `mod x { ... }`'s `x` onto the `relative` offset of the module
6413+
// from the current directory's location. This ensures that `mod x { mod y; }`
6414+
// corresponds to `x/y.rs`, not `y.rs`
6415+
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
6416+
relative.push(id);
6417+
}
64146418
self.expect(&token::OpenDelim(token::Brace))?;
64156419
let mod_inner_lo = self.span;
64166420
let attrs = self.parse_inner_attributes()?;
@@ -6421,26 +6425,6 @@ impl<'a> Parser<'a> {
64216425
}
64226426
}
64236427

6424-
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
6425-
if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
6426-
self.directory.path.to_mut().push(&path.as_str());
6427-
self.directory.ownership = DirectoryOwnership::Owned { relative: None };
6428-
} else {
6429-
// We have to push on the current module name in the case of relative
6430-
// paths in order to ensure that any additional module paths from inline
6431-
// `mod x { ... }` come after the relative extension.
6432-
//
6433-
// For example, a `mod z { ... }` inside `x/y.rs` should set the current
6434-
// directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`.
6435-
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
6436-
if let Some(ident) = relative.take() { // remove the relative offset
6437-
self.directory.path.to_mut().push(ident.as_str());
6438-
}
6439-
}
6440-
self.directory.path.to_mut().push(&id.as_str());
6441-
}
6442-
}
6443-
64446428
pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option<PathBuf> {
64456429
if let Some(s) = attr::first_attr_value_str_by_name(attrs, "path") {
64466430
let s = s.as_str();
@@ -6460,21 +6444,20 @@ impl<'a> Parser<'a> {
64606444
/// Returns either a path to a module, or .
64616445
pub fn default_submod_path(
64626446
id: ast::Ident,
6463-
relative: Option<ast::Ident>,
6447+
relative: &[ast::Ident],
64646448
dir_path: &Path,
64656449
source_map: &SourceMap) -> ModulePath
64666450
{
6467-
// If we're in a foo.rs file instead of a mod.rs file,
6468-
// we need to look for submodules in
6469-
// `./foo/<id>.rs` and `./foo/<id>/mod.rs` rather than
6470-
// `./<id>.rs` and `./<id>/mod.rs`.
6471-
let relative_prefix_string;
6472-
let relative_prefix = if let Some(ident) = relative {
6473-
relative_prefix_string = format!("{}{}", ident.as_str(), path::MAIN_SEPARATOR);
6474-
&relative_prefix_string
6475-
} else {
6476-
""
6477-
};
6451+
// Offset the current directory first by the name of
6452+
// the file if not `mod.rs`, then by any nested modules.
6453+
// e.g. `mod y { mod z; }` in `x.rs` should look for
6454+
// `./x/y/z.rs` and `./x/y/z/mod.rs` rather than
6455+
// `./z.rs` and `./z/mod.rs`.
6456+
let mut relative_prefix = String::new();
6457+
for ident in relative {
6458+
relative_prefix.push_str(&ident.as_str());
6459+
relative_prefix.push(path::MAIN_SEPARATOR);
6460+
}
64786461

64796462
let mod_name = id.to_string();
64806463
let default_path_str = format!("{}{}.rs", relative_prefix, mod_name);
@@ -6489,14 +6472,14 @@ impl<'a> Parser<'a> {
64896472
(true, false) => Ok(ModulePathSuccess {
64906473
path: default_path,
64916474
directory_ownership: DirectoryOwnership::Owned {
6492-
relative: Some(id),
6475+
relative: vec![id],
64936476
},
64946477
warn: false,
64956478
}),
64966479
(false, true) => Ok(ModulePathSuccess {
64976480
path: secondary_path,
64986481
directory_ownership: DirectoryOwnership::Owned {
6499-
relative: None,
6482+
relative: vec![],
65006483
},
65016484
warn: false,
65026485
}),
@@ -6535,27 +6518,18 @@ impl<'a> Parser<'a> {
65356518
// Note that this will produce weirdness when a file named `foo.rs` is
65366519
// `#[path]` included and contains a `mod foo;` declaration.
65376520
// If you encounter this, it's your own darn fault :P
6538-
Some(_) => DirectoryOwnership::Owned { relative: None },
6521+
Some(_) => DirectoryOwnership::Owned { relative: vec![] },
65396522
_ => DirectoryOwnership::UnownedViaMod(true),
65406523
},
65416524
path,
65426525
warn: false,
65436526
});
65446527
}
65456528

6546-
let relative = match self.directory.ownership {
6547-
DirectoryOwnership::Owned { relative } => {
6548-
// Push the usage onto the list of non-mod.rs mod uses.
6549-
// This is used later for feature-gate error reporting.
6550-
if let Some(cur_file_ident) = relative {
6551-
self.sess
6552-
.non_modrs_mods.borrow_mut()
6553-
.push((cur_file_ident, id_sp));
6554-
}
6555-
relative
6556-
},
6529+
let relative = match &self.directory.ownership {
6530+
DirectoryOwnership::Owned { relative } => &**relative,
65576531
DirectoryOwnership::UnownedViaBlock |
6558-
DirectoryOwnership::UnownedViaMod(_) => None,
6532+
DirectoryOwnership::UnownedViaMod(_) => &[],
65596533
};
65606534
let paths = Parser::default_submod_path(
65616535
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/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)
Please sign in to comment.