about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTinco Andringa <mail@tinco.nl>2018-07-11 15:19:32 +0200
committerTinco Andringa <mail@tinco.nl>2018-09-10 12:33:37 +0200
commitc3afb16e1608929a816d6c0e2a0118185199aef1 (patch)
tree65c1eeacf1972ad17c40407efd04091156aac7e1
parentb8d45da2747c0b0943f48854e653ebe0d1ba60c9 (diff)
downloadrust-c3afb16e1608929a816d6c0e2a0118185199aef1.tar.gz
rust-c3afb16e1608929a816d6c0e2a0118185199aef1.zip
Track whether module declarations are inline (fixes #12590)
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ext/build.rs1
-rw-r--r--src/libsyntax/ext/expand.rs1
-rw-r--r--src/libsyntax/fold.rs4
-rw-r--r--src/libsyntax/parse/parser.rs17
-rw-r--r--src/libsyntax/print/pprust.rs14
-rw-r--r--src/libsyntax/test.rs54
-rw-r--r--src/test/pretty/issue_12590_a.rs17
-rw-r--r--src/test/pretty/issue_12590_b.rs14
9 files changed, 114 insertions, 10 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 9851749be37..0fd59d8d9f4 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1841,6 +1841,8 @@ pub struct Mod {
     /// to the last token in the external file.
     pub inner: Span,
     pub items: Vec<P<Item>>,
+    /// For `mod foo;` inline is false, for `mod foo { .. }` it is true.
+    pub inline: bool,
 }
 
 /// Foreign module declaration.
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index b1bed9602f3..6210003a40d 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -1101,6 +1101,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             ast::ItemKind::Mod(ast::Mod {
                 inner: inner_span,
                 items,
+                inline: true
             })
         )
     }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 3bb19121ee3..389224e013e 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -290,6 +290,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 krate.module = ast::Mod {
                     inner: orig_mod_span,
                     items: vec![],
+                    inline: true,
                 };
             },
             _ => unreachable!(),
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 032393b4f12..b95ef5f4b7a 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1036,10 +1036,11 @@ pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> F
     header
 }
 
-pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
+pub fn noop_fold_mod<T: Folder>(Mod {inner, items, inline}: Mod, folder: &mut T) -> Mod {
     Mod {
         inner: folder.new_span(inner),
         items: items.move_flat_map(|x| folder.fold_item(x)),
+        inline: inline,
     }
 }
 
@@ -1069,6 +1070,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
         None => (ast::Mod {
             inner: span,
             items: vec![],
+            inline: true,
         }, vec![], span)
     };
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f57fca2cfcf..12156522242 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -6252,6 +6252,7 @@ impl<'a> Parser<'a> {
         Ok(ast::Mod {
             inner: inner_lo.to(hi),
             items,
+            inline: true
         })
     }
 
@@ -6287,8 +6288,10 @@ impl<'a> Parser<'a> {
                 // This mod is in an external file. Let's go get it!
                 let ModulePathSuccess { path, directory_ownership, warn } =
                     self.submod_path(id, &outer_attrs, id_span)?;
-                let (module, mut attrs) =
+                let (mut module, mut attrs) =
                     self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
+                // Record that we fetched the mod from an external file
+                module.inline = false;
                 if warn {
                     let attr = Attribute {
                         id: attr::mk_attr_id(),
@@ -6301,9 +6304,13 @@ impl<'a> Parser<'a> {
                     attr::mark_known(&attr);
                     attrs.push(attr);
                 }
-                Ok((id, module, Some(attrs)))
+                Ok((id, ItemKind::Mod(module), Some(attrs)))
             } else {
-                let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() };
+                let placeholder = ast::Mod {
+                    inner: syntax_pos::DUMMY_SP,
+                    items: Vec::new(),
+                    inline: false
+                };
                 Ok((id, ItemKind::Mod(placeholder), None))
             }
         } else {
@@ -6503,7 +6510,7 @@ impl<'a> Parser<'a> {
                     directory_ownership: DirectoryOwnership,
                     name: String,
                     id_sp: Span)
-                    -> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
+                    -> PResult<'a, (ast::Mod, Vec<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: ");
@@ -6525,7 +6532,7 @@ impl<'a> Parser<'a> {
         let mod_attrs = p0.parse_inner_attributes()?;
         let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
         self.sess.included_mod_stack.borrow_mut().pop();
-        Ok((ast::ItemKind::Mod(m0), mod_attrs))
+        Ok((m0, mod_attrs))
     }
 
     /// Parse a function declaration from a foreign module
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 85d29a5be89..fb4000294ea 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1260,10 +1260,16 @@ impl<'a> State<'a> {
             ast::ItemKind::Mod(ref _mod) => {
                 self.head(&visibility_qualified(&item.vis, "mod"))?;
                 self.print_ident(item.ident)?;
-                self.nbsp()?;
-                self.bopen()?;
-                self.print_mod(_mod, &item.attrs)?;
-                self.bclose(item.span)?;
+
+                if _mod.inline {
+                    self.nbsp()?;
+                    self.bopen()?;
+                    self.print_mod(_mod, &item.attrs)?;
+                    self.bclose(item.span)?;
+                } else {
+                    self.s.word(";")?;
+                }
+
             }
             ast::ItemKind::ForeignMod(ref nmod) => {
                 self.head("extern")?;
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index ab67736c389..408f250fd45 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -240,6 +240,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
     let reexport_mod = ast::Mod {
         inner: DUMMY_SP,
         items,
+        inline: true,
     };
 
     let sym = Ident::with_empty_ctxt(Symbol::gensym("__test_reexports"));
@@ -392,6 +393,59 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
         tokens: None,
     })
 
+    let testmod = ast::Mod {
+        inner: DUMMY_SP,
+        items: vec![import, mainfn, tests],
+        inline: true,
+    };
+    let item_ = ast::ItemKind::Mod(testmod);
+    let mod_ident = Ident::with_empty_ctxt(Symbol::gensym("__test"));
+
+    let mut expander = cx.ext_cx.monotonic_expander();
+    let item = expander.fold_item(P(ast::Item {
+        id: ast::DUMMY_NODE_ID,
+        ident: mod_ident,
+        attrs: vec![],
+        node: item_,
+        vis: dummy_spanned(ast::VisibilityKind::Public),
+        span: DUMMY_SP,
+        tokens: None,
+    })).pop().unwrap();
+    let reexport = cx.reexport_test_harness_main.map(|s| {
+        // building `use __test::main as <ident>;`
+        let rename = Ident::with_empty_ctxt(s);
+
+        let use_path = ast::UseTree {
+            span: DUMMY_SP,
+            prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
+            kind: ast::UseTreeKind::Simple(Some(rename), ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID),
+        };
+
+        expander.fold_item(P(ast::Item {
+            id: ast::DUMMY_NODE_ID,
+            ident: keywords::Invalid.ident(),
+            attrs: vec![],
+            node: ast::ItemKind::Use(P(use_path)),
+            vis: dummy_spanned(ast::VisibilityKind::Inherited),
+            span: DUMMY_SP,
+            tokens: None,
+        })).pop().unwrap()
+    });
+
+    debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item));
+
+    (item, reexport)
+}
+
+fn nospan<T>(t: T) -> codemap::Spanned<T> {
+    codemap::Spanned { node: t, span: DUMMY_SP }
+}
+
+fn path_node(ids: Vec<Ident>) -> ast::Path {
+    ast::Path {
+        span: DUMMY_SP,
+        segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id)).collect(),
+    }
 }
 
 fn path_name_i(idents: &[Ident]) -> String {
diff --git a/src/test/pretty/issue_12590_a.rs b/src/test/pretty/issue_12590_a.rs
new file mode 100644
index 00000000000..0087c3c4558
--- /dev/null
+++ b/src/test/pretty/issue_12590_a.rs
@@ -0,0 +1,17 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+
+// The next line should not be expanded
+
+mod issue_12590_b;
+
+fn main() { }
diff --git a/src/test/pretty/issue_12590_b.rs b/src/test/pretty/issue_12590_b.rs
new file mode 100644
index 00000000000..ebb6310b047
--- /dev/null
+++ b/src/test/pretty/issue_12590_b.rs
@@ -0,0 +1,14 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Second part of two file test
+fn b() { }
+
+fn main() { }