diff options
| author | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-06-26 02:19:34 +0000 |
|---|---|---|
| committer | Jeffrey Seyfried <jeffrey.seyfried@gmail.com> | 2016-06-26 02:20:14 +0000 |
| commit | 9bb3ea0febcbb8f6d7715256a5644daa985cf4e7 (patch) | |
| tree | eeed21468b6bceeed80766490852c8cee2653170 /src | |
| parent | 8eddf0280014972e051856dfe949054acf53c043 (diff) | |
| parent | 8cad25199acb346bf8d6b1771f1f50dc9e59374c (diff) | |
| download | rust-9bb3ea0febcbb8f6d7715256a5644daa985cf4e7.tar.gz rust-9bb3ea0febcbb8f6d7715256a5644daa985cf4e7.zip | |
Rollup merge of #34436 - jseyfried:no_block_expr, r=eddyb
To allow these braced macro invocation, this PR removes the optional expression from `ast::Block` and instead uses a `StmtKind::Expr` at the end of the statement list.
Currently, braced macro invocations in blocks can expand into statements (and items) except when they are last in a block, in which case they can only expand into expressions.
For example,
```rust
macro_rules! make_stmt {
() => { let x = 0; }
}
fn f() {
make_stmt! {} //< This is OK...
let x = 0; //< ... unless this line is commented out.
}
```
Fixes #34418.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/hir/lowering.rs | 17 | ||||
| -rw-r--r-- | src/librustc_driver/driver.rs | 24 | ||||
| -rw-r--r-- | src/librustc_driver/pretty.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 52 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/quote.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 27 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 42 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/clone.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/cmp/eq.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/debug.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/encodable.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/generic/mod.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/hash.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/mod.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax_ext/format.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-34418.rs | 31 |
22 files changed, 161 insertions, 116 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index a32631ac53d..5b655522f34 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -574,10 +574,23 @@ impl<'a> LoweringContext<'a> { } fn lower_block(&mut self, b: &Block) -> P<hir::Block> { + let mut stmts = Vec::new(); + let mut expr = None; + + if let Some((last, rest)) = b.stmts.split_last() { + stmts = rest.iter().map(|s| self.lower_stmt(s)).collect::<Vec<_>>(); + let last = self.lower_stmt(last); + if let hir::StmtExpr(e, _) = last.node { + expr = Some(e); + } else { + stmts.push(last); + } + } + P(hir::Block { id: b.id, - stmts: b.stmts.iter().map(|s| self.lower_stmt(s)).collect(), - expr: b.expr.as_ref().map(|ref x| self.lower_expr(x)), + stmts: stmts.into(), + expr: expr, rules: self.lower_block_check_mode(&b.rules), span: b.span, }) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 927953b034b..eb442c0a34e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -763,6 +763,9 @@ pub fn phase_2_configure_and_expand<'a>(sess: &Session, } pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate { + use syntax::ptr::P; + use syntax::util::move_map::MoveMap; + struct NodeIdAssigner<'a> { sess: &'a Session, } @@ -772,6 +775,27 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate { assert_eq!(old_id, ast::DUMMY_NODE_ID); self.sess.next_node_id() } + + fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> { + block.map(|mut block| { + block.id = self.new_id(block.id); + + let stmt = block.stmts.pop(); + block.stmts = block.stmts.move_flat_map(|s| self.fold_stmt(s).into_iter()); + if let Some(ast::Stmt { node: ast::StmtKind::Expr(expr), span, .. }) = stmt { + let expr = self.fold_expr(expr); + block.stmts.push(ast::Stmt { + id: expr.id, + node: ast::StmtKind::Expr(expr), + span: span, + }); + } else if let Some(stmt) = stmt { + block.stmts.extend(self.fold_stmt(stmt)); + } + + block + }) + } } let krate = time(sess.time_passes(), diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 80eea76e107..baac455a25f 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -657,8 +657,11 @@ impl fold::Folder for ReplaceBodyWithLoop { fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> { fn expr_to_block(rules: ast::BlockCheckMode, e: Option<P<ast::Expr>>) -> P<ast::Block> { P(ast::Block { - expr: e, - stmts: vec![], + stmts: e.map(|e| ast::Stmt { + id: ast::DUMMY_NODE_ID, + span: e.span, + node: ast::StmtKind::Expr(e), + }).into_iter().collect(), rules: rules, id: ast::DUMMY_NODE_ID, span: syntax_pos::DUMMY_SP, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dcdc1e60a99..a352715b20b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -557,9 +557,6 @@ impl PartialEq for MetaItemKind { pub struct Block { /// Statements in a block pub stmts: Vec<Stmt>, - /// An expression at the end of the block - /// without a semicolon, if any - pub expr: Option<P<Expr>>, pub id: NodeId, /// Distinguishes between `unsafe { ... }` and `{ ... }` pub rules: BlockCheckMode, @@ -832,7 +829,7 @@ pub enum StmtKind { /// An item definition. Item(P<Item>), - /// Expr without trailing semi-colon (must have unit type). + /// Expr without trailing semi-colon. Expr(P<Expr>), Semi(P<Expr>), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index f4ae23ed8be..435241f426e 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -88,6 +88,7 @@ pub trait AstBuilder { // statements fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt; + fn stmt_semi(&self, expr: P<ast::Expr>) -> ast::Stmt; fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident, ex: P<ast::Expr>) -> ast::Stmt; fn stmt_let_typed(&self, sp: Span, @@ -99,12 +100,8 @@ pub trait AstBuilder { fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt; // blocks - fn block(&self, span: Span, stmts: Vec<ast::Stmt>, - expr: Option<P<ast::Expr>>) -> P<ast::Block>; + fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block>; fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block>; - fn block_all(&self, span: Span, - stmts: Vec<ast::Stmt>, - expr: Option<P<ast::Expr>>) -> P<ast::Block>; // expressions fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr>; @@ -512,6 +509,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, + node: ast::StmtKind::Expr(expr), + } + } + + fn stmt_semi(&self, expr: P<ast::Expr>) -> ast::Stmt { + ast::Stmt { + id: ast::DUMMY_NODE_ID, + span: expr.span, node: ast::StmtKind::Semi(expr), } } @@ -567,11 +572,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }) } - fn block(&self, span: Span, stmts: Vec<ast::Stmt>, - expr: Option<P<Expr>>) -> P<ast::Block> { - self.block_all(span, stmts, expr) - } - fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt { ast::Stmt { id: ast::DUMMY_NODE_ID, @@ -581,19 +581,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> { - self.block_all(expr.span, Vec::new(), Some(expr)) - } - fn block_all(&self, - span: Span, - stmts: Vec<ast::Stmt>, - expr: Option<P<ast::Expr>>) -> P<ast::Block> { - P(ast::Block { - stmts: stmts, - expr: expr, - id: ast::DUMMY_NODE_ID, - rules: BlockCheckMode::Default, - span: span, - }) + self.block(expr.span, vec![ast::Stmt { + id: ast::DUMMY_NODE_ID, + span: expr.span, + node: ast::StmtKind::Expr(expr), + }]) + } + fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> { + P(ast::Block { + stmts: stmts, + id: ast::DUMMY_NODE_ID, + rules: BlockCheckMode::Default, + span: span, + }) } fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr> { @@ -962,14 +962,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ids: Vec<ast::Ident>, stmts: Vec<ast::Stmt>) -> P<ast::Expr> { - self.lambda(span, ids, self.block(span, stmts, None)) + self.lambda(span, ids, self.block(span, stmts)) } fn lambda_stmts_0(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Expr> { - self.lambda0(span, self.block(span, stmts, None)) + self.lambda0(span, self.block(span, stmts)) } fn lambda_stmts_1(&self, span: Span, stmts: Vec<ast::Stmt>, ident: ast::Ident) -> P<ast::Expr> { - self.lambda1(span, self.block(span, stmts, None), ident) + self.lambda1(span, self.block(span, stmts), ident) } fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 32635f5cdd2..3036a88430a 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -611,23 +611,14 @@ pub fn expand_block(blk: P<Block>, fld: &mut MacroExpander) -> P<Block> { // expand the elements of a block. pub fn expand_block_elts(b: P<Block>, fld: &mut MacroExpander) -> P<Block> { - b.map(|Block {id, stmts, expr, rules, span}| { + b.map(|Block {id, stmts, rules, span}| { let new_stmts = stmts.into_iter().flat_map(|x| { // perform pending renames and expand macros in the statement fld.fold_stmt(x).into_iter() }).collect(); - let new_expr = expr.map(|x| { - let expr = { - let pending_renames = &mut fld.cx.syntax_env.info().pending_renames; - let mut rename_fld = IdentRenamer{renames:pending_renames}; - rename_fld.fold_expr(x) - }; - fld.fold_expr(expr) - }); Block { id: fld.new_id(id), stmts: new_stmts, - expr: new_expr, rules: rules, span: span } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 3dc7c92f016..68527b0797d 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -513,10 +513,8 @@ pub fn expand_quote_matcher(cx: &mut ExtCtxt, let (cx_expr, tts) = parse_arguments_to_quote(cx, tts); let mut vector = mk_stmts_let(cx, sp); vector.extend(statements_mk_tts(cx, &tts[..], true)); - let block = cx.expr_block( - cx.block_all(sp, - vector, - Some(cx.expr_ident(sp, id_ext("tt"))))); + vector.push(cx.stmt_expr(cx.expr_ident(sp, id_ext("tt")))); + let block = cx.expr_block(cx.block(sp, vector)); let expanded = expand_wrapper(cx, sp, cx_expr, block, &[&["syntax", "ext", "quote", "rt"]]); base::MacEager::expr(expanded) @@ -766,8 +764,9 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, matcher: bool) -> Vec<ast::Stm let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp)); let mut tts_stmts = vec![stmt_let_tt]; tts_stmts.extend(statements_mk_tts(cx, &seq.tts[..], matcher)); - let e_tts = cx.expr_block(cx.block(sp, tts_stmts, - Some(cx.expr_ident(sp, id_ext("tt"))))); + tts_stmts.push(cx.stmt_expr(cx.expr_ident(sp, id_ext("tt")))); + let e_tts = cx.expr_block(cx.block(sp, tts_stmts)); + let e_separator = match seq.separator { Some(ref sep) => cx.expr_some(sp, expr_mk_token(cx, sp, sep)), None => cx.expr_none(sp), @@ -882,10 +881,8 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[TokenTree]) let mut vector = mk_stmts_let(cx, sp); vector.extend(statements_mk_tts(cx, &tts[..], false)); - let block = cx.expr_block( - cx.block_all(sp, - vector, - Some(cx.expr_ident(sp, id_ext("tt"))))); + vector.push(cx.stmt_expr(cx.expr_ident(sp, id_ext("tt")))); + let block = cx.expr_block(cx.block(sp, vector)); (cx_expr, block) } @@ -899,13 +896,14 @@ fn expand_wrapper(cx: &ExtCtxt, let cx_expr_borrow = cx.expr_addr_of(sp, cx.expr_deref(sp, cx_expr)); let stmt_let_ext_cx = cx.stmt_let(sp, false, id_ext("ext_cx"), cx_expr_borrow); - let stmts = imports.iter().map(|path| { + let mut stmts = imports.iter().map(|path| { // make item: `use ...;` let path = path.iter().map(|s| s.to_string()).collect(); cx.stmt_item(sp, cx.item_use_glob(sp, ast::Visibility::Inherited, ids_ext(path))) - }).chain(Some(stmt_let_ext_cx)).collect(); + }).chain(Some(stmt_let_ext_cx)).collect::<Vec<_>>(); + stmts.push(cx.stmt_expr(expr)); - cx.expr_block(cx.block_all(sp, stmts, Some(expr))) + cx.expr_block(cx.block(sp, stmts)) } fn expand_parse_call(cx: &ExtCtxt, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index b2b286c9b14..6789e7be058 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -818,10 +818,9 @@ fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T) } pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> { - b.map(|Block {id, stmts, expr, rules, span}| Block { + b.map(|Block {id, stmts, rules, span}| Block { id: folder.new_id(id), stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()), - expr: expr.and_then(|x| folder.fold_opt_expr(x)), rules: rules, span: folder.new_span(span), }) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0c5a672dfbc..bbcc044d43c 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -957,7 +957,6 @@ mod tests { attrs: ThinVec::new()})), id: ast::DUMMY_NODE_ID, span: sp(17,19)}), - expr: None, id: ast::DUMMY_NODE_ID, rules: ast::BlockCheckMode::Default, // no idea span: sp(15,21), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 83401011ed4..813d90103b8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3236,9 +3236,12 @@ impl<'a> Parser<'a> { let body_expr = self.parse_expr()?; P(ast::Block { id: ast::DUMMY_NODE_ID, - stmts: vec![], span: body_expr.span, - expr: Some(body_expr), + stmts: vec![Stmt { + span: body_expr.span, + node: StmtKind::Expr(body_expr), + id: ast::DUMMY_NODE_ID, + }], rules: BlockCheckMode::Default, }) } @@ -4098,7 +4101,6 @@ impl<'a> Parser<'a> { /// Precondition: already parsed the '{'. fn parse_block_tail(&mut self, lo: BytePos, s: BlockCheckMode) -> PResult<'a, P<Block>> { let mut stmts = vec![]; - let mut expr = None; while !self.eat(&token::CloseDelim(token::Brace)) { let Stmt {node, span, ..} = if let Some(s) = self.parse_stmt_() { @@ -4112,10 +4114,10 @@ impl<'a> Parser<'a> { match node { StmtKind::Expr(e) => { - self.handle_expression_like_statement(e, span, &mut stmts, &mut expr)?; + self.handle_expression_like_statement(e, span, &mut stmts)?; } StmtKind::Mac(mac) => { - self.handle_macro_in_block(mac.unwrap(), span, &mut stmts, &mut expr)?; + self.handle_macro_in_block(mac.unwrap(), span, &mut stmts)?; } _ => { // all other kinds of statements: let mut hi = span.hi; @@ -4135,7 +4137,6 @@ impl<'a> Parser<'a> { Ok(P(ast::Block { stmts: stmts, - expr: expr, id: ast::DUMMY_NODE_ID, rules: s, span: mk_sp(lo, self.last_span.hi), @@ -4145,8 +4146,7 @@ impl<'a> Parser<'a> { fn handle_macro_in_block(&mut self, (mac, style, attrs): (ast::Mac, MacStmtStyle, ThinVec<Attribute>), span: Span, - stmts: &mut Vec<Stmt>, - last_block_expr: &mut Option<P<Expr>>) + stmts: &mut Vec<Stmt>) -> PResult<'a, ()> { if style == MacStmtStyle::NoBraces { // statement macro without braces; might be an @@ -4165,7 +4165,7 @@ impl<'a> Parser<'a> { let lo = e.span.lo; let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?; let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?; - self.handle_expression_like_statement(e, span, stmts, last_block_expr)?; + self.handle_expression_like_statement(e, span, stmts)?; } } } else { @@ -4179,11 +4179,6 @@ impl<'a> Parser<'a> { }); self.bump(); } - token::CloseDelim(token::Brace) => { - // if a block ends in `m!(arg)` without - // a `;`, it must be an expr - *last_block_expr = Some(self.mk_mac_expr(span.lo, span.hi, mac.node, attrs)); - } _ => { stmts.push(Stmt { id: ast::DUMMY_NODE_ID, @@ -4199,8 +4194,7 @@ impl<'a> Parser<'a> { fn handle_expression_like_statement(&mut self, e: P<Expr>, span: Span, - stmts: &mut Vec<Stmt>, - last_block_expr: &mut Option<P<Expr>>) + stmts: &mut Vec<Stmt>) -> PResult<'a, ()> { // expression without semicolon if classify::expr_requires_semi_to_be_stmt(&e) { @@ -4227,7 +4221,6 @@ impl<'a> Parser<'a> { span: span_with_semi, }); } - token::CloseDelim(token::Brace) => *last_block_expr = Some(e), _ => { stmts.push(Stmt { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index d399f538004..b56cec72a95 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1619,12 +1619,16 @@ impl<'a> State<'a> { try!(self.word_space("=")); try!(self.print_expr(&init)); } + try!(word(&mut self.s, ";")); self.end()?; } ast::StmtKind::Item(ref item) => self.print_item(&item)?, ast::StmtKind::Expr(ref expr) => { try!(self.space_if_not_bol()); try!(self.print_expr_outer_attr_style(&expr, false)); + if parse::classify::expr_requires_semi_to_be_stmt(expr) { + try!(word(&mut self.s, ";")); + } } ast::StmtKind::Semi(ref expr) => { try!(self.space_if_not_bol()); @@ -1646,9 +1650,6 @@ impl<'a> State<'a> { } } } - if parse::classify::stmt_ends_with_semi(&st.node) { - try!(word(&mut self.s, ";")); - } self.maybe_print_trailing_comment(st.span, None) } @@ -1692,17 +1693,17 @@ impl<'a> State<'a> { try!(self.print_inner_attributes(attrs)); - for st in &blk.stmts { - try!(self.print_stmt(st)); - } - match blk.expr { - Some(ref expr) => { - try!(self.space_if_not_bol()); - try!(self.print_expr_outer_attr_style(&expr, false)); - try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))); + for (i, st) in blk.stmts.iter().enumerate() { + match st.node { + ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => { + try!(self.space_if_not_bol()); + try!(self.print_expr_outer_attr_style(&expr, false)); + try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))); + } + _ => try!(self.print_stmt(st)), } - _ => () } + try!(self.bclose_maybe_open(blk.span, indented, close_box)); self.ann.post(self, NodeBlock(blk)) } @@ -2111,22 +2112,21 @@ impl<'a> State<'a> { _ => false }; - if !default_return || !body.stmts.is_empty() || body.expr.is_none() { - try!(self.print_block_unclosed(&body)); - } else { - // we extract the block, so as not to create another set of boxes - let i_expr = body.expr.as_ref().unwrap(); - match i_expr.node { - ast::ExprKind::Block(ref blk) => { + match body.stmts.last().map(|stmt| &stmt.node) { + Some(&ast::StmtKind::Expr(ref i_expr)) if default_return && + body.stmts.len() == 1 => { + // we extract the block, so as not to create another set of boxes + if let ast::ExprKind::Block(ref blk) = i_expr.node { try!(self.print_block_unclosed_with_attrs(&blk, &i_expr.attrs)); - } - _ => { + } else { // this is a bare expression try!(self.print_expr(&i_expr)); try!(self.end()); // need to close a box } } + _ => try!(self.print_block_unclosed(&body)), } + // a box will be closed by print_expr, but we didn't want an overall // wrapper so we closed the corresponding opening. so create an // empty box to satisfy the close. diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 078103f834a..0a60b7fd430 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -478,7 +478,7 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> { let main_attr = ecx.attribute(sp, main_meta); // pub fn main() { ... } let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(vec![])); - let main_body = ecx.block_all(sp, vec![call_test_main], None); + let main_body = ecx.block(sp, vec![call_test_main]); let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], main_ret_ty), ast::Unsafety::Normal, ast::Constness::NotConst, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 571965ef872..1fc4e54d218 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -590,7 +590,6 @@ pub fn walk_struct_field<V: Visitor>(visitor: &mut V, struct_field: &StructField pub fn walk_block<V: Visitor>(visitor: &mut V, block: &Block) { walk_list!(visitor, visit_stmt, &block.stmts); - walk_list!(visitor, visit_expr, &block.expr); } pub fn walk_stmt<V: Visitor>(visitor: &mut V, statement: &Stmt) { diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 00714002875..1e47ebb8583 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -145,12 +145,10 @@ fn cs_clone( match mode { Mode::Shallow => { - cx.expr_block(cx.block(trait_span, - all_fields.iter() - .map(subcall) - .map(|e| cx.stmt_expr(e)) - .collect(), - Some(cx.expr_deref(trait_span, cx.expr_self(trait_span))))) + let mut stmts: Vec<_> = + all_fields.iter().map(subcall).map(|e| cx.stmt_expr(e)).collect(); + stmts.push(cx.stmt_expr(cx.expr_deref(trait_span, cx.expr_self(trait_span)))); + cx.expr_block(cx.block(trait_span, stmts)) } Mode::Deep => { match *vdata { diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 4258e152088..9c5072eeb3e 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -30,7 +30,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, // create `a.<method>(); b.<method>(); c.<method>(); ...` // (where method is `assert_receiver_is_total_eq`) let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect(); - let block = cx.block(span, stmts, None); + let block = cx.block(span, stmts); cx.expr_block(block) }, Box::new(|cx, sp, _, _| { diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index dabe234eb9c..34c872bef11 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -78,7 +78,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, let fmt = substr.nonself_args[0].clone(); - let stmts = match *substr.fields { + let mut stmts = match *substr.fields { Struct(_, ref fields) | EnumMatching(_, _, ref fields) => { let mut stmts = vec![]; if !is_struct { @@ -136,7 +136,8 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, token::str_to_ident("finish"), vec![]); - let block = cx.block(span, stmts, Some(expr)); + stmts.push(cx.stmt_expr(expr)); + let block = cx.block(span, stmts); cx.expr_block(block) } diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 07a52105deb..ad378621247 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -285,7 +285,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, cx.expr_str(trait_span, substr.type_ident.name.as_str()), blk )); - cx.expr_block(cx.block(trait_span, vec!(me), Some(ret))) + cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)])) } _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)") diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 7d454fe38cc..647e414a7fd 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1332,8 +1332,8 @@ impl<'a> MethodDef<'a> { // } let all_match = cx.expr_match(sp, match_arg, match_arms); let arm_expr = cx.expr_if(sp, discriminant_test, all_match, Some(arm_expr)); - cx.expr_block( - cx.block_all(sp, index_let_stmts, Some(arm_expr))) + index_let_stmts.push(cx.stmt_expr(arm_expr)); + cx.expr_block(cx.block(sp, index_let_stmts)) } else if variants.is_empty() { // As an additional wrinkle, For a zero-variant enum A, // currently the compiler diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 245d3f0efa3..0fad96c84ef 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -99,5 +99,5 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) stmts.push(call_hash(span, self_.clone())); } - cx.expr_block(cx.block(trait_span, stmts, None)) + cx.expr_block(cx.block(trait_span, stmts)) } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index f9e0d2c2eae..169e8073661 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -298,8 +298,7 @@ fn call_intrinsic(cx: &ExtCtxt, let call = cx.expr_call_global(span, path, args); cx.expr_block(P(ast::Block { - stmts: vec![], - expr: Some(call), + stmts: vec![cx.stmt_expr(call)], id: ast::DUMMY_NODE_ID, rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), span: span })) diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 5be2bf7cdf9..f311f16f11b 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -449,7 +449,7 @@ impl<'a, 'b> Context<'a, 'b> { }; // Wrap the declaration in a block so that it forms a single expression. - ecx.expr_block(ecx.block(sp, vec![stmt], Some(ecx.expr_ident(sp, name)))) + ecx.expr_block(ecx.block(sp, vec![stmt, ecx.stmt_expr(ecx.expr_ident(sp, name))])) } /// Actually builds the expression which the iformat! block will be expanded diff --git a/src/test/compile-fail/issue-34418.rs b/src/test/compile-fail/issue-34418.rs new file mode 100644 index 00000000000..6bc0add2205 --- /dev/null +++ b/src/test/compile-fail/issue-34418.rs @@ -0,0 +1,31 @@ +// Copyright 2016 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. + +#![feature(rustc_attrs)] +#![allow(unused)] + +macro_rules! make_item { + () => { fn f() {} } +} + +macro_rules! make_stmt { + () => { let x = 0; } +} + +fn f() { + make_item! {} +} + +fn g() { + make_stmt! {} +} + +#[rustc_error] +fn main() {} //~ ERROR compilation successful |
