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

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