Skip to content

Commit c3afb16

Browse files
committed
Track whether module declarations are inline (fixes #12590)
1 parent b8d45da commit c3afb16

File tree

9 files changed

+114
-10
lines changed

9 files changed

+114
-10
lines changed

src/libsyntax/ast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,8 @@ pub struct Mod {
18411841
/// to the last token in the external file.
18421842
pub inner: Span,
18431843
pub items: Vec<P<Item>>,
1844+
/// For `mod foo;` inline is false, for `mod foo { .. }` it is true.
1845+
pub inline: bool,
18441846
}
18451847

18461848
/// Foreign module declaration.

src/libsyntax/ext/build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1101,6 +1101,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
11011101
ast::ItemKind::Mod(ast::Mod {
11021102
inner: inner_span,
11031103
items,
1104+
inline: true
11041105
})
11051106
)
11061107
}

src/libsyntax/ext/expand.rs

+1
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
290290
krate.module = ast::Mod {
291291
inner: orig_mod_span,
292292
items: vec![],
293+
inline: true,
293294
};
294295
},
295296
_ => unreachable!(),

src/libsyntax/fold.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1036,10 +1036,11 @@ pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> F
10361036
header
10371037
}
10381038

1039-
pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
1039+
pub fn noop_fold_mod<T: Folder>(Mod {inner, items, inline}: Mod, folder: &mut T) -> Mod {
10401040
Mod {
10411041
inner: folder.new_span(inner),
10421042
items: items.move_flat_map(|x| folder.fold_item(x)),
1043+
inline: inline,
10431044
}
10441045
}
10451046

@@ -1069,6 +1070,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
10691070
None => (ast::Mod {
10701071
inner: span,
10711072
items: vec![],
1073+
inline: true,
10721074
}, vec![], span)
10731075
};
10741076

src/libsyntax/parse/parser.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -6252,6 +6252,7 @@ impl<'a> Parser<'a> {
62526252
Ok(ast::Mod {
62536253
inner: inner_lo.to(hi),
62546254
items,
6255+
inline: true
62556256
})
62566257
}
62576258

@@ -6287,8 +6288,10 @@ impl<'a> Parser<'a> {
62876288
// This mod is in an external file. Let's go get it!
62886289
let ModulePathSuccess { path, directory_ownership, warn } =
62896290
self.submod_path(id, &outer_attrs, id_span)?;
6290-
let (module, mut attrs) =
6291+
let (mut module, mut attrs) =
62916292
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
6293+
// Record that we fetched the mod from an external file
6294+
module.inline = false;
62926295
if warn {
62936296
let attr = Attribute {
62946297
id: attr::mk_attr_id(),
@@ -6301,9 +6304,13 @@ impl<'a> Parser<'a> {
63016304
attr::mark_known(&attr);
63026305
attrs.push(attr);
63036306
}
6304-
Ok((id, module, Some(attrs)))
6307+
Ok((id, ItemKind::Mod(module), Some(attrs)))
63056308
} else {
6306-
let placeholder = ast::Mod { inner: syntax_pos::DUMMY_SP, items: Vec::new() };
6309+
let placeholder = ast::Mod {
6310+
inner: syntax_pos::DUMMY_SP,
6311+
items: Vec::new(),
6312+
inline: false
6313+
};
63076314
Ok((id, ItemKind::Mod(placeholder), None))
63086315
}
63096316
} else {
@@ -6503,7 +6510,7 @@ impl<'a> Parser<'a> {
65036510
directory_ownership: DirectoryOwnership,
65046511
name: String,
65056512
id_sp: Span)
6506-
-> PResult<'a, (ast::ItemKind, Vec<Attribute> )> {
6513+
-> PResult<'a, (ast::Mod, Vec<Attribute> )> {
65076514
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
65086515
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
65096516
let mut err = String::from("circular modules: ");
@@ -6525,7 +6532,7 @@ impl<'a> Parser<'a> {
65256532
let mod_attrs = p0.parse_inner_attributes()?;
65266533
let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
65276534
self.sess.included_mod_stack.borrow_mut().pop();
6528-
Ok((ast::ItemKind::Mod(m0), mod_attrs))
6535+
Ok((m0, mod_attrs))
65296536
}
65306537

65316538
/// Parse a function declaration from a foreign module

src/libsyntax/print/pprust.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1260,10 +1260,16 @@ impl<'a> State<'a> {
12601260
ast::ItemKind::Mod(ref _mod) => {
12611261
self.head(&visibility_qualified(&item.vis, "mod"))?;
12621262
self.print_ident(item.ident)?;
1263-
self.nbsp()?;
1264-
self.bopen()?;
1265-
self.print_mod(_mod, &item.attrs)?;
1266-
self.bclose(item.span)?;
1263+
1264+
if _mod.inline {
1265+
self.nbsp()?;
1266+
self.bopen()?;
1267+
self.print_mod(_mod, &item.attrs)?;
1268+
self.bclose(item.span)?;
1269+
} else {
1270+
self.s.word(";")?;
1271+
}
1272+
12671273
}
12681274
ast::ItemKind::ForeignMod(ref nmod) => {
12691275
self.head("extern")?;

src/libsyntax/test.rs

+54
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
240240
let reexport_mod = ast::Mod {
241241
inner: DUMMY_SP,
242242
items,
243+
inline: true,
243244
};
244245

245246
let sym = Ident::with_empty_ctxt(Symbol::gensym("__test_reexports"));
@@ -392,6 +393,59 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
392393
tokens: None,
393394
})
394395

396+
let testmod = ast::Mod {
397+
inner: DUMMY_SP,
398+
items: vec![import, mainfn, tests],
399+
inline: true,
400+
};
401+
let item_ = ast::ItemKind::Mod(testmod);
402+
let mod_ident = Ident::with_empty_ctxt(Symbol::gensym("__test"));
403+
404+
let mut expander = cx.ext_cx.monotonic_expander();
405+
let item = expander.fold_item(P(ast::Item {
406+
id: ast::DUMMY_NODE_ID,
407+
ident: mod_ident,
408+
attrs: vec![],
409+
node: item_,
410+
vis: dummy_spanned(ast::VisibilityKind::Public),
411+
span: DUMMY_SP,
412+
tokens: None,
413+
})).pop().unwrap();
414+
let reexport = cx.reexport_test_harness_main.map(|s| {
415+
// building `use __test::main as <ident>;`
416+
let rename = Ident::with_empty_ctxt(s);
417+
418+
let use_path = ast::UseTree {
419+
span: DUMMY_SP,
420+
prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
421+
kind: ast::UseTreeKind::Simple(Some(rename), ast::DUMMY_NODE_ID, ast::DUMMY_NODE_ID),
422+
};
423+
424+
expander.fold_item(P(ast::Item {
425+
id: ast::DUMMY_NODE_ID,
426+
ident: keywords::Invalid.ident(),
427+
attrs: vec![],
428+
node: ast::ItemKind::Use(P(use_path)),
429+
vis: dummy_spanned(ast::VisibilityKind::Inherited),
430+
span: DUMMY_SP,
431+
tokens: None,
432+
})).pop().unwrap()
433+
});
434+
435+
debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item));
436+
437+
(item, reexport)
438+
}
439+
440+
fn nospan<T>(t: T) -> codemap::Spanned<T> {
441+
codemap::Spanned { node: t, span: DUMMY_SP }
442+
}
443+
444+
fn path_node(ids: Vec<Ident>) -> ast::Path {
445+
ast::Path {
446+
span: DUMMY_SP,
447+
segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id)).collect(),
448+
}
395449
}
396450

397451
fn path_name_i(idents: &[Ident]) -> String {

src/test/pretty/issue_12590_a.rs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// pp-exact
12+
13+
// The next line should not be expanded
14+
15+
mod issue_12590_b;
16+
17+
fn main() { }

src/test/pretty/issue_12590_b.rs

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Second part of two file test
12+
fn b() { }
13+
14+
fn main() { }

0 commit comments

Comments
 (0)