about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-05 04:16:26 +0000
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>2016-11-22 01:48:10 +0000
commit5675d9d28007691c4f396abcd4b29a228150eeb4 (patch)
treeff28ee180c2e904520168d953a6946574c94b18b /src/libsyntax
parent7b3eeea22c9b81f6e7277b79517a0dab25b9f383 (diff)
downloadrust-5675d9d28007691c4f396abcd4b29a228150eeb4.tar.gz
rust-5675d9d28007691c4f396abcd4b29a228150eeb4.zip
Clean up directory ownership semantics.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/base.rs8
-rw-r--r--src/libsyntax/ext/expand.rs24
-rw-r--r--src/libsyntax/ext/source_util.rs5
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs13
-rw-r--r--src/libsyntax/parse/mod.rs17
-rw-r--r--src/libsyntax/parse/parser.rs106
6 files changed, 94 insertions, 79 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index ddf4cf11f20..ddbca47429d 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -18,7 +18,7 @@ use errors::DiagnosticBuilder;
 use ext::expand::{self, Expansion};
 use ext::hygiene::Mark;
 use fold::{self, Folder};
-use parse::{self, parser};
+use parse::{self, parser, DirectoryOwnership};
 use parse::token;
 use ptr::P;
 use symbol::Symbol;
@@ -568,9 +568,7 @@ pub struct ExpansionData {
     pub depth: usize,
     pub backtrace: ExpnId,
     pub module: Rc<ModuleData>,
-
-    // True if non-inline modules without a `#[path]` are forbidden at the root of this expansion.
-    pub no_noninline_mod: bool,
+    pub directory_ownership: DirectoryOwnership,
 }
 
 /// One of these is made during expansion and incrementally updated as we go;
@@ -601,7 +599,7 @@ impl<'a> ExtCtxt<'a> {
                 depth: 0,
                 backtrace: NO_EXPANSION,
                 module: Rc::new(ModuleData { mod_path: Vec::new(), directory: PathBuf::new() }),
-                no_noninline_mod: false,
+                directory_ownership: DirectoryOwnership::Owned,
             },
         }
     }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 844fb77e29d..3e8f118ce62 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -21,7 +21,7 @@ use ext::base::*;
 use feature_gate::{self, Features};
 use fold;
 use fold::*;
-use parse::{ParseSess, PResult, lexer};
+use parse::{ParseSess, DirectoryOwnership, PResult, lexer};
 use parse::parser::Parser;
 use parse::token;
 use print::pprust;
@@ -727,9 +727,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
     }
 
     fn fold_block(&mut self, block: P<Block>) -> P<Block> {
-        let no_noninline_mod = mem::replace(&mut self.cx.current_expansion.no_noninline_mod, true);
+        let old_directory_ownership = self.cx.current_expansion.directory_ownership;
+        self.cx.current_expansion.directory_ownership = DirectoryOwnership::UnownedViaBlock;
         let result = noop_fold_block(block, self);
-        self.cx.current_expansion.no_noninline_mod = no_noninline_mod;
+        self.cx.current_expansion.directory_ownership = old_directory_ownership;
         result
     }
 
@@ -768,7 +769,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
                     return noop_fold_item(item, self);
                 }
 
-                let orig_no_noninline_mod = self.cx.current_expansion.no_noninline_mod;
+                let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
                 let mut module = (*self.cx.current_expansion.module).clone();
                 module.mod_path.push(item.ident);
 
@@ -779,23 +780,28 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
 
                 if inline_module {
                     if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, "path") {
-                        self.cx.current_expansion.no_noninline_mod = false;
+                        self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned;
                         module.directory.push(&*path.as_str());
                     } else {
                         module.directory.push(&*item.ident.name.as_str());
                     }
                 } else {
-                    self.cx.current_expansion.no_noninline_mod = false;
-                    module.directory =
+                    let mut path =
                         PathBuf::from(self.cx.parse_sess.codemap().span_to_filename(inner));
-                    module.directory.pop();
+                    let directory_ownership = match path.file_name().unwrap().to_str() {
+                        Some("mod.rs") => DirectoryOwnership::Owned,
+                        _ => DirectoryOwnership::UnownedViaMod,
+                    };
+                    path.pop();
+                    module.directory = path;
+                    self.cx.current_expansion.directory_ownership = directory_ownership;
                 }
 
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
                 let result = noop_fold_item(item, self);
                 self.cx.current_expansion.module = orig_module;
-                self.cx.current_expansion.no_noninline_mod = orig_no_noninline_mod;
+                self.cx.current_expansion.directory_ownership = orig_directory_ownership;
                 return result;
             }
             // Ensure that test functions are accessible from the test harness.
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 320d49b6463..39b92c7d007 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -13,7 +13,7 @@ use syntax_pos::{self, Pos, Span};
 use ext::base::*;
 use ext::base;
 use ext::build::AstBuilder;
-use parse::token;
+use parse::{token, DirectoryOwnership};
 use parse;
 use print::pprust;
 use ptr::P;
@@ -90,7 +90,8 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
     };
     // The file will be added to the code map by the parser
     let path = res_rel_file(cx, sp, Path::new(&file));
-    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, true, None, sp);
+    let directory_ownership = DirectoryOwnership::Owned;
+    let p = parse::new_sub_parser_from_file(cx.parse_sess(), &path, directory_ownership, None, sp);
 
     struct ExpandResult<'a> {
         p: parse::parser::Parser<'a>,
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 59b8b50e88c..4164b4a93ec 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -19,7 +19,7 @@ use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal};
 use ext::tt::macro_parser::{parse, parse_failure_msg};
 use parse::ParseSess;
 use parse::lexer::new_tt_reader;
-use parse::parser::{Parser, Restrictions};
+use parse::parser::Parser;
 use parse::token::{self, NtTT, Token};
 use parse::token::Token::*;
 use print;
@@ -117,11 +117,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 let trncbr =
                     new_tt_reader(&cx.parse_sess.span_diagnostic, Some(named_matches), rhs);
                 let mut p = Parser::new(cx.parse_sess(), Box::new(trncbr));
-                p.directory = cx.current_expansion.module.directory.clone();
-                p.restrictions = match cx.current_expansion.no_noninline_mod {
-                    true => Restrictions::NO_NONINLINE_MOD,
-                    false => Restrictions::empty(),
-                };
+                let module = &cx.current_expansion.module;
+                p.directory.path = module.directory.clone();
+                p.directory.ownership = cx.current_expansion.directory_ownership;
+                p.root_module_name =
+                    module.mod_path.last().map(|id| (*id.name.as_str()).to_owned());
+
                 p.check_unknown_macro_variable();
                 // Let the context choose how to interpret the result.
                 // Weird, but useful for X-macros.
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index be340a5b5aa..f969e45b83a 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -76,6 +76,19 @@ impl ParseSess {
     }
 }
 
+#[derive(Clone)]
+pub struct Directory {
+    pub path: PathBuf,
+    pub ownership: DirectoryOwnership,
+}
+
+#[derive(Copy, Clone)]
+pub enum DirectoryOwnership {
+    Owned,
+    UnownedViaBlock,
+    UnownedViaMod,
+}
+
 // a bunch of utility functions of the form parse_<thing>_from_<source>
 // where <thing> includes crate, expr, item, stmt, tts, and one that
 // 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>
 /// On an error, use the given span as the source of the problem.
 pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
                                     path: &Path,
-                                    owns_directory: bool,
+                                    directory_ownership: DirectoryOwnership,
                                     module_name: Option<String>,
                                     sp: Span) -> Parser<'a> {
     let mut p = filemap_to_parser(sess, file_to_filemap(sess, path, Some(sp)));
-    p.owns_directory = owns_directory;
+    p.directory.ownership = directory_ownership;
     p.root_module_name = module_name;
     p
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 4997e464c2b..ee69125ffae 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -49,7 +49,7 @@ use parse::common::SeqSep;
 use parse::lexer::{Reader, TokenAndSpan};
 use parse::obsolete::ObsoleteSyntax;
 use parse::token::{self, MatchNt, SubstNt};
-use parse::{new_sub_parser_from_file, ParseSess};
+use parse::{new_sub_parser_from_file, ParseSess, Directory, DirectoryOwnership};
 use util::parser::{AssocOp, Fixity};
 use print::pprust;
 use ptr::P;
@@ -68,7 +68,6 @@ bitflags! {
     flags Restrictions: u8 {
         const RESTRICTION_STMT_EXPR         = 1 << 0,
         const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
-        const NO_NONINLINE_MOD  = 1 << 2,
     }
 }
 
@@ -200,12 +199,9 @@ pub struct Parser<'a> {
     /// extra detail when the same error is seen twice
     pub obsolete_set: HashSet<ObsoleteSyntax>,
     /// Used to determine the path to externally loaded source files
-    pub directory: PathBuf,
+    pub directory: Directory,
     /// Stack of open delimiters and their spans. Used for error message.
     pub open_braces: Vec<(token::DelimToken, Span)>,
-    /// Flag if this parser "owns" the directory that it is currently parsing
-    /// in. This will affect how nested files are looked up.
-    pub owns_directory: bool,
     /// Name of the root module this parser originated from. If `None`, then the
     /// name is not known. This does not change while the parser is descending
     /// into modules, and sub-parsers have new values for this name.
@@ -245,8 +241,8 @@ pub struct ModulePath {
 }
 
 pub struct ModulePathSuccess {
-    pub path: ::std::path::PathBuf,
-    pub owns_directory: bool,
+    pub path: PathBuf,
+    pub directory_ownership: DirectoryOwnership,
 }
 
 pub struct ModulePathError {
@@ -296,9 +292,8 @@ impl<'a> Parser<'a> {
             quote_depth: 0,
             parsing_token_tree: false,
             obsolete_set: HashSet::new(),
-            directory: PathBuf::new(),
+            directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned },
             open_braces: Vec::new(),
-            owns_directory: true,
             root_module_name: None,
             expected_tokens: Vec::new(),
             tts: Vec::new(),
@@ -310,8 +305,8 @@ impl<'a> Parser<'a> {
         parser.token = tok.tok;
         parser.span = tok.sp;
         if parser.span != syntax_pos::DUMMY_SP {
-            parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span));
-            parser.directory.pop();
+            parser.directory.path = PathBuf::from(sess.codemap().span_to_filename(parser.span));
+            parser.directory.path.pop();
         }
         parser
     }
@@ -3966,9 +3961,11 @@ impl<'a> Parser<'a> {
             }
         } else {
             // FIXME: Bad copy of attrs
-            let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD;
-            match self.with_res(restrictions,
-                                |this| this.parse_item_(attrs.clone(), false, true))? {
+            let old_directory_ownership =
+                mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
+            let item = self.parse_item_(attrs.clone(), false, true)?;
+            self.directory.ownership = old_directory_ownership;
+            match item {
                 Some(i) => Stmt {
                     id: ast::DUMMY_NODE_ID,
                     span: mk_sp(lo, i.span.hi),
@@ -5271,33 +5268,33 @@ impl<'a> Parser<'a> {
             self.bump();
             if in_cfg {
                 // This mod is in an external file. Let's go get it!
-                let (m, attrs) = self.eval_src_mod(id, &outer_attrs, id_span)?;
-                Ok((id, m, Some(attrs)))
+                let ModulePathSuccess { path, directory_ownership } =
+                    self.submod_path(id, &outer_attrs, id_span)?;
+                let (module, attrs) =
+                    self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
+                Ok((id, module, Some(attrs)))
             } else {
                 let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() };
                 Ok((id, ItemKind::Mod(placeholder), None))
             }
         } else {
-            let directory = self.directory.clone();
-            let restrictions = self.push_directory(id, &outer_attrs);
+            let old_directory = self.directory.clone();
+            self.push_directory(id, &outer_attrs);
             self.expect(&token::OpenDelim(token::Brace))?;
             let mod_inner_lo = self.span.lo;
             let attrs = self.parse_inner_attributes()?;
-            let m = self.with_res(restrictions, |this| {
-                this.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)
-            })?;
-            self.directory = directory;
-            Ok((id, ItemKind::Mod(m), Some(attrs)))
+            let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?;
+            self.directory = old_directory;
+            Ok((id, ItemKind::Mod(module), Some(attrs)))
         }
     }
 
-    fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) -> Restrictions {
+    fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
         if let Some(path) = ::attr::first_attr_value_str_by_name(attrs, "path") {
-            self.directory.push(&*path.as_str());
-            self.restrictions - Restrictions::NO_NONINLINE_MOD
+            self.directory.path.push(&*path.as_str());
+            self.directory.ownership = DirectoryOwnership::Owned;
         } else {
-            self.directory.push(&*id.name.as_str());
-            self.restrictions
+            self.directory.path.push(&*id.name.as_str());
         }
     }
 
@@ -5317,8 +5314,14 @@ impl<'a> Parser<'a> {
         let secondary_exists = codemap.file_exists(&secondary_path);
 
         let result = match (default_exists, secondary_exists) {
-            (true, false) => Ok(ModulePathSuccess { path: default_path, owns_directory: false }),
-            (false, true) => Ok(ModulePathSuccess { path: secondary_path, owns_directory: true }),
+            (true, false) => Ok(ModulePathSuccess {
+                path: default_path,
+                directory_ownership: DirectoryOwnership::UnownedViaMod,
+            }),
+            (false, true) => Ok(ModulePathSuccess {
+                path: secondary_path,
+                directory_ownership: DirectoryOwnership::Owned,
+            }),
             (false, false) => Err(ModulePathError {
                 err_msg: format!("file not found for module `{}`", mod_name),
                 help_msg: format!("name the file either {} or {} inside the directory {:?}",
@@ -5346,13 +5349,19 @@ impl<'a> Parser<'a> {
                    id: ast::Ident,
                    outer_attrs: &[ast::Attribute],
                    id_sp: Span) -> PResult<'a, ModulePathSuccess> {
-        if let Some(p) = Parser::submod_path_from_attr(outer_attrs, &self.directory) {
-            return Ok(ModulePathSuccess { path: p, owns_directory: true });
+        if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) {
+            return Ok(ModulePathSuccess {
+                directory_ownership: match path.file_name().and_then(|s| s.to_str()) {
+                    Some("mod.rs") => DirectoryOwnership::Owned,
+                    _ => DirectoryOwnership::UnownedViaMod,
+                },
+                path: path,
+            });
         }
 
-        let paths = Parser::default_submod_path(id, &self.directory, self.sess.codemap());
+        let paths = Parser::default_submod_path(id, &self.directory.path, self.sess.codemap());
 
-        if self.restrictions.contains(Restrictions::NO_NONINLINE_MOD) {
+        if let DirectoryOwnership::UnownedViaBlock = self.directory.ownership {
             let msg =
                 "Cannot declare a non-inline module inside a block unless it has a path attribute";
             let mut err = self.diagnostic().struct_span_err(id_sp, msg);
@@ -5362,10 +5371,10 @@ impl<'a> Parser<'a> {
                 err.span_note(id_sp, &msg);
             }
             return Err(err);
-        } else if !self.owns_directory {
+        } else if let DirectoryOwnership::UnownedViaMod = self.directory.ownership {
             let mut err = self.diagnostic().struct_span_err(id_sp,
                 "cannot declare a new module at this location");
-            let this_module = match self.directory.file_name() {
+            let this_module = match self.directory.path.file_name() {
                 Some(file_name) => file_name.to_str().unwrap().to_owned(),
                 None => self.root_module_name.as_ref().unwrap().clone(),
             };
@@ -5390,25 +5399,11 @@ impl<'a> Parser<'a> {
 
     /// Read a module from a source file.
     fn eval_src_mod(&mut self,
-                    id: ast::Ident,
-                    outer_attrs: &[ast::Attribute],
+                    path: PathBuf,
+                    directory_ownership: DirectoryOwnership,
+                    name: String,
                     id_sp: Span)
                     -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
-        let ModulePathSuccess { path, owns_directory } = self.submod_path(id,
-                                                                          outer_attrs,
-                                                                          id_sp)?;
-
-        self.eval_src_mod_from_path(path,
-                                    owns_directory,
-                                    id.to_string(),
-                                    id_sp)
-    }
-
-    fn eval_src_mod_from_path(&mut self,
-                              path: PathBuf,
-                              owns_directory: bool,
-                              name: String,
-                              id_sp: Span) -> PResult<'a, (ast::ItemKind, Vec<ast::Attribute> )> {
         let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
         if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
             let mut err = String::from("circular modules: ");
@@ -5423,7 +5418,8 @@ impl<'a> Parser<'a> {
         included_mod_stack.push(path.clone());
         drop(included_mod_stack);
 
-        let mut p0 = new_sub_parser_from_file(self.sess, &path, owns_directory, Some(name), id_sp);
+        let mut p0 =
+            new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp);
         let mod_inner_lo = p0.span.lo;
         let mod_attrs = p0.parse_inner_attributes()?;
         let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;