1
Fork 0

Merge the ExprFnBlock and ExprUnboxedClosure into one ExprClosure with an optional unboxed closure kind.

This commit is contained in:
Niko Matsakis 2014-11-19 11:18:17 -05:00
parent 8e44688889
commit 3e2929d362
27 changed files with 126 additions and 187 deletions

View file

@ -288,9 +288,12 @@ pub fn closure_to_block(closure_id: ast::NodeId,
match tcx.map.get(closure_id) { match tcx.map.get(closure_id) {
ast_map::NodeExpr(expr) => match expr.node { ast_map::NodeExpr(expr) => match expr.node {
ast::ExprProc(_, ref block) | ast::ExprProc(_, ref block) |
ast::ExprFnBlock(_, _, ref block) | ast::ExprClosure(_, _, _, ref block) => {
ast::ExprUnboxedFn(_, _, _, ref block) => { block.id } block.id
_ => panic!("encountered non-closure id: {}", closure_id) }
_ => {
panic!("encountered non-closure id: {}", closure_id)
}
}, },
_ => panic!("encountered non-expr id: {}", closure_id) _ => panic!("encountered non-expr id: {}", closure_id)
} }

View file

@ -496,9 +496,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
} }
ast::ExprMac(..) | ast::ExprMac(..) |
ast::ExprFnBlock(..) | ast::ExprClosure(..) |
ast::ExprProc(..) | ast::ExprProc(..) |
ast::ExprUnboxedFn(..) |
ast::ExprLit(..) | ast::ExprLit(..) |
ast::ExprPath(..) => { ast::ExprPath(..) => {
self.straightline(expr, pred, None::<ast::Expr>.iter()) self.straightline(expr, pred, None::<ast::Expr>.iter())

View file

@ -48,9 +48,8 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
self.visit_expr(&**e); self.visit_expr(&**e);
self.with_context(Loop, |v| v.visit_block(&**b)); self.with_context(Loop, |v| v.visit_block(&**b));
} }
ast::ExprFnBlock(_, _, ref b) | ast::ExprClosure(_, _, _, ref b) |
ast::ExprProc(_, ref b) | ast::ExprProc(_, ref b) => {
ast::ExprUnboxedFn(_, _, _, ref b) => {
self.with_context(Closure, |v| v.visit_block(&**b)); self.with_context(Closure, |v| v.visit_block(&**b));
} }
ast::ExprBreak(_) => self.require_loop("break", e.span), ast::ExprBreak(_) => self.require_loop("break", e.span),

View file

@ -496,8 +496,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
self.consume_expr(&**count); self.consume_expr(&**count);
} }
ast::ExprFnBlock(..) | ast::ExprClosure(..) |
ast::ExprUnboxedFn(..) |
ast::ExprProc(..) => { ast::ExprProc(..) => {
self.walk_captures(expr) self.walk_captures(expr)
} }

View file

@ -458,7 +458,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
} }
visit::walk_expr(ir, expr); visit::walk_expr(ir, expr);
} }
ast::ExprFnBlock(..) | ast::ExprProc(..) | ast::ExprUnboxedFn(..) => { ast::ExprClosure(..) | ast::ExprProc(..) => {
// Interesting control flow (for loops can contain labeled // Interesting control flow (for loops can contain labeled
// breaks or continues) // breaks or continues)
ir.add_live_node_for_node(expr.id, ExprNode(expr.span)); ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@ -975,10 +975,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_expr(&**e, succ) self.propagate_through_expr(&**e, succ)
} }
ast::ExprFnBlock(_, _, ref blk) | ast::ExprClosure(_, _, _, ref blk) |
ast::ExprProc(_, ref blk) | ast::ExprProc(_, ref blk) => {
ast::ExprUnboxedFn(_, _, _, ref blk) => { debug!("{} is an ExprClosure or ExprProc",
debug!("{} is an ExprFnBlock, ExprProc, or ExprUnboxedFn",
expr_to_string(expr)); expr_to_string(expr));
/* /*
@ -1495,7 +1494,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) | ast::ExprBreak(..) | ast::ExprAgain(..) | ast::ExprLit(_) |
ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) | ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
ast::ExprFnBlock(..) | ast::ExprProc(..) | ast::ExprUnboxedFn(..) | ast::ExprClosure(..) | ast::ExprProc(..) |
ast::ExprPath(..) | ast::ExprBox(..) | ast::ExprSlice(..) => { ast::ExprPath(..) | ast::ExprBox(..) | ast::ExprSlice(..) => {
visit::walk_expr(this, expr); visit::walk_expr(this, expr);
} }

View file

@ -520,8 +520,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
ast::ExprAddrOf(..) | ast::ExprCall(..) | ast::ExprAddrOf(..) | ast::ExprCall(..) |
ast::ExprAssign(..) | ast::ExprAssignOp(..) | ast::ExprAssign(..) | ast::ExprAssignOp(..) |
ast::ExprFnBlock(..) | ast::ExprProc(..) | ast::ExprClosure(..) | ast::ExprProc(..) |
ast::ExprUnboxedFn(..) | ast::ExprRet(..) | ast::ExprRet(..) |
ast::ExprUnary(..) | ast::ExprSlice(..) | ast::ExprUnary(..) | ast::ExprSlice(..) |
ast::ExprMethodCall(..) | ast::ExprCast(..) | ast::ExprMethodCall(..) | ast::ExprCast(..) |
ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) | ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
@ -693,9 +693,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
}; };
match fn_expr.node { match fn_expr.node {
ast::ExprFnBlock(_, _, ref body) |
ast::ExprProc(_, ref body) | ast::ExprProc(_, ref body) |
ast::ExprUnboxedFn(_, _, _, ref body) => body.id, ast::ExprClosure(_, _, _, ref body) => body.id,
_ => unreachable!() _ => unreachable!()
} }
}; };

View file

@ -50,8 +50,8 @@ use util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum}; use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField}; use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
use syntax::ast::{ExprFnBlock, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall}; use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
use syntax::ast::{ExprPath, ExprProc, ExprStruct, ExprUnboxedFn, FnDecl}; use syntax::ast::{ExprPath, ExprProc, ExprStruct, FnDecl};
use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics}; use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic, Generics};
use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod}; use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod};
use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct}; use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct};
@ -5903,24 +5903,19 @@ impl<'a> Resolver<'a> {
visit::walk_expr(self, expr); visit::walk_expr(self, expr);
} }
ExprFnBlock(capture_clause, ref fn_decl, ref block) => { ExprClosure(capture_clause, _, ref fn_decl, ref block) => {
self.capture_mode_map.insert(expr.id, capture_clause); self.capture_mode_map.insert(expr.id, capture_clause);
self.resolve_function(ClosureRibKind(expr.id, ast::DUMMY_NODE_ID), self.resolve_function(ClosureRibKind(expr.id, ast::DUMMY_NODE_ID),
Some(&**fn_decl), NoTypeParameters, Some(&**fn_decl), NoTypeParameters,
&**block); &**block);
} }
ExprProc(ref fn_decl, ref block) => { ExprProc(ref fn_decl, ref block) => {
self.capture_mode_map.insert(expr.id, ast::CaptureByValue); self.capture_mode_map.insert(expr.id, ast::CaptureByValue);
self.resolve_function(ClosureRibKind(expr.id, block.id), self.resolve_function(ClosureRibKind(expr.id, block.id),
Some(&**fn_decl), NoTypeParameters, Some(&**fn_decl), NoTypeParameters,
&**block); &**block);
} }
ExprUnboxedFn(capture_clause, _, ref fn_decl, ref block) => {
self.capture_mode_map.insert(expr.id, capture_clause);
self.resolve_function(ClosureRibKind(expr.id, block.id),
Some(&**fn_decl), NoTypeParameters,
&**block);
}
ExprStruct(ref path, _, _) => { ExprStruct(ref path, _, _) => {
// Resolve the path to the structure it goes to. We don't // Resolve the path to the structure it goes to. We don't

View file

@ -3922,9 +3922,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
ast::ExprTup(..) | ast::ExprTup(..) |
ast::ExprIf(..) | ast::ExprIf(..) |
ast::ExprMatch(..) | ast::ExprMatch(..) |
ast::ExprFnBlock(..) | ast::ExprClosure(..) |
ast::ExprProc(..) | ast::ExprProc(..) |
ast::ExprUnboxedFn(..) |
ast::ExprBlock(..) | ast::ExprBlock(..) |
ast::ExprRepeat(..) | ast::ExprRepeat(..) |
ast::ExprVec(..) => { ast::ExprVec(..) => {

View file

@ -1047,7 +1047,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
} }
ast::TyInfer => { ast::TyInfer => {
// TyInfer also appears as the type of arguments or return // TyInfer also appears as the type of arguments or return
// values in a ExprFnBlock, ExprProc, or ExprUnboxedFn, or as // values in a ExprClosure or ExprProc, or as
// the type of local variables. Both of these cases are // the type of local variables. Both of these cases are
// handled specially and will not descend into this routine. // handled specially and will not descend into this routine.
this.ty_infer(ast_ty.span) this.ty_infer(ast_ty.span)

View file

@ -26,12 +26,38 @@ use syntax::ast;
use syntax::ast_util; use syntax::ast_util;
use util::ppaux::Repr; use util::ppaux::Repr;
pub fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
expr: &ast::Expr, expr: &ast::Expr,
kind: ast::UnboxedClosureKind, opt_kind: Option<ast::UnboxedClosureKind>,
decl: &ast::FnDecl, decl: &ast::FnDecl,
body: &ast::Block, body: &ast::Block,
expected: Expectation<'tcx>) { expected: Expectation<'tcx>) {
match opt_kind {
None => { // old-school boxed closure
let region = astconv::opt_ast_region_to_region(fcx,
fcx.infcx(),
expr.span,
&None);
check_boxed_closure(fcx,
expr,
ty::RegionTraitStore(region, ast::MutMutable),
decl,
body,
expected);
}
Some(kind) => {
check_unboxed_closure(fcx, expr, kind, decl, body, expected)
}
}
}
fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
expr: &ast::Expr,
kind: ast::UnboxedClosureKind,
decl: &ast::FnDecl,
body: &ast::Block,
expected: Expectation<'tcx>) {
let expr_def_id = ast_util::local_def(expr.id); let expr_def_id = ast_util::local_def(expr.id);
let expected_sig_and_kind = match expected.resolve(fcx) { let expected_sig_and_kind = match expected.resolve(fcx) {
@ -215,12 +241,12 @@ fn deduce_unboxed_closure_expectations_from_obligations<'a,'tcx>(
} }
pub fn check_expr_fn<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, pub fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
expr: &ast::Expr, expr: &ast::Expr,
store: ty::TraitStore, store: ty::TraitStore,
decl: &ast::FnDecl, decl: &ast::FnDecl,
body: &ast::Block, body: &ast::Block,
expected: Expectation<'tcx>) { expected: Expectation<'tcx>) {
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
// Find the expected input/output types (if any). Substitute // Find the expected input/output types (if any). Substitute

View file

@ -2823,9 +2823,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}; };
for (i, arg) in args.iter().take(t).enumerate() { for (i, arg) in args.iter().take(t).enumerate() {
let is_block = match arg.node { let is_block = match arg.node {
ast::ExprFnBlock(..) | ast::ExprClosure(..) | ast::ExprProc(..) => true,
ast::ExprProc(..) |
ast::ExprUnboxedFn(..) => true,
_ => false _ => false
}; };
@ -4148,33 +4146,16 @@ fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
ast::ExprMatch(ref discrim, ref arms, _) => { ast::ExprMatch(ref discrim, ref arms, _) => {
_match::check_match(fcx, expr, &**discrim, arms.as_slice()); _match::check_match(fcx, expr, &**discrim, arms.as_slice());
} }
ast::ExprFnBlock(_, ref decl, ref body) => { ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
let region = astconv::opt_ast_region_to_region(fcx, closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);
fcx.infcx(),
expr.span,
&None);
closure::check_expr_fn(fcx,
expr,
ty::RegionTraitStore(region, ast::MutMutable),
&**decl,
&**body,
expected);
}
ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
closure::check_unboxed_closure(fcx,
expr,
kind,
&**decl,
&**body,
expected);
} }
ast::ExprProc(ref decl, ref body) => { ast::ExprProc(ref decl, ref body) => {
closure::check_expr_fn(fcx, closure::check_boxed_closure(fcx,
expr, expr,
ty::UniqTraitStore, ty::UniqTraitStore,
&**decl, &**decl,
&**body, &**body,
expected); expected);
} }
ast::ExprBlock(ref b) => { ast::ExprBlock(ref b) => {
check_block_with_expected(fcx, &**b, expected); check_block_with_expected(fcx, &**b, expected);

View file

@ -742,9 +742,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
visit::walk_expr(rcx, expr); visit::walk_expr(rcx, expr);
} }
ast::ExprFnBlock(_, _, ref body) |
ast::ExprProc(_, ref body) | ast::ExprProc(_, ref body) |
ast::ExprUnboxedFn(_, _, _, ref body) => { ast::ExprClosure(_, _, _, ref body) => {
check_expr_fn_block(rcx, expr, &**body); check_expr_fn_block(rcx, expr, &**body);
} }

View file

@ -122,9 +122,8 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
MethodCall::expr(e.id)); MethodCall::expr(e.id));
match e.node { match e.node {
ast::ExprFnBlock(_, ref decl, _) | ast::ExprClosure(_, _, ref decl, _) |
ast::ExprProc(ref decl, _) | ast::ExprProc(ref decl, _) => {
ast::ExprUnboxedFn(_, _, ref decl, _) => {
for input in decl.inputs.iter() { for input in decl.inputs.iter() {
let _ = self.visit_node_id(ResolvingExpr(e.span), let _ = self.visit_node_id(ResolvingExpr(e.span),
input.id); input.id);

View file

@ -241,8 +241,7 @@ mod svh_visitor {
SawExprIf, SawExprIf,
SawExprWhile, SawExprWhile,
SawExprMatch, SawExprMatch,
SawExprFnBlock, SawExprClosure,
SawExprUnboxedFn,
SawExprProc, SawExprProc,
SawExprBlock, SawExprBlock,
SawExprAssign, SawExprAssign,
@ -274,8 +273,7 @@ mod svh_visitor {
ExprWhile(..) => SawExprWhile, ExprWhile(..) => SawExprWhile,
ExprLoop(_, id) => SawExprLoop(id.map(content)), ExprLoop(_, id) => SawExprLoop(id.map(content)),
ExprMatch(..) => SawExprMatch, ExprMatch(..) => SawExprMatch,
ExprFnBlock(..) => SawExprFnBlock, ExprClosure(..) => SawExprClosure,
ExprUnboxedFn(..) => SawExprUnboxedFn,
ExprProc(..) => SawExprProc, ExprProc(..) => SawExprProc,
ExprBlock(..) => SawExprBlock, ExprBlock(..) => SawExprBlock,
ExprAssign(..) => SawExprAssign, ExprAssign(..) => SawExprAssign,

View file

@ -1345,7 +1345,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
"Expected struct type, but not ty_struct"), "Expected struct type, but not ty_struct"),
} }
}, },
ast::ExprFnBlock(_, ref decl, ref body) => { ast::ExprClosure(_, _, ref decl, ref body) => {
if generated_code(body.span) { if generated_code(body.span) {
return return
} }

View file

@ -1385,9 +1385,8 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
} }
Some(ast_map::NodeExpr(e)) => { Some(ast_map::NodeExpr(e)) => {
match e.node { match e.node {
ast::ExprFnBlock(_, _, ref blk) | ast::ExprClosure(_, _, _, ref blk) |
ast::ExprProc(_, ref blk) | ast::ExprProc(_, ref blk) => {
ast::ExprUnboxedFn(_, _, _, ref blk) => {
let mut explicit = CheckForNestedReturnsVisitor::explicit(); let mut explicit = CheckForNestedReturnsVisitor::explicit();
let mut implicit = CheckForNestedReturnsVisitor::implicit(); let mut implicit = CheckForNestedReturnsVisitor::implicit();
visit::walk_expr(&mut explicit, e); visit::walk_expr(&mut explicit, e);

View file

@ -1232,9 +1232,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
} }
ast_map::NodeExpr(ref expr) => { ast_map::NodeExpr(ref expr) => {
match expr.node { match expr.node {
ast::ExprFnBlock(_, ref fn_decl, ref top_level_block) |
ast::ExprProc(ref fn_decl, ref top_level_block) | ast::ExprProc(ref fn_decl, ref top_level_block) |
ast::ExprUnboxedFn(_, _, ref fn_decl, ref top_level_block) => { ast::ExprClosure(_, _, ref fn_decl, ref top_level_block) => {
let name = format!("fn{}", token::gensym("fn")); let name = format!("fn{}", token::gensym("fn"));
let name = token::str_to_ident(name.as_slice()); let name = token::str_to_ident(name.as_slice());
(name, &**fn_decl, (name, &**fn_decl,
@ -1310,7 +1309,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
file_metadata, file_metadata,
&mut function_name); &mut function_name);
// There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, // There is no ast_map::Path for ast::ExprClosure-type functions. For now,
// just don't put them into a namespace. In the future this could be improved // just don't put them into a namespace. In the future this could be improved
// somehow (storing a path in the ast_map, or construct a path using the // somehow (storing a path in the ast_map, or construct a path using the
// enclosing function). // enclosing function).
@ -3578,9 +3577,8 @@ fn populate_scope_map(cx: &CrateContext,
}) })
} }
ast::ExprFnBlock(_, ref decl, ref block) |
ast::ExprProc(ref decl, ref block) | ast::ExprProc(ref decl, ref block) |
ast::ExprUnboxedFn(_, _, ref decl, ref block) => { ast::ExprClosure(_, _, ref decl, ref block) => {
with_new_scope(cx, with_new_scope(cx,
block.span, block.span,
scope_stack, scope_stack,

View file

@ -77,6 +77,7 @@ use trans::machine::{llsize_of, llsize_of_alloc};
use trans::type_::Type; use trans::type_::Type;
use syntax::ast; use syntax::ast;
use syntax::ast_util;
use syntax::codemap; use syntax::codemap;
use syntax::print::pprust::{expr_to_string}; use syntax::print::pprust::{expr_to_string};
use syntax::ptr::P; use syntax::ptr::P;
@ -1059,16 +1060,23 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
ast::ExprVec(..) | ast::ExprRepeat(..) => { ast::ExprVec(..) | ast::ExprRepeat(..) => {
tvec::trans_fixed_vstore(bcx, expr, dest) tvec::trans_fixed_vstore(bcx, expr, dest)
} }
ast::ExprFnBlock(_, ref decl, ref body) | ast::ExprClosure(_, _, ref decl, ref body) |
ast::ExprProc(ref decl, ref body) => { ast::ExprProc(ref decl, ref body) => {
let expr_ty = expr_ty(bcx, expr); // Check the side-table to see whether this is an unboxed
let store = ty::ty_closure_store(expr_ty); // closure or an older, legacy style closure. Store this
debug!("translating block function {} with type {}", // into a variable to ensure the the RefCell-lock is
expr_to_string(expr), expr_ty.repr(tcx)); // released before we recurse.
closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest) let is_unboxed_closure =
} bcx.tcx().unboxed_closures.borrow().contains_key(&ast_util::local_def(expr.id));
ast::ExprUnboxedFn(_, _, ref decl, ref body) => { if is_unboxed_closure {
closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest) closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest)
} else {
let expr_ty = expr_ty(bcx, expr);
let store = ty::ty_closure_store(expr_ty);
debug!("translating block function {} with type {}",
expr_to_string(expr), expr_ty.repr(tcx));
closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest)
}
} }
ast::ExprCall(ref f, ref args) => { ast::ExprCall(ref f, ref args) => {
if bcx.tcx().is_method_call(expr.id) { if bcx.tcx().is_method_call(expr.id) {

View file

@ -667,9 +667,8 @@ pub enum Expr_ {
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic. // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprLoop(P<Block>, Option<Ident>), ExprLoop(P<Block>, Option<Ident>),
ExprMatch(P<Expr>, Vec<Arm>, MatchSource), ExprMatch(P<Expr>, Vec<Arm>, MatchSource),
ExprFnBlock(CaptureClause, P<FnDecl>, P<Block>), ExprClosure(CaptureClause, Option<UnboxedClosureKind>, P<FnDecl>, P<Block>),
ExprProc(P<FnDecl>, P<Block>), ExprProc(P<FnDecl>, P<Block>),
ExprUnboxedFn(CaptureClause, UnboxedClosureKind, P<FnDecl>, P<Block>),
ExprBlock(P<Block>), ExprBlock(P<Block>),
ExprAssign(P<Expr>, P<Expr>), ExprAssign(P<Expr>, P<Expr>),

View file

@ -37,7 +37,7 @@ use visit;
/// ///
/// More specifically, it is one of either: /// More specifically, it is one of either:
/// - A function item, /// - A function item,
/// - A closure expr (i.e. an ExprFnBlock or ExprProc), or /// - A closure expr (i.e. an ExprClosure or ExprProc), or
/// - The default implementation for a trait method. /// - The default implementation for a trait method.
/// ///
/// To construct one, use the `Code::from_node` function. /// To construct one, use the `Code::from_node` function.
@ -71,7 +71,7 @@ impl MaybeFnLike for ast::TraitItem {
impl MaybeFnLike for ast::Expr { impl MaybeFnLike for ast::Expr {
fn is_fn_like(&self) -> bool { fn is_fn_like(&self) -> bool {
match self.node { match self.node {
ast::ExprFnBlock(..) | ast::ExprProc(..) => true, ast::ExprClosure(..) | ast::ExprProc(..) => true,
_ => false, _ => false,
} }
} }
@ -215,7 +215,7 @@ impl<'a> FnLikeNode<'a> {
} }
} }
ast_map::NodeExpr(e) => match e.node { ast_map::NodeExpr(e) => match e.node {
ast::ExprFnBlock(_, ref decl, ref block) => ast::ExprClosure(_, _, ref decl, ref block) =>
closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
ast::ExprProc(ref decl, ref block) => ast::ExprProc(ref decl, ref block) =>
closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),

View file

@ -864,14 +864,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
fn lambda_fn_decl(&self, span: Span, fn lambda_fn_decl(&self, span: Span,
fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr> { fn_decl: P<ast::FnDecl>, blk: P<ast::Block>) -> P<ast::Expr> {
self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk)) self.expr(span, ast::ExprClosure(ast::CaptureByRef, None, fn_decl, blk))
} }
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( let fn_decl = self.fn_decl(
ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(), ids.iter().map(|id| self.arg(span, *id, self.ty_infer(span))).collect(),
self.ty_infer(span)); self.ty_infer(span));
self.expr(span, ast::ExprFnBlock(ast::CaptureByRef, fn_decl, blk)) self.expr(span, ast::ExprClosure(ast::CaptureByRef, None, fn_decl, blk))
} }
fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> { fn lambda0(&self, span: Span, blk: P<ast::Block>) -> P<ast::Expr> {
self.lambda(span, Vec::new(), blk) self.lambda(span, Vec::new(), blk)

View file

@ -207,10 +207,11 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
fld.cx.expr(span, ast::ExprForLoop(pat, head, body, opt_ident)) fld.cx.expr(span, ast::ExprForLoop(pat, head, body, opt_ident))
} }
ast::ExprFnBlock(capture_clause, fn_decl, block) => { ast::ExprClosure(capture_clause, opt_kind, fn_decl, block) => {
let (rewritten_fn_decl, rewritten_block) let (rewritten_fn_decl, rewritten_block)
= expand_and_rename_fn_decl_and_block(fn_decl, block, fld); = expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
let new_node = ast::ExprFnBlock(capture_clause, let new_node = ast::ExprClosure(capture_clause,
opt_kind,
rewritten_fn_decl, rewritten_fn_decl,
rewritten_block); rewritten_block);
P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)}) P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)})
@ -1555,7 +1556,7 @@ mod test {
0) 0)
} }
// closure arg hygiene (ExprFnBlock) // closure arg hygiene (ExprClosure)
// expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);} // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);}
#[test] fn closure_arg_hygiene(){ #[test] fn closure_arg_hygiene(){
run_renaming_test( run_renaming_test(

View file

@ -309,7 +309,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
fn visit_expr(&mut self, e: &ast::Expr) { fn visit_expr(&mut self, e: &ast::Expr) {
match e.node { match e.node {
ast::ExprUnboxedFn(..) => { ast::ExprClosure(_, Some(_), _, _) => {
self.gate_feature("unboxed_closures", self.gate_feature("unboxed_closures",
e.span, e.span,
"unboxed closures are a work-in-progress \ "unboxed closures are a work-in-progress \

View file

@ -1316,18 +1316,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
arms.move_map(|x| folder.fold_arm(x)), arms.move_map(|x| folder.fold_arm(x)),
source) source)
} }
ExprFnBlock(capture_clause, decl, body) => {
ExprFnBlock(capture_clause,
folder.fold_fn_decl(decl),
folder.fold_block(body))
}
ExprProc(decl, body) => { ExprProc(decl, body) => {
ExprProc(folder.fold_fn_decl(decl), ExprProc(folder.fold_fn_decl(decl),
folder.fold_block(body)) folder.fold_block(body))
} }
ExprUnboxedFn(capture_clause, kind, decl, body) => { ExprClosure(capture_clause, opt_kind, decl, body) => {
ExprUnboxedFn(capture_clause, ExprClosure(capture_clause,
kind, opt_kind,
folder.fold_fn_decl(decl), folder.fold_fn_decl(decl),
folder.fold_block(body)) folder.fold_block(body))
} }

View file

@ -25,10 +25,10 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprBreak, ExprCall, ExprCast};
use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice};
use ast::{ExprLit, ExprLoop, ExprMac}; use ast::{ExprLit, ExprLoop, ExprMac};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
use ast::{Once, Many}; use ast::{Once, Many};
use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
@ -2950,7 +2950,8 @@ impl<'a> Parser<'a> {
// `|args| expr` // `|args| expr`
pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause) pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause)
-> P<Expr> { -> P<Expr>
{
let lo = self.span.lo; let lo = self.span.lo;
let (decl, optional_unboxed_closure_kind) = let (decl, optional_unboxed_closure_kind) =
self.parse_fn_block_decl(); self.parse_fn_block_decl();
@ -2964,21 +2965,10 @@ impl<'a> Parser<'a> {
rules: DefaultBlock, rules: DefaultBlock,
}); });
match optional_unboxed_closure_kind { self.mk_expr(
Some(unboxed_closure_kind) => { lo,
self.mk_expr(lo, fakeblock.span.hi,
fakeblock.span.hi, ExprClosure(capture_clause, optional_unboxed_closure_kind, decl, fakeblock))
ExprUnboxedFn(capture_clause,
unboxed_closure_kind,
decl,
fakeblock))
}
None => {
self.mk_expr(lo,
fakeblock.span.hi,
ExprFnBlock(capture_clause, decl, fakeblock))
}
}
} }
pub fn parse_else_expr(&mut self) -> P<Expr> { pub fn parse_else_expr(&mut self) -> P<Expr> {

View file

@ -434,9 +434,8 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String {
fn needs_parentheses(expr: &ast::Expr) -> bool { fn needs_parentheses(expr: &ast::Expr) -> bool {
match expr.node { match expr.node {
ast::ExprAssign(..) | ast::ExprBinary(..) | ast::ExprAssign(..) | ast::ExprBinary(..) |
ast::ExprFnBlock(..) | ast::ExprProc(..) | ast::ExprClosure(..) | ast::ExprProc(..) |
ast::ExprUnboxedFn(..) | ast::ExprAssignOp(..) | ast::ExprAssignOp(..) | ast::ExprCast(..) => true,
ast::ExprCast(..) => true,
_ => false, _ => false,
} }
} }
@ -1652,49 +1651,11 @@ impl<'a> State<'a> {
} }
try!(self.bclose_(expr.span, indent_unit)); try!(self.bclose_(expr.span, indent_unit));
} }
ast::ExprFnBlock(capture_clause, ref decl, ref body) => { ast::ExprClosure(capture_clause, opt_kind, ref decl, ref body) => {
try!(self.print_capture_clause(capture_clause)); try!(self.print_capture_clause(capture_clause));
// in do/for blocks we don't want to show an empty try!(self.print_fn_block_args(&**decl, opt_kind));
// argument list, but at this point we don't know which
// we are inside.
//
// if !decl.inputs.is_empty() {
try!(self.print_fn_block_args(&**decl, None));
try!(space(&mut self.s)); try!(space(&mut self.s));
// }
if !body.stmts.is_empty() || !body.expr.is_some() {
try!(self.print_block_unclosed(&**body));
} else {
// we extract the block, so as not to create another set of boxes
match body.expr.as_ref().unwrap().node {
ast::ExprBlock(ref blk) => {
try!(self.print_block_unclosed(&**blk));
}
_ => {
// this is a bare expression
try!(self.print_expr(&**body.expr.as_ref().unwrap()));
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
// empty box to satisfy the close.
try!(self.ibox(0));
}
ast::ExprUnboxedFn(capture_clause, kind, ref decl, ref body) => {
try!(self.print_capture_clause(capture_clause));
// in do/for blocks we don't want to show an empty
// argument list, but at this point we don't know which
// we are inside.
//
// if !decl.inputs.is_empty() {
try!(self.print_fn_block_args(&**decl, Some(kind)));
try!(space(&mut self.s));
// }
if !body.stmts.is_empty() || !body.expr.is_some() { if !body.stmts.is_empty() || !body.expr.is_some() {
try!(self.print_block_unclosed(&**body)); try!(self.print_block_unclosed(&**body));

View file

@ -803,14 +803,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_arm(arm) visitor.visit_arm(arm)
} }
} }
ExprFnBlock(_, ref function_declaration, ref body) => { ExprClosure(_, _, ref function_declaration, ref body) => {
visitor.visit_fn(FkFnBlock,
&**function_declaration,
&**body,
expression.span,
expression.id)
}
ExprUnboxedFn(_, _, ref function_declaration, ref body) => {
visitor.visit_fn(FkFnBlock, visitor.visit_fn(FkFnBlock,
&**function_declaration, &**function_declaration,
&**body, &**body,