thread tighter span for closures around

Track the span corresponding to the `|...|` part of the closure.
This commit is contained in:
Niko Matsakis 2016-04-20 14:44:07 -04:00 committed by Manish Goregaokar
parent 23ccaddaa7
commit ecd10f04ce
29 changed files with 87 additions and 53 deletions

View File

@ -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) => {

View File

@ -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,

View File

@ -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)),

View File

@ -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,

View File

@ -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>),

View File

@ -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)?;

View File

@ -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,

View File

@ -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));

View File

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

View File

@ -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
}
_ => {

View File

@ -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");
}

View File

@ -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),

View File

@ -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);

View File

@ -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"),
}
}

View File

@ -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),

View File

@ -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,

View File

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

View File

@ -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) => {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

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

View File

@ -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>),

View File

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

View File

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

View File

@ -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) => {

View File

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

View File

@ -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)?;

View File

@ -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,