syntax: don't fake a block around closures' bodies during parsing.

This commit is contained in:
Eduard Burtescu 2016-10-26 02:17:29 +03:00
parent da2ce22768
commit 49772fbf5d
16 changed files with 109 additions and 156 deletions

View File

@ -994,10 +994,10 @@ impl<'a> ast_visit::Visitor for EarlyContext<'a> {
}
fn visit_fn(&mut self, fk: ast_visit::FnKind, decl: &ast::FnDecl,
body: &ast::Block, span: Span, id: ast::NodeId) {
run_lints!(self, check_fn, early_passes, fk, decl, body, span, id);
ast_visit::walk_fn(self, fk, decl, body, span);
run_lints!(self, check_fn_post, early_passes, fk, decl, body, span, id);
span: Span, id: ast::NodeId) {
run_lints!(self, check_fn, early_passes, fk, decl, span, id);
ast_visit::walk_fn(self, fk, decl, span);
run_lints!(self, check_fn_post, early_passes, fk, decl, span, id);
}
fn visit_variant_data(&mut self,

View File

@ -200,9 +200,9 @@ pub trait EarlyLintPass: LintPass {
fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { }
fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { }
fn check_fn(&mut self, _: &EarlyContext,
_: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
_: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { }
fn check_fn_post(&mut self, _: &EarlyContext,
_: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
_: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { }
fn check_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
fn check_trait_item_post(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
fn check_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { }

View File

@ -295,11 +295,10 @@ impl<'v> ast_visit::Visitor for StatCollector<'v> {
fn visit_fn(&mut self,
fk: ast_visit::FnKind,
fd: &ast::FnDecl,
b: &ast::Block,
s: Span,
_: NodeId) {
self.record("FnDecl", Id::None, fd);
ast_visit::walk_fn(self, fk, fd, b, s)
ast_visit::walk_fn(self, fk, fd, s)
}
fn visit_trait_item(&mut self, ti: &ast::TraitItem) {

View File

@ -596,7 +596,6 @@ impl<'a> Visitor for Resolver<'a> {
fn visit_fn(&mut self,
function_kind: FnKind,
declaration: &FnDecl,
block: &Block,
_: Span,
node_id: NodeId) {
let rib_kind = match function_kind {
@ -604,13 +603,45 @@ impl<'a> Visitor for Resolver<'a> {
self.visit_generics(generics);
ItemRibKind
}
FnKind::Method(_, sig, _) => {
FnKind::Method(_, sig, _, _) => {
self.visit_generics(&sig.generics);
MethodRibKind(!sig.decl.has_self())
}
FnKind::Closure => ClosureRibKind(node_id),
FnKind::Closure(_) => ClosureRibKind(node_id),
};
self.resolve_function(rib_kind, declaration, block);
// Create a value rib for the function.
self.value_ribs.push(Rib::new(rib_kind));
// Create a label rib for the function.
self.label_ribs.push(Rib::new(rib_kind));
// Add each argument to the rib.
let mut bindings_list = FxHashMap();
for argument in &declaration.inputs {
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
self.visit_ty(&argument.ty);
debug!("(resolving function) recorded argument");
}
visit::walk_fn_ret_ty(self, &declaration.output);
// Resolve the function body.
match function_kind {
FnKind::ItemFn(.., body) |
FnKind::Method(.., body) => {
self.visit_block(body);
}
FnKind::Closure(body) => {
self.visit_expr(body);
}
};
debug!("(resolving function) leaving function");
self.label_ribs.pop();
self.value_ribs.pop();
}
}
@ -1856,36 +1887,6 @@ impl<'a> Resolver<'a> {
self.value_ribs.pop();
}
fn resolve_function(&mut self,
rib_kind: RibKind<'a>,
declaration: &FnDecl,
block: &Block) {
// Create a value rib for the function.
self.value_ribs.push(Rib::new(rib_kind));
// Create a label rib for the function.
self.label_ribs.push(Rib::new(rib_kind));
// Add each argument to the rib.
let mut bindings_list = FxHashMap();
for argument in &declaration.inputs {
self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
self.visit_ty(&argument.ty);
debug!("(resolving function) recorded argument");
}
visit::walk_fn_ret_ty(self, &declaration.output);
// Resolve the function body.
self.visit_block(block);
debug!("(resolving function) leaving function");
self.label_ribs.pop();
self.value_ribs.pop();
}
fn resolve_trait_reference(&mut self,
id: NodeId,
trait_path: &Path,

View File

@ -1414,7 +1414,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
}
// walk the body
self.nest(ex.id, |v| v.visit_block(&body));
self.nest(ex.id, |v| v.visit_expr(body));
}
ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) |
ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => {

View File

@ -1017,10 +1017,10 @@ pub enum ExprKind {
Loop(P<Block>, Option<SpannedIdent>),
/// A `match` block.
Match(P<Expr>, Vec<Arm>),
/// A closure (for example, `move |a, b, c| {a + b + c}`)
/// A closure (for example, `move |a, b, c| a + b + c`)
///
/// The final span is the span of the argument block `|...|`
Closure(CaptureBy, P<FnDecl>, P<Block>, Span),
Closure(CaptureBy, P<FnDecl>, P<Expr>, Span),
/// A block (`{ ... }`)
Block(P<Block>),

View File

@ -198,17 +198,13 @@ pub trait AstBuilder {
fn lambda_fn_decl(&self,
span: Span,
fn_decl: P<ast::FnDecl>,
blk: P<ast::Block>,
body: P<ast::Expr>,
fn_decl_span: Span)
-> 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>;
fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident> , blk: P<ast::Expr>) -> P<ast::Expr>;
fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr>;
fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
fn lambda(&self, span: Span, ids: Vec<ast::Ident>, body: P<ast::Expr>) -> P<ast::Expr>;
fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr>;
fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr>;
fn lambda_stmts(&self, span: Span, ids: Vec<ast::Ident>,
blk: Vec<ast::Stmt>) -> P<ast::Expr>;
@ -940,19 +936,19 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn lambda_fn_decl(&self,
span: Span,
fn_decl: P<ast::FnDecl>,
blk: P<ast::Block>,
body: P<ast::Expr>,
fn_decl_span: Span) // span of the `|...|` part
-> P<ast::Expr> {
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref,
fn_decl,
blk,
body,
fn_decl_span))
}
fn lambda(&self,
span: Span,
ids: Vec<ast::Ident>,
blk: P<ast::Block>)
body: P<ast::Expr>)
-> P<ast::Expr> {
let fn_decl = self.fn_decl(
ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
@ -962,26 +958,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
// 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))
self.expr(span, ast::ExprKind::Closure(ast::CaptureBy::Ref, fn_decl, body, span))
}
fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> {
self.lambda(span, Vec::new(), blk)
fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
self.lambda(span, Vec::new(), body)
}
fn lambda1(&self, span: Span, blk: P<ast::Block>, ident: ast::Ident) -> P<ast::Expr> {
self.lambda(span, vec![ident], blk)
}
fn lambda_expr(&self, span: Span, ids: Vec<ast::Ident>,
expr: P<ast::Expr>) -> P<ast::Expr> {
self.lambda(span, ids, self.block_expr(expr))
}
fn lambda_expr_0(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
self.lambda0(span, self.block_expr(expr))
}
fn lambda_expr_1(&self, span: Span, expr: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
self.lambda1(span, self.block_expr(expr), ident)
fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: ast::Ident) -> P<ast::Expr> {
self.lambda(span, vec![ident], body)
}
fn lambda_stmts(&self,
@ -989,14 +974,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
ids: Vec<ast::Ident>,
stmts: Vec<ast::Stmt>)
-> P<ast::Expr> {
self.lambda(span, ids, self.block(span, stmts))
self.lambda(span, ids, self.expr_block(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))
self.lambda0(span, self.expr_block(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), ident)
self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
}
fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg {

View File

@ -1228,12 +1228,11 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
fn visit_fn(&mut self,
fn_kind: FnKind,
fn_decl: &ast::FnDecl,
block: &ast::Block,
span: Span,
_node_id: NodeId) {
// check for const fn declarations
match fn_kind {
FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _) => {
FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) => {
gate_feature_post!(&self, const_fn, span, "const fn is unstable");
}
_ => {
@ -1245,13 +1244,13 @@ impl<'a> Visitor for PostExpansionVisitor<'a> {
}
match fn_kind {
FnKind::ItemFn(_, _, _, _, abi, _) |
FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => {
FnKind::ItemFn(_, _, _, _, abi, _, _) |
FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => {
self.check_abi(abi, span);
}
_ => {}
}
visit::walk_fn(self, fn_kind, fn_decl, block, span);
visit::walk_fn(self, fn_kind, fn_decl, span);
}
fn visit_trait_item(&mut self, ti: &ast::TraitItem) {

View File

@ -1201,7 +1201,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
ExprKind::Closure(capture_clause, decl, body, span) => {
ExprKind::Closure(capture_clause,
folder.fold_fn_decl(decl),
folder.fold_block(body),
folder.fold_expr(body),
folder.new_span(span))
}
ExprKind::Block(blk) => ExprKind::Block(folder.fold_block(blk)),

View File

@ -3162,25 +3162,12 @@ impl<'a> Parser<'a> {
let decl = self.parse_fn_block_decl()?;
let decl_hi = self.prev_span.hi;
let body = match decl.output {
FunctionRetTy::Default(_) => {
// If no explicit return type is given, parse any
// expr and wrap it up in a dummy block:
let body_expr = self.parse_expr()?;
P(ast::Block {
id: ast::DUMMY_NODE_ID,
span: body_expr.span,
stmts: vec![Stmt {
span: body_expr.span,
node: StmtKind::Expr(body_expr),
id: ast::DUMMY_NODE_ID,
}],
rules: BlockCheckMode::Default,
})
}
FunctionRetTy::Default(_) => self.parse_expr()?,
_ => {
// If an explicit return type is given, require a
// block to appear (RFC 968).
self.parse_block()?
let body_lo = self.span.lo;
self.parse_block_expr(body_lo, BlockCheckMode::Default, ThinVec::new())?
}
};

View File

@ -2128,26 +2128,8 @@ impl<'a> State<'a> {
try!(self.print_fn_block_args(&decl));
try!(space(&mut self.s));
let default_return = match decl.output {
ast::FunctionRetTy::Default(..) => true,
_ => false
};
match body.stmts.last().map(|stmt| &stmt.node) {
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));
} 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)),
}
try!(self.print_expr(body));
try!(self.end()); // need to close a box
// 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

View File

@ -75,9 +75,9 @@ impl Visitor for NodeCounter {
self.count += 1;
walk_generics(self, g)
}
fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId) {
fn visit_fn(&mut self, fk: FnKind, fd: &FnDecl, s: Span, _: NodeId) {
self.count += 1;
walk_fn(self, fk, fd, b, s)
walk_fn(self, fk, fd, s)
}
fn visit_trait_item(&mut self, ti: &TraitItem) {
self.count += 1;

View File

@ -31,13 +31,13 @@ use codemap::Spanned;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> {
/// fn foo() or extern "Abi" fn foo()
ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility),
ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility, &'a Block),
/// fn foo(&self)
Method(Ident, &'a MethodSig, Option<&'a Visibility>),
Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
/// |x, y| {}
Closure,
/// |x, y| body
Closure(&'a Expr),
}
/// Each method of the Visitor trait is a hook to be potentially
@ -68,8 +68,8 @@ pub trait Visitor: Sized {
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_fn(&mut self, fk: FnKind, fd: &FnDecl, s: Span, _: NodeId) {
walk_fn(self, fk, fd, s)
}
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) }
@ -246,9 +246,8 @@ pub fn walk_item<V: Visitor>(visitor: &mut V, item: &Item) {
}
ItemKind::Fn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety,
constness, abi, &item.vis),
constness, abi, &item.vis, body),
declaration,
body,
item.span,
item.id)
}
@ -519,24 +518,25 @@ pub fn walk_fn_decl<V: Visitor>(visitor: &mut V, function_declaration: &FnDecl)
visitor.visit_fn_ret_ty(&function_declaration.output)
}
pub fn walk_fn_kind<V: Visitor>(visitor: &mut V, function_kind: FnKind) {
match function_kind {
FnKind::ItemFn(_, generics, _, _, _, _) => {
visitor.visit_generics(generics);
}
FnKind::Method(_, ref sig, _) => {
visitor.visit_generics(&sig.generics);
}
FnKind::Closure => {}
}
}
pub fn walk_fn<V>(visitor: &mut V, kind: FnKind, declaration: &FnDecl, body: &Block, _span: Span)
pub fn walk_fn<V>(visitor: &mut V, kind: FnKind, declaration: &FnDecl, _span: Span)
where V: Visitor,
{
walk_fn_kind(visitor, kind);
walk_fn_decl(visitor, declaration);
visitor.visit_block(body)
match kind {
FnKind::ItemFn(_, generics, _, _, _, _, body) => {
visitor.visit_generics(generics);
walk_fn_decl(visitor, declaration);
visitor.visit_block(body);
}
FnKind::Method(_, ref sig, _, body) => {
visitor.visit_generics(&sig.generics);
walk_fn_decl(visitor, declaration);
visitor.visit_block(body);
}
FnKind::Closure(body) => {
walk_fn_decl(visitor, declaration);
visitor.visit_expr(body);
}
}
}
pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
@ -552,8 +552,8 @@ pub fn walk_trait_item<V: Visitor>(visitor: &mut V, trait_item: &TraitItem) {
walk_fn_decl(visitor, &sig.decl);
}
TraitItemKind::Method(ref sig, Some(ref body)) => {
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None), &sig.decl,
body, trait_item.span, trait_item.id);
visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None, body),
&sig.decl, trait_item.span, trait_item.id);
}
TraitItemKind::Type(ref bounds, ref default) => {
walk_list!(visitor, visit_ty_param_bound, bounds);
@ -575,8 +575,8 @@ pub fn walk_impl_item<V: Visitor>(visitor: &mut V, impl_item: &ImplItem) {
visitor.visit_expr(expr);
}
ImplItemKind::Method(ref sig, ref body) => {
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis)), &sig.decl,
body, impl_item.span, impl_item.id);
visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), body),
&sig.decl, impl_item.span, impl_item.id);
}
ImplItemKind::Type(ref ty) => {
visitor.visit_ty(ty);
@ -711,9 +711,8 @@ pub fn walk_expr<V: Visitor>(visitor: &mut V, expression: &Expr) {
walk_list!(visitor, visit_arm, arms);
}
ExprKind::Closure(_, ref function_declaration, ref body, _decl_span) => {
visitor.visit_fn(FnKind::Closure,
visitor.visit_fn(FnKind::Closure(body),
function_declaration,
body,
expression.span,
expression.id)
}

View File

@ -133,7 +133,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
cx.ident_of("read_struct"),
vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
cx.expr_usize(trait_span, nfields),
cx.lambda_expr_1(trait_span, result, blkarg)])
cx.lambda1(trait_span, result, blkarg)])
}
StaticEnum(_, ref fields) => {
let variant = cx.ident_of("i");
@ -165,7 +165,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
let result =
cx.expr_ok(trait_span,
cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms));
let lambda = cx.lambda_expr(trait_span, vec![blkarg, variant], result);
let lambda = cx.lambda(trait_span, vec![blkarg, variant], result);
let variant_vec = cx.expr_vec(trait_span, variants);
let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
let result = cx.expr_method_call(trait_span,
@ -176,7 +176,7 @@ fn decodable_substructure(cx: &mut ExtCtxt,
decoder,
cx.ident_of("read_enum"),
vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
cx.lambda_expr_1(trait_span, result, blkarg)])
cx.lambda1(trait_span, result, blkarg)])
}
_ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
};

View File

@ -197,7 +197,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
};
let self_ref = cx.expr_addr_of(span, self_.clone());
let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
let lambda = cx.lambda_expr_1(span, enc, blkarg);
let lambda = cx.lambda1(span, enc, blkarg);
let call = cx.expr_method_call(span,
blkencoder.clone(),
emit_struct_field,
@ -246,7 +246,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
let self_ref = cx.expr_addr_of(span, self_.clone());
let enc =
cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
let lambda = cx.lambda_expr_1(span, enc, blkarg);
let lambda = cx.lambda1(span, enc, blkarg);
let call = cx.expr_method_call(span,
blkencoder.clone(),
emit_variant_arg,
@ -273,7 +273,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
cx.expr_usize(trait_span, idx),
cx.expr_usize(trait_span, fields.len()),
blk]);
let blk = cx.lambda_expr_1(trait_span, call, blkarg);
let blk = cx.lambda1(trait_span, call, blkarg);
let ret = cx.expr_method_call(trait_span,
encoder,
cx.ident_of("emit_enum"),

View File

@ -12,5 +12,6 @@
// unless it uses braces.
fn main() {
let x = || -> i32 22; //~ ERROR expected `{`, found `22`
let x = || -> i32 22;
//~^ ERROR expected one of `!`, `(`, `::`, `<`, or `{`, found `22`
}