From c3afb16e1608929a816d6c0e2a0118185199aef1 Mon Sep 17 00:00:00 2001 From: Tinco Andringa Date: Wed, 11 Jul 2018 15:19:32 +0200 Subject: Track whether module declarations are inline (fixes #12590) --- src/libsyntax/ast.rs | 2 ++ src/libsyntax/ext/build.rs | 1 + src/libsyntax/ext/expand.rs | 1 + src/libsyntax/fold.rs | 4 +++- src/libsyntax/parse/parser.rs | 17 ++++++++++---- src/libsyntax/print/pprust.rs | 14 +++++++---- src/libsyntax/test.rs | 54 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 83 insertions(+), 10 deletions(-) (limited to 'src/libsyntax') 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>, + /// 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(mut header: FnHeader, folder: &mut T) -> F header } -pub fn noop_fold_mod(Mod {inner, items}: Mod, folder: &mut T) -> Mod { +pub fn noop_fold_mod(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(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 )> { + -> PResult<'a, (ast::Mod, Vec )> { 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 { 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 ;` + 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) -> codemap::Spanned { + codemap::Spanned { node: t, span: DUMMY_SP } +} + +fn path_node(ids: Vec) -> 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 { -- cgit 1.4.1-3-g733a5