about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2016-04-20 14:44:07 -0400
committerManish Goregaokar <manishsmail@gmail.com>2016-04-24 18:10:57 +0530
commitecd10f04cea34352ff240b0462d40cd1d95a4e0f (patch)
treefb7f1f7adc4a1044d3a9316631fef61e46ce984b /src
parent23ccaddaa7d1cb71e49ef1b1f423b3245fa3a879 (diff)
downloadrust-ecd10f04cea34352ff240b0462d40cd1d95a4e0f.tar.gz
rust-ecd10f04cea34352ff240b0462d40cd1d95a4e0f.zip
thread tighter span for closures around
Track the span corresponding to the `|...|` part of the closure.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/fold.rs5
-rw-r--r--src/librustc/hir/intravisit.rs2
-rw-r--r--src/librustc/hir/lowering.rs5
-rw-r--r--src/librustc/hir/map/blocks.rs2
-rw-r--r--src/librustc/hir/mod.rs6
-rw-r--r--src/librustc/hir/print.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs10
-rw-r--r--src/librustc/middle/liveness.rs2
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs2
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_passes/loops.rs2
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs2
-rw-r--r--src/librustc_trans/base.rs2
-rw-r--r--src/librustc_trans/consts.rs2
-rw-r--r--src/librustc_trans/debuginfo/create_scope_map.rs2
-rw-r--r--src/librustc_trans/expr.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/check/regionck.rs2
-rw-r--r--src/librustc_typeck/check/upvar.rs2
-rw-r--r--src/librustc_typeck/check/writeback.rs2
-rw-r--r--src/libstd/collections/hash/map.rs6
-rw-r--r--src/libsyntax/ast.rs4
-rw-r--r--src/libsyntax/ext/build.rs37
-rw-r--r--src/libsyntax/ext/expand.rs13
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/parse/parser.rs9
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/visit.rs2
29 files changed, 87 insertions, 53 deletions
diff --git a/src/librustc/hir/fold.rs b/src/librustc/hir/fold.rs
index a6ff7164885..1c27e7c53f9 100644
--- a/src/librustc/hir/fold.rs
+++ b/src/librustc/hir/fold.rs
@@ -1060,10 +1060,11 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
                           arms.move_map(|x| folder.fold_arm(x)),
                           source)
             }
-            ExprClosure(capture_clause, decl, body) => {
+            ExprClosure(capture_clause, decl, body, fn_decl_span) => {
                 ExprClosure(capture_clause,
                             folder.fold_fn_decl(decl),
-                            folder.fold_block(body))
+                            folder.fold_block(body),
+                            folder.new_span(fn_decl_span))
             }
             ExprBlock(blk) => ExprBlock(folder.fold_block(blk)),
             ExprAssign(el, er) => {
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 6e6f845abd3..ec9b465521b 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -785,7 +785,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprClosure(_, ref function_declaration, ref body) => {
+        ExprClosure(_, ref function_declaration, ref body, _fn_decl_span) => {
             visitor.visit_fn(FnKind::Closure(expression.attrs.as_attr_slice()),
                              function_declaration,
                              body,
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 0a01cc91f0e..6f30553e266 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1260,11 +1260,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
                                arms.iter().map(|x| lower_arm(lctx, x)).collect(),
                                hir::MatchSource::Normal)
             }
-            ExprKind::Closure(capture_clause, ref decl, ref body) => {
+            ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
                 lctx.with_parent_def(e.id, || {
                     hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
                                      lower_fn_decl(lctx, decl),
-                                     lower_block(lctx, body))
+                                     lower_block(lctx, body),
+                                     fn_decl_span)
                 })
             }
             ExprKind::Block(ref blk) => hir::ExprBlock(lower_block(lctx, blk)),
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 8c626226bd3..4af37fe16ad 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -250,7 +250,7 @@ impl<'a> FnLikeNode<'a> {
                 }
             }
             map::NodeExpr(e) => match e.node {
-                ast::ExprClosure(_, ref decl, ref block) =>
+                ast::ExprClosure(_, ref decl, ref block, _fn_decl_span) =>
                     closure(ClosureParts::new(&decl,
                                               &block,
                                               e.id,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 4e752003523..7eaace91ae9 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -949,8 +949,10 @@ pub enum Expr_ {
     /// A `match` block, with a source that indicates whether or not it is
     /// the result of a desugaring, and if so, which kind.
     ExprMatch(P<Expr>, HirVec<Arm>, MatchSource),
-    /// A closure (for example, `move |a, b, c| {a + b + c}`)
-    ExprClosure(CaptureClause, P<FnDecl>, P<Block>),
+    /// A closure (for example, `move |a, b, c| {a + b + c}`).
+    ///
+    /// The final span is the span of the argument block `|...|`
+    ExprClosure(CaptureClause, P<FnDecl>, P<Block>, Span),
     /// A block (`{ ... }`)
     ExprBlock(P<Block>),
 
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index e595c619e85..8335ce3c736 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -1392,7 +1392,7 @@ impl<'a> State<'a> {
                 }
                 self.bclose_(expr.span, indent_unit)?;
             }
-            hir::ExprClosure(capture_clause, ref decl, ref body) => {
+            hir::ExprClosure(capture_clause, ref decl, ref body, _fn_decl_span) => {
                 self.print_capture_clause(capture_clause)?;
 
                 self.print_fn_block_args(&decl)?;
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index c4d6f100671..002f202796c 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -537,8 +537,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 self.consume_expr(&count);
             }
 
-            hir::ExprClosure(..) => {
-                self.walk_captures(expr)
+            hir::ExprClosure(_, _, _, fn_decl_span) => {
+                self.walk_captures(expr, fn_decl_span)
             }
 
             hir::ExprBox(ref base) => {
@@ -1142,7 +1142,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         }));
     }
 
-    fn walk_captures(&mut self, closure_expr: &hir::Expr) {
+    fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) {
         debug!("walk_captures({:?})", closure_expr);
 
         self.tcx().with_freevars(closure_expr.id, |freevars| {
@@ -1152,7 +1152,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                                              closure_expr_id: closure_expr.id };
                 let upvar_capture = self.typer.upvar_capture(upvar_id).unwrap();
                 let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
-                                                                   closure_expr.span,
+                                                                   fn_decl_span,
                                                                    freevar.def));
                 match upvar_capture {
                     ty::UpvarCapture::ByValue => {
@@ -1161,7 +1161,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                     }
                     ty::UpvarCapture::ByRef(upvar_borrow) => {
                         self.delegate.borrow(closure_expr.id,
-                                             closure_expr.span,
+                                             fn_decl_span,
                                              cmt_var,
                                              upvar_borrow.region,
                                              upvar_borrow.kind,
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 35991ae56c8..ff20d41ce9d 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -948,7 +948,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
               self.propagate_through_expr(&e, succ)
           }
 
-          hir::ExprClosure(_, _, ref blk) => {
+          hir::ExprClosure(_, _, ref blk, _) => {
               debug!("{} is an ExprClosure",
                      expr_to_string(expr));
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 2f77552c389..7b31cd81567 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -728,7 +728,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             };
 
             match fn_expr.node {
-                hir::ExprClosure(_, _, ref body) => body.id,
+                hir::ExprClosure(_, _, ref body, _) => body.id,
                 _ => bug!()
             }
         };
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index d7c928b8d6e..15db356b1ba 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -415,7 +415,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
                         tcx: &TyCtxt) -> ast::NodeId {
     match tcx.map.get(closure_id) {
         hir_map::NodeExpr(expr) => match expr.node {
-            hir::ExprClosure(_, _, ref block) => {
+            hir::ExprClosure(_, _, ref block, _) => {
                 block.id
             }
             _ => {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 12dcb32da3f..7dab8c4c5fb 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -725,7 +725,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             let body_id = match cx.tcx.map.find(closure_expr_id) {
                 Some(map::NodeExpr(expr)) => {
                     match expr.node {
-                        hir::ExprClosure(_, _, ref body) => body.id,
+                        hir::ExprClosure(_, _, ref body, _) => body.id,
                         _ => {
                             span_bug!(expr.span, "closure expr is not a closure expr");
                         }
diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs
index 9a58a704c52..2174d1cf9b8 100644
--- a/src/librustc_passes/loops.rs
+++ b/src/librustc_passes/loops.rs
@@ -48,7 +48,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
             hir::ExprLoop(ref b, _) => {
                 self.with_context(Loop, |v| v.visit_block(&b));
             }
-            hir::ExprClosure(_, _, ref b) => {
+            hir::ExprClosure(_, _, ref b, _) => {
                 self.with_context(Closure, |v| v.visit_block(&b));
             }
             hir::ExprBreak(_) => self.require_loop("break", e.span),
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index bf6ad703963..e96be4714d0 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1258,7 +1258,7 @@ impl<'v, 'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'v> for DumpVisitor<'l, 'tcx,
                                    ty),
                 }
             }
-            ast::ExprKind::Closure(_, ref decl, ref body) => {
+            ast::ExprKind::Closure(_, ref decl, ref body, _fn_decl_span) => {
                 let mut id = String::from("$");
                 id.push_str(&ex.id.to_string());
                 self.process_formals(&decl.inputs, &id);
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index cea67f46db5..9190389b722 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1339,7 +1339,7 @@ fn build_cfg(tcx: &TyCtxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
         }
         Some(hir_map::NodeExpr(e)) => {
             match e.node {
-                hir::ExprClosure(_, _, ref blk) => blk,
+                hir::ExprClosure(_, _, ref blk, _) => blk,
                 _ => bug!("unexpected expr variant in has_nested_returns"),
             }
         }
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 89f3b295c8d..b9af0bbe3d1 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -990,7 +990,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 None => C_nil(cx),
             }
         },
-        hir::ExprClosure(_, ref decl, ref body) => {
+        hir::ExprClosure(_, ref decl, ref body, _) => {
             match ety.sty {
                 ty::TyClosure(def_id, ref substs) => {
                     closure::trans_closure_expr(closure::Dest::Ignore(cx),
diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs
index 4b1292e4086..3a8974c2aca 100644
--- a/src/librustc_trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/debuginfo/create_scope_map.rs
@@ -479,7 +479,7 @@ fn walk_expr(cx: &CrateContext,
             })
         }
 
-        hir::ExprClosure(_, ref decl, ref block) => {
+        hir::ExprClosure(_, ref decl, ref block, _) => {
             with_new_scope(cx,
                            block.span,
                            scope_stack,
diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs
index 6955d51cecc..cd11ca58689 100644
--- a/src/librustc_trans/expr.rs
+++ b/src/librustc_trans/expr.rs
@@ -1118,7 +1118,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         hir::ExprVec(..) | hir::ExprRepeat(..) => {
             tvec::trans_fixed_vstore(bcx, expr, dest)
         }
-        hir::ExprClosure(_, ref decl, ref body) => {
+        hir::ExprClosure(_, ref decl, ref body, _) => {
             let dest = match dest {
                 SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
                 Ignore => closure::Dest::Ignore(bcx.ccx())
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 67b91f7838c..d187f82c596 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -3530,7 +3530,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
       hir::ExprMatch(ref discrim, ref arms, match_src) => {
         _match::check_match(fcx, expr, &discrim, arms, expected, match_src);
       }
-      hir::ExprClosure(capture, ref decl, ref body) => {
+      hir::ExprClosure(capture, ref decl, ref body, _) => {
           closure::check_expr_closure(fcx, expr, capture, &decl, &body, expected);
       }
       hir::ExprBlock(ref b) => {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 2a4de6e091b..5efd57c4d1f 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -782,7 +782,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
             intravisit::walk_expr(rcx, expr);
         }
 
-        hir::ExprClosure(_, _, ref body) => {
+        hir::ExprClosure(_, _, ref body, _) => {
             check_expr_fn_block(rcx, expr, &body);
         }
 
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 40481cda762..c39e992eb36 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -98,7 +98,7 @@ struct SeedBorrowKind<'a,'tcx:'a> {
 impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            hir::ExprClosure(cc, _, ref body) => {
+            hir::ExprClosure(cc, _, ref body, _) => {
                 self.check_closure(expr, cc, &body);
             }
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 68327ccd39a..ad78740921c 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -156,7 +156,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         self.visit_method_map_entry(ResolvingExpr(e.span),
                                     MethodCall::expr(e.id));
 
-        if let hir::ExprClosure(_, ref decl, _) = e.node {
+        if let hir::ExprClosure(_, ref decl, _, _) = e.node {
             for input in &decl.inputs {
                 self.visit_node_id(ResolvingExpr(e.span), input.id);
             }
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index c20270e8306..70b3edac5c5 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -830,7 +830,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
+    pub fn keys(&self) -> Keys<K, V> {
         Keys { inner: self.iter() }
     }
 
@@ -852,7 +852,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+    pub fn values(&self) -> Values<K, V> {
         Values { inner: self.iter() }
     }
 
@@ -880,7 +880,7 @@ impl<K, V, S> HashMap<K, V, S>
     /// }
     /// ```
     #[unstable(feature = "map_values_mut", reason = "recently added", issue = "32551")]
-    pub fn values_mut<'a>(&'a mut self) -> ValuesMut<'a, K, V> {
+    pub fn values_mut<'a>(&'a mut self) -> ValuesMut<K, V> {
         ValuesMut { inner: self.iter_mut() }
     }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index df9f935446d..dc59d475286 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -986,7 +986,9 @@ pub enum ExprKind {
     /// A `match` block.
     Match(P<Expr>, Vec<Arm>),
     /// A closure (for example, `move |a, b, c| {a + b + c}`)
-    Closure(CaptureBy, P<FnDecl>, P<Block>),
+    ///
+    /// The final span is the span of the argument block `|...|`
+    Closure(CaptureBy, P<FnDecl>, P<Block>, Span),
     /// A block (`{ ... }`)
     Block(P<Block>),
 
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index a4e5b68277d..8ebf4863af5 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -194,10 +194,14 @@ pub trait AstBuilder {
                cond: P<ast::Expr>, then: P<ast::Expr>, els: Option<P<ast::Expr>>) -> P<ast::Expr>;
     fn expr_loop(&self, span: Span, block: P<ast::Block>) -> P<ast::Expr>;
 
-    fn lambda_fn_decl(&self, span: Span,
-                      fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr>;
+    fn lambda_fn_decl(&self,
+                      span: Span,
+                      fn_decl: P<ast::FnDecl>,
+                      blk: P<ast::Block>,
+                      fn_decl_span: Span)
+                      -> P<ast::Expr>;
 
-    fn lambda(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Block>) -> P<ast::Expr>;
+    fn lambda(&self, span: Span, ids: Vec<ast::Ident>, blk: P<ast::Block>) -> P<ast::Expr>;
     fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr>;
     fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr>;
 
@@ -894,17 +898,34 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr(span, ast::ExprKind::Loop(block, None))
     }
 
-    fn lambda_fn_decl(&self, span: Span,
-                      fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr> {
-        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk))
+    fn lambda_fn_decl(&self,
+                      span: Span,
+                      fn_decl: P<ast::FnDecl>,
+                      blk: P<ast::Block>,
+                      fn_decl_span: Span) // span of the `|...|` part
+                      -> P<ast::Expr> {
+        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
+                                               fn_decl,
+                                               blk,
+                                               fn_decl_span))
     }
-    fn lambda(&self, span: Span, ids: Vec<ast::Ident>, blk: P<ast::Block>) -> P<ast::Expr> {
+
+    fn lambda(&self,
+              span: Span,
+              ids: Vec<ast::Ident>,
+              blk: P<ast::Block>)
+              -> P<ast::Expr> {
         let fn_decl = self.fn_decl(
             ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
             self.ty_infer(span));
 
-        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk))
+        // FIXME -- We are using `span` as the span of the `|...|`
+        // part of the lambda, but it probably (maybe?) corresponds to
+        // the entire lambda body. Probably we should extend the API
+        // here, but that's not entirely clear.
+        self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk, span))
     }
+
     fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> {
         self.lambda(span, Vec::new(), blk)
     }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index cd7b0fcfb00..38132eb42ee 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -149,14 +149,17 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             fld.cx.expr(span, il).with_attrs(fold_thin_attrs(attrs, fld))
         }
 
-        ast::ExprKind::Closure(capture_clause, fn_decl, block) => {
+        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);
-            P(ast::Expr{id:id, node: new_node, span: fld.new_span(span),
-                        attrs: fold_thin_attrs(attrs, fld)})
+                                                  rewritten_fn_decl,
+                                                  rewritten_block,
+                                                  fld.new_span(fn_decl_span));
+            P(ast::Expr{ id:id,
+                         node: new_node,
+                         span: fld.new_span(span),
+                         attrs: fold_thin_attrs(attrs, fld) })
         }
 
         _ => {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 89451e79550..3f788a52d2b 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1241,10 +1241,11 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                 ExprKind::Match(folder.fold_expr(expr),
                           arms.move_map(|x| folder.fold_arm(x)))
             }
-            ExprKind::Closure(capture_clause, decl, body) => {
+            ExprKind::Closure(capture_clause, decl, body, span) => {
                 ExprKind::Closure(capture_clause,
-                            folder.fold_fn_decl(decl),
-                            folder.fold_block(body))
+                                  folder.fold_fn_decl(decl),
+                                  folder.fold_block(body),
+                                  folder.new_span(span))
             }
             ExprKind::Block(blk) => ExprKind::Block(folder.fold_block(blk)),
             ExprKind::Assign(el, er) => {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f3d3bbd9f99..a4284d0b674 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3225,13 +3225,15 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(lo, hi, ExprKind::IfLet(pat, expr, thn, els), attrs))
     }
 
-    // `|args| expr`
-    pub fn parse_lambda_expr(&mut self, lo: BytePos,
+    // `move |args| expr`
+    pub fn parse_lambda_expr(&mut self,
+                             lo: BytePos,
                              capture_clause: CaptureBy,
                              attrs: ThinAttributes)
                              -> PResult<'a, P<Expr>>
     {
         let decl = self.parse_fn_block_decl()?;
+        let decl_hi = self.last_span.hi;
         let body = match decl.output {
             FunctionRetTy::Default(_) => {
                 // If no explicit return type is given, parse any
@@ -3255,7 +3257,8 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(
             lo,
             body.span.hi,
-            ExprKind::Closure(capture_clause, decl, body), attrs))
+            ExprKind::Closure(capture_clause, decl, body, mk_sp(lo, decl_hi)),
+            attrs))
     }
 
     // `else` token already eaten
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 95f1b63168b..d2668669875 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -2086,7 +2086,7 @@ impl<'a> State<'a> {
                 }
                 self.bclose_(expr.span, INDENT_UNIT)?;
             }
-            ast::ExprKind::Closure(capture_clause, ref decl, ref body) => {
+            ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => {
                 self.print_capture_clause(capture_clause)?;
 
                 self.print_fn_block_args(&decl)?;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 413017c7271..f50a480e5e5 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -743,7 +743,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprKind::Closure(_, ref function_declaration, ref body) => {
+        ExprKind::Closure(_, ref function_declaration, ref body, _decl_span) => {
             visitor.visit_fn(FnKind::Closure,
                              function_declaration,
                              body,