Auto merge of #52319 - tinco:issue_12590, r=pnkfelix

Track whether module declarations are inline (fixes #12590)

To track whether module declarations are inline I added a field `inline: bool` to `ast::Mod`. The main use case is for pretty to know whether it should render the items associated with the module, but perhaps there are use cases for this information to not be forgotten in the AST.
This commit is contained in:
bors 2018-09-27 09:51:12 +00:00
commit c4501a0f1d
12 changed files with 143 additions and 17 deletions

View file

@ -1885,6 +1885,8 @@ pub struct Mod {
/// to the last token in the external file. /// to the last token in the external file.
pub inner: Span, pub inner: Span,
pub items: Vec<P<Item>>, pub items: Vec<P<Item>>,
/// For `mod foo;` inline is false, for `mod foo { .. }` it is true.
pub inline: bool,
} }
/// Foreign module declaration. /// Foreign module declaration.

View file

@ -1101,6 +1101,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
ast::ItemKind::Mod(ast::Mod { ast::ItemKind::Mod(ast::Mod {
inner: inner_span, inner: inner_span,
items, items,
inline: true
}) })
) )
} }

View file

@ -303,6 +303,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
krate.module = ast::Mod { krate.module = ast::Mod {
inner: orig_mod_span, inner: orig_mod_span,
items: vec![], items: vec![],
inline: true,
}; };
}, },
_ => unreachable!(), _ => unreachable!(),

View file

@ -1044,10 +1044,11 @@ pub fn noop_fold_fn_header<T: Folder>(mut header: FnHeader, folder: &mut T) -> F
header 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 { Mod {
inner: folder.new_span(inner), inner: folder.new_span(inner),
items: items.move_flat_map(|x| folder.fold_item(x)), items: items.move_flat_map(|x| folder.fold_item(x)),
inline: inline,
} }
} }
@ -1077,6 +1078,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
None => (ast::Mod { None => (ast::Mod {
inner: span, inner: span,
items: vec![], items: vec![],
inline: true,
}, vec![], span) }, vec![], span)
}; };

View file

@ -6297,6 +6297,7 @@ impl<'a> Parser<'a> {
Ok(ast::Mod { Ok(ast::Mod {
inner: inner_lo.to(hi), inner: inner_lo.to(hi),
items, items,
inline: true
}) })
} }
@ -6334,6 +6335,7 @@ impl<'a> Parser<'a> {
self.submod_path(id, &outer_attrs, id_span)?; self.submod_path(id, &outer_attrs, id_span)?;
let (module, mut attrs) = let (module, mut attrs) =
self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?; self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?;
// Record that we fetched the mod from an external file
if warn { if warn {
let attr = Attribute { let attr = Attribute {
id: attr::mk_attr_id(), id: attr::mk_attr_id(),
@ -6346,9 +6348,13 @@ impl<'a> Parser<'a> {
attr::mark_known(&attr); attr::mark_known(&attr);
attrs.push(attr); attrs.push(attr);
} }
Ok((id, module, Some(attrs))) Ok((id, ItemKind::Mod(module), Some(attrs)))
} else { } 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)) Ok((id, ItemKind::Mod(placeholder), None))
} }
} else { } else {
@ -6548,7 +6554,7 @@ impl<'a> Parser<'a> {
directory_ownership: DirectoryOwnership, directory_ownership: DirectoryOwnership,
name: String, name: String,
id_sp: Span) 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(); let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { if let Some(i) = included_mod_stack.iter().position(|p| *p == path) {
let mut err = String::from("circular modules: "); let mut err = String::from("circular modules: ");
@ -6568,9 +6574,10 @@ impl<'a> Parser<'a> {
p0.cfg_mods = self.cfg_mods; p0.cfg_mods = self.cfg_mods;
let mod_inner_lo = p0.span; let mod_inner_lo = p0.span;
let mod_attrs = p0.parse_inner_attributes()?; let mod_attrs = p0.parse_inner_attributes()?;
let m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?;
m0.inline = false;
self.sess.included_mod_stack.borrow_mut().pop(); 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 /// Parse a function declaration from a foreign module

View file

@ -61,6 +61,7 @@ pub struct State<'a> {
cur_cmnt: usize, cur_cmnt: usize,
boxes: Vec<pp::Breaks>, boxes: Vec<pp::Breaks>,
ann: &'a (dyn PpAnn+'a), ann: &'a (dyn PpAnn+'a),
is_expanded: bool
} }
fn rust_printer<'a>(writer: Box<dyn Write+'a>, ann: &'a dyn PpAnn) -> State<'a> { fn rust_printer<'a>(writer: Box<dyn Write+'a>, ann: &'a dyn PpAnn) -> State<'a> {
@ -72,6 +73,7 @@ fn rust_printer<'a>(writer: Box<dyn Write+'a>, ann: &'a dyn PpAnn) -> State<'a>
cur_cmnt: 0, cur_cmnt: 0,
boxes: Vec::new(), boxes: Vec::new(),
ann, ann,
is_expanded: false
} }
} }
@ -133,14 +135,17 @@ impl<'a> State<'a> {
// If the code is post expansion, don't use the table of // If the code is post expansion, don't use the table of
// literals, since it doesn't correspond with the literals // literals, since it doesn't correspond with the literals
// in the AST anymore. // in the AST anymore.
if is_expanded { None } else { Some(lits) }) if is_expanded { None } else { Some(lits) },
is_expanded
)
} }
pub fn new(cm: &'a SourceMap, pub fn new(cm: &'a SourceMap,
out: Box<dyn Write+'a>, out: Box<dyn Write+'a>,
ann: &'a dyn PpAnn, ann: &'a dyn PpAnn,
comments: Option<Vec<comments::Comment>>, comments: Option<Vec<comments::Comment>>,
literals: Option<Vec<comments::Literal>>) -> State<'a> { literals: Option<Vec<comments::Literal>>,
is_expanded: bool) -> State<'a> {
State { State {
s: pp::mk_printer(out, DEFAULT_COLUMNS), s: pp::mk_printer(out, DEFAULT_COLUMNS),
cm: Some(cm), cm: Some(cm),
@ -149,6 +154,7 @@ impl<'a> State<'a> {
cur_cmnt: 0, cur_cmnt: 0,
boxes: Vec::new(), boxes: Vec::new(),
ann, ann,
is_expanded: is_expanded
} }
} }
} }
@ -1260,10 +1266,18 @@ impl<'a> State<'a> {
ast::ItemKind::Mod(ref _mod) => { ast::ItemKind::Mod(ref _mod) => {
self.head(&visibility_qualified(&item.vis, "mod"))?; self.head(&visibility_qualified(&item.vis, "mod"))?;
self.print_ident(item.ident)?; self.print_ident(item.ident)?;
self.nbsp()?;
self.bopen()?; if _mod.inline || self.is_expanded {
self.print_mod(_mod, &item.attrs)?; self.nbsp()?;
self.bclose(item.span)?; self.bopen()?;
self.print_mod(_mod, &item.attrs)?;
self.bclose(item.span)?;
} else {
self.s.word(";")?;
self.end()?; // end inner head-block
self.end()?; // end outer head-block
}
} }
ast::ItemKind::ForeignMod(ref nmod) => { ast::ItemKind::ForeignMod(ref nmod) => {
self.head("extern")?; self.head("extern")?;

View file

@ -237,6 +237,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
})).collect(); })).collect();
let reexport_mod = ast::Mod { let reexport_mod = ast::Mod {
inline: true,
inner: DUMMY_SP, inner: DUMMY_SP,
items, items,
}; };

View file

@ -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() { }

View file

@ -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() { }

View file

@ -0,0 +1,28 @@
#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use ::std::prelude::v1::*;
#[macro_use]
extern crate std;
// 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.
// pretty-compare-only
// pretty-mode:expanded
// pp-exact:issue_12590_c.pp
// The next line should be expanded
mod issue_12590_b {
fn b() { }
fn main() { }
}
fn main() { }

View file

@ -0,0 +1,19 @@
// 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.
// pretty-compare-only
// pretty-mode:expanded
// pp-exact:issue_12590_c.pp
// The next line should be expanded
mod issue_12590_b;
fn main() { }

View file

@ -240,6 +240,11 @@ struct DebuggerCommands {
breakpoint_lines: Vec<usize>, breakpoint_lines: Vec<usize>,
} }
enum ReadFrom {
Path,
Stdin(String),
}
impl<'test> TestCx<'test> { impl<'test> TestCx<'test> {
/// Code executed for each revision in turn (or, if there are no /// Code executed for each revision in turn (or, if there are no
/// revisions, exactly once, with revision == None). /// revisions, exactly once, with revision == None).
@ -450,8 +455,14 @@ impl<'test> TestCx<'test> {
round, self.revision round, self.revision
), ),
); );
let proc_res = self.print_source(srcs[round].to_owned(), &self.props.pretty_mode); let read_from = if round == 0 {
ReadFrom::Path
} else {
ReadFrom::Stdin(srcs[round].to_owned())
};
let proc_res = self.print_source(read_from,
&self.props.pretty_mode);
if !proc_res.status.success() { if !proc_res.status.success() {
self.fatal_proc_rec( self.fatal_proc_rec(
&format!( &format!(
@ -506,7 +517,7 @@ impl<'test> TestCx<'test> {
} }
// additionally, run `--pretty expanded` and try to build it. // additionally, run `--pretty expanded` and try to build it.
let proc_res = self.print_source(srcs[round].clone(), "expanded"); let proc_res = self.print_source(ReadFrom::Path, "expanded");
if !proc_res.status.success() { if !proc_res.status.success() {
self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res); self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
} }
@ -524,12 +535,16 @@ impl<'test> TestCx<'test> {
} }
} }
fn print_source(&self, src: String, pretty_type: &str) -> ProcRes { fn print_source(&self, read_from: ReadFrom, pretty_type: &str) -> ProcRes {
let aux_dir = self.aux_output_dir_name(); let aux_dir = self.aux_output_dir_name();
let input: &str = match read_from {
ReadFrom::Stdin(_) => "-",
ReadFrom::Path => self.testpaths.file.to_str().unwrap(),
};
let mut rustc = Command::new(&self.config.rustc_path); let mut rustc = Command::new(&self.config.rustc_path);
rustc rustc
.arg("-") .arg(input)
.args(&["-Z", &format!("unpretty={}", pretty_type)]) .args(&["-Z", &format!("unpretty={}", pretty_type)])
.args(&["--target", &self.config.target]) .args(&["--target", &self.config.target])
.arg("-L") .arg("-L")
@ -538,11 +553,16 @@ impl<'test> TestCx<'test> {
.args(&self.props.compile_flags) .args(&self.props.compile_flags)
.envs(self.props.exec_env.clone()); .envs(self.props.exec_env.clone());
let src = match read_from {
ReadFrom::Stdin(src) => Some(src),
ReadFrom::Path => None
};
self.compose_and_run( self.compose_and_run(
rustc, rustc,
self.config.compile_lib_path.to_str().unwrap(), self.config.compile_lib_path.to_str().unwrap(),
Some(aux_dir.to_str().unwrap()), Some(aux_dir.to_str().unwrap()),
Some(src), src,
) )
} }