]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #34436 - jseyfried:no_block_expr, r=eddyb
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Sun, 26 Jun 2016 02:19:34 +0000 (02:19 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Sun, 26 Jun 2016 02:20:14 +0000 (02:20 +0000)
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.

21 files changed:
1  2 
src/librustc/hir/lowering.rs
src/librustc_driver/driver.rs
src/librustc_driver/pretty.rs
src/libsyntax/ast.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/test.rs
src/libsyntax/visit.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/cmp/eq.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/hash.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/format.rs

Simple merge
index 927953b034ba2496c1c1232adca94246c0904a8b,c0be92984392e60a04d5aa67f4a3b4a4c5a9850a..eb442c0a34e74cb68ba015fb765b3f2e61e262c3
@@@ -763,6 -763,10 +763,9 @@@ pub fn phase_2_configure_and_expand<'a>
  }
  
  pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
 -    use syntax::codemap::Spanned;
+     use syntax::ptr::P;
+     use syntax::util::move_map::MoveMap;
      struct NodeIdAssigner<'a> {
          sess: &'a Session,
      }
              assert_eq!(old_id, ast::DUMMY_NODE_ID);
              self.sess.next_node_id()
          }
 -                if let Some(Spanned { node: ast::StmtKind::Expr(expr, _), span }) = stmt {
+         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());
 -                    let id = expr.id;
 -                    block.stmts.push(Spanned {
++                if let Some(ast::Stmt { node: ast::StmtKind::Expr(expr), span, .. }) = stmt {
+                     let expr = self.fold_expr(expr);
 -                        node: ast::StmtKind::Expr(expr, id)
++                    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(),
index 80eea76e107565ea6790efb4bb72dcc078d2f62f,4c0082ed5b85cb56448d7261f6d8196bf6973de0..baac455a25f334c7c6c6a3194f0ed6c00f44da56
@@@ -657,11 -657,13 +657,14 @@@ impl fold::Folder for ReplaceBodyWithLo
      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| codemap::Spanned {
++                stmts: e.map(|e| ast::Stmt {
++                    id: ast::DUMMY_NODE_ID,
+                     span: e.span,
 -                    node: ast::StmtKind::Expr(e, ast::DUMMY_NODE_ID),
++                    node: ast::StmtKind::Expr(e),
+                 }).into_iter().collect(),
                  rules: rules,
                  id: ast::DUMMY_NODE_ID,
 -                span: codemap::DUMMY_SP,
 +                span: syntax_pos::DUMMY_SP,
              })
          }
  
index dcdc1e60a99cd0bd8012716220dacebf563f1e5f,e138119149c679fef66635cf9aad3a98f081989a..a352715b20b129a21ec56e1776a8a897b932f778
@@@ -826,18 -797,31 +823,18 @@@ impl fmt::Debug for Stmt 
  
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
  pub enum StmtKind {
 -    /// Could be an item or a local (let) binding:
 -    Decl(P<Decl>, NodeId),
 +    /// A local (let) binding.
 +    Local(P<Local>),
  
 -    /// Expr without trailing semi-colon
 -    Expr(P<Expr>, NodeId),
 +    /// An item definition.
 +    Item(P<Item>),
  
-     /// Expr without trailing semi-colon (must have unit type).
 -    /// Expr with trailing semi-colon (may have any type):
 -    Semi(P<Expr>, NodeId),
++    /// Expr without trailing semi-colon.
 +    Expr(P<Expr>),
  
 -    Mac(P<Mac>, MacStmtStyle, ThinAttributes),
 -}
 +    Semi(P<Expr>),
  
 -impl StmtKind {
 -    pub fn id(&self) -> Option<NodeId> {
 -        match *self {
 -            StmtKind::Decl(_, id) => Some(id),
 -            StmtKind::Expr(_, id) => Some(id),
 -            StmtKind::Semi(_, id) => Some(id),
 -            StmtKind::Mac(..) => None,
 -        }
 -    }
 -
 -    pub fn attrs(&self) -> &[Attribute] {
 -        HasAttrs::attrs(self)
 -    }
 +    Mac(P<(Mac, MacStmtStyle, ThinVec<Attribute>)>),
  }
  
  #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
index f4ae23ed8be788bb07146420f315adaaeda53b61,4bfbd37edd9fa496387436442efaf31353e16fa6..435241f426ec6f4329e90a2dc6dea8c093e3e723
@@@ -509,11 -505,11 +506,19 @@@ impl<'a> AstBuilder for ExtCtxt<'a> 
      }
  
      fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
 -        respan(expr.span, ast::StmtKind::Expr(expr, ast::DUMMY_NODE_ID))
++        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 {
 -        respan(expr.span, ast::StmtKind::Semi(expr, ast::DUMMY_NODE_ID))
 +        ast::Stmt {
 +            id: ast::DUMMY_NODE_ID,
 +            span: expr.span,
 +            node: ast::StmtKind::Semi(expr),
 +        }
      }
  
      fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident,
              init: Some(ex),
              id: ast::DUMMY_NODE_ID,
              span: sp,
 -            attrs: None,
 +            attrs: ast::ThinVec::new(),
          });
 -        let decl = respan(sp, ast::DeclKind::Local(local));
 -        P(respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)))
 +        P(ast::Stmt {
 +            id: ast::DUMMY_NODE_ID,
 +            node: ast::StmtKind::Local(local),
 +            span: sp,
 +        })
      }
  
-     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 {
 -        let decl = respan(sp, ast::DeclKind::Item(item));
 -        respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
 +        ast::Stmt {
 +            id: ast::DUMMY_NODE_ID,
 +            node: ast::StmtKind::Item(item),
 +            span: sp,
 +        }
      }
  
      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![Spanned {
++        self.block(expr.span, vec![ast::Stmt {
++            id: ast::DUMMY_NODE_ID,
+             span: expr.span,
 -            node: ast::StmtKind::Expr(expr, ast::DUMMY_NODE_ID),
++            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> {
Simple merge
Simple merge
Simple merge
index 0c5a672dfbc9ee460768139d1a4c6f245f0f57ac,f79d6e8421a7919f1e16754107d6f151442d88ce..bbcc044d43c6b74b8701924847df75867f0a8ec6
@@@ -954,10 -950,9 +954,9 @@@ mod tests 
                                                          ),
                                                        }),
                                                  span: sp(17,18),
 -                                                attrs: None,}),
 -                                                ast::DUMMY_NODE_ID),
 +                                                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),
index 83401011ed44e3b952e4aa4790ebc47b8ae5c927,dea6589fe7caeb348ab2813fb2ab536519ee4c79..813d90103b8878000bf4f103078bc3781c3e28dd
@@@ -3236,9 -3217,11 +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![Spanned {
++                    stmts: vec![Stmt {
+                         span: body_expr.span,
 -                        node: StmtKind::Expr(body_expr, ast::DUMMY_NODE_ID),
++                        node: StmtKind::Expr(body_expr),
++                        id: ast::DUMMY_NODE_ID,
+                     }],
                      rules: BlockCheckMode::Default,
                  })
              }
      /// 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 Spanned {node, span} = if let Some(s) = self.parse_stmt_() {
 +            let Stmt {node, span, ..} = if let Some(s) = self.parse_stmt_() {
                  s
              } else if self.token == token::Eof {
                  break;
                  // Found only `;` or `}`.
                  continue;
              };
 +
              match node {
 -                StmtKind::Expr(e, _) => {
 +                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, MacStmtStyle::NoBraces, attrs) => {
 -                    // statement macro without braces
 -                    match self.token {
 -                        token::Semi => {
 -                            stmts.push(Spanned {
 -                                node: StmtKind::Mac(mac, MacStmtStyle::Semicolon, attrs),
 -                                span: mk_sp(span.lo, self.span.hi),
 -                            });
 -                            self.bump();
 -                        }
 -                        _ => {
 -                            let e = self.mk_mac_expr(span.lo, span.hi,
 -                                                     mac.and_then(|m| m.node),
 -                                                     None);
 -                            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, &mut stmts)?;
 -                        }
 -                    }
 -                }
 -                StmtKind::Mac(m, style, attrs) => {
 -                    // statement macro; might be an expr
 -                    match self.token {
 -                        token::Semi => {
 -                            stmts.push(Spanned {
 -                                node: StmtKind::Mac(m, MacStmtStyle::Semicolon, attrs),
 -                                span: mk_sp(span.lo, self.span.hi),
 -                            });
 -                            self.bump();
 -                        }
 -                        _ => {
 -                            stmts.push(Spanned {
 -                                node: StmtKind::Mac(m, style, attrs),
 -                                span: span
 -                            });
 -                        }
 -                    }
 +                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;
          }))
      }
  
-                              stmts: &mut Vec<Stmt>,
-                              last_block_expr: &mut Option<P<Expr>>)
 +    fn handle_macro_in_block(&mut self,
 +                             (mac, style, attrs): (ast::Mac, MacStmtStyle, ThinVec<Attribute>),
 +                             span: Span,
-                     self.handle_expression_like_statement(e, span, stmts, last_block_expr)?;
++                             stmts: &mut Vec<Stmt>)
 +                             -> PResult<'a, ()> {
 +        if style == MacStmtStyle::NoBraces {
 +            // statement macro without braces; might be an
 +            // expr depending on whether a semicolon follows
 +            match self.token {
 +                token::Semi => {
 +                    stmts.push(Stmt {
 +                        id: ast::DUMMY_NODE_ID,
 +                        node: StmtKind::Mac(P((mac, MacStmtStyle::Semicolon, attrs))),
 +                        span: mk_sp(span.lo, self.span.hi),
 +                    });
 +                    self.bump();
 +                }
 +                _ => {
 +                    let e = self.mk_mac_expr(span.lo, span.hi, mac.node, ThinVec::new());
 +                    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))?;
-                 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));
-                 }
++                    self.handle_expression_like_statement(e, span, stmts)?;
 +                }
 +            }
 +        } else {
 +            // statement macro; might be an expr
 +            match self.token {
 +                token::Semi => {
 +                    stmts.push(Stmt {
 +                        id: ast::DUMMY_NODE_ID,
 +                        node: StmtKind::Mac(P((mac, MacStmtStyle::Semicolon, attrs))),
 +                        span: mk_sp(span.lo, self.span.hi),
 +                    });
 +                    self.bump();
 +                }
 +                _ => {
 +                    stmts.push(Stmt {
 +                        id: ast::DUMMY_NODE_ID,
 +                        node: StmtKind::Mac(P((mac, style, attrs))),
 +                        span: span
 +                    });
 +                }
 +            }
 +        }
 +        Ok(())
 +    }
 +
      fn handle_expression_like_statement(&mut self,
                                          e: P<Expr>,
                                          span: Span,
                      span: span_with_semi,
                  });
              }
-             token::CloseDelim(token::Brace) => *last_block_expr = Some(e),
              _ => {
 -                stmts.push(Spanned {
 -                    node: StmtKind::Expr(e, ast::DUMMY_NODE_ID),
 +                stmts.push(Stmt {
 +                    id: ast::DUMMY_NODE_ID,
 +                    node: StmtKind::Expr(e),
                      span: span
                  });
              }
index d399f53800469c083c9d3f64c5c5aaa07b5bb3db,00edd5585c28b86e7343c24934104082efea2e8e..b56cec72a956e0555a8b0d5a710c0378c8e72690
@@@ -1605,28 -1593,17 +1605,32 @@@ impl<'a> State<'a> 
      pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
          try!(self.maybe_print_comment(st.span.lo));
          match st.node {
 -            ast::StmtKind::Decl(ref decl, _) => {
 -                try!(self.print_decl(&decl));
 +            ast::StmtKind::Local(ref loc) => {
 +                try!(self.print_outer_attributes(&loc.attrs));
 +                try!(self.space_if_not_bol());
 +                try!(self.ibox(INDENT_UNIT));
 +                try!(self.word_nbsp("let"));
 +
 +                try!(self.ibox(INDENT_UNIT));
 +                try!(self.print_local_decl(&loc));
 +                try!(self.end());
 +                if let Some(ref init) = loc.init {
 +                    try!(self.nbsp());
 +                    try!(self.word_space("="));
 +                    try!(self.print_expr(&init));
 +                }
++                try!(word(&mut self.s, ";"));
 +                self.end()?;
              }
 -            ast::StmtKind::Expr(ref expr, _) => {
 +            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, _) => {
 +            ast::StmtKind::Semi(ref expr) => {
                  try!(self.space_if_not_bol());
                  try!(self.print_expr_outer_attr_style(&expr, false));
                  try!(word(&mut self.s, ";"));
  
          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 => {
++                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))
      }
                      _ => 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 => {
++                    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.as_attr_slice()));
 +                            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
Simple merge
index 571965ef8728623abcfe70558dcfabeeee06a2bb,cf91f5ece725b71f9cd15d8a8d56117682d6f8e6..1fc4e54d21807c26145f6d10e98e7d85f34eed15
@@@ -588,22 -606,19 +588,21 @@@ pub fn walk_struct_field<V: Visitor>(vi
      walk_list!(visitor, visit_attribute, &struct_field.attrs);
  }
  
 -pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
 +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, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
 +pub fn walk_stmt<V: Visitor>(visitor: &mut V, statement: &Stmt) {
      match statement.node {
 -        StmtKind::Decl(ref declaration, _) => visitor.visit_decl(declaration),
 -        StmtKind::Expr(ref expression, _) | StmtKind::Semi(ref expression, _) => {
 +        StmtKind::Local(ref local) => visitor.visit_local(local),
 +        StmtKind::Item(ref item) => visitor.visit_item(item),
 +        StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
              visitor.visit_expr(expression)
          }
 -        StmtKind::Mac(ref mac, _, ref attrs) => {
 +        StmtKind::Mac(ref mac) => {
 +            let (ref mac, _, ref attrs) = **mac;
              visitor.visit_mac(mac);
 -            for attr in attrs.as_attr_slice() {
 +            for attr in attrs.iter() {
                  visitor.visit_attribute(attr);
              }
          }
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 5be2bf7cdf92b7b374c976160cf0a987fc59ef69,8cf956256949327f3d8f034ffdd291196bca94bc..f311f16f11b0efbebd7c59390f75102f537c171b
@@@ -442,14 -441,13 +442,14 @@@ impl<'a, 'b> Context<'a, 'b> 
  
          let name = ecx.ident_of(name);
          let item = ecx.item(sp, name, vec![], st);
 -        let decl = respan(sp, ast::DeclKind::Item(item));
 +        let stmt = ast::Stmt {
 +            id: ast::DUMMY_NODE_ID,
 +            node: ast::StmtKind::Item(item),
 +            span: sp,
 +        };
  
          // 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![
 -            respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID)),
 -            ecx.stmt_expr(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