Skip to content

Commit 5675d9d

Browse files
committed
Clean up directory ownership semantics.
1 parent 7b3eeea commit 5675d9d

File tree

6 files changed

+94
-79
lines changed

6 files changed

+94
-79
lines changed

src/libsyntax/ext/base.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use errors::DiagnosticBuilder;
1818
use ext::expand::{self, Expansion};
1919
use ext::hygiene::Mark;
2020
use fold::{self, Folder};
21-
use parse::{self, parser};
21+
use parse::{self, parser, DirectoryOwnership};
2222
use parse::token;
2323
use ptr::P;
2424
use symbol::Symbol;
@@ -568,9 +568,7 @@ pub struct ExpansionData {
568568
pub depth: usize,
569569
pub backtrace: ExpnId,
570570
pub module: Rc<ModuleData>,
571-
572-
// True if non-inline modules without a `#[path]` are forbidden at the root of this expansion.
573-
pub no_noninline_mod: bool,
571+
pub directory_ownership: DirectoryOwnership,
574572
}
575573

576574
/// One of these is made during expansion and incrementally updated as we go;
@@ -601,7 +599,7 @@ impl<'a> ExtCtxt<'a> {
601599
depth: 0,
602600
backtrace: NO_EXPANSION,
603601
module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
604-
no_noninline_mod: false,
602+
directory_ownership: DirectoryOwnership::Owned,
605603
},
606604
}
607605
}

src/libsyntax/ext/expand.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use ext::base::*;
2121
use feature_gate::{self, Features};
2222
use fold;
2323
use fold::*;
24-
use parse::{ParseSess, PResult, lexer};
24+
use parse::{ParseSess, DirectoryOwnership, PResult, lexer};
2525
use parse::parser::Parser;
2626
use parse::token;
2727
use print::pprust;
@@ -727,9 +727,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
727727
}
728728

729729
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
730-
let no_noninline_mod = mem::replace(&mut self.cx.current_expansion.no_noninline_mod, true);
730+
let old_directory_ownership = self.cx.current_expansion.directory_ownership;
731+
self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
731732
let result = noop_fold_block(block, self);
732-
self.cx.current_expansion.no_noninline_mod = no_noninline_mod;
733+
self.cx.current_expansion.directory_ownership = old_directory_ownership;
733734
result
734735
}
735736

@@ -768,7 +769,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
768769
return noop_fold_item(item, self);
769770
}
770771

771-
let orig_no_noninline_mod = self.cx.current_expansion.no_noninline_mod;
772+
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
772773
let mut module = (*self.cx.current_expansion.module).clone();
773774
module.mod_path.push(item.ident);
774775

@@ -779,23 +780,28 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
779780

780781
if inline_module {
781782
if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
782-
self.cx.current_expansion.no_noninline_mod = false;
783+
self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned;
783784
module.directory.push(&*path.as_str());
784785
} else {
785786
module.directory.push(&*item.ident.name.as_str());
786787
}
787788
} else {
788-
self.cx.current_expansion.no_noninline_mod = false;
789-
module.directory =
789+
let mut path =
790790
PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner));
791-
module.directory.pop();
791+
let directory_ownership = match path.file_name().unwrap().to_str() {
792+
Some("mod.rs") => DirectoryOwnership::Owned,
793+
_ => DirectoryOwnership::UnownedViaMod,
794+
};
795+
path.pop();
796+
module.directory = path;
797+
self.cx.current_expansion.directory_ownership = directory_ownership;
792798
}
793799

794800
let orig_module =
795801
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
796802
let result = noop_fold_item(item, self);
797803
self.cx.current_expansion.module = orig_module;
798-
self.cx.current_expansion.no_noninline_mod = orig_no_noninline_mod;
804+
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
799805
return result;
800806
}
801807
// Ensure that test functions are accessible from the test harness.

src/libsyntax/ext/source_util.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use syntax_pos::{self, Pos, Span};
1313
use ext::base::*;
1414
use ext::base;
1515
use ext::build::AstBuilder;
16-
use parse::token;
16+
use parse::{token, DirectoryOwnership};
1717
use parse;
1818
use print::pprust;
1919
use ptr::P;
@@ -90,7 +90,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
9090
};
9191
// The file will be added to the code map by the parser
9292
let path = res_rel_file(cx, sp, Path::new(&file));
93-
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, true, None, sp);
93+
let directory_ownership = DirectoryOwnership::Owned;
94+
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
9495

9596
struct ExpandResult<'a> {
9697
p: parse::parser::Parser<'a>,

src/libsyntax/ext/tt/macro_rules.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
1919
use ext::tt::macro_parser::{parse, parse_failure_msg};
2020
use parse::ParseSess;
2121
use parse::lexer::new_tt_reader;
22-
use parse::parser::{Parser, Restrictions};
22+
use parse::parser::Parser;
2323
use parse::token::{self, NtTT, Token};
2424
use parse::token::Token::*;
2525
use print;
@@ -117,11 +117,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
117117
let trncbr =
118118
new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs);
119119
let mut p = Parser::new(cx.parse_sess(), Box::new(trncbr));
120-
p.directory = cx.current_expansion.module.directory.clone();
121-
p.restrictions = match cx.current_expansion.no_noninline_mod {
122-
true => Restrictions::NO_NONINLINE_MOD,
123-
false => Restrictions::empty(),
124-
};
120+
let module = &cx.current_expansion.module;
121+
p.directory.path = module.directory.clone();
122+
p.directory.ownership = cx.current_expansion.directory_ownership;
123+
p.root_module_name =
124+
module.mod_path.last().map(|id| (*id.name.as_str()).to_owned());
125+
125126
p.check_unknown_macro_variable();
126127
// Let the context choose how to interpret the result.
127128
// Weird, but useful for X-macros.

src/libsyntax/parse/mod.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ impl ParseSess {
7676
}
7777
}
7878

79+
#[derive(Clone)]
80+
pub struct Directory {
81+
pub path: PathBuf,
82+
pub ownership: DirectoryOwnership,
83+
}
84+
85+
#[derive(Copy, Clone)]
86+
pub enum DirectoryOwnership {
87+
Owned,
88+
UnownedViaBlock,
89+
UnownedViaMod,
90+
}
91+
7992
// a bunch of utility functions of the form parse_<thing>_from_<source>
8093
// where <thing> includes crate, expr, item, stmt, tts, and one that
8194
// uses a HOF to parse anything, and <source> includes file and
@@ -152,11 +165,11 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path) -> Parser<'a>
152165
/// On an error, use the given span as the source of the problem.
153166
pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
154167
path: &Path,
155-
owns_directory: bool,
168+
directory_ownership: DirectoryOwnership,
156169
module_name: Option<String>,
157170
sp: Span) -> Parser<'a> {
158171
let mut p = filemap_to_parser(sess, file_to_filemap(sess, path, Some(sp)));
159-
p.owns_directory = owns_directory;
172+
p.directory.ownership = directory_ownership;
160173
p.root_module_name = module_name;
161174
p
162175
}

src/libsyntax/parse/parser.rs

+51-55
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use parse::common::SeqSep;
4949
use parse::lexer::{Reader, TokenAndSpan};
5050
use parse::obsolete::ObsoleteSyntax;
5151
use parse::token::{self, MatchNt, SubstNt};
52-
use parse::{new_sub_parser_from_file, ParseSess};
52+
use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership};
5353
use util::parser::{AssocOp, Fixity};
5454
use print::pprust;
5555
use ptr::P;
@@ -68,7 +68,6 @@ bitflags! {
6868
flags Restrictions: u8 {
6969
const RESTRICTION_STMT_EXPR = 1 << 0,
7070
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
71-
const NO_NONINLINE_MOD = 1 << 2,
7271
}
7372
}
7473

@@ -200,12 +199,9 @@ pub struct Parser<'a> {
200199
/// extra detail when the same error is seen twice
201200
pub obsolete_set: HashSet<ObsoleteSyntax>,
202201
/// Used to determine the path to externally loaded source files
203-
pub directory: PathBuf,
202+
pub directory: Directory,
204203
/// Stack of open delimiters and their spans. Used for error message.
205204
pub open_braces: Vec<(token::DelimToken, Span)>,
206-
/// Flag if this parser "owns" the directory that it is currently parsing
207-
/// in. This will affect how nested files are looked up.
208-
pub owns_directory: bool,
209205
/// Name of the root module this parser originated from. If `None`, then the
210206
/// name is not known. This does not change while the parser is descending
211207
/// into modules, and sub-parsers have new values for this name.
@@ -245,8 +241,8 @@ pub struct ModulePath {
245241
}
246242

247243
pub struct ModulePathSuccess {
248-
pub path: ::std::path::PathBuf,
249-
pub owns_directory: bool,
244+
pub path: PathBuf,
245+
pub directory_ownership: DirectoryOwnership,
250246
}
251247

252248
pub struct ModulePathError {
@@ -296,9 +292,8 @@ impl<'a> Parser<'a> {
296292
quote_depth: 0,
297293
parsing_token_tree: false,
298294
obsolete_set: HashSet::new(),
299-
directory: PathBuf::new(),
295+
directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
300296
open_braces: Vec::new(),
301-
owns_directory: true,
302297
root_module_name: None,
303298
expected_tokens: Vec::new(),
304299
tts: Vec::new(),
@@ -310,8 +305,8 @@ impl<'a> Parser<'a> {
310305
parser.token = tok.tok;
311306
parser.span = tok.sp;
312307
if parser.span != syntax_pos::DUMMY_SP {
313-
parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span));
314-
parser.directory.pop();
308+
parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
309+
parser.directory.path.pop();
315310
}
316311
parser
317312
}
@@ -3966,9 +3961,11 @@ impl<'a> Parser<'a> {
39663961
}
39673962
} else {
39683963
// FIXME: Bad copy of attrs
3969-
let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD;
3970-
match self.with_res(restrictions,
3971-
|this| this.parse_item_(attrs.clone(), false, true))? {
3964+
let old_directory_ownership =
3965+
mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
3966+
let item = self.parse_item_(attrs.clone(), false, true)?;
3967+
self.directory.ownership = old_directory_ownership;
3968+
match item {
39723969
Some(i) => Stmt {
39733970
id: ast::DUMMY_NODE_ID,
39743971
span: mk_sp(lo, i.span.hi),
@@ -5271,33 +5268,33 @@ impl<'a> Parser<'a> {
52715268
self.bump();
52725269
if in_cfg {
52735270
// This mod is in an external file. Let's go get it!
5274-
let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?;
5275-
Ok((id, m, Some(attrs)))
5271+
let ModulePathSuccess { path, directory_ownership } =
5272+
self.submod_path(id, &outer_attrs, id_span)?;
5273+
let (module, attrs) =
5274+
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
5275+
Ok((id, module, Some(attrs)))
52765276
} else {
52775277
let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() };
52785278
Ok((id, ItemKind::Mod(placeholder), None))
52795279
}
52805280
} else {
5281-
let directory = self.directory.clone();
5282-
let restrictions = self.push_directory(id, &outer_attrs);
5281+
let old_directory = self.directory.clone();
5282+
self.push_directory(id, &outer_attrs);
52835283
self.expect(&token::OpenDelim(token::Brace))?;
52845284
let mod_inner_lo = self.span.lo;
52855285
let attrs = self.parse_inner_attributes()?;
5286-
let m = self.with_res(restrictions, |this| {
5287-
this.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)
5288-
})?;
5289-
self.directory = directory;
5290-
Ok((id, ItemKind::Mod(m), Some(attrs)))
5286+
let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
5287+
self.directory = old_directory;
5288+
Ok((id, ItemKind::Mod(module), Some(attrs)))
52915289
}
52925290
}
52935291

5294-
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) -> Restrictions {
5292+
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
52955293
if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") {
5296-
self.directory.push(&*path.as_str());
5297-
self.restrictions - Restrictions::NO_NONINLINE_MOD
5294+
self.directory.path.push(&*path.as_str());
5295+
self.directory.ownership = DirectoryOwnership::Owned;
52985296
} else {
5299-
self.directory.push(&*id.name.as_str());
5300-
self.restrictions
5297+
self.directory.path.push(&*id.name.as_str());
53015298
}
53025299
}
53035300

@@ -5317,8 +5314,14 @@ impl<'a> Parser<'a> {
53175314
let secondary_exists = codemap.file_exists(&secondary_path);
53185315

53195316
let result = match (default_exists, secondary_exists) {
5320-
(true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }),
5321-
(false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }),
5317+
(true, false) => Ok(ModulePathSuccess {
5318+
path: default_path,
5319+
directory_ownership: DirectoryOwnership::UnownedViaMod,
5320+
}),
5321+
(false, true) => Ok(ModulePathSuccess {
5322+
path: secondary_path,
5323+
directory_ownership: DirectoryOwnership::Owned,
5324+
}),
53225325
(false, false) => Err(ModulePathError {
53235326
err_msg: format!("file not found for module `{}`", mod_name),
53245327
help_msg: format!("name the file either {} or {} inside the directory {:?}",
@@ -5346,13 +5349,19 @@ impl<'a> Parser<'a> {
53465349
id: ast::Ident,
53475350
outer_attrs: &[ast::Attribute],
53485351
id_sp: Span) -> PResult<'a, ModulePathSuccess> {
5349-
if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &self.directory) {
5350-
return Ok(ModulePathSuccess { path: p, owns_directory: true });
5352+
if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
5353+
return Ok(ModulePathSuccess {
5354+
directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
5355+
Some("mod.rs") => DirectoryOwnership::Owned,
5356+
_ => DirectoryOwnership::UnownedViaMod,
5357+
},
5358+
path: path,
5359+
});
53515360
}
53525361

5353-
let paths = Parser::default_submod_path(id, &self.directory, self.sess.codemap());
5362+
let paths = Parser::default_submod_path(id, &self.directory.path, self.sess.codemap());
53545363

5355-
if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) {
5364+
if let DirectoryOwnership::UnownedViaBlock = self.directory.ownership {
53565365
let msg =
53575366
"Cannot declare a non-inline module inside a block unless it has a path attribute";
53585367
let mut err = self.diagnostic().struct_span_err(id_sp, msg);
@@ -5362,10 +5371,10 @@ impl<'a> Parser<'a> {
53625371
err.span_note(id_sp, &msg);
53635372
}
53645373
return Err(err);
5365-
} else if !self.owns_directory {
5374+
} else if let DirectoryOwnership::UnownedViaMod = self.directory.ownership {
53665375
let mut err = self.diagnostic().struct_span_err(id_sp,
53675376
"cannot declare a new module at this location");
5368-
let this_module = match self.directory.file_name() {
5377+
let this_module = match self.directory.path.file_name() {
53695378
Some(file_name) => file_name.to_str().unwrap().to_owned(),
53705379
None => self.root_module_name.as_ref().unwrap().clone(),
53715380
};
@@ -5390,25 +5399,11 @@ impl<'a> Parser<'a> {
53905399

53915400
/// Read a module from a source file.
53925401
fn eval_src_mod(&mut self,
5393-
id: ast::Ident,
5394-
outer_attrs: &[ast::Attribute],
5402+
path: PathBuf,
5403+
directory_ownership: DirectoryOwnership,
5404+
name: String,
53955405
id_sp: Span)
53965406
-> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
5397-
let ModulePathSuccess { path, owns_directory } = self.submod_path(id,
5398-
outer_attrs,
5399-
id_sp)?;
5400-
5401-
self.eval_src_mod_from_path(path,
5402-
owns_directory,
5403-
id.to_string(),
5404-
id_sp)
5405-
}
5406-
5407-
fn eval_src_mod_from_path(&mut self,
5408-
path: PathBuf,
5409-
owns_directory: bool,
5410-
name: String,
5411-
id_sp: Span) -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
54125407
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
54135408
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
54145409
let mut err = String::from("circular modules: ");
@@ -5423,7 +5418,8 @@ impl<'a> Parser<'a> {
54235418
included_mod_stack.push(path.clone());
54245419
drop(included_mod_stack);
54255420

5426-
let mut p0 = new_sub_parser_from_file(self.sess, &path, owns_directory, Some(name), id_sp);
5421+
let mut p0 =
5422+
new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
54275423
let mod_inner_lo = p0.span.lo;
54285424
let mod_attrs = p0.parse_inner_attributes()?;
54295425
let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;

0 commit comments

Comments
 (0)