From ecd10f04cea34352ff240b0462d40cd1d95a4e0f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 20 Apr 2016 14:44:07 -0400 Subject: thread tighter span for closures around Track the span corresponding to the `|...|` part of the closure. --- src/libsyntax/ast.rs | 4 +++- src/libsyntax/ext/build.rs | 37 +++++++++++++++++++++++++++++-------- src/libsyntax/ext/expand.rs | 13 ++++++++----- src/libsyntax/fold.rs | 7 ++++--- src/libsyntax/parse/parser.rs | 9 ++++++--- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- 7 files changed, 52 insertions(+), 22 deletions(-) (limited to 'src/libsyntax') 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, Vec), /// A closure (for example, `move |a, b, c| {a + b + c}`) - Closure(CaptureBy, P, P), + /// + /// The final span is the span of the argument block `|...|` + Closure(CaptureBy, P, P, Span), /// A block (`{ ... }`) Block(P), 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, then: P, els: Option>) -> P; fn expr_loop(&self, span: Span, block: P) -> P; - fn lambda_fn_decl(&self, span: Span, - fn_decl: P, blk: P) -> P; + fn lambda_fn_decl(&self, + span: Span, + fn_decl: P, + blk: P, + fn_decl_span: Span) + -> P; - fn lambda(&self, span: Span, ids: Vec , blk: P) -> P; + fn lambda(&self, span: Span, ids: Vec, blk: P) -> P; fn lambda0(&self, span: Span, blk: P) -> P; fn lambda1(&self, span: Span, blk: P, ident: ast::Ident) -> P; @@ -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, blk: P) -> P { - self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, blk)) + fn lambda_fn_decl(&self, + span: Span, + fn_decl: P, + blk: P, + fn_decl_span: Span) // span of the `|...|` part + -> P { + self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, + fn_decl, + blk, + fn_decl_span)) } - fn lambda(&self, span: Span, ids: Vec, blk: P) -> P { + + fn lambda(&self, + span: Span, + ids: Vec, + blk: P) + -> P { 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) -> P { 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, fld: &mut MacroExpander) -> P { 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(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> { 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, -- cgit 1.4.1-3-g733a5