]> 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

index a32631ac53ddd2fb827e827266527013110ef860,2690edc46448988de4194c7cc7549a1fb18258dd..5b655522f342f6ef82149b52f6009924e2093af3
@@@ -50,12 -50,12 +50,12 @@@ use session::Session
  use std::collections::BTreeMap;
  use std::iter;
  use syntax::ast::*;
 -use syntax::attr::{ThinAttributes, ThinAttributesExt};
  use syntax::ptr::P;
 -use syntax::codemap::{respan, Spanned, Span};
 +use syntax::codemap::{respan, Spanned};
  use syntax::parse::token;
  use syntax::std_inject;
  use syntax::visit::{self, Visitor};
 +use syntax_pos::Span;
  
  pub struct LoweringContext<'a> {
      crate_root: Option<&'static str>,
@@@ -137,8 -137,8 +137,8 @@@ impl<'a> LoweringContext<'a> 
              lctx: &'lcx mut LoweringContext<'interner>,
          }
  
 -        impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
 -            fn visit_item(&mut self, item: &'lcx Item) {
 +        impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> {
 +            fn visit_item(&mut self, item: &Item) {
                  self.items.insert(item.id, self.lctx.lower_item(item));
                  visit::walk_item(self, item);
              }
          }
      }
  
 -    fn lower_decl(&mut self, d: &Decl) -> P<hir::Decl> {
 -        match d.node {
 -            DeclKind::Local(ref l) => P(Spanned {
 -                node: hir::DeclLocal(self.lower_local(l)),
 -                span: d.span,
 -            }),
 -            DeclKind::Item(ref it) => P(Spanned {
 -                node: hir::DeclItem(self.lower_item_id(it)),
 -                span: d.span,
 -            }),
 -        }
 -    }
 -
      fn lower_ty_binding(&mut self, b: &TypeBinding) -> hir::TypeBinding {
          hir::TypeBinding {
              id: b.id,
      }
  
      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,
          })
                          hir::TypeTraitItem(this.lower_bounds(bounds),
                                             default.as_ref().map(|x| this.lower_ty(x)))
                      }
 +                    TraitItemKind::Macro(..) => panic!("Shouldn't exist any more"),
                  },
                  span: i.span,
              }
                                                pats.iter().map(|x| self.lower_pat(x)).collect(),
                                                ddpos)
                  }
 -                PatKind::Path(ref pth) => {
 +                PatKind::Path(None, ref pth) => {
                      hir::PatKind::Path(self.lower_path(pth))
                  }
 -                PatKind::QPath(ref qself, ref pth) => {
 +                PatKind::Path(Some(ref qself), ref pth) => {
                      let qself = hir::QSelf {
                          ty: self.lower_ty(&qself.ty),
                          position: qself.position,
  
                      let make_call = |this: &mut LoweringContext, p, args| {
                          let path = this.core_path(e.span, p);
 -                        let path = this.expr_path(path, None);
 -                        this.expr_call(e.span, path, args, None)
 +                        let path = this.expr_path(path, ThinVec::new());
 +                        this.expr_call(e.span, path, args)
                      };
  
                      let mk_stmt_let = |this: &mut LoweringContext, bind, expr| {
 -                        this.stmt_let(e.span, false, bind, expr, None)
 +                        this.stmt_let(e.span, false, bind, expr)
                      };
  
                      let mk_stmt_let_mut = |this: &mut LoweringContext, bind, expr| {
 -                        this.stmt_let(e.span, true, bind, expr, None)
 +                        this.stmt_let(e.span, true, bind, expr)
                      };
  
                      // let placer = <placer_expr> ;
                                                                   placer_expr,
                                                                   e.span,
                                                                   hir::PopUnstableBlock,
 -                                                                 None);
 +                                                                 ThinVec::new());
                          mk_stmt_let(self, placer_ident, placer_expr)
                      };
  
                      // let mut place = Placer::make_place(placer);
                      let (s2, place_binding) = {
 -                        let placer = self.expr_ident(e.span, placer_ident, None, placer_binding);
 +                        let placer = self.expr_ident(e.span, placer_ident, placer_binding);
                          let call = make_call(self, &make_place, hir_vec![placer]);
                          mk_stmt_let_mut(self, place_ident, call)
                      };
  
                      // let p_ptr = Place::pointer(&mut place);
                      let (s3, p_ptr_binding) = {
 -                        let agent = self.expr_ident(e.span, place_ident, None, place_binding);
 -                        let args = hir_vec![self.expr_mut_addr_of(e.span, agent, None)];
 +                        let agent = self.expr_ident(e.span, place_ident, place_binding);
 +                        let args = hir_vec![self.expr_mut_addr_of(e.span, agent)];
                          let call = make_call(self, &place_pointer, args);
                          mk_stmt_let(self, p_ptr_ident, call)
                      };
                                                                  value_expr,
                                                                  e.span,
                                                                  hir::PopUnstableBlock,
 -                                                                None);
 +                                                                ThinVec::new());
                          self.signal_block_expr(hir_vec![],
                                                 value_expr,
                                                 e.span,
 -                                               hir::PopUnsafeBlock(hir::CompilerGenerated), None)
 +                                               hir::PopUnsafeBlock(hir::CompilerGenerated),
 +                                               ThinVec::new())
                      };
  
                      // push_unsafe!({
                      //     InPlace::finalize(place)
                      // })
                      let expr = {
 -                        let ptr = self.expr_ident(e.span, p_ptr_ident, None, p_ptr_binding);
 +                        let ptr = self.expr_ident(e.span, p_ptr_ident, p_ptr_binding);
                          let call_move_val_init =
                              hir::StmtSemi(
                                  make_call(self, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
                                  self.next_id());
                          let call_move_val_init = respan(e.span, call_move_val_init);
  
 -                        let place = self.expr_ident(e.span, place_ident, None, place_binding);
 +                        let place = self.expr_ident(e.span, place_ident, place_binding);
                          let call = make_call(self, &inplace_finalize, hir_vec![place]);
                          self.signal_block_expr(hir_vec![call_move_val_init],
                                                 call,
                                                 e.span,
 -                                               hir::PushUnsafeBlock(hir::CompilerGenerated), None)
 +                                               hir::PushUnsafeBlock(hir::CompilerGenerated),
 +                                               ThinVec::new())
                      };
  
                      return self.signal_block_expr(hir_vec![s1, s2, s3],
                                      rules: hir::DefaultBlock,
                                      span: span,
                                  });
 -                                self.expr_block(blk, None)
 +                                self.expr_block(blk, ThinVec::new())
                              }
                              _ => self.lower_expr(els),
                          }
                                                                            expr,
                                                                            e.span,
                                                                            hir::PopUnstableBlock,
 -                                                                          None);
 +                                                                          ThinVec::new());
                                  this.field(token::intern(s), signal_block, ast_expr.span)
                              }).collect();
                              let attrs = ast_expr.attrs.clone();
                                                 hir_expr,
                                                 ast_expr.span,
                                                 hir::PushUnstableBlock,
 -                                               None)
 +                                               ThinVec::new())
                      }
  
                      use syntax::ast::RangeLimits::*;
                      hir::ExprPath(hir_qself, self.lower_path(path))
                  }
                  ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)),
 -                ExprKind::Again(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
 +                ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
                  ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))),
                  ExprKind::InlineAsm(InlineAsm {
                          ref inputs,
                              ex.span = e.span;
                          }
                          // merge attributes into the inner expression.
 -                        ex.attrs.update(|attrs| {
 -                            attrs.prepend(e.attrs.clone())
 -                        });
 +                        let mut attrs = e.attrs.clone();
 +                        attrs.extend::<Vec<_>>(ex.attrs.into());
 +                        ex.attrs = attrs;
                          ex
                      });
                  }
                      // `<pat> => <body>`
                      let pat_arm = {
                          let body = self.lower_block(body);
 -                        let body_expr = self.expr_block(body, None);
 +                        let body_expr = self.expr_block(body, ThinVec::new());
                          let pat = self.lower_pat(pat);
                          self.arm(hir_vec![pat], body_expr)
                      };
                                                  attrs: hir_vec![],
                                                  pats: hir_vec![pat_under],
                                                  guard: Some(cond),
 -                                                body: self.expr_block(then, None),
 +                                                body: self.expr_block(then, ThinVec::new()),
                                              });
                                              else_opt.map(|else_opt| (else_opt, true))
                                          }
                      let else_arm = {
                          let pat_under = self.pat_wild(e.span);
                          let else_expr =
 -                            else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![], None));
 +                            else_opt.unwrap_or_else(|| self.expr_tuple(e.span, hir_vec![]));
                          self.arm(hir_vec![pat_under], else_expr)
                      };
  
                      // `<pat> => <body>`
                      let pat_arm = {
                          let body = self.lower_block(body);
 -                        let body_expr = self.expr_block(body, None);
 +                        let body_expr = self.expr_block(body, ThinVec::new());
                          let pat = self.lower_pat(pat);
                          self.arm(hir_vec![pat], body_expr)
                      };
                      // `_ => break`
                      let break_arm = {
                          let pat_under = self.pat_wild(e.span);
 -                        let break_expr = self.expr_break(e.span, None);
 +                        let break_expr = self.expr_break(e.span, ThinVec::new());
                          self.arm(hir_vec![pat_under], break_expr)
                      };
  
                                                 hir::ExprMatch(sub_expr,
                                                                arms,
                                                                hir::MatchSource::WhileLetDesugar),
 -                                               None);
 +                                               ThinVec::new());
  
                      // `[opt_ident]: loop { ... }`
                      let loop_block = self.block_expr(match_expr);
                              id: self.next_id(),
                              node: hir::ExprBlock(body_block),
                              span: body_span,
 -                            attrs: None,
 +                            attrs: ThinVec::new(),
                          });
                          let pat = self.lower_pat(pat);
                          let some_pat = self.pat_some(e.span, pat);
  
                      // `::std::option::Option::None => break`
                      let break_arm = {
 -                        let break_expr = self.expr_break(e.span, None);
 +                        let break_expr = self.expr_break(e.span, ThinVec::new());
                          let pat = self.pat_none(e.span);
                          self.arm(hir_vec![pat], break_expr)
                      };
  
                              self.path_global(e.span, strs)
                          };
 -                        let iter = self.expr_ident(e.span, iter, None, iter_pat.id);
 -                        let ref_mut_iter = self.expr_mut_addr_of(e.span, iter, None);
 -                        let next_path = self.expr_path(next_path, None);
 -                        let next_expr = self.expr_call(e.span,
 -                                                       next_path,
 -                                                       hir_vec![ref_mut_iter],
 -                                                       None);
 +                        let iter = self.expr_ident(e.span, iter, iter_pat.id);
 +                        let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
 +                        let next_path = self.expr_path(next_path, ThinVec::new());
 +                        let next_expr = self.expr_call(e.span, next_path, hir_vec![ref_mut_iter]);
                          let arms = hir_vec![pat_arm, break_arm];
  
                          self.expr(e.span,
                                    hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar),
 -                                  None)
 +                                  ThinVec::new())
                      };
  
                      // `[opt_ident]: loop { ... }`
                      let loop_block = self.block_expr(match_expr);
                      let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident));
 -                    let loop_expr =
 -                        P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
 +                    let loop_expr = P(hir::Expr {
 +                        id: e.id,
 +                        node: loop_expr,
 +                        span: e.span,
 +                        attrs: ThinVec::new(),
 +                    });
  
                      // `mut iter => { ... }`
                      let iter_arm = self.arm(hir_vec![iter_pat], loop_expr);
                              self.path_global(e.span, strs)
                          };
  
 -                        let into_iter = self.expr_path(into_iter_path, None);
 -                        self.expr_call(e.span, into_iter, hir_vec![head], None)
 +                        let into_iter = self.expr_path(into_iter_path, ThinVec::new());
 +                        self.expr_call(e.span, into_iter, hir_vec![head])
                      };
  
                      let match_expr = self.expr_match(e.span,
                                                       into_iter_expr,
                                                       hir_vec![iter_arm],
 -                                                     hir::MatchSource::ForLoopDesugar,
 -                                                     None);
 +                                                     hir::MatchSource::ForLoopDesugar);
  
                      // `{ let _result = ...; _result }`
                      // underscore prevents an unused_variables lint if the head diverges
                      let result_ident = self.str_to_ident("_result");
                      let (let_stmt, let_stmt_binding) =
 -                        self.stmt_let(e.span, false, result_ident, match_expr, None);
 +                        self.stmt_let(e.span, false, result_ident, match_expr);
  
 -                    let result = self.expr_ident(e.span, result_ident, None, let_stmt_binding);
 +                    let result = self.expr_ident(e.span, result_ident, let_stmt_binding);
                      let block = self.block_all(e.span, hir_vec![let_stmt], Some(result));
                      // add the attributes to the outer returned expr node
                      return self.expr_block(block, e.attrs.clone());
                      let ok_arm = {
                          let val_ident = self.str_to_ident("val");
                          let val_pat = self.pat_ident(e.span, val_ident);
 -                        let val_expr = self.expr_ident(e.span, val_ident, None, val_pat.id);
 +                        let val_expr = self.expr_ident(e.span, val_ident, val_pat.id);
                          let ok_pat = self.pat_ok(e.span, val_pat);
  
                          self.arm(hir_vec![ok_pat], val_expr)
                          let from_expr = {
                              let path = self.std_path(&["convert", "From", "from"]);
                              let path = self.path_global(e.span, path);
 -                            let from = self.expr_path(path, None);
 -                            let err_expr = self.expr_ident(e.span, err_ident, None, err_local.id);
 +                            let from = self.expr_path(path, ThinVec::new());
 +                            let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
  
 -                            self.expr_call(e.span, from, hir_vec![err_expr], None)
 +                            self.expr_call(e.span, from, hir_vec![err_expr])
                          };
                          let err_expr = {
                              let path = self.std_path(&["result", "Result", "Err"]);
                              let path = self.path_global(e.span, path);
 -                            let err_ctor = self.expr_path(path, None);
 -                            self.expr_call(e.span, err_ctor, hir_vec![from_expr], None)
 +                            let err_ctor = self.expr_path(path, ThinVec::new());
 +                            self.expr_call(e.span, err_ctor, hir_vec![from_expr])
                          };
                          let err_pat = self.pat_err(e.span, err_local);
                          let ret_expr = self.expr(e.span,
 -                                                 hir::Expr_::ExprRet(Some(err_expr)), None);
 -
 +                                                 hir::Expr_::ExprRet(Some(err_expr)),
 +                                                 ThinVec::new());
                          self.arm(hir_vec![err_pat], ret_expr)
                      };
  
                      return self.expr_match(e.span, sub_expr, hir_vec![err_arm, ok_arm],
 -                                           hir::MatchSource::TryDesugar, None);
 +                                           hir::MatchSource::TryDesugar);
                  }
  
                  ExprKind::Mac(_) => panic!("Shouldn't exist here"),
  
      fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
          match s.node {
 -            StmtKind::Decl(ref d, id) => {
 -                Spanned {
 -                    node: hir::StmtDecl(self.lower_decl(d), id),
 +            StmtKind::Local(ref l) => Spanned {
 +                node: hir::StmtDecl(P(Spanned {
 +                    node: hir::DeclLocal(self.lower_local(l)),
                      span: s.span,
 -                }
 -            }
 -            StmtKind::Expr(ref e, id) => {
 +                }), s.id),
 +                span: s.span,
 +            },
 +            StmtKind::Item(ref it) => Spanned {
 +                node: hir::StmtDecl(P(Spanned {
 +                    node: hir::DeclItem(self.lower_item_id(it)),
 +                    span: s.span,
 +                }), s.id),
 +                span: s.span,
 +            },
 +            StmtKind::Expr(ref e) => {
                  Spanned {
 -                    node: hir::StmtExpr(self.lower_expr(e), id),
 +                    node: hir::StmtExpr(self.lower_expr(e), s.id),
                      span: s.span,
                  }
              }
 -            StmtKind::Semi(ref e, id) => {
 +            StmtKind::Semi(ref e) => {
                  Spanned {
 -                    node: hir::StmtSemi(self.lower_expr(e), id),
 +                    node: hir::StmtSemi(self.lower_expr(e), s.id),
                      span: s.span,
                  }
              }
          }
      }
  
 -    fn expr_break(&mut self, span: Span, attrs: ThinAttributes) -> P<hir::Expr> {
 +    fn expr_break(&mut self, span: Span, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
          self.expr(span, hir::ExprBreak(None), attrs)
      }
  
 -    fn expr_call(&mut self,
 -                 span: Span,
 -                 e: P<hir::Expr>,
 -                 args: hir::HirVec<P<hir::Expr>>,
 -                 attrs: ThinAttributes)
 +    fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<P<hir::Expr>>)
                   -> P<hir::Expr> {
 -        self.expr(span, hir::ExprCall(e, args), attrs)
 +        self.expr(span, hir::ExprCall(e, args), ThinVec::new())
      }
  
 -    fn expr_ident(&mut self, span: Span, id: Name, attrs: ThinAttributes, binding: NodeId)
 -                  -> P<hir::Expr> {
 +    fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> P<hir::Expr> {
          let expr_path = hir::ExprPath(None, self.path_ident(span, id));
 -        let expr = self.expr(span, expr_path, attrs);
 +        let expr = self.expr(span, expr_path, ThinVec::new());
  
          let def = self.resolver.definitions().map(|defs| {
              Def::Local(defs.local_def_id(binding), binding)
          expr
      }
  
 -    fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>, attrs: ThinAttributes)
 -                        -> P<hir::Expr> {
 -        self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), attrs)
 +    fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> P<hir::Expr> {
 +        self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
      }
  
 -    fn expr_path(&mut self, path: hir::Path, attrs: ThinAttributes) -> P<hir::Expr> {
 +    fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
          let def = self.resolver.resolve_generated_global_path(&path, true);
          let expr = self.expr(path.span, hir::ExprPath(None, path), attrs);
          self.resolver.record_resolution(expr.id, def);
                    span: Span,
                    arg: P<hir::Expr>,
                    arms: hir::HirVec<hir::Arm>,
 -                  source: hir::MatchSource,
 -                  attrs: ThinAttributes)
 +                  source: hir::MatchSource)
                    -> P<hir::Expr> {
 -        self.expr(span, hir::ExprMatch(arg, arms, source), attrs)
 +        self.expr(span, hir::ExprMatch(arg, arms, source), ThinVec::new())
      }
  
 -    fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinAttributes) -> P<hir::Expr> {
 +    fn expr_block(&mut self, b: P<hir::Block>, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
          self.expr(b.span, hir::ExprBlock(b), attrs)
      }
  
 -    fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<P<hir::Expr>>, attrs: ThinAttributes)
 -                  -> P<hir::Expr> {
 -        self.expr(sp, hir::ExprTup(exprs), attrs)
 +    fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<P<hir::Expr>>) -> P<hir::Expr> {
 +        self.expr(sp, hir::ExprTup(exprs), ThinVec::new())
      }
  
      fn expr_struct(&mut self,
                     path: hir::Path,
                     fields: hir::HirVec<hir::Field>,
                     e: Option<P<hir::Expr>>,
 -                   attrs: ThinAttributes) -> P<hir::Expr> {
 +                   attrs: ThinVec<Attribute>) -> P<hir::Expr> {
          let def = self.resolver.resolve_generated_global_path(&path, false);
          let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs);
          self.resolver.record_resolution(expr.id, def);
          expr
      }
  
 -    fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinAttributes) -> P<hir::Expr> {
 +    fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
          P(hir::Expr {
              id: self.next_id(),
              node: node,
          })
      }
  
 -    fn stmt_let(&mut self,
 -                sp: Span,
 -                mutbl: bool,
 -                ident: Name,
 -                ex: P<hir::Expr>,
 -                attrs: ThinAttributes)
 +    fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
                  -> (hir::Stmt, NodeId) {
          let pat = if mutbl {
              self.pat_ident_binding_mode(sp, ident, hir::BindByValue(hir::MutMutable))
              init: Some(ex),
              id: self.next_id(),
              span: sp,
 -            attrs: attrs,
 +            attrs: ThinVec::new(),
          });
          let decl = respan(sp, hir::DeclLocal(local));
          (respan(sp, hir::StmtDecl(P(decl), self.next_id())), pat_id)
                           expr: P<hir::Expr>,
                           span: Span,
                           rule: hir::BlockCheckMode,
 -                         attrs: ThinAttributes)
 +                         attrs: ThinVec<Attribute>)
                           -> P<hir::Expr> {
          let id = self.next_id();
          let block = P(hir::Block {
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
@@@ -31,12 -31,12 +31,12 @@@ use rustc_mir::pretty::write_mir_pretty
  use rustc_mir::graphviz::write_mir_graphviz;
  
  use syntax::ast::{self, BlockCheckMode};
 -use syntax::codemap;
  use syntax::fold::{self, Folder};
  use syntax::print::{pp, pprust};
  use syntax::print::pprust::PrintState;
  use syntax::ptr::P;
  use syntax::util::small_vector::SmallVector;
 +use syntax_pos;
  
  use graphviz as dot;
  
@@@ -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,
              })
          }
  
              let loop_expr = P(ast::Expr {
                  node: ast::ExprKind::Loop(empty_block, None),
                  id: ast::DUMMY_NODE_ID,
 -                span: codemap::DUMMY_SP,
 -                attrs: None,
 +                span: syntax_pos::DUMMY_SP,
 +                attrs: ast::ThinVec::new(),
              });
  
              expr_to_block(b.rules, Some(loop_expr))
diff --combined src/libsyntax/ast.rs
index dcdc1e60a99cd0bd8012716220dacebf563f1e5f,e138119149c679fef66635cf9aad3a98f081989a..a352715b20b129a21ec56e1776a8a897b932f778
@@@ -14,19 -14,22 +14,19 @@@ pub use self::TyParamBound::*
  pub use self::UnsafeSource::*;
  pub use self::ViewPath_::*;
  pub use self::PathParameters::*;
 +pub use util::ThinVec;
  
 -use attr::{ThinAttributes, HasAttrs};
 -use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId};
 +use syntax_pos::{mk_sp, Span, DUMMY_SP, ExpnId};
 +use codemap::{respan, Spanned};
  use abi::Abi;
  use errors;
 -use ext::base;
 -use ext::tt::macro_parser;
  use parse::token::{self, keywords, InternedString};
 -use parse::lexer;
 -use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
  use print::pprust;
  use ptr::P;
 +use tokenstream::{TokenTree};
  
  use std::fmt;
  use std::rc::Rc;
 -use std::borrow::Cow;
  use std::hash::{Hash, Hasher};
  use serialize::{Encodable, Decodable, Encoder, Decoder};
  
@@@ -168,19 -171,16 +168,19 @@@ impl fmt::Debug for Lifetime 
      }
  }
  
 -/// A lifetime definition, eg `'a: 'b+'c+'d`
 +/// A lifetime definition, e.g. `'a: 'b+'c+'d`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct LifetimeDef {
      pub lifetime: Lifetime,
      pub bounds: Vec<Lifetime>
  }
  
 -/// A "Path" is essentially Rust's notion of a name; for instance:
 -/// std::cmp::PartialEq  .  It's represented as a sequence of identifiers,
 +/// A "Path" is essentially Rust's notion of a name.
 +///
 +/// It's represented as a sequence of identifiers,
  /// along with a bunch of supporting information.
 +///
 +/// E.g. `std::cmp::PartialEq`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
  pub struct Path {
      pub span: Span,
@@@ -220,9 -220,8 +220,9 @@@ impl Path 
      }
  }
  
 -/// A segment of a path: an identifier, an optional lifetime, and a set of
 -/// types.
 +/// A segment of a path: an identifier, an optional lifetime, and a set of types.
 +///
 +/// E.g. `std`, `String` or `Box<T>`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct PathSegment {
      /// The identifier portion of this path segment.
      pub parameters: PathParameters,
  }
  
 +/// Parameters of a path segment.
 +///
 +/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum PathParameters {
      /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
@@@ -326,8 -322,7 +326,8 @@@ pub struct AngleBracketedParameterData 
      /// The type parameters for this path segment, if present.
      pub types: P<[P<Ty>]>,
      /// Bindings (equality constraints) on associated types, if present.
 -    /// e.g., `Foo<A=Bar>`.
 +    ///
 +    /// E.g., `Foo<A=Bar>`.
      pub bindings: P<[TypeBinding]>,
  }
  
@@@ -452,9 -447,7 +452,9 @@@ pub enum WherePredicate 
      EqPredicate(WhereEqPredicate),
  }
  
 -/// A type bound, e.g. `for<'c> Foo: Send+Clone+'c`
 +/// A type bound.
 +///
 +/// E.g. `for<'c> Foo: Send+Clone+'c`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct WhereBoundPredicate {
      pub span: Span,
      pub bounds: TyParamBounds,
  }
  
 -/// A lifetime predicate, e.g. `'a: 'b+'c`
 +/// A lifetime predicate.
 +///
 +/// E.g. `'a: 'b+'c`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct WhereRegionPredicate {
      pub span: Span,
      pub bounds: Vec<Lifetime>,
  }
  
 -/// An equality predicate (unsupported), e.g. `T=int`
 +/// An equality predicate (unsupported).
 +///
 +/// E.g. `T=int`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct WhereEqPredicate {
      pub id: NodeId,
@@@ -500,27 -489,12 +500,27 @@@ pub struct Crate 
      pub exported_macros: Vec<MacroDef>,
  }
  
 +/// A spanned compile-time attribute item.
 +///
 +/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
  pub type MetaItem = Spanned<MetaItemKind>;
  
 +/// A compile-time attribute item.
 +///
 +/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`
  #[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum MetaItemKind {
 +    /// Word meta item.
 +    ///
 +    /// E.g. `test` as in `#[test]`
      Word(InternedString),
 +    /// List meta item.
 +    ///
 +    /// E.g. `derive(..)` as in `#[derive(..)]`
      List(InternedString, Vec<P<MetaItem>>),
 +    /// Name value meta item.
 +    ///
 +    /// E.g. `feature = "foo"` as in `#[feature = "foo"]`
      NameValue(InternedString, Lit),
  }
  
@@@ -550,16 -524,10 +550,13 @@@ impl PartialEq for MetaItemKind 
      }
  }
  
 +/// A Block (`{ .. }`).
 +///
 +/// E.g. `{ .. }` as in `fn foo() { .. }`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  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,
@@@ -608,6 -576,7 +605,6 @@@ impl Pat 
              PatKind::Range(_, _) |
              PatKind::Ident(_, _, _) |
              PatKind::Path(..) |
 -            PatKind::QPath(_, _) |
              PatKind::Mac(_) => {
                  true
              }
@@@ -655,11 -624,15 +652,11 @@@ pub enum PatKind 
      /// 0 <= position <= subpats.len()
      TupleStruct(Path, Vec<P<Pat>>, Option<usize>),
  
 -    /// A path pattern.
 -    /// Such pattern can be resolved to a unit struct/variant or a constant.
 -    Path(Path),
 -
 -    /// An associated const named using the qualified path `<T>::CONST` or
 -    /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
 -    /// referred to as simply `T::CONST`, in which case they will end up as
 -    /// PatKind::Path, and the resolver will have to sort that out.
 -    QPath(QSelf, Path),
 +    /// A possibly qualified path pattern.
 +    /// Unquailfied path patterns `A::B::C` can legally refer to variants, structs, constants
 +    /// or associated constants. Quailfied path patterns `<A>::B::C`/`<A as Trait>::B::C` can
 +    /// only legally refer to associated constants.
 +    Path(Option<QSelf>, Path),
  
      /// A tuple pattern `(a, b)`.
      /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@@ -810,34 -783,45 +807,34 @@@ impl UnOp 
  }
  
  /// A statement
 -pub type Stmt = Spanned<StmtKind>;
 +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 +pub struct Stmt {
 +    pub id: NodeId,
 +    pub node: StmtKind,
 +    pub span: Span,
 +}
  
  impl fmt::Debug for Stmt {
      fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 -        write!(f, "stmt({}: {})",
 -               self.node.id()
 -                   .map_or(Cow::Borrowed("<macro>"),|id|Cow::Owned(id.to_string())),
 -               pprust::stmt_to_string(self))
 +        write!(f, "stmt({}: {})", self.id.to_string(), pprust::stmt_to_string(self))
      }
  }
  
  
  #[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)]
@@@ -864,19 -848,32 +861,19 @@@ pub struct Local 
      pub init: Option<P<Expr>>,
      pub id: NodeId,
      pub span: Span,
 -    pub attrs: ThinAttributes,
 -}
 -
 -impl Local {
 -    pub fn attrs(&self) -> &[Attribute] {
 -        HasAttrs::attrs(self)
 -    }
 +    pub attrs: ThinVec<Attribute>,
  }
  
 -pub type Decl = Spanned<DeclKind>;
 -
 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 -pub enum DeclKind {
 -    /// A local (let) binding:
 -    Local(P<Local>),
 -    /// An item binding:
 -    Item(P<Item>),
 -}
 -
 -impl Decl {
 -    pub fn attrs(&self) -> &[Attribute] {
 -        HasAttrs::attrs(self)
 -    }
 -}
 -
 -/// represents one arm of a 'match'
 +/// An arm of a 'match'.
 +///
 +/// E.g. `0...10 => { println!("match!") }` as in
 +///
 +/// ```rust,ignore
 +/// match n {
 +///     0...10 => { println!("match!") },
 +///     // ..
 +/// }
 +/// ```
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct Arm {
      pub attrs: Vec<Attribute>,
@@@ -912,7 -909,13 +909,7 @@@ pub struct Expr 
      pub id: NodeId,
      pub node: ExprKind,
      pub span: Span,
 -    pub attrs: ThinAttributes
 -}
 -
 -impl Expr {
 -    pub fn attrs(&self) -> &[Attribute] {
 -        HasAttrs::attrs(self)
 -    }
 +    pub attrs: ThinVec<Attribute>
  }
  
  impl fmt::Debug for Expr {
@@@ -1027,7 -1030,7 +1024,7 @@@ pub enum ExprKind 
      /// parameters, e.g. foo::bar::<baz>.
      ///
      /// Optionally "qualified",
 -    /// e.g. `<Vec<T> as SomeTrait>::SomeType`.
 +    /// E.g. `<Vec<T> as SomeTrait>::SomeType`.
      Path(Option<QSelf>, Path),
  
      /// A referencing operation (`&a` or `&mut a`)
      /// A `break`, with an optional label to break
      Break(Option<SpannedIdent>),
      /// A `continue`, with an optional label
 -    Again(Option<SpannedIdent>),
 +    Continue(Option<SpannedIdent>),
      /// A `return`, with an optional value to be returned
      Ret(Option<P<Expr>>),
  
  /// separately. `position` represents the index of the associated
  /// item qualified with this Self type.
  ///
 -/// ```ignore
 +/// ```rust,ignore
  /// <Vec<T> as a::b::Trait>::AssociatedItem
  ///  ^~~~~     ~~~~~~~~~~~~~~^
  ///  ty        position = 3
@@@ -1091,6 -1094,193 +1088,6 @@@ pub enum CaptureBy 
      Ref,
  }
  
 -/// A delimited sequence of token trees
 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 -pub struct Delimited {
 -    /// The type of delimiter
 -    pub delim: token::DelimToken,
 -    /// The span covering the opening delimiter
 -    pub open_span: Span,
 -    /// The delimited sequence of token trees
 -    pub tts: Vec<TokenTree>,
 -    /// The span covering the closing delimiter
 -    pub close_span: Span,
 -}
 -
 -impl Delimited {
 -    /// Returns the opening delimiter as a token.
 -    pub fn open_token(&self) -> token::Token {
 -        token::OpenDelim(self.delim)
 -    }
 -
 -    /// Returns the closing delimiter as a token.
 -    pub fn close_token(&self) -> token::Token {
 -        token::CloseDelim(self.delim)
 -    }
 -
 -    /// Returns the opening delimiter as a token tree.
 -    pub fn open_tt(&self) -> TokenTree {
 -        TokenTree::Token(self.open_span, self.open_token())
 -    }
 -
 -    /// Returns the closing delimiter as a token tree.
 -    pub fn close_tt(&self) -> TokenTree {
 -        TokenTree::Token(self.close_span, self.close_token())
 -    }
 -}
 -
 -/// A sequence of token trees
 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 -pub struct SequenceRepetition {
 -    /// The sequence of token trees
 -    pub tts: Vec<TokenTree>,
 -    /// The optional separator
 -    pub separator: Option<token::Token>,
 -    /// Whether the sequence can be repeated zero (*), or one or more times (+)
 -    pub op: KleeneOp,
 -    /// The number of `MatchNt`s that appear in the sequence (and subsequences)
 -    pub num_captures: usize,
 -}
 -
 -/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
 -/// for token sequences.
 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 -pub enum KleeneOp {
 -    ZeroOrMore,
 -    OneOrMore,
 -}
 -
 -/// When the main rust parser encounters a syntax-extension invocation, it
 -/// parses the arguments to the invocation as a token-tree. This is a very
 -/// loose structure, such that all sorts of different AST-fragments can
 -/// be passed to syntax extensions using a uniform type.
 -///
 -/// If the syntax extension is an MBE macro, it will attempt to match its
 -/// LHS token tree against the provided token tree, and if it finds a
 -/// match, will transcribe the RHS token tree, splicing in any captured
 -/// macro_parser::matched_nonterminals into the `SubstNt`s it finds.
 -///
 -/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
 -/// Nothing special happens to misnamed or misplaced `SubstNt`s.
 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 -pub enum TokenTree {
 -    /// A single token
 -    Token(Span, token::Token),
 -    /// A delimited sequence of token trees
 -    Delimited(Span, Rc<Delimited>),
 -
 -    // This only makes sense in MBE macros.
 -
 -    /// A kleene-style repetition sequence with a span
 -    // FIXME(eddyb) #12938 Use DST.
 -    Sequence(Span, Rc<SequenceRepetition>),
 -}
 -
 -impl TokenTree {
 -    pub fn len(&self) -> usize {
 -        match *self {
 -            TokenTree::Token(_, token::DocComment(name)) => {
 -                match doc_comment_style(&name.as_str()) {
 -                    AttrStyle::Outer => 2,
 -                    AttrStyle::Inner => 3
 -                }
 -            }
 -            TokenTree::Token(_, token::SpecialVarNt(..)) => 2,
 -            TokenTree::Token(_, token::MatchNt(..)) => 3,
 -            TokenTree::Delimited(_, ref delimed) => {
 -                delimed.tts.len() + 2
 -            }
 -            TokenTree::Sequence(_, ref seq) => {
 -                seq.tts.len()
 -            }
 -            TokenTree::Token(..) => 0
 -        }
 -    }
 -
 -    pub fn get_tt(&self, index: usize) -> TokenTree {
 -        match (self, index) {
 -            (&TokenTree::Token(sp, token::DocComment(_)), 0) => {
 -                TokenTree::Token(sp, token::Pound)
 -            }
 -            (&TokenTree::Token(sp, token::DocComment(name)), 1)
 -            if doc_comment_style(&name.as_str()) == AttrStyle::Inner => {
 -                TokenTree::Token(sp, token::Not)
 -            }
 -            (&TokenTree::Token(sp, token::DocComment(name)), _) => {
 -                let stripped = strip_doc_comment_decoration(&name.as_str());
 -
 -                // Searches for the occurrences of `"#*` and returns the minimum number of `#`s
 -                // required to wrap the text.
 -                let num_of_hashes = stripped.chars().scan(0, |cnt, x| {
 -                    *cnt = if x == '"' {
 -                        1
 -                    } else if *cnt != 0 && x == '#' {
 -                        *cnt + 1
 -                    } else {
 -                        0
 -                    };
 -                    Some(*cnt)
 -                }).max().unwrap_or(0);
 -
 -                TokenTree::Delimited(sp, Rc::new(Delimited {
 -                    delim: token::Bracket,
 -                    open_span: sp,
 -                    tts: vec![TokenTree::Token(sp, token::Ident(token::str_to_ident("doc"))),
 -                              TokenTree::Token(sp, token::Eq),
 -                              TokenTree::Token(sp, token::Literal(
 -                                  token::StrRaw(token::intern(&stripped), num_of_hashes), None))],
 -                    close_span: sp,
 -                }))
 -            }
 -            (&TokenTree::Delimited(_, ref delimed), _) => {
 -                if index == 0 {
 -                    return delimed.open_tt();
 -                }
 -                if index == delimed.tts.len() + 1 {
 -                    return delimed.close_tt();
 -                }
 -                delimed.tts[index - 1].clone()
 -            }
 -            (&TokenTree::Token(sp, token::SpecialVarNt(var)), _) => {
 -                let v = [TokenTree::Token(sp, token::Dollar),
 -                         TokenTree::Token(sp, token::Ident(token::str_to_ident(var.as_str())))];
 -                v[index].clone()
 -            }
 -            (&TokenTree::Token(sp, token::MatchNt(name, kind)), _) => {
 -                let v = [TokenTree::Token(sp, token::SubstNt(name)),
 -                         TokenTree::Token(sp, token::Colon),
 -                         TokenTree::Token(sp, token::Ident(kind))];
 -                v[index].clone()
 -            }
 -            (&TokenTree::Sequence(_, ref seq), _) => {
 -                seq.tts[index].clone()
 -            }
 -            _ => panic!("Cannot expand a token tree")
 -        }
 -    }
 -
 -    /// Returns the `Span` corresponding to this token tree.
 -    pub fn get_span(&self) -> Span {
 -        match *self {
 -            TokenTree::Token(span, _)     => span,
 -            TokenTree::Delimited(span, _) => span,
 -            TokenTree::Sequence(span, _)  => span,
 -        }
 -    }
 -
 -    /// Use this token tree as a matcher to parse given tts.
 -    pub fn parse(cx: &base::ExtCtxt, mtch: &[TokenTree], tts: &[TokenTree])
 -                 -> macro_parser::NamedParseResult {
 -        // `None` is because we're not interpolating
 -        let arg_rdr = lexer::new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic,
 -                                                         None,
 -                                                         None,
 -                                                         tts.iter().cloned().collect(),
 -                                                         true);
 -        macro_parser::parse(cx.parse_sess(), cx.cfg(), arg_rdr, mtch)
 -    }
 -}
 -
  pub type Mac = Spanned<Mac_>;
  
  /// Represents a macro invocation. The Path indicates which macro
  pub struct Mac_ {
      pub path: Path,
      pub tts: Vec<TokenTree>,
 -    pub ctxt: SyntaxContext,
  }
  
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@@ -1125,9 -1316,6 +1122,9 @@@ pub enum LitIntType 
      Unsuffixed,
  }
  
 +/// Literal kind.
 +///
 +/// E.g. `"foo"`, `42`, `12.34` or `bool`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum LitKind {
      /// A string literal (`"foo"`)
@@@ -1195,7 -1383,6 +1192,7 @@@ pub enum TraitItemKind 
      Const(P<Ty>, Option<P<Expr>>),
      Method(MethodSig, Option<P<Block>>),
      Type(TyParamBounds, Option<P<Ty>>),
 +    Macro(Mac),
  }
  
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@@ -1396,8 -1583,8 +1393,8 @@@ pub struct BareFnTy 
      pub decl: P<FnDecl>
  }
  
 -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  /// The different kinds of types recognized by the compiler
 +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum TyKind {
      Vec(P<Ty>),
      /// A fixed length array (`[T; n]`)
      Mac(Mac),
  }
  
 +/// Inline assembly dialect.
 +///
 +/// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")``
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
  pub enum AsmDialect {
      Att,
      Intel,
  }
  
 +/// Inline assembly.
 +///
 +/// E.g. `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")``
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct InlineAsmOutput {
      pub constraint: InternedString,
      pub is_indirect: bool,
  }
  
 +/// Inline assembly.
 +///
 +/// E.g. `asm!("NOP");`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct InlineAsm {
      pub asm: InternedString,
      pub expn_id: ExpnId,
  }
  
 -/// represents an argument in a function header
 +/// An argument in a function header.
 +///
 +/// E.g. `bar: usize` as in `fn foo(bar: usize)`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct Arg {
      pub ty: P<Ty>,
  }
  
  /// Alternative representation for `Arg`s describing `self` parameter of methods.
 +///
 +/// E.g. `&mut self` as in `fn foo(&mut self)`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum SelfKind {
      /// `self`, `mut self`
@@@ -1547,9 -1721,7 +1544,9 @@@ impl Arg 
      }
  }
  
 -/// Represents the header (not the body) of a function declaration
 +/// Header (not the body) of a function declaration.
 +///
 +/// E.g. `fn foo(bar: baz)`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct FnDecl {
      pub inputs: Vec<Arg>,
@@@ -1636,9 -1808,6 +1633,9 @@@ impl FunctionRetTy 
      }
  }
  
 +/// Module declaration.
 +///
 +/// E.g. `mod foo;` or `mod foo { .. }`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct Mod {
      /// A span from the first token past `{` to the last token until `}`.
      pub items: Vec<P<Item>>,
  }
  
 +/// Foreign module declaration.
 +///
 +/// E.g. `extern { .. }` or `extern C { .. }`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct ForeignMod {
      pub abi: Abi,
@@@ -1667,7 -1833,7 +1664,7 @@@ pub struct Variant_ 
      pub name: Ident,
      pub attrs: Vec<Attribute>,
      pub data: VariantData,
 -    /// Explicit discriminant, eg `Foo = 1`
 +    /// Explicit discriminant, e.g. `Foo = 1`
      pub disr_expr: Option<P<Expr>>,
  }
  
@@@ -1677,12 -1843,12 +1674,12 @@@ pub type Variant = Spanned<Variant_>
  pub enum PathListItemKind {
      Ident {
          name: Ident,
 -        /// renamed in list, eg `use foo::{bar as baz};`
 +        /// renamed in list, e.g. `use foo::{bar as baz};`
          rename: Option<Ident>,
          id: NodeId
      },
      Mod {
 -        /// renamed in list, eg `use foo::{self as baz};`
 +        /// renamed in list, e.g. `use foo::{self as baz};`
          rename: Option<Ident>,
          id: NodeId
      }
@@@ -1795,9 -1961,6 +1792,9 @@@ pub enum Visibility 
      Inherited,
  }
  
 +/// Field of a struct.
 +///
 +/// E.g. `bar: usize` as in `struct Foo { bar: usize }`
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub struct StructField {
      pub span: Span,
  /// Id of the whole struct lives in `Item`.
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum VariantData {
 +    /// Struct variant.
 +    ///
 +    /// E.g. `Bar { .. }` as in `enum Foo { Bar { .. } }`
      Struct(Vec<StructField>, NodeId),
 +    /// Tuple variant.
 +    ///
 +    /// E.g. `Bar(..)` as in `enum Foo { Bar(..) }`
      Tuple(Vec<StructField>, NodeId),
 +    /// Unit variant.
 +    ///
 +    /// E.g. `Bar = ..` as in `enum Foo { Bar = .. }`
      Unit(NodeId),
  }
  
@@@ -1875,68 -2029,52 +1872,68 @@@ pub struct Item 
      pub span: Span,
  }
  
 -impl Item {
 -    pub fn attrs(&self) -> &[Attribute] {
 -        &self.attrs
 -    }
 -}
 -
  #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
  pub enum ItemKind {
 -    /// An`extern crate` item, with optional original crate name,
 +    /// An`extern crate` item, with optional original crate name.
      ///
 -    /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
 +    /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
      ExternCrate(Option<Name>),
 -    /// A `use` or `pub use` item
 +    /// A use declaration (`use` or `pub use`) item.
 +    ///
 +    /// E.g. `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`
      Use(P<ViewPath>),
 -
 -    /// A `static` item
 +    /// A static item (`static` or `pub static`).
 +    ///
 +    /// E.g. `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`
      Static(P<Ty>, Mutability, P<Expr>),
 -    /// A `const` item
 +    /// A constant item (`const` or `pub const`).
 +    ///
 +    /// E.g. `const FOO: i32 = 42;`
      Const(P<Ty>, P<Expr>),
 -    /// A function declaration
 +    /// A function declaration (`fn` or `pub fn`).
 +    ///
 +    /// E.g. `fn foo(bar: usize) -> usize { .. }`
      Fn(P<FnDecl>, Unsafety, Constness, Abi, Generics, P<Block>),
 -    /// A module
 +    /// A module declaration (`mod` or `pub mod`).
 +    ///
 +    /// E.g. `mod foo;` or `mod foo { .. }`
      Mod(Mod),
 -    /// An external module
 +    /// An external module (`extern` or `pub extern`).
 +    ///
 +    /// E.g. `extern {}` or `extern "C" {}`
      ForeignMod(ForeignMod),
 -    /// A type alias, e.g. `type Foo = Bar<u8>`
 +    /// A type alias (`type` or `pub type`).
 +    ///
 +    /// E.g. `type Foo = Bar<u8>;`
      Ty(P<Ty>, Generics),
 -    /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
 +    /// An enum definition (`enum` or `pub enum`).
 +    ///
 +    /// E.g. `enum Foo<A, B> { C<A>, D<B> }`
      Enum(EnumDef, Generics),
 -    /// A struct definition, e.g. `struct Foo<A> {x: A}`
 +    /// A struct definition (`struct` or `pub struct`).
 +    ///
 +    /// E.g. `struct Foo<A> { x: A }`
      Struct(VariantData, Generics),
 -    /// Represents a Trait Declaration
 +    /// A Trait declaration (`trait` or `pub trait`).
 +    ///
 +    /// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
      Trait(Unsafety, Generics, TyParamBounds, Vec<TraitItem>),
 -
 -    // Default trait implementations
 +    // Default trait implementation.
      ///
 -    // `impl Trait for .. {}`
 +    /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
      DefaultImpl(Unsafety, TraitRef),
 -    /// An implementation, eg `impl<A> Trait for Foo { .. }`
 +    /// An implementation.
 +    ///
 +    /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
      Impl(Unsafety,
               ImplPolarity,
               Generics,
               Option<TraitRef>, // (optional) trait this impl implements
               P<Ty>, // self
               Vec<ImplItem>),
 -    /// A macro invocation (which includes macro definition)
 +    /// A macro invocation (which includes macro definition).
 +    ///
 +    /// E.g. `macro_rules! foo { .. }` or `foo!(..)`
      Mac(Mac),
  }
  
index f4ae23ed8be788bb07146420f315adaaeda53b61,4bfbd37edd9fa496387436442efaf31353e16fa6..435241f426ec6f4329e90a2dc6dea8c093e3e723
@@@ -11,8 -11,7 +11,8 @@@
  use abi::Abi;
  use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
  use attr;
 -use codemap::{Span, respan, Spanned, DUMMY_SP, Pos};
 +use syntax_pos::{Span, DUMMY_SP, Pos};
 +use codemap::{respan, Spanned};
  use ext::base::ExtCtxt;
  use parse::token::{self, keywords, InternedString};
  use ptr::P;
@@@ -88,6 -87,7 +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,
      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>;
@@@ -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));
 -        respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
 +        ast::Stmt {
 +            id: ast::DUMMY_NODE_ID,
 +            node: ast::StmtKind::Local(local),
 +            span: sp,
 +        }
      }
  
      fn stmt_let_typed(&self,
              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> {
              id: ast::DUMMY_NODE_ID,
              node: node,
              span: span,
 -            attrs: None,
 +            attrs: ast::ThinVec::new(),
          })
      }
  
      }
      fn pat_enum(&self, span: Span, path: ast::Path, subpats: Vec<P<ast::Pat>>) -> P<ast::Pat> {
          let pat = if subpats.is_empty() {
 -            PatKind::Path(path)
 +            PatKind::Path(None, path)
          } else {
              PatKind::TupleStruct(path, subpats, None)
          };
                      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 {
index 32635f5cdd20db2f84249028563f15d5da540676,263c10cee5bf7b0b2f5c7d07e6eb4bb7656b55e1..3036a88430a2be6e82360049b2f121f745d15f91
@@@ -8,16 -8,17 +8,16 @@@
  // option. This file may not be copied, modified, or distributed
  // except according to those terms.
  
 -use ast::{Block, Crate, DeclKind, PatKind};
 +use ast::{Block, Crate, PatKind};
  use ast::{Local, Ident, Mac_, Name, SpannedIdent};
  use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
 -use ast::TokenTree;
  use ast;
 +use attr::HasAttrs;
  use ext::mtwt;
 -use ext::build::AstBuilder;
  use attr;
 -use attr::{AttrMetaMethods, WithAttrs, ThinAttributesExt};
 -use codemap;
 -use codemap::{Span, Spanned, ExpnInfo, ExpnId, NameAndSpan, MacroBang, MacroAttribute};
 +use attr::AttrMetaMethods;
 +use codemap::{Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
 +use syntax_pos::{self, Span, ExpnId};
  use config::StripUnconfigured;
  use ext::base::*;
  use feature_gate::{self, Features};
@@@ -26,7 -27,6 +26,7 @@@ use fold::*
  use util::move_map::MoveMap;
  use parse::token::{fresh_mark, fresh_name, intern, keywords};
  use ptr::P;
 +use tokenstream::TokenTree;
  use util::small_vector::SmallVector;
  use visit;
  use visit::Visitor;
@@@ -41,7 -41,7 +41,7 @@@ trait MacroGenerable: Sized 
  
      // Fold this node or list of nodes using the given folder.
      fn fold_with<F: Folder>(self, folder: &mut F) -> Self;
 -    fn visit_with<'v, V: Visitor<'v>>(&'v self, visitor: &mut V);
 +    fn visit_with<V: Visitor>(&self, visitor: &mut V);
  
      // Return a placeholder expansion to allow compilation to continue after an erroring expansion.
      fn dummy(span: Span) -> Self;
@@@ -62,7 -62,7 +62,7 @@@ macro_rules! impl_macro_generable 
                  $( folder.$fold(self) )*
                  $( self.into_iter().flat_map(|item| folder. $fold_elt (item)).collect() )*
              }
 -            fn visit_with<'v, V: Visitor<'v>>(&'v self, visitor: &mut V) {
 +            fn visit_with<V: Visitor>(&self, visitor: &mut V) {
                  $( visitor.$visit(self) )*
                  $( for item in self.as_slice() { visitor. $visit_elt (item) } )*
              }
@@@ -80,11 -80,8 +80,11 @@@ impl_macro_generable! 
          "statement",  .make_stmts, lift .fold_stmt, lift .visit_stmt, |_span| SmallVector::zero();
      SmallVector<P<ast::Item>>:
          "item",       .make_items, lift .fold_item, lift .visit_item, |_span| SmallVector::zero();
 +    SmallVector<ast::TraitItem>:
 +        "trait item", .make_trait_items, lift .fold_trait_item, lift .visit_trait_item,
 +        |_span| SmallVector::zero();
      SmallVector<ast::ImplItem>:
 -        "impl item",  .make_impl_items, lift .fold_impl_item, lift .visit_impl_item,
 +        "impl item",  .make_impl_items,  lift .fold_impl_item,  lift .visit_impl_item,
          |_span| SmallVector::zero();
  }
  
@@@ -97,23 -94,24 +97,23 @@@ impl MacroGenerable for Option<P<ast::E
      fn fold_with<F: Folder>(self, folder: &mut F) -> Self {
          self.and_then(|expr| folder.fold_opt_expr(expr))
      }
 -    fn visit_with<'v, V: Visitor<'v>>(&'v self, visitor: &mut V) {
 +    fn visit_with<V: Visitor>(&self, visitor: &mut V) {
          self.as_ref().map(|expr| visitor.visit_expr(expr));
      }
  }
  
 -pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
 +pub fn expand_expr(mut expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
      match expr.node {
          // expr_mac should really be expr_ext or something; it's the
          // entry-point for all syntax extensions.
          ast::ExprKind::Mac(mac) => {
 -            expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, fld)
 +            return expand_mac_invoc(mac, None, expr.attrs.into(), expr.span, fld);
          }
  
          ast::ExprKind::While(cond, body, opt_ident) => {
              let cond = fld.fold_expr(cond);
              let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
 -            fld.cx.expr(expr.span, ast::ExprKind::While(cond, body, opt_ident))
 -                .with_attrs(fold_thin_attrs(expr.attrs, fld))
 +            expr.node = ast::ExprKind::While(cond, body, opt_ident);
          }
  
          ast::ExprKind::WhileLet(pat, cond, body, opt_ident) => {
              });
              assert!(rewritten_pats.len() == 1);
  
 -            let wl = ast::ExprKind::WhileLet(rewritten_pats.remove(0), cond, body, opt_ident);
 -            fld.cx.expr(expr.span, wl).with_attrs(fold_thin_attrs(expr.attrs, fld))
 +            expr.node = ast::ExprKind::WhileLet(rewritten_pats.remove(0), cond, body, opt_ident);
          }
  
          ast::ExprKind::Loop(loop_block, opt_ident) => {
              let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
 -            fld.cx.expr(expr.span, ast::ExprKind::Loop(loop_block, opt_ident))
 -                .with_attrs(fold_thin_attrs(expr.attrs, fld))
 +            expr.node = ast::ExprKind::Loop(loop_block, opt_ident);
          }
  
          ast::ExprKind::ForLoop(pat, head, body, opt_ident) => {
              assert!(rewritten_pats.len() == 1);
  
              let head = fld.fold_expr(head);
 -            let fl = ast::ExprKind::ForLoop(rewritten_pats.remove(0), head, body, opt_ident);
 -            fld.cx.expr(expr.span, fl).with_attrs(fold_thin_attrs(expr.attrs, fld))
 +            expr.node = ast::ExprKind::ForLoop(rewritten_pats.remove(0), head, body, opt_ident);
          }
  
          ast::ExprKind::IfLet(pat, sub_expr, body, else_opt) => {
  
              let else_opt = else_opt.map(|else_opt| fld.fold_expr(else_opt));
              let sub_expr = fld.fold_expr(sub_expr);
 -            let il = ast::ExprKind::IfLet(rewritten_pats.remove(0), sub_expr, body, else_opt);
 -            fld.cx.expr(expr.span, il).with_attrs(fold_thin_attrs(expr.attrs, fld))
 +            expr.node = ast::ExprKind::IfLet(rewritten_pats.remove(0), sub_expr, body, else_opt);
          }
  
          ast::ExprKind::Closure(capture_clause, fn_decl, block, fn_decl_span) => {
              let (rewritten_fn_decl, rewritten_block)
                  = expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
 -            let new_node = ast::ExprKind::Closure(capture_clause,
 -                                                  rewritten_fn_decl,
 -                                                  rewritten_block,
 -                                                  fn_decl_span);
 -            P(ast::Expr{ id: expr.id,
 -                         node: new_node,
 -                         span: expr.span,
 -                         attrs: fold_thin_attrs(expr.attrs, fld) })
 +            expr.node = ast::ExprKind::Closure(capture_clause,
 +                                               rewritten_fn_decl,
 +                                               rewritten_block,
 +                                               fn_decl_span);
          }
  
 -        _ => P(noop_fold_expr(expr, fld)),
 -    }
 +        _ => expr = noop_fold_expr(expr, fld),
 +    };
 +    P(expr)
  }
  
  /// Expand a macro invocation. Returns the result of expansion.
@@@ -243,7 -248,7 +243,7 @@@ fn expand_mac_invoc<T>(mac: ast::Mac, i
                      },
                  });
  
 -                let marked_tts = mark_tts(&tts[..], mark);
 +                let marked_tts = mark_tts(tts, mark);
                  Some(expandfun.expand(fld.cx, call_site, &marked_tts))
              }
  
                      }
                  });
  
 -                let marked_tts = mark_tts(&tts, mark);
 +                let marked_tts = mark_tts(tts, mark);
                  Some(expander.expand(fld.cx, call_site, ident, marked_tts))
              }
  
@@@ -439,25 -444,25 +439,25 @@@ fn expand_stmt(stmt: Stmt, fld: &mut Ma
      };
  
      let (mac, style, attrs) = match stmt.node {
 -        StmtKind::Mac(mac, style, attrs) => (mac, style, attrs),
 +        StmtKind::Mac(mac) => mac.unwrap(),
          _ => return expand_non_macro_stmt(stmt, fld)
      };
  
      let mut fully_expanded: SmallVector<ast::Stmt> =
 -        expand_mac_invoc(mac.unwrap(), None, attrs.into_attr_vec(), stmt.span, fld);
 +        expand_mac_invoc(mac, None, attrs.into(), stmt.span, fld);
  
      // If this is a macro invocation with a semicolon, then apply that
      // semicolon to the final statement produced by expansion.
      if style == MacStmtStyle::Semicolon {
          if let Some(stmt) = fully_expanded.pop() {
 -            let new_stmt = Spanned {
 +            fully_expanded.push(Stmt {
 +                id: stmt.id,
                  node: match stmt.node {
 -                    StmtKind::Expr(e, stmt_id) => StmtKind::Semi(e, stmt_id),
 +                    StmtKind::Expr(expr) => StmtKind::Semi(expr),
                      _ => stmt.node /* might already have a semi */
                  },
 -                span: stmt.span
 -            };
 -            fully_expanded.push(new_stmt);
 +                span: stmt.span,
 +            });
          }
      }
  
  
  // expand a non-macro stmt. this is essentially the fallthrough for
  // expand_stmt, above.
 -fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroExpander)
 +fn expand_non_macro_stmt(stmt: Stmt, fld: &mut MacroExpander)
                           -> SmallVector<Stmt> {
      // is it a let?
 -    match node {
 -        StmtKind::Decl(decl, node_id) => decl.and_then(|Spanned {node: decl, span}| match decl {
 -            DeclKind::Local(local) => {
 -                // take it apart:
 -                let rewritten_local = local.map(|Local {id, pat, ty, init, span, attrs}| {
 -                    // expand the ty since TyKind::FixedLengthVec contains an Expr
 -                    // and thus may have a macro use
 -                    let expanded_ty = ty.map(|t| fld.fold_ty(t));
 -                    // expand the pat (it might contain macro uses):
 -                    let expanded_pat = fld.fold_pat(pat);
 -                    // find the PatIdents in the pattern:
 -                    // oh dear heaven... this is going to include the enum
 -                    // names, as well... but that should be okay, as long as
 -                    // the new names are gensyms for the old ones.
 -                    // generate fresh names, push them to a new pending list
 -                    let idents = pattern_bindings(&expanded_pat);
 -                    let mut new_pending_renames =
 -                        idents.iter().map(|ident| (*ident, fresh_name(*ident))).collect();
 -                    // rewrite the pattern using the new names (the old
 -                    // ones have already been applied):
 -                    let rewritten_pat = {
 -                        // nested binding to allow borrow to expire:
 -                        let mut rename_fld = IdentRenamer{renames: &mut new_pending_renames};
 -                        rename_fld.fold_pat(expanded_pat)
 -                    };
 -                    // add them to the existing pending renames:
 -                    fld.cx.syntax_env.info().pending_renames
 -                          .extend(new_pending_renames);
 -                    Local {
 -                        id: id,
 -                        ty: expanded_ty,
 -                        pat: rewritten_pat,
 -                        // also, don't forget to expand the init:
 -                        init: init.map(|e| fld.fold_expr(e)),
 -                        span: span,
 -                        attrs: fold::fold_thin_attrs(attrs, fld),
 -                    }
 -                });
 -                SmallVector::one(Spanned {
 -                    node: StmtKind::Decl(P(Spanned {
 -                            node: DeclKind::Local(rewritten_local),
 -                            span: span
 -                        }),
 -                        node_id),
 -                    span: stmt_span
 -                })
 -            }
 -            _ => {
 -                noop_fold_stmt(Spanned {
 -                    node: StmtKind::Decl(P(Spanned {
 -                            node: decl,
 -                            span: span
 -                        }),
 -                        node_id),
 -                    span: stmt_span
 -                }, fld)
 -            }
 -        }),
 -        _ => {
 -            noop_fold_stmt(Spanned {
 -                node: node,
 -                span: stmt_span
 -            }, fld)
 +    match stmt.node {
 +        StmtKind::Local(local) => {
 +            // take it apart:
 +            let rewritten_local = local.map(|Local {id, pat, ty, init, span, attrs}| {
 +                // expand the ty since TyKind::FixedLengthVec contains an Expr
 +                // and thus may have a macro use
 +                let expanded_ty = ty.map(|t| fld.fold_ty(t));
 +                // expand the pat (it might contain macro uses):
 +                let expanded_pat = fld.fold_pat(pat);
 +                // find the PatIdents in the pattern:
 +                // oh dear heaven... this is going to include the enum
 +                // names, as well... but that should be okay, as long as
 +                // the new names are gensyms for the old ones.
 +                // generate fresh names, push them to a new pending list
 +                let idents = pattern_bindings(&expanded_pat);
 +                let mut new_pending_renames =
 +                    idents.iter().map(|ident| (*ident, fresh_name(*ident))).collect();
 +                // rewrite the pattern using the new names (the old
 +                // ones have already been applied):
 +                let rewritten_pat = {
 +                    // nested binding to allow borrow to expire:
 +                    let mut rename_fld = IdentRenamer{renames: &mut new_pending_renames};
 +                    rename_fld.fold_pat(expanded_pat)
 +                };
 +                // add them to the existing pending renames:
 +                fld.cx.syntax_env.info().pending_renames
 +                      .extend(new_pending_renames);
 +                Local {
 +                    id: id,
 +                    ty: expanded_ty,
 +                    pat: rewritten_pat,
 +                    // also, don't forget to expand the init:
 +                    init: init.map(|e| fld.fold_expr(e)),
 +                    span: span,
 +                    attrs: fold::fold_thin_attrs(attrs, fld),
 +                }
 +            });
 +            SmallVector::one(Stmt {
 +                id: stmt.id,
 +                node: StmtKind::Local(rewritten_local),
 +                span: stmt.span,
 +            })
          }
 +        _ => noop_fold_stmt(stmt, fld),
      }
  }
  
@@@ -570,7 -595,7 +570,7 @@@ struct PatIdentFinder 
      ident_accumulator: Vec<ast::Ident>
  }
  
 -impl<'v> Visitor<'v> for PatIdentFinder {
 +impl Visitor for PatIdentFinder {
      fn visit_pat(&mut self, pattern: &ast::Pat) {
          match *pattern {
              ast::Pat { id: _, node: PatKind::Ident(_, ref path1, ref inner), span: _ } => {
@@@ -611,23 -636,14 +611,14 @@@ pub fn expand_block(blk: P<Block>, fld
  
  // 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
          }
@@@ -699,7 -715,11 +690,7 @@@ impl<'a> Folder for PatIdentRenamer<'a
      }
  }
  
 -fn expand_annotatable(a: Annotatable,
 -                      fld: &mut MacroExpander)
 -                      -> SmallVector<Annotatable> {
 -    let a = expand_item_multi_modifier(a, fld);
 -
 +fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
      let new_items: SmallVector<Annotatable> = match a {
          Annotatable::Item(it) => match it.node {
              ast::ItemKind::Mac(..) => {
              _ => noop_fold_item(it, fld),
          }.into_iter().map(|i| Annotatable::Item(i)).collect(),
  
 -        Annotatable::TraitItem(it) => match it.node {
 -            ast::TraitItemKind::Method(_, Some(_)) => {
 -                let ti = it.unwrap();
 -                SmallVector::one(ast::TraitItem {
 -                    id: ti.id,
 -                    ident: ti.ident,
 -                    attrs: ti.attrs,
 -                    node: match ti.node  {
 -                        ast::TraitItemKind::Method(sig, Some(body)) => {
 -                            let (sig, body) = expand_and_rename_method(sig, body, fld);
 -                            ast::TraitItemKind::Method(sig, Some(body))
 -                        }
 -                        _ => unreachable!()
 -                    },
 -                    span: ti.span,
 -                })
 -            }
 -            _ => fold::noop_fold_trait_item(it.unwrap(), fld)
 -        }.into_iter().map(|ti| Annotatable::TraitItem(P(ti))).collect(),
 +        Annotatable::TraitItem(it) => {
 +            expand_trait_item(it.unwrap(), fld).into_iter().
 +                map(|it| Annotatable::TraitItem(P(it))).collect()
 +        }
  
          Annotatable::ImplItem(ii) => {
              expand_impl_item(ii.unwrap(), fld).into_iter().
@@@ -752,6 -787,29 +743,6 @@@ fn decorate(a: Annotatable, fld: &mut M
      new_items
  }
  
 -// Partition a set of attributes into one kind of attribute, and other kinds.
 -macro_rules! partition {
 -    ($fn_name: ident, $variant: ident) => {
 -        #[allow(deprecated)] // The `allow` is needed because the `Modifier` variant might be used.
 -        fn $fn_name(attrs: &[ast::Attribute],
 -                    fld: &MacroExpander)
 -                     -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
 -            attrs.iter().cloned().partition(|attr| {
 -                match fld.cx.syntax_env.find(intern(&attr.name())) {
 -                    Some(rc) => match *rc {
 -                        $variant(..) => true,
 -                        _ => false
 -                    },
 -                    _ => false
 -                }
 -            })
 -        }
 -    }
 -}
 -
 -partition!(multi_modifiers, MultiModifier);
 -
 -
  fn expand_decorators(a: Annotatable,
                       fld: &mut MacroExpander,
                       decorator_items: &mut SmallVector<Annotatable>,
      }
  }
  
 -fn expand_item_multi_modifier(mut it: Annotatable,
 -                              fld: &mut MacroExpander)
 -                              -> Annotatable {
 -    let (modifiers, other_attrs) = multi_modifiers(it.attrs(), fld);
 -
 -    // Update the attrs, leave everything else alone. Is this mutation really a good idea?
 -    it = it.fold_attrs(other_attrs);
 -
 -    if modifiers.is_empty() {
 -        return it
 -    }
 -
 -    for attr in &modifiers {
 -        let mname = intern(&attr.name());
 -
 -        match fld.cx.syntax_env.find(mname) {
 -            Some(rc) => match *rc {
 -                MultiModifier(ref mac) => {
 -                    attr::mark_used(attr);
 -                    fld.cx.bt_push(ExpnInfo {
 -                        call_site: attr.span,
 -                        callee: NameAndSpan {
 -                            format: MacroAttribute(mname),
 -                            span: Some(attr.span),
 -                            // attributes can do whatever they like,
 -                            // for now
 -                            allow_internal_unstable: true,
 -                        }
 -                    });
 -                    it = mac.expand(fld.cx, attr.span, &attr.node.value, it);
 -                    fld.cx.bt_pop();
 +fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
 +    let mut multi_modifier = None;
 +    item = item.map_attrs(|mut attrs| {
 +        for i in 0..attrs.len() {
 +            if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) {
 +                if let MultiModifier(..) = *extension {
 +                    multi_modifier = Some((attrs.remove(i), extension));
 +                    break;
                  }
 -                _ => unreachable!()
 -            },
 -            _ => unreachable!()
 +            }
          }
 -    }
 +        attrs
 +    });
  
 -    // Expansion may have added new ItemKind::Modifiers.
 -    expand_item_multi_modifier(it, fld)
 +    match multi_modifier {
 +        None => expand_multi_modified(item, fld),
 +        Some((attr, extension)) => match *extension {
 +            MultiModifier(ref mac) => {
 +                attr::mark_used(&attr);
 +                fld.cx.bt_push(ExpnInfo {
 +                    call_site: attr.span,
 +                    callee: NameAndSpan {
 +                        format: MacroAttribute(intern(&attr.name())),
 +                        span: Some(attr.span),
 +                        // attributes can do whatever they like, for now
 +                        allow_internal_unstable: true,
 +                    }
 +                });
 +                let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item);
 +                fld.cx.bt_pop();
 +                modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect()
 +            }
 +            _ => unreachable!(),
 +        }
 +    }
  }
  
  fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
      }
  }
  
 +fn expand_trait_item(ti: ast::TraitItem, fld: &mut MacroExpander)
 +                     -> SmallVector<ast::TraitItem> {
 +    match ti.node {
 +        ast::TraitItemKind::Method(_, Some(_)) => {
 +            SmallVector::one(ast::TraitItem {
 +                id: ti.id,
 +                ident: ti.ident,
 +                attrs: ti.attrs,
 +                node: match ti.node  {
 +                    ast::TraitItemKind::Method(sig, Some(body)) => {
 +                        let (sig, body) = expand_and_rename_method(sig, body, fld);
 +                        ast::TraitItemKind::Method(sig, Some(body))
 +                    }
 +                    _ => unreachable!()
 +                },
 +                span: ti.span,
 +            })
 +        }
 +        ast::TraitItemKind::Macro(mac) => {
 +            expand_mac_invoc(mac, None, ti.attrs, ti.span, fld)
 +        }
 +        _ => fold::noop_fold_trait_item(ti, fld)
 +    }
 +}
 +
  /// Given a fn_decl and a block and a MacroExpander, expand the fn_decl, then use the
  /// PatIdents in its arguments to perform renaming in the FnDecl and
  /// the block, returning both the new FnDecl and the new Block.
@@@ -964,9 -1002,9 +955,9 @@@ impl<'a, 'b> MacroExpander<'a, 'b> 
              at_crate_root: bool,
          }
  
 -        impl<'a, 'b, 'v> Visitor<'v> for MacroLoadingVisitor<'a, 'b> {
 -            fn visit_mac(&mut self, _: &'v ast::Mac) {}
 -            fn visit_item(&mut self, item: &'v ast::Item) {
 +        impl<'a, 'b> Visitor for MacroLoadingVisitor<'a, 'b> {
 +            fn visit_mac(&mut self, _: &ast::Mac) {}
 +            fn visit_item(&mut self, item: &ast::Item) {
                  if let ast::ItemKind::ExternCrate(..) = item.node {
                      // We need to error on `#[macro_use] extern crate` when it isn't at the
                      // crate root, because `$crate` won't work properly.
                      self.at_crate_root = at_crate_root;
                  }
              }
 -            fn visit_block(&mut self, block: &'v ast::Block) {
 +            fn visit_block(&mut self, block: &ast::Block) {
                  let at_crate_root = ::std::mem::replace(&mut self.at_crate_root, false);
                  visit::walk_block(self, block);
                  self.at_crate_root = at_crate_root;
@@@ -1006,7 -1044,7 +997,7 @@@ impl<'a, 'b> Folder for MacroExpander<'
      fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
          expr.and_then(|expr| match expr.node {
              ast::ExprKind::Mac(mac) =>
 -                expand_mac_invoc(mac, None, expr.attrs.into_attr_vec(), expr.span, self),
 +                expand_mac_invoc(mac, None, expr.attrs.into(), expr.span, self),
              _ => Some(expand_expr(expr, self)),
          })
      }
                  result = expand_item(item, self);
                  self.pop_mod_path();
              } else {
 -                let filename = if inner != codemap::DUMMY_SP {
 +                let filename = if inner != syntax_pos::DUMMY_SP {
                      Some(self.cx.parse_sess.codemap().span_to_filename(inner))
                  } else { None };
                  let orig_filename = replace(&mut self.cx.filename, filename);
@@@ -1186,7 -1224,8 +1177,7 @@@ impl Folder for Marker 
          Spanned {
              node: Mac_ {
                  path: self.fold_path(node.path),
 -                tts: self.fold_tts(&node.tts),
 -                ctxt: mtwt::apply_mark(self.mark, node.ctxt),
 +                tts: self.fold_tts(node.tts),
              },
              span: self.new_span(span),
          }
  }
  
  // apply a given mark to the given token trees. Used prior to expansion of a macro.
 -fn mark_tts(tts: &[TokenTree], m: Mrk) -> Vec<TokenTree> {
 +fn mark_tts(tts: Vec<TokenTree>, m: Mrk) -> Vec<TokenTree> {
      noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None})
  }
  
@@@ -1212,7 -1251,7 +1203,7 @@@ mod tests 
      use super::{PatIdentFinder, IdentRenamer, PatIdentRenamer, ExpansionConfig};
      use ast;
      use ast::Name;
 -    use codemap;
 +    use syntax_pos;
      use ext::base::{ExtCtxt, DummyMacroLoader};
      use ext::mtwt;
      use fold::Folder;
          path_accumulator: Vec<ast::Path> ,
      }
  
 -    impl<'v> Visitor<'v> for PathExprFinderContext {
 +    impl Visitor for PathExprFinderContext {
          fn visit_expr(&mut self, expr: &ast::Expr) {
              if let ast::ExprKind::Path(None, ref p) = expr.node {
                  self.path_accumulator.push(p.clone());
          ident_accumulator: Vec<ast::Ident>
      }
  
 -    impl<'v> Visitor<'v> for IdentFinder {
 -        fn visit_ident(&mut self, _: codemap::Span, id: ast::Ident){
 +    impl Visitor for IdentFinder {
 +        fn visit_ident(&mut self, _: syntax_pos::Span, id: ast::Ident){
              self.ident_accumulator.push(id);
          }
      }
index 3dc7c92f0160953152bc38bc9fee86d29675da4e,74a88842d22c281f38dbc55be3ad0c2d2ee4cb68..68527b0797d5b6031da5ca6dcc4a2d9eb2c24341
@@@ -8,8 -8,8 +8,8 @@@
  // option. This file may not be copied, modified, or distributed
  // except according to those terms.
  
 -use ast::{self, Arg, Arm, Block, Expr, Item, Pat, Stmt, TokenTree, Ty};
 -use codemap::Span;
 +use ast::{self, Arg, Arm, Block, Expr, Item, Pat, Stmt, Ty};
 +use syntax_pos::Span;
  use ext::base::ExtCtxt;
  use ext::base;
  use ext::build::AstBuilder;
@@@ -17,7 -17,6 +17,7 @@@ use parse::parser::{Parser, PathStyle}
  use parse::token::*;
  use parse::token;
  use ptr::P;
 +use tokenstream::{self, TokenTree};
  
  /// Quasiquoting works via token trees.
  ///
@@@ -32,12 -31,12 +32,12 @@@ pub mod rt 
      use ext::base::ExtCtxt;
      use parse::{self, token, classify};
      use ptr::P;
 -    use std::rc::Rc;
  
 -    use ast::TokenTree;
 +    use tokenstream::{self, TokenTree};
  
      pub use parse::new_parser_from_tts;
 -    pub use codemap::{BytePos, Span, dummy_spanned, DUMMY_SP};
 +    pub use syntax_pos::{BytePos, Span, DUMMY_SP};
 +    pub use codemap::{dummy_spanned};
  
      pub trait ToTokens {
          fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
              if self.node.style == ast::AttrStyle::Inner {
                  r.push(TokenTree::Token(self.span, token::Not));
              }
 -            r.push(TokenTree::Delimited(self.span, Rc::new(ast::Delimited {
 +            r.push(TokenTree::Delimited(self.span, tokenstream::Delimited {
                  delim: token::Bracket,
                  open_span: self.span,
                  tts: self.node.value.to_tokens(cx),
                  close_span: self.span,
 -            })));
 +            }));
              r
          }
      }
  
      impl ToTokens for () {
          fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
 -            vec![TokenTree::Delimited(DUMMY_SP, Rc::new(ast::Delimited {
 +            vec![TokenTree::Delimited(DUMMY_SP, tokenstream::Delimited {
                  delim: token::Paren,
                  open_span: DUMMY_SP,
                  tts: vec![],
                  close_span: DUMMY_SP,
 -            }))]
 +            })]
          }
      }
  
                  id: ast::DUMMY_NODE_ID,
                  node: ast::ExprKind::Lit(P(self.clone())),
                  span: DUMMY_SP,
 -                attrs: None,
 +                attrs: ast::ThinVec::new(),
              }).to_tokens(cx)
          }
      }
                          id: ast::DUMMY_NODE_ID,
                          node: ast::ExprKind::Lit(P(dummy_spanned(lit))),
                          span: DUMMY_SP,
 -                        attrs: None,
 +                        attrs: ast::ThinVec::new(),
                      });
                      if *self >= 0 {
                          return lit.to_tokens(cx);
                          id: ast::DUMMY_NODE_ID,
                          node: ast::ExprKind::Unary(ast::UnOp::Neg, lit),
                          span: DUMMY_SP,
 -                        attrs: None,
 +                        attrs: ast::ThinVec::new(),
                      }).to_tokens(cx)
                  }
              }
@@@ -513,10 -512,8 +513,8 @@@ pub fn expand_quote_matcher(cx: &mut Ex
      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)
@@@ -549,7 -546,7 +547,7 @@@ fn mk_name(cx: &ExtCtxt, sp: Span, iden
  }
  
  fn mk_tt_path(cx: &ExtCtxt, sp: Span, name: &str) -> P<ast::Expr> {
 -    let idents = vec!(id_ext("syntax"), id_ext("ast"), id_ext("TokenTree"), id_ext(name));
 +    let idents = vec!(id_ext("syntax"), id_ext("tokenstream"), id_ext("TokenTree"), id_ext(name));
      cx.expr_path(cx.path_global(sp, idents))
  }
  
@@@ -766,19 -763,20 +764,20 @@@ fn statements_mk_tt(cx: &ExtCtxt, tt: &
              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),
              };
              let e_op = match seq.op {
 -                ast::KleeneOp::ZeroOrMore => "ZeroOrMore",
 -                ast::KleeneOp::OneOrMore => "OneOrMore",
 +                tokenstream::KleeneOp::ZeroOrMore => "ZeroOrMore",
 +                tokenstream::KleeneOp::OneOrMore => "OneOrMore",
              };
              let e_op_idents = vec![
                  id_ext("syntax"),
 -                id_ext("ast"),
 +                id_ext("tokenstream"),
                  id_ext("KleeneOp"),
                  id_ext(e_op),
              ];
                                cx.field_imm(sp, id_ext("op"), e_op),
                                cx.field_imm(sp, id_ext("num_captures"),
                                                 cx.expr_usize(sp, seq.num_captures))];
 -            let seq_path = vec![id_ext("syntax"), id_ext("ast"), id_ext("SequenceRepetition")];
 +            let seq_path = vec![id_ext("syntax"),
 +                                id_ext("tokenstream"),
 +                                id_ext("SequenceRepetition")];
              let e_seq_struct = cx.expr_struct(sp, cx.path_global(sp, seq_path), fields);
 -            let e_rc_new = cx.expr_call_global(sp, vec![id_ext("std"),
 -                                                        id_ext("rc"),
 -                                                        id_ext("Rc"),
 -                                                        id_ext("new")],
 -                                                   vec![e_seq_struct]);
              let e_tok = cx.expr_call(sp,
                                       mk_tt_path(cx, sp, "Sequence"),
 -                                     vec!(e_sp, e_rc_new));
 +                                     vec!(e_sp, e_seq_struct));
              let e_push =
                  cx.expr_method_call(sp,
                                      cx.expr_ident(sp, id_ext("tt")),
@@@ -882,10 -883,8 +881,8 @@@ fn expand_tts(cx: &ExtCtxt, sp: Span, t
  
      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 -898,14 +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 --combined src/libsyntax/fold.rs
index b2b286c9b1409d008111ae30a097b99da0dc8446,8647937027b40b64844b1675cea6c042df0c3a46..6789e7be058bfcd7177991c3e2bb7c0b5a9c7176
  
  use ast::*;
  use ast;
 -use attr::{ThinAttributes, ThinAttributesExt};
 -use codemap::{respan, Span, Spanned};
 +use syntax_pos::Span;
 +use codemap::{Spanned, respan};
  use parse::token::{self, keywords};
  use ptr::P;
 +use tokenstream::*;
  use util::small_vector::SmallVector;
  use util::move_map::MoveMap;
  
 -use std::rc::Rc;
 -
  pub trait Folder : Sized {
      // Any additions to this trait should happen in form
      // of a call to a public `noop_*` function that only calls
          noop_fold_pat(p, self)
      }
  
 -    fn fold_decl(&mut self, d: P<Decl>) -> SmallVector<P<Decl>> {
 -        noop_fold_decl(d, self)
 -    }
 -
      fn fold_expr(&mut self, e: P<Expr>) -> P<Expr> {
          e.map(|e| noop_fold_expr(e, self))
      }
          noop_fold_ty_params(tps, self)
      }
  
 -    fn fold_tt(&mut self, tt: &TokenTree) -> TokenTree {
 +    fn fold_tt(&mut self, tt: TokenTree) -> TokenTree {
          noop_fold_tt(tt, self)
      }
  
 -    fn fold_tts(&mut self, tts: &[TokenTree]) -> Vec<TokenTree> {
 +    fn fold_tts(&mut self, tts: Vec<TokenTree>) -> Vec<TokenTree> {
          noop_fold_tts(tts, self)
      }
  
@@@ -331,8 -336,8 +331,8 @@@ pub fn fold_attrs<T: Folder>(attrs: Vec
      attrs.move_flat_map(|x| fld.fold_attribute(x))
  }
  
 -pub fn fold_thin_attrs<T: Folder>(attrs: ThinAttributes, fld: &mut T) -> ThinAttributes {
 -    attrs.map_thin_attrs(|v| fold_attrs(v, fld))
 +pub fn fold_thin_attrs<T: Folder>(attrs: ThinVec<Attribute>, fld: &mut T) -> ThinVec<Attribute> {
 +    fold_attrs(attrs.into(), fld).into()
  }
  
  pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
      }
  }
  
 -pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
 -    d.and_then(|Spanned {node, span}| match node {
 -        DeclKind::Local(l) => SmallVector::one(P(Spanned {
 -            node: DeclKind::Local(fld.fold_local(l)),
 -            span: fld.new_span(span)
 -        })),
 -        DeclKind::Item(it) => fld.fold_item(it).into_iter().map(|i| P(Spanned {
 -            node: DeclKind::Item(i),
 -            span: fld.new_span(span)
 -        })).collect()
 -    })
 -}
 -
  pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
      TypeBinding {
          id: fld.new_id(b.id),
@@@ -480,7 -498,7 +480,7 @@@ pub fn noop_fold_local<T: Folder>(l: P<
          pat: fld.fold_pat(pat),
          init: init.map(|e| fld.fold_expr(e)),
          span: fld.new_span(span),
 -        attrs: attrs.map_thin_attrs(|v| fold_attrs(v, fld)),
 +        attrs: fold_attrs(attrs.into(), fld).into(),
      })
  }
  
@@@ -501,7 -519,8 +501,7 @@@ pub fn noop_fold_mac<T: Folder>(Spanne
      Spanned {
          node: Mac_ {
              path: fld.fold_path(node.path),
 -            tts: fld.fold_tts(&node.tts),
 -            ctxt: node.ctxt,
 +            tts: fld.fold_tts(node.tts),
          },
          span: fld.new_span(span)
      }
@@@ -528,26 -547,34 +528,26 @@@ pub fn noop_fold_arg<T: Folder>(Arg {id
      }
  }
  
 -pub fn noop_fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree {
 -    match *tt {
 +pub fn noop_fold_tt<T: Folder>(tt: TokenTree, fld: &mut T) -> TokenTree {
 +    match tt {
          TokenTree::Token(span, ref tok) =>
              TokenTree::Token(span, fld.fold_token(tok.clone())),
 -        TokenTree::Delimited(span, ref delimed) => {
 -            TokenTree::Delimited(span, Rc::new(
 -                            Delimited {
 -                                delim: delimed.delim,
 -                                open_span: delimed.open_span,
 -                                tts: fld.fold_tts(&delimed.tts),
 -                                close_span: delimed.close_span,
 -                            }
 -                        ))
 -        },
 -        TokenTree::Sequence(span, ref seq) =>
 -            TokenTree::Sequence(span,
 -                       Rc::new(SequenceRepetition {
 -                           tts: fld.fold_tts(&seq.tts),
 -                           separator: seq.separator.clone().map(|tok| fld.fold_token(tok)),
 -                           ..**seq
 -                       })),
 +        TokenTree::Delimited(span, delimed) => TokenTree::Delimited(span, Delimited {
 +            delim: delimed.delim,
 +            open_span: delimed.open_span,
 +            tts: fld.fold_tts(delimed.tts),
 +            close_span: delimed.close_span,
 +        }),
 +        TokenTree::Sequence(span, seq) => TokenTree::Sequence(span, SequenceRepetition {
 +            tts: fld.fold_tts(seq.tts),
 +            separator: seq.separator.clone().map(|tok| fld.fold_token(tok)),
 +            ..seq
 +        }),
      }
  }
  
 -pub fn noop_fold_tts<T: Folder>(tts: &[TokenTree], fld: &mut T) -> Vec<TokenTree> {
 -    // FIXME: Does this have to take a tts slice?
 -    // Could use move_map otherwise...
 -    tts.iter().map(|tt| fld.fold_tt(tt)).collect()
 +pub fn noop_fold_tts<T: Folder>(tts: Vec<TokenTree>, fld: &mut T) -> Vec<TokenTree> {
 +    tts.move_map(|tt| fld.fold_tt(tt))
  }
  
  // apply ident folder if it's an ident, apply other folds to interpolated nodes
@@@ -605,7 -632,7 +605,7 @@@ pub fn noop_fold_interpolated<T: Folder
              token::NtIdent(Box::new(Spanned::<Ident>{node: fld.fold_ident(id.node), ..*id})),
          token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)),
          token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))),
 -        token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))),
 +        token::NtTT(tt) => token::NtTT(tt.map(|tt| fld.fold_tt(tt))),
          token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)),
          token::NtImplItem(arm) =>
              token::NtImplItem(arm.map(|arm| fld.fold_impl_item(arm)
@@@ -818,10 -845,9 +818,9 @@@ fn noop_fold_bounds<T: Folder>(bounds: 
  }
  
  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),
      })
@@@ -918,9 -944,6 +917,9 @@@ pub fn noop_fold_trait_item<T: Folder>(
                  TraitItemKind::Type(folder.fold_bounds(bounds),
                                default.map(|x| folder.fold_ty(x)))
              }
 +            ast::TraitItemKind::Macro(mac) => {
 +                TraitItemKind::Macro(folder.fold_mac(mac))
 +            }
          },
          span: folder.new_span(i.span)
      })
@@@ -1064,11 -1087,12 +1063,11 @@@ pub fn noop_fold_pat<T: Folder>(p: P<Pa
                  PatKind::TupleStruct(folder.fold_path(pth),
                          pats.move_map(|x| folder.fold_pat(x)), ddpos)
              }
 -            PatKind::Path(pth) => {
 -                PatKind::Path(folder.fold_path(pth))
 -            }
 -            PatKind::QPath(qself, pth) => {
 -                let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself};
 -                PatKind::QPath(qself, folder.fold_path(pth))
 +            PatKind::Path(opt_qself, pth) => {
 +                let opt_qself = opt_qself.map(|qself| {
 +                    QSelf { ty: folder.fold_ty(qself.ty), position: qself.position }
 +                });
 +                PatKind::Path(opt_qself, folder.fold_path(pth))
              }
              PatKind::Struct(pth, fields, etc) => {
                  let pth = folder.fold_path(pth);
@@@ -1230,7 -1254,7 +1229,7 @@@ pub fn noop_fold_expr<T: Folder>(Expr {
                  respan(folder.new_span(label.span),
                         folder.fold_ident(label.node)))
              ),
 -            ExprKind::Again(opt_ident) => ExprKind::Again(opt_ident.map(|label|
 +            ExprKind::Continue(opt_ident) => ExprKind::Continue(opt_ident.map(|label|
                  respan(folder.new_span(label.span),
                         folder.fold_ident(label.node)))
              ),
              ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
          },
          span: folder.new_span(span),
 -        attrs: attrs.map_thin_attrs(|v| fold_attrs(v, folder)),
 +        attrs: fold_attrs(attrs.into(), folder).into(),
      }
  }
  
@@@ -1287,50 -1311,44 +1286,50 @@@ pub fn noop_fold_exprs<T: Folder>(es: V
      es.move_flat_map(|e| folder.fold_opt_expr(e))
  }
  
 -pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
 +pub fn noop_fold_stmt<T: Folder>(Stmt {node, span, id}: Stmt, folder: &mut T)
                                   -> SmallVector<Stmt> {
 +    let id = folder.new_id(id);
      let span = folder.new_span(span);
 +
      match node {
 -        StmtKind::Decl(d, id) => {
 -            let id = folder.new_id(id);
 -            folder.fold_decl(d).into_iter().map(|d| Spanned {
 -                node: StmtKind::Decl(d, id),
 -                span: span
 -            }).collect()
 -        }
 -        StmtKind::Expr(e, id) => {
 -            let id = folder.new_id(id);
 -            if let Some(e) = folder.fold_opt_expr(e) {
 -                SmallVector::one(Spanned {
 -                    node: StmtKind::Expr(e, id),
 -                    span: span
 +        StmtKind::Local(local) => SmallVector::one(Stmt {
 +            id: id,
 +            node: StmtKind::Local(folder.fold_local(local)),
 +            span: span,
 +        }),
 +        StmtKind::Item(item) => folder.fold_item(item).into_iter().map(|item| Stmt {
 +            id: id,
 +            node: StmtKind::Item(item),
 +            span: span,
 +        }).collect(),
 +        StmtKind::Expr(expr) => {
 +            if let Some(expr) = folder.fold_opt_expr(expr) {
 +                SmallVector::one(Stmt {
 +                    id: id,
 +                    node: StmtKind::Expr(expr),
 +                    span: span,
                  })
              } else {
                  SmallVector::zero()
              }
          }
 -        StmtKind::Semi(e, id) => {
 -            let id = folder.new_id(id);
 -            if let Some(e) = folder.fold_opt_expr(e) {
 -                SmallVector::one(Spanned {
 -                    node: StmtKind::Semi(e, id),
 -                    span: span
 +        StmtKind::Semi(expr) => {
 +            if let Some(expr) = folder.fold_opt_expr(expr) {
 +                SmallVector::one(Stmt {
 +                    id: id,
 +                    node: StmtKind::Semi(expr),
 +                    span: span,
                  })
              } else {
                  SmallVector::zero()
              }
          }
 -        StmtKind::Mac(mac, semi, attrs) => SmallVector::one(Spanned {
 -            node: StmtKind::Mac(mac.map(|m| folder.fold_mac(m)),
 -                                semi,
 -                                attrs.map_thin_attrs(|v| fold_attrs(v, folder))),
 -            span: span
 +        StmtKind::Mac(mac) => SmallVector::one(Stmt {
 +            id: id,
 +            node: StmtKind::Mac(mac.map(|(mac, semi, attrs)| {
 +                (folder.fold_mac(mac), semi, fold_attrs(attrs.into(), folder).into())
 +            })),
 +            span: span,
          })
      }
  }
index 0c5a672dfbc9ee460768139d1a4c6f245f0f57ac,f79d6e8421a7919f1e16754107d6f151442d88ce..bbcc044d43c6b74b8701924847df75867f0a8ec6
  //! The main parser interface
  
  use ast;
 -use codemap::{self, Span, CodeMap, FileMap};
 +use codemap::CodeMap;
 +use syntax_pos::{self, Span, FileMap};
  use errors::{Handler, ColorConfig, DiagnosticBuilder};
  use parse::parser::Parser;
  use parse::token::InternedString;
  use ptr::P;
  use str::char_at;
 +use tokenstream;
  
  use std::cell::RefCell;
  use std::iter;
@@@ -162,7 -160,7 +162,7 @@@ pub fn parse_tts_from_source_str<'a>(na
                                       source: String,
                                       cfg: ast::CrateConfig,
                                       sess: &'a ParseSess)
 -                                     -> PResult<'a, Vec<ast::TokenTree>> {
 +                                     -> PResult<'a, Vec<tokenstream::TokenTree>> {
      let mut p = new_parser_from_source_str(
          sess,
          cfg,
@@@ -213,8 -211,8 +213,8 @@@ pub fn filemap_to_parser<'a>(sess: &'a 
      let end_pos = filemap.end_pos;
      let mut parser = tts_to_parser(sess, filemap_to_tts(sess, filemap), cfg);
  
 -    if parser.token == token::Eof && parser.span == codemap::DUMMY_SP {
 -        parser.span = codemap::mk_sp(end_pos, end_pos);
 +    if parser.token == token::Eof && parser.span == syntax_pos::DUMMY_SP {
 +        parser.span = syntax_pos::mk_sp(end_pos, end_pos);
      }
  
      parser
  // compiler expands into it
  pub fn new_parser_from_tts<'a>(sess: &'a ParseSess,
                                 cfg: ast::CrateConfig,
 -                               tts: Vec<ast::TokenTree>) -> Parser<'a> {
 +                               tts: Vec<tokenstream::TokenTree>) -> Parser<'a> {
      tts_to_parser(sess, tts, cfg)
  }
  
@@@ -249,7 -247,7 +249,7 @@@ fn file_to_filemap(sess: &ParseSess, pa
  
  /// Given a filemap, produce a sequence of token-trees
  pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
 -    -> Vec<ast::TokenTree> {
 +    -> Vec<tokenstream::TokenTree> {
      // it appears to me that the cfg doesn't matter here... indeed,
      // parsing tt's probably shouldn't require a parser at all.
      let cfg = Vec::new();
  
  /// Given tts and cfg, produce a parser
  pub fn tts_to_parser<'a>(sess: &'a ParseSess,
 -                         tts: Vec<ast::TokenTree>,
 +                         tts: Vec<tokenstream::TokenTree>,
                           cfg: ast::CrateConfig) -> Parser<'a> {
      let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts);
      let mut p = Parser::new(sess, cfg, Box::new(trdr));
@@@ -662,9 -660,9 +662,9 @@@ pub fn integer_lit(s: &str
  #[cfg(test)]
  mod tests {
      use super::*;
 -    use std::rc::Rc;
 -    use codemap::{Span, BytePos, Pos, Spanned, NO_EXPANSION};
 -    use ast::{self, TokenTree, PatKind};
 +    use syntax_pos::{Span, BytePos, Pos, NO_EXPANSION};
 +    use codemap::Spanned;
 +    use ast::{self, PatKind};
      use abi::Abi;
      use attr::{first_attr_value_str_by_name, AttrMetaMethods};
      use parse;
      use parse::token::{str_to_ident};
      use print::pprust::item_to_string;
      use ptr::P;
 +    use tokenstream::{self, TokenTree};
      use util::parser_testing::{string_to_tts, string_to_parser};
      use util::parser_testing::{string_to_expr, string_to_item, string_to_stmt};
 +    use util::ThinVec;
  
 -    // produce a codemap::span
 +    // produce a syntax_pos::span
      fn sp(a: u32, b: u32) -> Span {
          Span {lo: BytePos(a), hi: BytePos(b), expn_id: NO_EXPANSION}
      }
                          ),
                      }),
                      span: sp(0, 1),
 -                    attrs: None,
 +                    attrs: ThinVec::new(),
                     }))
      }
  
                              )
                          }),
                      span: sp(0, 6),
 -                    attrs: None,
 +                    attrs: ThinVec::new(),
                     }))
      }
  
      #[test]
      fn string_to_tts_macro () {
          let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string());
 -        let tts: &[ast::TokenTree] = &tts[..];
 +        let tts: &[tokenstream::TokenTree] = &tts[..];
  
          match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) {
              (
                              )
                              if first_delimed.delim == token::Paren
                              && ident.name.as_str() == "a" => {},
 -                            _ => panic!("value 3: {:?}", **first_delimed),
 +                            _ => panic!("value 3: {:?}", *first_delimed),
                          }
                          let tts = &second_delimed.tts[..];
                          match (tts.len(), tts.get(0), tts.get(1)) {
                              )
                              if second_delimed.delim == token::Paren
                              && ident.name.as_str() == "a" => {},
 -                            _ => panic!("value 4: {:?}", **second_delimed),
 +                            _ => panic!("value 4: {:?}", *second_delimed),
                          }
                      },
 -                    _ => panic!("value 2: {:?}", **macro_delimed),
 +                    _ => panic!("value 2: {:?}", *macro_delimed),
                  }
              },
              _ => panic!("value: {:?}",tts),
              TokenTree::Token(sp(3, 4), token::Ident(str_to_ident("a"))),
              TokenTree::Delimited(
                  sp(5, 14),
 -                Rc::new(ast::Delimited {
 +                tokenstream::Delimited {
                      delim: token::DelimToken::Paren,
                      open_span: sp(5, 6),
                      tts: vec![
                          TokenTree::Token(sp(10, 13), token::Ident(str_to_ident("i32"))),
                      ],
                      close_span: sp(13, 14),
 -                })),
 +                }),
              TokenTree::Delimited(
                  sp(15, 21),
 -                Rc::new(ast::Delimited {
 +                tokenstream::Delimited {
                      delim: token::DelimToken::Brace,
                      open_span: sp(15, 16),
                      tts: vec![
                          TokenTree::Token(sp(18, 19), token::Semi),
                      ],
                      close_span: sp(20, 21),
 -                }))
 +                })
          ];
  
          assert_eq!(tts, expected);
                              ),
                          }),
                          span:sp(7,8),
 -                        attrs: None,
 +                        attrs: ThinVec::new(),
                      }))),
                      span:sp(0,8),
 -                    attrs: None,
 +                    attrs: ThinVec::new(),
                     }))
      }
  
      #[test] fn parse_stmt_1 () {
          assert!(string_to_stmt("b;".to_string()) ==
 -                   Some(Spanned{
 +                   Some(ast::Stmt {
                         node: ast::StmtKind::Expr(P(ast::Expr {
                             id: ast::DUMMY_NODE_ID,
                             node: ast::ExprKind::Path(None, ast::Path {
                                 ),
                              }),
                             span: sp(0,1),
 -                           attrs: None}),
 -                                           ast::DUMMY_NODE_ID),
 +                           attrs: ThinVec::new()})),
 +                       id: ast::DUMMY_NODE_ID,
                         span: sp(0,1)}))
  
      }
                                          }
                                      },
                                      P(ast::Block {
 -                                        stmts: vec!(Spanned{
 +                                        stmts: vec!(ast::Stmt {
                                              node: ast::StmtKind::Semi(P(ast::Expr{
                                                  id: ast::DUMMY_NODE_ID,
                                                  node: ast::ExprKind::Path(None,
                                                          ),
                                                        }),
                                                  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),
          struct PatIdentVisitor {
              spans: Vec<Span>
          }
 -        impl<'v> ::visit::Visitor<'v> for PatIdentVisitor {
 -            fn visit_pat(&mut self, p: &'v ast::Pat) {
 +        impl ::visit::Visitor for PatIdentVisitor {
 +            fn visit_pat(&mut self, p: &ast::Pat) {
                  match p.node {
                      PatKind::Ident(_ , ref spannedident, _) => {
                          self.spans.push(spannedident.span.clone());
index 83401011ed44e3b952e4aa4790ebc47b8ae5c927,dea6589fe7caeb348ab2813fb2ab536519ee4c79..813d90103b8878000bf4f103078bc3781c3e28dd
@@@ -16,8 -16,8 +16,8 @@@ use ast::{Mod, Arg, Arm, Attribute, Bin
  use ast::Block;
  use ast::{BlockCheckMode, CaptureBy};
  use ast::{Constness, Crate, CrateConfig};
 -use ast::{Decl, DeclKind, Defaultness};
 -use ast::{EMPTY_CTXT, EnumDef};
 +use ast::Defaultness;
 +use ast::EnumDef;
  use ast::{Expr, ExprKind, RangeLimits};
  use ast::{Field, FnDecl};
  use ast::{ForeignItem, ForeignItemKind, FunctionRetTy};
@@@ -33,14 -33,14 +33,14 @@@ use ast::{Stmt, StmtKind}
  use ast::{VariantData, StructField};
  use ast::StrStyle;
  use ast::SelfKind;
 -use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
 +use ast::{TraitItem, TraitRef};
  use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
  use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
  use ast::{Visibility, WhereClause};
 -use attr::{ThinAttributes, ThinAttributesExt, AttributesExt};
  use ast::{BinOpKind, UnOp};
  use ast;
 -use codemap::{self, Span, BytePos, Spanned, spanned, mk_sp, CodeMap};
 +use codemap::{self, CodeMap, Spanned, spanned};
 +use syntax_pos::{self, Span, BytePos, mk_sp};
  use errors::{self, DiagnosticBuilder};
  use ext::tt::macro_parser;
  use parse;
@@@ -55,8 -55,6 +55,8 @@@ use util::parser::{AssocOp, Fixity}
  use print::pprust;
  use ptr::P;
  use parse::PResult;
 +use tokenstream::{self, Delimited, SequenceRepetition, TokenTree};
 +use util::ThinVec;
  
  use std::collections::HashSet;
  use std::mem;
@@@ -122,7 -120,7 +122,7 @@@ macro_rules! maybe_whole_expr 
                          _ => unreachable!()
                      };
                      let span = $p.span;
 -                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), None))
 +                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new()))
                  }
                  token::Interpolated(token::NtBlock(_)) => {
                      // FIXME: The following avoids an issue with lexical borrowck scopes,
                          _ => unreachable!()
                      };
                      let span = $p.span;
 -                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), None))
 +                    Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new()))
                  }
                  _ => None
              };
@@@ -318,12 -316,12 +318,12 @@@ pub struct ModulePathError 
  
  pub enum LhsExpr {
      NotYetParsed,
 -    AttributesParsed(ThinAttributes),
 +    AttributesParsed(ThinVec<Attribute>),
      AlreadyParsed(P<Expr>),
  }
  
 -impl From<Option<ThinAttributes>> for LhsExpr {
 -    fn from(o: Option<ThinAttributes>) -> Self {
 +impl From<Option<ThinVec<Attribute>>> for LhsExpr {
 +    fn from(o: Option<ThinVec<Attribute>>) -> Self {
          if let Some(attrs) = o {
              LhsExpr::AttributesParsed(attrs)
          } else {
@@@ -346,7 -344,7 +346,7 @@@ impl<'a> Parser<'a> 
      {
          let tok0 = rdr.real_token();
          let span = tok0.sp;
 -        let filename = if span != codemap::DUMMY_SP {
 +        let filename = if span != syntax_pos::DUMMY_SP {
              Some(sess.codemap().span_to_filename(span))
          } else { None };
          let placeholder = TokenAndSpan {
      }
  
      /// Parse the items in a trait declaration
 -    pub fn parse_trait_items(&mut self) -> PResult<'a,  Vec<TraitItem>> {
 -        self.parse_unspanned_seq(
 -            &token::OpenDelim(token::Brace),
 -            &token::CloseDelim(token::Brace),
 -            SeqSep::none(),
 -            |p| -> PResult<'a, TraitItem> {
 -            maybe_whole!(no_clone_from_p p, NtTraitItem);
 -            let mut attrs = p.parse_outer_attributes()?;
 -            let lo = p.span.lo;
 -
 -            let (name, node) = if p.eat_keyword(keywords::Type) {
 -                let TyParam {ident, bounds, default, ..} = p.parse_ty_param()?;
 -                p.expect(&token::Semi)?;
 -                (ident, TraitItemKind::Type(bounds, default))
 -            } else if p.is_const_item() {
 -                p.expect_keyword(keywords::Const)?;
 -                let ident = p.parse_ident()?;
 -                p.expect(&token::Colon)?;
 -                let ty = p.parse_ty_sum()?;
 -                let default = if p.check(&token::Eq) {
 -                    p.bump();
 -                    let expr = p.parse_expr()?;
 -                    p.commit_expr_expecting(&expr, token::Semi)?;
 -                    Some(expr)
 -                } else {
 -                    p.expect(&token::Semi)?;
 -                    None
 -                };
 -                (ident, TraitItemKind::Const(ty, default))
 +    pub fn parse_trait_item(&mut self) -> PResult<'a, TraitItem> {
 +        maybe_whole!(no_clone_from_p self, NtTraitItem);
 +        let mut attrs = self.parse_outer_attributes()?;
 +        let lo = self.span.lo;
 +
 +        let (name, node) = if self.eat_keyword(keywords::Type) {
 +            let TyParam {ident, bounds, default, ..} = self.parse_ty_param()?;
 +            self.expect(&token::Semi)?;
 +            (ident, TraitItemKind::Type(bounds, default))
 +        } else if self.is_const_item() {
 +                self.expect_keyword(keywords::Const)?;
 +            let ident = self.parse_ident()?;
 +            self.expect(&token::Colon)?;
 +            let ty = self.parse_ty_sum()?;
 +            let default = if self.check(&token::Eq) {
 +                self.bump();
 +                let expr = self.parse_expr()?;
 +                self.commit_expr_expecting(&expr, token::Semi)?;
 +                Some(expr)
 +            } else {
 +                self.expect(&token::Semi)?;
 +                None
 +            };
 +            (ident, TraitItemKind::Const(ty, default))
 +        } else if !self.token.is_any_keyword()
 +            && self.look_ahead(1, |t| *t == token::Not)
 +            && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren))
 +                || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) {
 +                // trait item macro.
 +                // code copied from parse_macro_use_or_failure... abstraction!
 +                let lo = self.span.lo;
 +                let pth = self.parse_ident_into_path()?;
 +                self.expect(&token::Not)?;
 +
 +                // eat a matched-delimiter token tree:
 +                let delim = self.expect_open_delim()?;
 +                let tts = self.parse_seq_to_end(&token::CloseDelim(delim),
 +                                             SeqSep::none(),
 +                                             |pp| pp.parse_token_tree())?;
 +                let m_ = Mac_ { path: pth, tts: tts };
 +                let m: ast::Mac = codemap::Spanned { node: m_,
 +                                                     span: mk_sp(lo,
 +                                                                 self.last_span.hi) };
 +                if delim != token::Brace {
 +                    self.expect(&token::Semi)?
 +                }
 +                (keywords::Invalid.ident(), ast::TraitItemKind::Macro(m))
              } else {
 -                let (constness, unsafety, abi) = match p.parse_fn_front_matter() {
 +                let (constness, unsafety, abi) = match self.parse_fn_front_matter() {
                      Ok(cua) => cua,
                      Err(e) => {
                          loop {
 -                            match p.token {
 +                            match self.token {
                                  token::Eof => break,
 -
                                  token::CloseDelim(token::Brace) |
                                  token::Semi => {
 -                                    p.bump();
 +                                    self.bump();
                                      break;
                                  }
 -
                                  token::OpenDelim(token::Brace) => {
 -                                    p.parse_token_tree()?;
 +                                    self.parse_token_tree()?;
                                      break;
                                  }
 -
 -                                _ => p.bump()
 +                                _ => self.bump()
                              }
                          }
  
                      }
                  };
  
 -                let ident = p.parse_ident()?;
 -                let mut generics = p.parse_generics()?;
 +                let ident = self.parse_ident()?;
 +                let mut generics = self.parse_generics()?;
  
 -                let d = p.parse_fn_decl_with_self(|p: &mut Parser<'a>|{
 +                let d = self.parse_fn_decl_with_self(|p: &mut Parser<'a>|{
                      // This is somewhat dubious; We don't want to allow
                      // argument names to be left off if there is a
                      // definition...
                      p.parse_arg_general(false)
                  })?;
  
 -                generics.where_clause = p.parse_where_clause()?;
 +                generics.where_clause = self.parse_where_clause()?;
                  let sig = ast::MethodSig {
                      unsafety: unsafety,
                      constness: constness,
                      abi: abi,
                  };
  
 -                let body = match p.token {
 -                  token::Semi => {
 -                    p.bump();
 -                    debug!("parse_trait_methods(): parsing required method");
 -                    None
 -                  }
 -                  token::OpenDelim(token::Brace) => {
 -                    debug!("parse_trait_methods(): parsing provided method");
 -                    let (inner_attrs, body) =
 -                        p.parse_inner_attrs_and_block()?;
 -                    attrs.extend(inner_attrs.iter().cloned());
 -                    Some(body)
 -                  }
 +                let body = match self.token {
 +                    token::Semi => {
 +                        self.bump();
 +                        debug!("parse_trait_methods(): parsing required method");
 +                        None
 +                    }
 +                    token::OpenDelim(token::Brace) => {
 +                        debug!("parse_trait_methods(): parsing provided method");
 +                        let (inner_attrs, body) =
 +                            self.parse_inner_attrs_and_block()?;
 +                        attrs.extend(inner_attrs.iter().cloned());
 +                        Some(body)
 +                    }
  
 -                  _ => {
 -                      let token_str = p.this_token_to_string();
 -                      return Err(p.fatal(&format!("expected `;` or `{{`, found `{}`",
 -                                       token_str)[..]))
 -                  }
 +                    _ => {
 +                        let token_str = self.this_token_to_string();
 +                        return Err(self.fatal(&format!("expected `;` or `{{`, found `{}`",
 +                                                    token_str)[..]))
 +                    }
                  };
                  (ident, ast::TraitItemKind::Method(sig, body))
              };
 +        Ok(TraitItem {
 +            id: ast::DUMMY_NODE_ID,
 +            ident: name,
 +            attrs: attrs,
 +            node: node,
 +            span: mk_sp(lo, self.last_span.hi),
 +        })
 +    }
  
 -            Ok(TraitItem {
 -                id: ast::DUMMY_NODE_ID,
 -                ident: name,
 -                attrs: attrs,
 -                node: node,
 -                span: mk_sp(lo, p.last_span.hi),
 +
 +    /// Parse the items in a trait declaration
 +    pub fn parse_trait_items(&mut self) -> PResult<'a,  Vec<TraitItem>> {
 +        self.parse_unspanned_seq(
 +            &token::OpenDelim(token::Brace),
 +            &token::CloseDelim(token::Brace),
 +            SeqSep::none(),
 +            |p| -> PResult<'a, TraitItem> {
 +                p.parse_trait_item()
              })
 -        })
      }
  
      /// Parse a possibly mutable type
                                                  SeqSep::none(),
                                                  |p| p.parse_token_tree())?;
                  let hi = self.span.hi;
 -                TyKind::Mac(spanned(lo, hi, Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }))
 +                TyKind::Mac(spanned(lo, hi, Mac_ { path: path, tts: tts }))
              } else {
                  // NAMED TYPE
                  TyKind::Path(None, path)
          let lo = self.span.lo;
          let literal = P(self.parse_lit()?);
          let hi = self.last_span.hi;
 -        let expr = self.mk_expr(lo, hi, ExprKind::Lit(literal), None);
 +        let expr = self.mk_expr(lo, hi, ExprKind::Lit(literal), ThinVec::new());
  
          if minus_present {
              let minus_hi = self.last_span.hi;
              let unary = self.mk_unary(UnOp::Neg, expr);
 -            Ok(self.mk_expr(minus_lo, minus_hi, unary, None))
 +            Ok(self.mk_expr(minus_lo, minus_hi, unary, ThinVec::new()))
          } else {
              Ok(expr)
          }
          })
      }
  
 -    pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos,
 -                   node: ExprKind, attrs: ThinAttributes) -> P<Expr> {
 +    pub fn mk_expr(&mut self, lo: BytePos, hi: BytePos, node: ExprKind, attrs: ThinVec<Attribute>)
 +                   -> P<Expr> {
          P(Expr {
              id: ast::DUMMY_NODE_ID,
              node: node,
              span: mk_sp(lo, hi),
 -            attrs: attrs,
 +            attrs: attrs.into(),
          })
      }
  
      }
  
      pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos,
 -                       m: Mac_, attrs: ThinAttributes) -> P<Expr> {
 +                       m: Mac_, attrs: ThinVec<Attribute>) -> P<Expr> {
          P(Expr {
              id: ast::DUMMY_NODE_ID,
              node: ExprKind::Mac(codemap::Spanned {node: m, span: mk_sp(lo, hi)}),
          })
      }
  
 -    pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinAttributes) -> P<Expr> {
 +    pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec<Attribute>) -> P<Expr> {
          let span = &self.span;
          let lv_lit = P(codemap::Spanned {
              node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)),
          //
          // Therefore, prevent sub-parser from parsing
          // attributes by giving them a empty "already parsed" list.
 -        let mut attrs = None;
 +        let mut attrs = ThinVec::new();
  
          let lo = self.span.lo;
          let mut hi = self.span.hi;
              token::OpenDelim(token::Paren) => {
                  self.bump();
  
 -                let attrs = self.parse_inner_attributes()?
 -                    .into_thin_attrs()
 -                    .prepend(attrs);
 +                attrs.extend(self.parse_inner_attributes()?);
  
                  // (e) is parenthesized e
                  // (e,) is a tuple with only one field, e
              token::OpenDelim(token::Bracket) => {
                  self.bump();
  
 -                let inner_attrs = self.parse_inner_attributes()?
 -                    .into_thin_attrs();
 -                attrs.update(|attrs| attrs.append(inner_attrs));
 +                attrs.extend(self.parse_inner_attributes()?);
  
                  if self.check(&token::CloseDelim(token::Bracket)) {
                      // Empty vector.
                  }
                  if self.eat_keyword(keywords::Continue) {
                      let ex = if self.token.is_lifetime() {
 -                        let ex = ExprKind::Again(Some(Spanned{
 +                        let ex = ExprKind::Continue(Some(Spanned{
                              node: self.get_lifetime(),
                              span: self.span
                          }));
                          self.bump();
                          ex
                      } else {
 -                        ExprKind::Again(None)
 +                        ExprKind::Continue(None)
                      };
                      let hi = self.last_span.hi;
                      return Ok(self.mk_expr(lo, hi, ex, attrs));
  
                          return Ok(self.mk_mac_expr(lo,
                                                     hi,
 -                                                   Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT },
 +                                                   Mac_ { path: pth, tts: tts },
                                                     attrs));
                      }
                      if self.check(&token::OpenDelim(token::Brace)) {
                              let mut fields = Vec::new();
                              let mut base = None;
  
 -                            let attrs = attrs.append(
 -                                self.parse_inner_attributes()?
 -                                    .into_thin_attrs());
 +                            attrs.extend(self.parse_inner_attributes()?);
  
                              while self.token != token::CloseDelim(token::Brace) {
                                  if self.eat(&token::DotDot) {
      }
  
      fn parse_or_use_outer_attributes(&mut self,
 -                                     already_parsed_attrs: Option<ThinAttributes>)
 -                                     -> PResult<'a, ThinAttributes> {
 +                                     already_parsed_attrs: Option<ThinVec<Attribute>>)
 +                                     -> PResult<'a, ThinVec<Attribute>> {
          if let Some(attrs) = already_parsed_attrs {
              Ok(attrs)
          } else {
 -            self.parse_outer_attributes().map(|a| a.into_thin_attrs())
 +            self.parse_outer_attributes().map(|a| a.into())
          }
      }
  
      /// Parse a block or unsafe block
      pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode,
 -                            attrs: ThinAttributes)
 +                            outer_attrs: ThinVec<Attribute>)
                              -> PResult<'a, P<Expr>> {
  
 -        let outer_attrs = attrs;
          self.expect(&token::OpenDelim(token::Brace))?;
  
 -        let inner_attrs = self.parse_inner_attributes()?.into_thin_attrs();
 -        let attrs = outer_attrs.append(inner_attrs);
 +        let mut attrs = outer_attrs;
 +        attrs.extend(self.parse_inner_attributes()?);
  
          let blk = self.parse_block_tail(lo, blk_mode)?;
          return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), attrs));
  
      /// parse a.b or a(13) or a[4] or just a
      pub fn parse_dot_or_call_expr(&mut self,
 -                                  already_parsed_attrs: Option<ThinAttributes>)
 +                                  already_parsed_attrs: Option<ThinVec<Attribute>>)
                                    -> PResult<'a, P<Expr>> {
          let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
  
      pub fn parse_dot_or_call_expr_with(&mut self,
                                         e0: P<Expr>,
                                         lo: BytePos,
 -                                       attrs: ThinAttributes)
 +                                       mut attrs: ThinVec<Attribute>)
                                         -> PResult<'a, P<Expr>> {
          // Stitch the list of outer attributes onto the return value.
          // A little bit ugly, but the best way given the current code
          self.parse_dot_or_call_expr_with_(e0, lo)
          .map(|expr|
              expr.map(|mut expr| {
 -                expr.attrs.update(|a| a.prepend(attrs));
 +                attrs.extend::<Vec<_>>(expr.attrs.into());
 +                expr.attrs = attrs;
                  match expr.node {
                      ExprKind::If(..) | ExprKind::IfLet(..) => {
 -                        if !expr.attrs.as_attr_slice().is_empty() {
 +                        if !expr.attrs.is_empty() {
                              // Just point to the first attribute in there...
 -                            let span = expr.attrs.as_attr_slice()[0].span;
 +                            let span = expr.attrs[0].span;
  
                              self.span_err(span,
                                  "attributes are not yet allowed on `if` \
                  es.insert(0, self_value);
                  let id = spanned(ident_span.lo, ident_span.hi, ident);
                  let nd = self.mk_method_call(id, tys, es);
 -                self.mk_expr(lo, hi, nd, None)
 +                self.mk_expr(lo, hi, nd, ThinVec::new())
              }
              // Field access.
              _ => {
  
                  let id = spanned(ident_span.lo, ident_span.hi, ident);
                  let field = self.mk_field(self_value, id);
 -                self.mk_expr(lo, ident_span.hi, field, None)
 +                self.mk_expr(lo, ident_span.hi, field, ThinVec::new())
              }
          })
      }
              // expr?
              while self.eat(&token::Question) {
                  let hi = self.last_span.hi;
 -                e = self.mk_expr(lo, hi, ExprKind::Try(e), None);
 +                e = self.mk_expr(lo, hi, ExprKind::Try(e), ThinVec::new());
              }
  
              // expr.f
                          Some(n) => {
                              let id = spanned(dot, hi, n);
                              let field = self.mk_tup_field(e, id);
 -                            e = self.mk_expr(lo, hi, field, None);
 +                            e = self.mk_expr(lo, hi, field, ThinVec::new());
                          }
                          None => {
                              let last_span = self.last_span;
                  hi = self.last_span.hi;
  
                  let nd = self.mk_call(e, es);
 -                e = self.mk_expr(lo, hi, nd, None);
 +                e = self.mk_expr(lo, hi, nd, ThinVec::new());
                }
  
                // expr[...]
                  hi = self.span.hi;
                  self.commit_expr_expecting(&ix, token::CloseDelim(token::Bracket))?;
                  let index = self.mk_index(e, ix);
 -                e = self.mk_expr(lo, hi, index, None)
 +                e = self.mk_expr(lo, hi, index, ThinVec::new())
                }
                _ => return Ok(e)
              }
                      )?;
                      let (sep, repeat) = self.parse_sep_and_kleene_op()?;
                      let name_num = macro_parser::count_names(&seq);
 -                    return Ok(TokenTree::Sequence(mk_sp(sp.lo, seq_span.hi),
 -                                      Rc::new(SequenceRepetition {
 -                                          tts: seq,
 -                                          separator: sep,
 -                                          op: repeat,
 -                                          num_captures: name_num
 -                                      })));
 +                    return Ok(TokenTree::Sequence(mk_sp(sp.lo, seq_span.hi), SequenceRepetition {
 +                        tts: seq,
 +                        separator: sep,
 +                        op: repeat,
 +                        num_captures: name_num
 +                    }));
                  } else if self.token.is_keyword(keywords::Crate) {
                      self.bump();
                      return Ok(TokenTree::Token(sp, SpecialVarNt(SpecialMacroVar::CrateMacroVar)));
      /// Parse an optional separator followed by a Kleene-style
      /// repetition token (+ or *).
      pub fn parse_sep_and_kleene_op(&mut self)
 -                                   -> PResult<'a, (Option<token::Token>, ast::KleeneOp)> {
 -        fn parse_kleene_op<'a>(parser: &mut Parser<'a>) -> PResult<'a,  Option<ast::KleeneOp>> {
 +                                   -> PResult<'a, (Option<token::Token>, tokenstream::KleeneOp)> {
 +        fn parse_kleene_op<'a>(parser: &mut Parser<'a>) ->
 +          PResult<'a,  Option<tokenstream::KleeneOp>> {
              match parser.token {
                  token::BinOp(token::Star) => {
                      parser.bump();
 -                    Ok(Some(ast::KleeneOp::ZeroOrMore))
 +                    Ok(Some(tokenstream::KleeneOp::ZeroOrMore))
                  },
                  token::BinOp(token::Plus) => {
                      parser.bump();
 -                    Ok(Some(ast::KleeneOp::OneOrMore))
 +                    Ok(Some(tokenstream::KleeneOp::OneOrMore))
                  },
                  _ => Ok(None)
              }
                      _ => {}
                  }
  
 -                Ok(TokenTree::Delimited(span, Rc::new(Delimited {
 +                Ok(TokenTree::Delimited(span, Delimited {
                      delim: delim,
                      open_span: open_span,
                      tts: tts,
                      close_span: close_span,
 -                })))
 +                }))
              },
              _ => {
                  // invariants: the current token is not a left-delimiter,
  
      /// Parse a prefix-unary-operator expr
      pub fn parse_prefix_expr(&mut self,
 -                             already_parsed_attrs: Option<ThinAttributes>)
 +                             already_parsed_attrs: Option<ThinVec<Attribute>>)
                               -> PResult<'a, P<Expr>> {
          let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?;
          let lo = self.span.lo;
                  let blk = self.parse_block()?;
                  let span = blk.span;
                  hi = span.hi;
 -                let blk_expr = self.mk_expr(span.lo, span.hi, ExprKind::Block(blk),
 -                                            None);
 +                let blk_expr = self.mk_expr(span.lo, hi, ExprKind::Block(blk), ThinVec::new());
                  ExprKind::InPlace(place, blk_expr)
              }
              token::Ident(..) if self.token.is_keyword(keywords::Box) => {
      /// This parses an expression accounting for associativity and precedence of the operators in
      /// the expression.
      pub fn parse_assoc_expr(&mut self,
 -                            already_parsed_attrs: Option<ThinAttributes>)
 +                            already_parsed_attrs: Option<ThinVec<Attribute>>)
                              -> PResult<'a, P<Expr>> {
          self.parse_assoc_expr_with(0, already_parsed_attrs.into())
      }
              // Special cases:
              if op == AssocOp::As {
                  let rhs = self.parse_ty()?;
 -                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
 -                                   ExprKind::Cast(lhs, rhs), None);
 +                let (lo, hi) = (lhs_span.lo, rhs.span.hi);
 +                lhs = self.mk_expr(lo, hi, ExprKind::Cast(lhs, rhs), ThinVec::new());
                  continue
              } else if op == AssocOp::Colon {
                  let rhs = self.parse_ty()?;
 -                lhs = self.mk_expr(lhs_span.lo, rhs.span.hi,
 -                                   ExprKind::Type(lhs, rhs), None);
 +                let (lo, hi) = (lhs_span.lo, rhs.span.hi);
 +                lhs = self.mk_expr(lo, hi, ExprKind::Type(lhs, rhs), ThinVec::new());
                  continue
              } else if op == AssocOp::DotDot || op == AssocOp::DotDotDot {
                  // If we didn’t have to handle `x..`/`x...`, it would be pretty easy to
                  };
  
                  let r = try!(self.mk_range(Some(lhs), rhs, limits));
 -                lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, None);
 +                lhs = self.mk_expr(lhs_span.lo, rhs_span.hi, r, ThinVec::new());
                  break
              }
  
                  }),
              }?;
  
 +            let (lo, hi) = (lhs_span.lo, rhs.span.hi);
              lhs = match op {
                  AssocOp::Add | AssocOp::Subtract | AssocOp::Multiply | AssocOp::Divide |
                  AssocOp::Modulus | AssocOp::LAnd | AssocOp::LOr | AssocOp::BitXor |
                  AssocOp::Equal | AssocOp::Less | AssocOp::LessEqual | AssocOp::NotEqual |
                  AssocOp::Greater | AssocOp::GreaterEqual => {
                      let ast_op = op.to_ast_binop().unwrap();
 -                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                      let binary = self.mk_binary(codemap::respan(cur_op_span, ast_op), lhs, rhs);
 -                    self.mk_expr(lhs_span.lo, rhs_span.hi, binary, None)
 +                    self.mk_expr(lo, hi, binary, ThinVec::new())
                  }
                  AssocOp::Assign =>
 -                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::Assign(lhs, rhs), None),
 +                    self.mk_expr(lo, hi, ExprKind::Assign(lhs, rhs), ThinVec::new()),
                  AssocOp::Inplace =>
 -                    self.mk_expr(lhs_span.lo, rhs.span.hi, ExprKind::InPlace(lhs, rhs), None),
 +                    self.mk_expr(lo, hi, ExprKind::InPlace(lhs, rhs), ThinVec::new()),
                  AssocOp::AssignOp(k) => {
                      let aop = match k {
                          token::Plus =>    BinOpKind::Add,
                          token::Shl =>     BinOpKind::Shl,
                          token::Shr =>     BinOpKind::Shr,
                      };
 -                    let (lhs_span, rhs_span) = (lhs_span, rhs.span);
                      let aopexpr = self.mk_assign_op(codemap::respan(cur_op_span, aop), lhs, rhs);
 -                    self.mk_expr(lhs_span.lo, rhs_span.hi, aopexpr, None)
 +                    self.mk_expr(lo, hi, aopexpr, ThinVec::new())
                  }
                  AssocOp::As | AssocOp::Colon | AssocOp::DotDot | AssocOp::DotDotDot => {
                      self.bug("As, Colon, DotDot or DotDotDot branch reached")
  
      /// Parse prefix-forms of range notation: `..expr`, `..`, `...expr`
      fn parse_prefix_range_expr(&mut self,
 -                               already_parsed_attrs: Option<ThinAttributes>)
 +                               already_parsed_attrs: Option<ThinVec<Attribute>>)
                                 -> PResult<'a, P<Expr>> {
          debug_assert!(self.token == token::DotDot || self.token == token::DotDotDot);
          let tok = self.token.clone();
      }
  
      /// Parse an 'if' or 'if let' expression ('if' token already eaten)
 -    pub fn parse_if_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
 +    pub fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
          if self.check_keyword(keywords::Let) {
              return self.parse_if_let_expr(attrs);
          }
      }
  
      /// Parse an 'if let' expression ('if' token already eaten)
 -    pub fn parse_if_let_expr(&mut self, attrs: ThinAttributes)
 +    pub fn parse_if_let_expr(&mut self, attrs: ThinVec<Attribute>)
                               -> PResult<'a, P<Expr>> {
          let lo = self.last_span.lo;
          self.expect_keyword(keywords::Let)?;
      pub fn parse_lambda_expr(&mut self,
                               lo: BytePos,
                               capture_clause: CaptureBy,
 -                             attrs: ThinAttributes)
 +                             attrs: ThinVec<Attribute>)
                               -> PResult<'a, P<Expr>>
      {
          let decl = self.parse_fn_block_decl()?;
                  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,
                  })
              }
      // `else` token already eaten
      pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
          if self.eat_keyword(keywords::If) {
 -            return self.parse_if_expr(None);
 +            return self.parse_if_expr(ThinVec::new());
          } else {
              let blk = self.parse_block()?;
 -            return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), None));
 +            return Ok(self.mk_expr(blk.span.lo, blk.span.hi, ExprKind::Block(blk), ThinVec::new()));
          }
      }
  
      /// Parse a 'for' .. 'in' expression ('for' token already eaten)
      pub fn parse_for_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                            span_lo: BytePos,
 -                          attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
 +                          mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
          // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
  
          let pat = self.parse_pat()?;
          self.expect_keyword(keywords::In)?;
          let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?;
          let (iattrs, loop_block) = self.parse_inner_attrs_and_block()?;
 -        let attrs = attrs.append(iattrs.into_thin_attrs());
 +        attrs.extend(iattrs);
  
          let hi = self.last_span.hi;
  
      /// Parse a 'while' or 'while let' expression ('while' token already eaten)
      pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                              span_lo: BytePos,
 -                            attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
 +                            mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
          if self.token.is_keyword(keywords::Let) {
              return self.parse_while_let_expr(opt_ident, span_lo, attrs);
          }
          let cond = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?;
          let (iattrs, body) = self.parse_inner_attrs_and_block()?;
 -        let attrs = attrs.append(iattrs.into_thin_attrs());
 +        attrs.extend(iattrs);
          let hi = body.span.hi;
          return Ok(self.mk_expr(span_lo, hi, ExprKind::While(cond, body, opt_ident),
                                 attrs));
      /// Parse a 'while let' expression ('while' token already eaten)
      pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                                  span_lo: BytePos,
 -                                attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
 +                                mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
          self.expect_keyword(keywords::Let)?;
          let pat = self.parse_pat()?;
          self.expect(&token::Eq)?;
          let expr = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, None)?;
          let (iattrs, body) = self.parse_inner_attrs_and_block()?;
 -        let attrs = attrs.append(iattrs.into_thin_attrs());
 +        attrs.extend(iattrs);
          let hi = body.span.hi;
          return Ok(self.mk_expr(span_lo, hi, ExprKind::WhileLet(pat, expr, body, opt_ident), attrs));
      }
      // parse `loop {...}`, `loop` token already eaten
      pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                             span_lo: BytePos,
 -                           attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
 +                           mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
          let (iattrs, body) = self.parse_inner_attrs_and_block()?;
 -        let attrs = attrs.append(iattrs.into_thin_attrs());
 +        attrs.extend(iattrs);
          let hi = body.span.hi;
          Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs))
      }
  
      // `match` token already eaten
 -    fn parse_match_expr(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Expr>> {
 +    fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
          let match_span = self.last_span;
          let lo = self.last_span.lo;
          let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL,
              }
              return Err(e)
          }
 -        let attrs = attrs.append(
 -            self.parse_inner_attributes()?.into_thin_attrs());
 +        attrs.extend(self.parse_inner_attributes()?);
 +
          let mut arms: Vec<Arm> = Vec::new();
          while self.token != token::CloseDelim(token::Brace) {
              match self.parse_arm() {
  
      /// Parse an expression, subject to the given restrictions
      pub fn parse_expr_res(&mut self, r: Restrictions,
 -                          already_parsed_attrs: Option<ThinAttributes>)
 +                          already_parsed_attrs: Option<ThinVec<Attribute>>)
                            -> PResult<'a, P<Expr>> {
          self.with_res(r, |this| this.parse_assoc_expr(already_parsed_attrs))
      }
      }
  
      /// Parse the fields of a struct-like pattern
 -    fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPat>> , bool)> {
 +    fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPat>>, bool)> {
          let mut fields = Vec::new();
          let mut etc = false;
          let mut first = true;
              };
  
              fields.push(codemap::Spanned { span: mk_sp(lo, hi),
 -                                           node: ast::FieldPat { ident: fieldname,
 -                                                                 pat: subpat,
 -                                                                 is_shorthand: is_shorthand }});
 +                                              node: ast::FieldPat { ident: fieldname,
 +                                                                    pat: subpat,
 +                                                                    is_shorthand: is_shorthand }});
          }
          return Ok((fields, etc));
      }
                  (None, self.parse_path(PathStyle::Expr)?)
              };
              let hi = self.last_span.hi;
 -            Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), None))
 +            Ok(self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new()))
          } else {
              self.parse_pat_literal_maybe_minus()
          }
                          let tts = self.parse_seq_to_end(
                              &token::CloseDelim(delim),
                              SeqSep::none(), |p| p.parse_token_tree())?;
 -                        let mac = Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT };
 +                        let mac = Mac_ { path: path, tts: tts };
                          pat = PatKind::Mac(codemap::Spanned {node: mac,
 -                                                       span: mk_sp(lo, self.last_span.hi)});
 +                                                               span: mk_sp(lo, self.last_span.hi)});
                      } else {
                          // Parse ident @ pat
                          // This can give false positives and parse nullary enums,
                        token::DotDotDot => {
                          // Parse range
                          let hi = self.last_span.hi;
 -                        let begin = self.mk_expr(lo, hi, ExprKind::Path(qself, path), None);
 +                        let begin =
 +                              self.mk_expr(lo, hi, ExprKind::Path(qself, path), ThinVec::new());
                          self.bump();
                          let end = self.parse_pat_range_end()?;
                          pat = PatKind::Range(begin, end);
                          pat = PatKind::TupleStruct(path, fields, ddpos)
                        }
                        _ => {
 -                        pat = match qself {
 -                            // Parse qualified path
 -                            Some(qself) => PatKind::QPath(qself, path),
 -                            // Parse nullary enum
 -                            None => PatKind::Path(path)
 -                        };
 +                        pat = PatKind::Path(qself, path);
                        }
                      }
                  }
      }
  
      /// Parse a local variable declaration
 -    fn parse_local(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Local>> {
 +    fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
          let lo = self.span.lo;
          let pat = self.parse_pat()?;
  
          }))
      }
  
 -    /// Parse a "let" stmt
 -    fn parse_let(&mut self, attrs: ThinAttributes) -> PResult<'a, P<Decl>> {
 -        let lo = self.span.lo;
 -        let local = self.parse_local(attrs)?;
 -        Ok(P(spanned(lo, self.last_span.hi, DeclKind::Local(local))))
 -    }
 -
      /// Parse a structure field
      fn parse_name_and_ty(&mut self, pr: Visibility,
                           attrs: Vec<Attribute> ) -> PResult<'a, StructField> {
          let attrs = self.parse_outer_attributes()?;
          let lo = self.span.lo;
  
 -        Ok(Some(if self.check_keyword(keywords::Let) {
 -            self.expect_keyword(keywords::Let)?;
 -            let decl = self.parse_let(attrs.into_thin_attrs())?;
 -            let hi = decl.span.hi;
 -            let stmt = StmtKind::Decl(decl, ast::DUMMY_NODE_ID);
 -            spanned(lo, hi, stmt)
 +        Ok(Some(if self.eat_keyword(keywords::Let) {
 +            Stmt {
 +                id: ast::DUMMY_NODE_ID,
 +                node: StmtKind::Local(self.parse_local(attrs.into())?),
 +                span: mk_sp(lo, self.last_span.hi),
 +            }
          } else if self.token.is_ident()
              && !self.token.is_any_keyword()
              && self.look_ahead(1, |t| *t == token::Not) {
              };
  
              if id.name == keywords::Invalid.name() {
 -                let mac = P(spanned(lo, hi, Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }));
 -                let stmt = StmtKind::Mac(mac, style, attrs.into_thin_attrs());
 -                spanned(lo, hi, stmt)
 +                let mac = spanned(lo, hi, Mac_ { path: pth, tts: tts });
 +                Stmt {
 +                    id: ast::DUMMY_NODE_ID,
 +                    node: StmtKind::Mac(P((mac, style, attrs.into()))),
 +                    span: mk_sp(lo, hi),
 +                }
              } else {
                  // if it has a special ident, it's definitely an item
                  //
                                         followed by a semicolon");
                      }
                  }
 -                spanned(lo, hi, StmtKind::Decl(
 -                    P(spanned(lo, hi, DeclKind::Item(
 +                Stmt {
 +                    id: ast::DUMMY_NODE_ID,
 +                    span: mk_sp(lo, hi),
 +                    node: StmtKind::Item({
                          self.mk_item(
                              lo, hi, id /*id is good here*/,
 -                            ItemKind::Mac(spanned(lo, hi,
 -                                            Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
 -                            Visibility::Inherited, attrs)))),
 -                    ast::DUMMY_NODE_ID))
 +                            ItemKind::Mac(spanned(lo, hi, Mac_ { path: pth, tts: tts })),
 +                            Visibility::Inherited,
 +                            attrs)
 +                    }),
 +                }
              }
          } else {
              // FIXME: Bad copy of attrs
              let restrictions = self.restrictions | Restrictions::NO_NONINLINE_MOD;
              match self.with_res(restrictions,
                                  |this| this.parse_item_(attrs.clone(), false, true))? {
 -                Some(i) => {
 -                    let hi = i.span.hi;
 -                    let decl = P(spanned(lo, hi, DeclKind::Item(i)));
 -                    spanned(lo, hi, StmtKind::Decl(decl, ast::DUMMY_NODE_ID))
 -                }
 +                Some(i) => Stmt {
 +                    id: ast::DUMMY_NODE_ID,
 +                    span: mk_sp(lo, i.span.hi),
 +                    node: StmtKind::Item(i),
 +                },
                  None => {
                      let unused_attrs = |attrs: &[_], s: &mut Self| {
                          if attrs.len() > 0 {
  
                      // Remainder are line-expr stmts.
                      let e = self.parse_expr_res(
 -                        Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into_thin_attrs()))?;
 -                    let hi = e.span.hi;
 -                    let stmt = StmtKind::Expr(e, ast::DUMMY_NODE_ID);
 -                    spanned(lo, hi, stmt)
 +                        Restrictions::RESTRICTION_STMT_EXPR, Some(attrs.into()))?;
 +                    Stmt {
 +                        id: ast::DUMMY_NODE_ID,
 +                        span: mk_sp(lo, e.span.hi),
 +                        node: StmtKind::Expr(e),
 +                    }
                  }
              }
          }))
      /// 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;
                          hi = self.last_span.hi;
                      }
  
 -                    stmts.push(Spanned {
 +                    stmts.push(Stmt {
 +                        id: ast::DUMMY_NODE_ID,
                          node: node,
                          span: mk_sp(span.lo, hi)
                      });
  
          Ok(P(ast::Block {
              stmts: stmts,
-             expr: expr,
              id: ast::DUMMY_NODE_ID,
              rules: s,
              span: mk_sp(lo, self.last_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,
-                                         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) {
                      hi: self.last_span.hi,
                      expn_id: span.expn_id,
                  };
 -                stmts.push(Spanned {
 -                    node: StmtKind::Semi(e, ast::DUMMY_NODE_ID),
 +                stmts.push(Stmt {
 +                    id: ast::DUMMY_NODE_ID,
 +                    node: StmtKind::Semi(e),
                      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
                  });
              }
              let tts = self.parse_seq_to_end(&token::CloseDelim(delim),
                                              SeqSep::none(),
                                              |p| p.parse_token_tree())?;
 -            let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
 +            let m_ = Mac_ { path: pth, tts: tts };
              let m: ast::Mac = codemap::Spanned { node: m_,
 -                                                span: mk_sp(lo,
 -                                                            self.last_span.hi) };
 +                                                    span: mk_sp(lo,
 +                                                                self.last_span.hi) };
              if delim != token::Brace {
                  self.expect(&token::Semi)?
              }
  
      /// Parse trait Foo { ... }
      fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> {
 -
          let ident = self.parse_ident()?;
          let mut tps = self.parse_generics()?;
  
              return Err(self.fatal(&format!("expected item, found `{}`", token_str)));
          }
  
 -        let hi = if self.span == codemap::DUMMY_SP {
 +        let hi = if self.span == syntax_pos::DUMMY_SP {
              inner_lo
          } else {
              self.last_span.hi
                                              SeqSep::none(),
                                              |p| p.parse_token_tree())?;
              // single-variant-enum... :
 -            let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
 +            let m = Mac_ { path: pth, tts: tts };
              let m: ast::Mac = codemap::Spanned { node: m,
 -                                             span: mk_sp(mac_lo,
 -                                                         self.last_span.hi) };
 +                                                 span: mk_sp(mac_lo,
 +                                                             self.last_span.hi) };
  
              if delim != token::Brace {
                  if !self.eat(&token::Semi) {
index d399f53800469c083c9d3f64c5c5aaa07b5bb3db,00edd5585c28b86e7343c24934104082efea2e8e..b56cec72a956e0555a8b0d5a710c0378c8e72690
  pub use self::AnnNode::*;
  
  use abi::{self, Abi};
 -use ast::{self, TokenTree, BlockCheckMode, PatKind};
 +use ast::{self, BlockCheckMode, PatKind};
  use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
  use ast::Attribute;
 -use attr::ThinAttributesExt;
  use util::parser::AssocOp;
  use attr;
  use attr::{AttrMetaMethods, AttributeMethods};
 -use codemap::{self, CodeMap, BytePos};
 +use codemap::{self, CodeMap};
 +use syntax_pos::{self, BytePos};
  use errors;
  use parse::token::{self, keywords, BinOpToken, Token, InternedString};
  use parse::lexer::comments;
@@@ -28,7 -28,6 +28,7 @@@ use print::pp::{Breaks, eof}
  use print::pp::Breaks::{Consistent, Inconsistent};
  use ptr::P;
  use std_inject;
 +use tokenstream::{self, TokenTree};
  
  use std::ascii;
  use std::io::{self, Write, Read};
@@@ -331,11 -330,11 +331,11 @@@ pub fn lifetime_to_string(e: &ast::Life
      to_string(|s| s.print_lifetime(e))
  }
  
 -pub fn tt_to_string(tt: &ast::TokenTree) -> String {
 +pub fn tt_to_string(tt: &tokenstream::TokenTree) -> String {
      to_string(|s| s.print_tt(tt))
  }
  
 -pub fn tts_to_string(tts: &[ast::TokenTree]) -> String {
 +pub fn tts_to_string(tts: &[tokenstream::TokenTree]) -> String {
      to_string(|s| s.print_tts(tts))
  }
  
@@@ -843,11 -842,11 +843,11 @@@ impl<'a> State<'a> 
          self.end() // close the head-box
      }
  
 -    pub fn bclose_(&mut self, span: codemap::Span,
 +    pub fn bclose_(&mut self, span: syntax_pos::Span,
                     indented: usize) -> io::Result<()> {
          self.bclose_maybe_open(span, indented, true)
      }
 -    pub fn bclose_maybe_open(&mut self, span: codemap::Span,
 +    pub fn bclose_maybe_open(&mut self, span: syntax_pos::Span,
                               indented: usize, close_box: bool) -> io::Result<()> {
          try!(self.maybe_print_comment(span.hi));
          try!(self.break_offset_if_not_bol(1, -(indented as isize)));
          }
          Ok(())
      }
 -    pub fn bclose(&mut self, span: codemap::Span) -> io::Result<()> {
 +    pub fn bclose(&mut self, span: syntax_pos::Span) -> io::Result<()> {
          self.bclose_(span, INDENT_UNIT)
      }
  
                                    mut op: F,
                                    mut get_span: G) -> io::Result<()> where
          F: FnMut(&mut State, &T) -> io::Result<()>,
 -        G: FnMut(&T) -> codemap::Span,
 +        G: FnMut(&T) -> syntax_pos::Span,
      {
          try!(self.rbox(0, b));
          let len = elts.len();
  
      pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
                            generics: &ast::Generics, ident: ast::Ident,
 -                          span: codemap::Span,
 +                          span: syntax_pos::Span,
                            visibility: &ast::Visibility) -> io::Result<()> {
          try!(self.head(&visibility_qualified(visibility, "enum")));
          try!(self.print_ident(ident));
  
      pub fn print_variants(&mut self,
                            variants: &[ast::Variant],
 -                          span: codemap::Span) -> io::Result<()> {
 +                          span: syntax_pos::Span) -> io::Result<()> {
          try!(self.bopen());
          for v in variants {
              try!(self.space_if_not_bol());
                          struct_def: &ast::VariantData,
                          generics: &ast::Generics,
                          ident: ast::Ident,
 -                        span: codemap::Span,
 +                        span: syntax_pos::Span,
                          print_finalizer: bool) -> io::Result<()> {
          try!(self.print_ident(ident));
          try!(self.print_generics(generics));
      /// appropriate macro, transcribe back into the grammar we just parsed from,
      /// and then pretty-print the resulting AST nodes (so, e.g., we print
      /// expression arguments as expressions). It can be done! I think.
 -    pub fn print_tt(&mut self, tt: &ast::TokenTree) -> io::Result<()> {
 +    pub fn print_tt(&mut self, tt: &tokenstream::TokenTree) -> io::Result<()> {
          match *tt {
              TokenTree::Token(_, ref tk) => {
                  try!(word(&mut self.s, &token_to_string(tk)));
                      None => {},
                  }
                  match seq.op {
 -                    ast::KleeneOp::ZeroOrMore => word(&mut self.s, "*"),
 -                    ast::KleeneOp::OneOrMore => word(&mut self.s, "+"),
 +                    tokenstream::KleeneOp::ZeroOrMore => word(&mut self.s, "*"),
 +                    tokenstream::KleeneOp::OneOrMore => word(&mut self.s, "+"),
                  }
              }
          }
      }
  
 -    pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> io::Result<()> {
 +    pub fn print_tts(&mut self, tts: &[tokenstream::TokenTree]) -> io::Result<()> {
          try!(self.ibox(0));
          for (i, tt) in tts.iter().enumerate() {
              if i != 0 {
                  try!(self.print_associated_type(ti.ident, Some(bounds),
                                             default.as_ref().map(|ty| &**ty)));
              }
 +            ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
 +                // code copied from ItemKind::Mac:
 +                self.print_path(&node.path, false, 0)?;
 +                word(&mut self.s, "! ")?;
 +                self.cbox(INDENT_UNIT)?;
 +                self.popen()?;
 +                self.print_tts(&node.tts[..])?;
 +                self.pclose()?;
 +                word(&mut self.s, ";")?;
 +                self.end()?
 +            }
          }
          self.ann.post(self, NodeSubItem(ti.id))
      }
      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, ";"));
              }
 -            ast::StmtKind::Mac(ref mac, style, ref attrs) => {
 +            ast::StmtKind::Mac(ref mac) => {
 +                let (ref mac, style, ref attrs) = **mac;
                  try!(self.space_if_not_bol());
 -                try!(self.print_outer_attributes(attrs.as_attr_slice()));
 +                try!(self.print_outer_attributes(&attrs));
                  let delim = match style {
                      ast::MacStmtStyle::Braces => token::Brace,
                      _ => token::Paren
                  }
              }
          }
-         if parse::classify::stmt_ends_with_semi(&st.node) {
-             try!(word(&mut self.s, ";"));
-         }
          self.maybe_print_trailing_comment(st.span, None)
      }
  
  
          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))
      }
                                    is_inline: bool) -> io::Result<()> {
          try!(self.maybe_print_comment(expr.span.lo));
  
 -        let attrs = expr.attrs.as_attr_slice();
 +        let attrs = &expr.attrs;
          if is_inline {
              try!(self.print_outer_attributes_inline(attrs));
          } else {
                      _ => 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
                          }
                      }
+                     _ => 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.
                      try!(space(&mut self.s));
                  }
              }
 -            ast::ExprKind::Again(opt_ident) => {
 +            ast::ExprKind::Continue(opt_ident) => {
                  try!(word(&mut self.s, "continue"));
                  try!(space(&mut self.s));
                  if let Some(ident) = opt_ident {
          Ok(())
      }
  
 -    pub fn print_decl(&mut self, decl: &ast::Decl) -> io::Result<()> {
 -        try!(self.maybe_print_comment(decl.span.lo));
 -        match decl.node {
 -            ast::DeclKind::Local(ref loc) => {
 -                try!(self.print_outer_attributes(loc.attrs.as_attr_slice()));
 -                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::DeclKind::Item(ref item) => self.print_item(&item)
 -        }
 -    }
 -
      pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
          try!(word(&mut self.s, &ident.name.as_str()));
          self.ann.post(self, NodeIdent(&ident))
                  }
                  try!(self.pclose());
              }
 -            PatKind::Path(ref path) => {
 +            PatKind::Path(None, ref path) => {
                  try!(self.print_path(path, true, 0));
              }
 -            PatKind::QPath(ref qself, ref path) => {
 +            PatKind::Path(Some(ref qself), ref path) => {
                  try!(self.print_qpath(path, qself, false));
              }
              PatKind::Struct(ref path, ref fields, etc) => {
          self.end()
      }
  
 -    pub fn maybe_print_trailing_comment(&mut self, span: codemap::Span,
 +    pub fn maybe_print_trailing_comment(&mut self, span: syntax_pos::Span,
                                          next_pos: Option<BytePos>)
          -> io::Result<()> {
          let cm = match self.cm {
@@@ -3106,7 -3104,6 +3106,7 @@@ mod tests 
      use ast;
      use codemap;
      use parse::token;
 +    use syntax_pos;
  
      #[test]
      fn test_fun_to_string() {
  
          let decl = ast::FnDecl {
              inputs: Vec::new(),
 -            output: ast::FunctionRetTy::Default(codemap::DUMMY_SP),
 +            output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP),
              variadic: false
          };
          let generics = ast::Generics::default();
      fn test_variant_to_string() {
          let ident = token::str_to_ident("principal_skinner");
  
 -        let var = codemap::respan(codemap::DUMMY_SP, ast::Variant_ {
 +        let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
              name: ident,
              attrs: Vec::new(),
              // making this up as I go.... ?
diff --combined src/libsyntax/test.rs
index 078103f834a08b58b2acfd147616a4dae71829dc,39d3599e106070980f04270cc5c029bf1a347613..0a60b7fd430c427277fcbe33cf3d7668388c9ae5
@@@ -12,7 -12,6 +12,7 @@@
  
  #![allow(dead_code)]
  #![allow(unused_imports)]
 +
  use self::HasTestSignature::*;
  
  use std::iter;
@@@ -21,12 -20,9 +21,12 @@@ use std::mem
  use std::vec;
  use attr::AttrMetaMethods;
  use attr;
 -use codemap::{DUMMY_SP, Span, ExpnInfo, NameAndSpan, MacroAttribute};
 -use codemap;
 +use syntax_pos::{self, DUMMY_SP, NO_EXPANSION, Span, FileMap, BytePos};
 +use std::rc::Rc;
 +
 +use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute};
  use errors;
 +use errors::snippet::{RenderedLine, SnippetData};
  use config;
  use entry::{self, EntryPointType};
  use ext::base::{ExtCtxt, DummyMacroLoader};
@@@ -478,7 -474,7 +478,7 @@@ fn mk_main(cx: &mut TestCtxt) -> P<ast:
      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,
@@@ -608,10 -604,10 +608,10 @@@ fn mk_test_descs(cx: &TestCtxt) -> P<as
                      mk_test_desc_and_fn_rec(cx, test)
                  }).collect()),
                  span: DUMMY_SP,
 -                attrs: None,
 +                attrs: ast::ThinVec::new(),
              })),
          span: DUMMY_SP,
 -        attrs: None,
 +        attrs: ast::ThinVec::new(),
      })
  }
  
diff --combined src/libsyntax/visit.rs
index 571965ef8728623abcfe70558dcfabeeee06a2bb,cf91f5ece725b71f9cd15d8a8d56117682d6f8e6..1fc4e54d21807c26145f6d10e98e7d85f34eed15
@@@ -25,8 -25,8 +25,8 @@@
  
  use abi::Abi;
  use ast::*;
 -use attr::ThinAttributesExt;
 -use codemap::{Span, Spanned};
 +use syntax_pos::Span;
 +use codemap::Spanned;
  
  #[derive(Copy, Clone, PartialEq, Eq)]
  pub enum FnKind<'a> {
  /// explicitly, you need to override each method.  (And you also need
  /// to monitor future changes to `Visitor` in case a new method with a
  /// new default implementation gets introduced.)
 -pub trait Visitor<'v> : Sized {
 +pub trait Visitor: Sized {
      fn visit_name(&mut self, _span: Span, _name: Name) {
          // Nothing to do.
      }
      fn visit_ident(&mut self, span: Span, ident: Ident) {
          walk_ident(self, span, ident);
      }
 -    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
 -    fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) }
 -    fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) }
 -    fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) }
 -    fn visit_block(&mut self, b: &'v Block) { walk_block(self, b) }
 -    fn visit_stmt(&mut self, s: &'v Stmt) { walk_stmt(self, s) }
 -    fn visit_arm(&mut self, a: &'v Arm) { walk_arm(self, a) }
 -    fn visit_pat(&mut self, p: &'v Pat) { walk_pat(self, p) }
 -    fn visit_decl(&mut self, d: &'v Decl) { walk_decl(self, d) }
 -    fn visit_expr(&mut self, ex: &'v Expr) { walk_expr(self, ex) }
 -    fn visit_expr_post(&mut self, _ex: &'v Expr) { }
 -    fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) }
 -    fn visit_generics(&mut self, g: &'v Generics) { walk_generics(self, g) }
 -    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
 +    fn visit_mod(&mut self, m: &Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
 +    fn visit_foreign_item(&mut self, i: &ForeignItem) { walk_foreign_item(self, i) }
 +    fn visit_item(&mut self, i: &Item) { walk_item(self, i) }
 +    fn visit_local(&mut self, l: &Local) { walk_local(self, l) }
 +    fn visit_block(&mut self, b: &Block) { walk_block(self, b) }
 +    fn visit_stmt(&mut self, s: &Stmt) { walk_stmt(self, s) }
 +    fn visit_arm(&mut self, a: &Arm) { walk_arm(self, a) }
 +    fn visit_pat(&mut self, p: &Pat) { walk_pat(self, p) }
 +    fn visit_expr(&mut self, ex: &Expr) { walk_expr(self, ex) }
 +    fn visit_expr_post(&mut self, _ex: &Expr) { }
 +    fn visit_ty(&mut self, t: &Ty) { walk_ty(self, t) }
 +    fn visit_generics(&mut self, g: &Generics) { walk_generics(self, g) }
 +    fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId) {
          walk_fn(self, fk, fd, b, s)
      }
 -    fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) }
 -    fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) }
 -    fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
 -    fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
 +    fn visit_trait_item(&mut self, ti: &TraitItem) { walk_trait_item(self, ti) }
 +    fn visit_impl_item(&mut self, ii: &ImplItem) { walk_impl_item(self, ii) }
 +    fn visit_trait_ref(&mut self, t: &TraitRef) { walk_trait_ref(self, t) }
 +    fn visit_ty_param_bound(&mut self, bounds: &TyParamBound) {
          walk_ty_param_bound(self, bounds)
      }
 -    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
 +    fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) {
          walk_poly_trait_ref(self, t, m)
      }
 -    fn visit_variant_data(&mut self, s: &'v VariantData, _: Ident,
 -                        _: &'v Generics, _: NodeId, _: Span) {
 +    fn visit_variant_data(&mut self, s: &VariantData, _: Ident,
 +                          _: &Generics, _: NodeId, _: Span) {
          walk_struct_def(self, s)
      }
 -    fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) }
 -    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef,
 -                      generics: &'v Generics, item_id: NodeId, _: Span) {
 +    fn visit_struct_field(&mut self, s: &StructField) { walk_struct_field(self, s) }
 +    fn visit_enum_def(&mut self, enum_definition: &EnumDef,
 +                      generics: &Generics, item_id: NodeId, _: Span) {
          walk_enum_def(self, enum_definition, generics, item_id)
      }
 -    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
 +    fn visit_variant(&mut self, v: &Variant, g: &Generics, item_id: NodeId) {
          walk_variant(self, v, g, item_id)
      }
 -    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
 +    fn visit_lifetime(&mut self, lifetime: &Lifetime) {
          walk_lifetime(self, lifetime)
      }
 -    fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
 +    fn visit_lifetime_def(&mut self, lifetime: &LifetimeDef) {
          walk_lifetime_def(self, lifetime)
      }
 -    fn visit_mac(&mut self, _mac: &'v Mac) {
 +    fn visit_mac(&mut self, _mac: &Mac) {
          panic!("visit_mac disabled by default");
          // NB: see note about macros above.
          // if you really want a visitor that
          // definition in your trait impl:
          // visit::walk_mac(self, _mac)
      }
 -    fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
 +    fn visit_path(&mut self, path: &Path, _id: NodeId) {
          walk_path(self, path)
      }
 -    fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
 +    fn visit_path_list_item(&mut self, prefix: &Path, item: &PathListItem) {
          walk_path_list_item(self, prefix, item)
      }
 -    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
 +    fn visit_path_segment(&mut self, path_span: Span, path_segment: &PathSegment) {
          walk_path_segment(self, path_span, path_segment)
      }
 -    fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) {
 +    fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &PathParameters) {
          walk_path_parameters(self, path_span, path_parameters)
      }
 -    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
 +    fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
          walk_assoc_type_binding(self, type_binding)
      }
 -    fn visit_attribute(&mut self, _attr: &'v Attribute) {}
 -    fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
 +    fn visit_attribute(&mut self, _attr: &Attribute) {}
 +    fn visit_macro_def(&mut self, macro_def: &MacroDef) {
          walk_macro_def(self, macro_def)
      }
 -    fn visit_vis(&mut self, vis: &'v Visibility) {
 +    fn visit_vis(&mut self, vis: &Visibility) {
          walk_vis(self, vis)
      }
  }
@@@ -144,46 -145,47 +144,46 @@@ macro_rules! walk_list 
      }
  }
  
 -pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
 +pub fn walk_opt_name<V: Visitor>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
      if let Some(name) = opt_name {
          visitor.visit_name(span, name);
      }
  }
  
 -pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
 +pub fn walk_opt_ident<V: Visitor>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
      if let Some(ident) = opt_ident {
          visitor.visit_ident(span, ident);
      }
  }
  
 -pub fn walk_opt_sp_ident<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                             opt_sp_ident: &Option<Spanned<Ident>>) {
 +pub fn walk_opt_sp_ident<V: Visitor>(visitor: &mut V, opt_sp_ident: &Option<Spanned<Ident>>) {
      if let Some(ref sp_ident) = *opt_sp_ident {
          visitor.visit_ident(sp_ident.span, sp_ident.node);
      }
  }
  
 -pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
 +pub fn walk_ident<V: Visitor>(visitor: &mut V, span: Span, ident: Ident) {
      visitor.visit_name(span, ident.name);
  }
  
 -pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
 +pub fn walk_crate<V: Visitor>(visitor: &mut V, krate: &Crate) {
      visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
      walk_list!(visitor, visit_attribute, &krate.attrs);
      walk_list!(visitor, visit_macro_def, &krate.exported_macros);
  }
  
 -pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
 +pub fn walk_macro_def<V: Visitor>(visitor: &mut V, macro_def: &MacroDef) {
      visitor.visit_ident(macro_def.span, macro_def.ident);
      walk_opt_ident(visitor, macro_def.span, macro_def.imported_from);
      walk_list!(visitor, visit_attribute, &macro_def.attrs);
  }
  
 -pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
 +pub fn walk_mod<V: Visitor>(visitor: &mut V, module: &Mod) {
      walk_list!(visitor, visit_item, &module.items);
  }
  
 -pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
 -    for attr in local.attrs.as_attr_slice() {
 +pub fn walk_local<V: Visitor>(visitor: &mut V, local: &Local) {
 +    for attr in local.attrs.iter() {
          visitor.visit_attribute(attr);
      }
      visitor.visit_pat(&local.pat);
      walk_list!(visitor, visit_expr, &local.init);
  }
  
 -pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
 +pub fn walk_lifetime<V: Visitor>(visitor: &mut V, lifetime: &Lifetime) {
      visitor.visit_name(lifetime.span, lifetime.name);
  }
  
 -pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                              lifetime_def: &'v LifetimeDef) {
 +pub fn walk_lifetime_def<V: Visitor>(visitor: &mut V, lifetime_def: &LifetimeDef) {
      visitor.visit_lifetime(&lifetime_def.lifetime);
      walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
  }
  
 -pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
 -                                  trait_ref: &'v PolyTraitRef,
 -                                  _modifier: &'v TraitBoundModifier)
 -    where V: Visitor<'v>
 +pub fn walk_poly_trait_ref<V>(visitor: &mut V, trait_ref: &PolyTraitRef, _: &TraitBoundModifier)
 +    where V: Visitor,
  {
      walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
      visitor.visit_trait_ref(&trait_ref.trait_ref);
  }
  
 -pub fn walk_trait_ref<'v,V>(visitor: &mut V,
 -                                   trait_ref: &'v TraitRef)
 -    where V: Visitor<'v>
 -{
 +pub fn walk_trait_ref<V: Visitor>(visitor: &mut V, trait_ref: &TraitRef) {
      visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
  }
  
 -pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
 +pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
      visitor.visit_vis(&item.vis);
      visitor.visit_ident(item.span, item.ident);
      match item.node {
      walk_list!(visitor, visit_attribute, &item.attrs);
  }
  
 -pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                         enum_definition: &'v EnumDef,
 -                                         generics: &'v Generics,
 -                                         item_id: NodeId) {
 +pub fn walk_enum_def<V: Visitor>(visitor: &mut V,
 +                                 enum_definition: &EnumDef,
 +                                 generics: &Generics,
 +                                 item_id: NodeId) {
      walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id);
  }
  
 -pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                        variant: &'v Variant,
 -                                        generics: &'v Generics,
 -                                        item_id: NodeId) {
 +pub fn walk_variant<V>(visitor: &mut V, variant: &Variant, generics: &Generics, item_id: NodeId)
 +    where V: Visitor,
 +{
      visitor.visit_ident(variant.span, variant.node.name);
      visitor.visit_variant_data(&variant.node.data, variant.node.name,
                               generics, item_id, variant.span);
      walk_list!(visitor, visit_attribute, &variant.node.attrs);
  }
  
 -pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
 +pub fn walk_ty<V: Visitor>(visitor: &mut V, typ: &Ty) {
      match typ.node {
          TyKind::Vec(ref ty) | TyKind::Paren(ref ty) => {
              visitor.visit_ty(ty)
      }
  }
  
 -pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
 +pub fn walk_path<V: Visitor>(visitor: &mut V, path: &Path) {
      for segment in &path.segments {
          visitor.visit_path_segment(path.span, segment);
      }
  }
  
 -pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, _prefix: &'v Path,
 -                                               item: &'v PathListItem) {
 +pub fn walk_path_list_item<V: Visitor>(visitor: &mut V, _prefix: &Path, item: &PathListItem) {
      walk_opt_ident(visitor, item.span, item.node.name());
      walk_opt_ident(visitor, item.span, item.node.rename());
  }
  
 -pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                             path_span: Span,
 -                                             segment: &'v PathSegment) {
 +pub fn walk_path_segment<V: Visitor>(visitor: &mut V, path_span: Span, segment: &PathSegment) {
      visitor.visit_ident(path_span, segment.identifier);
      visitor.visit_path_parameters(path_span, &segment.parameters);
  }
  
 -pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                                _path_span: Span,
 -                                                path_parameters: &'v PathParameters) {
 +pub fn walk_path_parameters<V>(visitor: &mut V, _path_span: Span, path_parameters: &PathParameters)
 +    where V: Visitor,
 +{
      match *path_parameters {
          PathParameters::AngleBracketed(ref data) => {
              walk_list!(visitor, visit_ty, &data.types);
      }
  }
  
 -pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                                   type_binding: &'v TypeBinding) {
 +pub fn walk_assoc_type_binding<V: Visitor>(visitor: &mut V, type_binding: &TypeBinding) {
      visitor.visit_ident(type_binding.span, type_binding.ident);
      visitor.visit_ty(&type_binding.ty);
  }
  
 -pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
 +pub fn walk_pat<V: Visitor>(visitor: &mut V, pattern: &Pat) {
      match pattern.node {
          PatKind::TupleStruct(ref path, ref children, _) => {
              visitor.visit_path(path, pattern.id);
              walk_list!(visitor, visit_pat, children);
          }
 -        PatKind::Path(ref path) => {
 -            visitor.visit_path(path, pattern.id);
 -        }
 -        PatKind::QPath(ref qself, ref path) => {
 -            visitor.visit_ty(&qself.ty);
 +        PatKind::Path(ref opt_qself, ref path) => {
 +            if let Some(ref qself) = *opt_qself {
 +                visitor.visit_ty(&qself.ty);
 +            }
              visitor.visit_path(path, pattern.id)
          }
          PatKind::Struct(ref path, ref fields, _) => {
      }
  }
  
 -pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                             foreign_item: &'v ForeignItem) {
 +pub fn walk_foreign_item<V: Visitor>(visitor: &mut V, foreign_item: &ForeignItem) {
      visitor.visit_vis(&foreign_item.vis);
      visitor.visit_ident(foreign_item.span, foreign_item.ident);
  
      walk_list!(visitor, visit_attribute, &foreign_item.attrs);
  }
  
 -pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                               bound: &'v TyParamBound) {
 +pub fn walk_ty_param_bound<V: Visitor>(visitor: &mut V, bound: &TyParamBound) {
      match *bound {
          TraitTyParamBound(ref typ, ref modifier) => {
              visitor.visit_poly_trait_ref(typ, modifier);
      }
  }
  
 -pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
 +pub fn walk_generics<V: Visitor>(visitor: &mut V, generics: &Generics) {
      for param in &generics.ty_params {
          visitor.visit_ident(param.span, param.ident);
          walk_list!(visitor, visit_ty_param_bound, &param.bounds);
      }
  }
  
 -pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
 +pub fn walk_fn_ret_ty<V: Visitor>(visitor: &mut V, ret_ty: &FunctionRetTy) {
      if let FunctionRetTy::Ty(ref output_ty) = *ret_ty {
          visitor.visit_ty(output_ty)
      }
  }
  
 -pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
 +pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, function_declaration: &FnDecl) {
      for argument in &function_declaration.inputs {
          visitor.visit_pat(&argument.pat);
          visitor.visit_ty(&argument.ty)
      walk_fn_ret_ty(visitor, &function_declaration.output)
  }
  
 -pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                        function_kind: FnKind<'v>) {
 +pub fn walk_fn_kind<V: Visitor>(visitor: &mut V, function_kind: FnKind) {
      match function_kind {
          FnKind::ItemFn(_, generics, _, _, _, _) => {
              visitor.visit_generics(generics);
      }
  }
  
 -pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                   function_kind: FnKind<'v>,
 -                                   function_declaration: &'v FnDecl,
 -                                   function_body: &'v Block,
 -                                   _span: Span) {
 -    walk_fn_decl(visitor, function_declaration);
 -    walk_fn_kind(visitor, function_kind);
 -    visitor.visit_block(function_body)
 +pub fn walk_fn<V>(visitor: &mut V, kind: FnKind, declaration: &FnDecl, body: &Block, _span: Span)
 +    where V: Visitor,
 +{
 +    walk_fn_decl(visitor, declaration);
 +    walk_fn_kind(visitor, kind);
 +    visitor.visit_block(body)
  }
  
 -pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
 +pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
      visitor.visit_ident(trait_item.span, trait_item.ident);
      walk_list!(visitor, visit_attribute, &trait_item.attrs);
      match trait_item.node {
              walk_list!(visitor, visit_ty_param_bound, bounds);
              walk_list!(visitor, visit_ty, default);
          }
 +        TraitItemKind::Macro(ref mac) => {
 +            visitor.visit_mac(mac);
 +        }
      }
  }
  
 -pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
 +pub fn walk_impl_item<V: Visitor>(visitor: &mut V, impl_item: &ImplItem) {
      visitor.visit_vis(&impl_item.vis);
      visitor.visit_ident(impl_item.span, impl_item.ident);
      walk_list!(visitor, visit_attribute, &impl_item.attrs);
      }
  }
  
 -pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                           struct_definition: &'v VariantData) {
 +pub fn walk_struct_def<V: Visitor>(visitor: &mut V, struct_definition: &VariantData) {
      walk_list!(visitor, visit_struct_field, struct_definition.fields());
  }
  
 -pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
 -                                             struct_field: &'v StructField) {
 +pub fn walk_struct_field<V: Visitor>(visitor: &mut V, struct_field: &StructField) {
      visitor.visit_vis(&struct_field.vis);
      walk_opt_ident(visitor, struct_field.span, struct_field.ident);
      visitor.visit_ty(&struct_field.ty);
      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);
              }
          }
      }
  }
  
 -pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
 -    match declaration.node {
 -        DeclKind::Local(ref local) => visitor.visit_local(local),
 -        DeclKind::Item(ref item) => visitor.visit_item(item),
 -    }
 -}
 -
 -pub fn walk_mac<'v, V: Visitor<'v>>(_: &mut V, _: &'v Mac) {
 +pub fn walk_mac<V: Visitor>(_: &mut V, _: &Mac) {
      // Empty!
  }
  
 -pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
 -    for attr in expression.attrs.as_attr_slice() {
 +pub fn walk_expr<V: Visitor>(visitor: &mut V, expression: &Expr) {
 +    for attr in expression.attrs.iter() {
          visitor.visit_attribute(attr);
      }
      match expression.node {
              }
              visitor.visit_path(path, expression.id)
          }
 -        ExprKind::Break(ref opt_sp_ident) | ExprKind::Again(ref opt_sp_ident) => {
 +        ExprKind::Break(ref opt_sp_ident) | ExprKind::Continue(ref opt_sp_ident) => {
              walk_opt_sp_ident(visitor, opt_sp_ident);
          }
          ExprKind::Ret(ref optional_expression) => {
      visitor.visit_expr_post(expression)
  }
  
 -pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
 +pub fn walk_arm<V: Visitor>(visitor: &mut V, arm: &Arm) {
      walk_list!(visitor, visit_pat, &arm.pats);
      walk_list!(visitor, visit_expr, &arm.guard);
      visitor.visit_expr(&arm.body);
      walk_list!(visitor, visit_attribute, &arm.attrs);
  }
  
 -pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
 +pub fn walk_vis<V: Visitor>(visitor: &mut V, vis: &Visibility) {
      if let Visibility::Restricted { ref path, id } = *vis {
          visitor.visit_path(path, id);
      }
index 007140028759139c7894588f0b51905862556a47,1e3e853df010e16d4a46799c0915457b58ba3f16..1e47ebb85837a761a9596bfafcb1369ba783db7e
@@@ -13,11 -13,11 +13,11 @@@ use deriving::generic::ty::*
  
  use syntax::ast::{Expr, ItemKind, Generics, MetaItem, VariantData};
  use syntax::attr;
 -use syntax::codemap::Span;
  use syntax::ext::base::{ExtCtxt, Annotatable};
  use syntax::ext::build::AstBuilder;
  use syntax::parse::token::InternedString;
  use syntax::ptr::P;
 +use syntax_pos::Span;
  
  #[derive(PartialEq)]
  enum Mode { Deep, Shallow }
@@@ -145,12 -145,10 +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 {
index 4258e152088e5c0a3e6c28cf2b049f1707c1b576,b0e4491ffe2b01a498ea0d16c268ca08cfac5c4b..9c5072eeb3e0b79dc9ba58c4b447eba4efc146a9
@@@ -12,11 -12,11 +12,11 @@@ use deriving::generic::*
  use deriving::generic::ty::*;
  
  use syntax::ast::{MetaItem, Expr};
 -use syntax::codemap::Span;
  use syntax::ext::base::{ExtCtxt, Annotatable};
  use syntax::ext::build::AstBuilder;
  use syntax::parse::token::InternedString;
  use syntax::ptr::P;
 +use syntax_pos::Span;
  
  pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                            span: Span,
@@@ -30,7 -30,7 +30,7 @@@
                  // 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, _, _| {
index dabe234eb9c19db5090af166018e8b23a8a82266,0c6548be60b710743951307c8fa471ec26805f70..34c872bef11d10916698f2a57a6475dfe798fa66
@@@ -13,11 -13,11 +13,11 @@@ use deriving::generic::ty::*
  
  use syntax::ast;
  use syntax::ast::{MetaItem, Expr};
 -use syntax::codemap::{Span, respan, DUMMY_SP};
  use syntax::ext::base::{ExtCtxt, Annotatable};
  use syntax::ext::build::AstBuilder;
  use syntax::parse::token;
  use syntax::ptr::P;
 +use syntax_pos::{Span, DUMMY_SP};
  
  pub fn expand_deriving_debug(cx: &mut ExtCtxt,
                              span: Span,
@@@ -78,7 -78,7 +78,7 @@@ fn show_substructure(cx: &mut ExtCtxt, 
  
      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 {
                                     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)
  }
  
@@@ -149,11 -150,8 +150,11 @@@ fn stmt_let_undescore(cx: &mut ExtCtxt
          init: Some(expr),
          id: ast::DUMMY_NODE_ID,
          span: sp,
 -        attrs: None,
 +        attrs: ast::ThinVec::new(),
      });
 -    let decl = respan(sp, ast::DeclKind::Local(local));
 -    respan(sp, ast::StmtKind::Decl(P(decl), ast::DUMMY_NODE_ID))
 +    ast::Stmt {
 +        id: ast::DUMMY_NODE_ID,
 +        node: ast::StmtKind::Local(local),
 +        span: sp,
 +    }
  }
index 07a52105debe6553ff9bacc8397f578c9b57acf2,76b83c8a0f1f0f2cf2985a5fccaf27128ec8531f..ad3786212475eaa76f23a82963fab1270827aa13
@@@ -93,11 -93,11 +93,11 @@@ use deriving::generic::*
  use deriving::generic::ty::*;
  
  use syntax::ast::{MetaItem, Expr, ExprKind, Mutability};
 -use syntax::codemap::Span;
  use syntax::ext::base::{ExtCtxt,Annotatable};
  use syntax::ext::build::AstBuilder;
  use syntax::parse::token;
  use syntax::ptr::P;
 +use syntax_pos::Span;
  
  pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
                                         span: Span,
@@@ -285,7 -285,7 +285,7 @@@ fn encodable_substructure(cx: &mut ExtC
                  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)")
index 7d454fe38cc84f69f6dbf4f18488ff0fc5135bbe,635d9ee5516e04ba4c9dfbeb875d3dd6de21c1c5..647e414a7fd2736cf6443e36ed8ce7be8b36458d
@@@ -197,12 -197,12 +197,12 @@@ use syntax::attr
  use syntax::attr::AttrMetaMethods;
  use syntax::ext::base::{ExtCtxt, Annotatable};
  use syntax::ext::build::AstBuilder;
 -use syntax::codemap::{self, respan, DUMMY_SP};
 -use syntax::codemap::Span;
 -use syntax::errors::Handler;
 +use syntax::codemap::{self, respan};
  use syntax::util::move_map::MoveMap;
  use syntax::parse::token::{keywords, InternedString};
  use syntax::ptr::P;
 +use syntax_pos::{Span, DUMMY_SP};
 +use errors::Handler;
  
  use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
  
@@@ -353,8 -353,8 +353,8 @@@ fn find_type_parameters(ty: &ast::Ty, t
          types: Vec<P<ast::Ty>>,
      }
  
 -    impl<'a> visit::Visitor<'a> for Visitor<'a> {
 -        fn visit_ty(&mut self, ty: &'a ast::Ty) {
 +    impl<'a> visit::Visitor for Visitor<'a> {
 +        fn visit_ty(&mut self, ty: &ast::Ty) {
              match ty.node {
                  ast::TyKind::Path(_, ref path) if !path.global => {
                      match path.segments.first() {
@@@ -1332,8 -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
index 245d3f0efa30325bf07145a8a93e360a294c3fff,1c7b36313c554126b8030c5723d0bf2f43e78bd3..0fad96c84ef3d2a859569768a4115995ebfc54b0
@@@ -13,10 -13,10 +13,10 @@@ use deriving::generic::*
  use deriving::generic::ty::*;
  
  use syntax::ast::{MetaItem, Expr, Mutability};
 -use syntax::codemap::Span;
  use syntax::ext::base::{ExtCtxt, Annotatable};
  use syntax::ext::build::AstBuilder;
  use syntax::ptr::P;
 +use syntax_pos::Span;
  
  pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                              span: Span,
@@@ -99,5 -99,5 +99,5 @@@ fn hash_substructure(cx: &mut ExtCtxt, 
          stmts.push(call_hash(span, self_.clone()));
      }
  
-     cx.expr_block(cx.block(trait_span, stmts, None))
+     cx.expr_block(cx.block(trait_span, stmts))
  }
index f9e0d2c2eaeba45d8209ab1e7cee0042cb10776d,41f93cb4744b6df6620f64da402933033c8a4904..169e8073661976cf56c709ac1b1aa3bcb641d3a5
@@@ -16,10 -16,9 +16,10 @@@ use syntax::ext::base::{ExtCtxt, Syntax
  use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
  use syntax::ext::build::AstBuilder;
  use syntax::feature_gate;
 -use syntax::codemap::{self, Span};
 +use syntax::codemap;
  use syntax::parse::token::{intern, intern_and_get_ident};
  use syntax::ptr::P;
 +use syntax_pos::Span;
  
  macro_rules! pathvec {
      ($($x:ident)::+) => (
@@@ -298,8 -297,7 +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 }))
index 5be2bf7cdf92b7b374c976160cf0a987fc59ef69,8cf956256949327f3d8f034ffdd291196bca94bc..f311f16f11b0efbebd7c59390f75102f537c171b
@@@ -14,14 -14,13 +14,14 @@@ use self::Position::*
  use fmt_macros as parse;
  
  use syntax::ast;
 -use syntax::codemap::{Span, respan, DUMMY_SP};
  use syntax::ext::base::*;
  use syntax::ext::base;
  use syntax::ext::build::AstBuilder;
  use syntax::fold::Folder;
  use syntax::parse::token::{self, keywords};
  use syntax::ptr::P;
 +use syntax_pos::{Span, DUMMY_SP};
 +use syntax::tokenstream;
  
  use std::collections::HashMap;
  
@@@ -81,7 -80,7 +81,7 @@@ struct Context<'a, 'b:'a> 
  /// Some((fmtstr, unnamed arguments, ordering of named arguments,
  ///       named arguments))
  /// ```
 -fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 +fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
                -> Option<(P<ast::Expr>, Vec<P<ast::Expr>>, Vec<String>,
                           HashMap<String, P<ast::Expr>>)> {
      let mut args = Vec::new();
@@@ -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
  }
  
  pub fn expand_format_args<'cx>(ecx: &'cx mut ExtCtxt, sp: Span,
 -                               tts: &[ast::TokenTree])
 +                               tts: &[tokenstream::TokenTree])
                                 -> Box<base::MacResult+'cx> {
  
      match parse_args(ecx, sp, tts) {