Skip to content

Commit

Permalink
Track whether module declarations are inline (fixes #12590)
Browse files Browse the repository at this point in the history
  • Loading branch information
tinco committed Sep 10, 2018
1 parent b8d45da commit c3afb16
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 10 deletions.
2 changes: 2 additions & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
ast::ItemKind::Mod(ast::Mod {
inner: inner_span,
items,
inline: true
})
)
}
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
krate.module = ast::Mod {
inner: orig_mod_span,
items: vec![],
inline: true,
};
},
_ => unreachable!(),
Expand Down
4 changes: 3 additions & 1 deletion src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down Expand Up @@ -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)
};

Expand Down
17 changes: 12 additions & 5 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6252,6 +6252,7 @@ impl<'a> Parser<'a> {
Ok(ast::Mod {
inner: inner_lo.to(hi),
items,
inline: true
})
}

Expand Down Expand Up @@ -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(),
Expand All @@ -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 {
Expand Down Expand Up @@ -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: ");
Expand All @@ -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
Expand Down
14 changes: 10 additions & 4 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")?;
Expand Down
54 changes: 54 additions & 0 deletions src/libsyntax/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down Expand Up @@ -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 {
Expand Down
17 changes: 17 additions & 0 deletions src/test/pretty/issue_12590_a.rs
Original file line number Diff line number Diff line change
@@ -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() { }
14 changes: 14 additions & 0 deletions src/test/pretty/issue_12590_b.rs
Original file line number Diff line number Diff line change
@@ -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() { }

0 comments on commit c3afb16

Please sign in to comment.