diff options
| author | bors <bors@rust-lang.org> | 2014-11-20 12:01:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-11-20 12:01:44 +0000 |
| commit | 1d81776209cfa2b5cb1825bdbf3965a7a7f0440a (patch) | |
| tree | 43c3aa55ebfb5fd8b24173e1315a4212346bbd8f /src/libsyntax | |
| parent | b825b3496aff1ed784f7a7ca935245208b95aabb (diff) | |
| parent | b9c5cd4dc420b90874784b253bcb8fd4ac72441a (diff) | |
| download | rust-1d81776209cfa2b5cb1825bdbf3965a7a7f0440a.tar.gz rust-1d81776209cfa2b5cb1825bdbf3965a7a7f0440a.zip | |
auto merge of #19113 : nikomatsakis/rust/unboxed-boxed-closure-unification, r=acrichto
Use the expected type to infer the argument/return types of unboxed closures. Also, in `||` expressions, use the expected type to decide if the result should be a boxed or unboxed closure (and if an unboxed closure, what kind). This supercedes PR #19089, which was already reviewed by @pcwalton.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ast_map/blocks.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 47 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 9 |
9 files changed, 27 insertions, 88 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index e3058c0a248..5d4fd2704a2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -667,9 +667,8 @@ pub enum Expr_ { // FIXME #6993: change to Option<Name> ... or not, if these are hygienic. ExprLoop(P<Block>, Option<Ident>), 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>), - ExprUnboxedFn(CaptureClause, UnboxedClosureKind, P<FnDecl>, P<Block>), ExprBlock(P<Block>), ExprAssign(P<Expr>, P<Expr>), diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index a35ee3ab1d0..8db12fbd835 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -37,7 +37,7 @@ use visit; /// /// More specifically, it is one of either: /// - 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. /// /// To construct one, use the `Code::from_node` function. @@ -71,7 +71,7 @@ impl MaybeFnLike for ast::TraitItem { impl MaybeFnLike for ast::Expr { fn is_fn_like(&self) -> bool { match self.node { - ast::ExprFnBlock(..) | ast::ExprProc(..) => true, + ast::ExprClosure(..) | ast::ExprProc(..) => true, _ => false, } } @@ -215,7 +215,7 @@ impl<'a> FnLikeNode<'a> { } } 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)), ast::ExprProc(ref decl, ref block) => closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index ffc42b67033..b18a0c8411c 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -864,14 +864,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn lambda_fn_decl(&self, span: Span, 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> { 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::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> { self.lambda(span, Vec::new(), blk) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 081456bebe1..04132679a03 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -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)) } - ast::ExprFnBlock(capture_clause, fn_decl, block) => { + ast::ExprClosure(capture_clause, opt_kind, fn_decl, block) => { let (rewritten_fn_decl, rewritten_block) = 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_block); P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)}) @@ -1555,7 +1556,7 @@ mod test { 0) } - // closure arg hygiene (ExprFnBlock) + // closure arg hygiene (ExprClosure) // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);} #[test] fn closure_arg_hygiene(){ run_renaming_test( diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 460a94a8d5a..9635f0175f0 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -309,7 +309,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprUnboxedFn(..) => { + ast::ExprClosure(_, Some(_), _, _) => { self.gate_feature("unboxed_closures", e.span, "unboxed closures are a work-in-progress \ diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 2e6ee49f0ff..1bdf9ea73df 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1326,18 +1326,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> arms.move_map(|x| folder.fold_arm(x)), source) } - ExprFnBlock(capture_clause, decl, body) => { - ExprFnBlock(capture_clause, - folder.fold_fn_decl(decl), - folder.fold_block(body)) - } ExprProc(decl, body) => { ExprProc(folder.fold_fn_decl(decl), folder.fold_block(body)) } - ExprUnboxedFn(capture_clause, kind, decl, body) => { - ExprUnboxedFn(capture_clause, - kind, + ExprClosure(capture_clause, opt_kind, decl, body) => { + ExprClosure(capture_clause, + opt_kind, folder.fold_fn_decl(decl), folder.fold_block(body)) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a6fe3902395..ab0543d64b7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -25,10 +25,10 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; 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::{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::{Once, Many}; use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; @@ -2999,7 +2999,8 @@ impl<'a> Parser<'a> { // `|args| expr` pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause) - -> P<Expr> { + -> P<Expr> + { let lo = self.span.lo; let (decl, optional_unboxed_closure_kind) = self.parse_fn_block_decl(); @@ -3013,21 +3014,10 @@ impl<'a> Parser<'a> { rules: DefaultBlock, }); - match optional_unboxed_closure_kind { - Some(unboxed_closure_kind) => { - self.mk_expr(lo, - fakeblock.span.hi, - ExprUnboxedFn(capture_clause, - unboxed_closure_kind, - decl, - fakeblock)) - } - None => { - self.mk_expr(lo, - fakeblock.span.hi, - ExprFnBlock(capture_clause, decl, fakeblock)) - } - } + self.mk_expr( + lo, + fakeblock.span.hi, + ExprClosure(capture_clause, optional_unboxed_closure_kind, decl, fakeblock)) } pub fn parse_else_expr(&mut self) -> P<Expr> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8e7804aaa71..5652a9a9d3a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -444,9 +444,8 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { fn needs_parentheses(expr: &ast::Expr) -> bool { match expr.node { ast::ExprAssign(..) | ast::ExprBinary(..) | - ast::ExprFnBlock(..) | ast::ExprProc(..) | - ast::ExprUnboxedFn(..) | ast::ExprAssignOp(..) | - ast::ExprCast(..) => true, + ast::ExprClosure(..) | ast::ExprProc(..) | + ast::ExprAssignOp(..) | ast::ExprCast(..) => true, _ => false, } } @@ -1662,49 +1661,11 @@ impl<'a> State<'a> { } 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)); - // 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, None)); + try!(self.print_fn_block_args(&**decl, opt_kind)); 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() { try!(self.print_block_unclosed(&**body)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 41a7ce7d78e..a0bdd739113 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -815,14 +815,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_arm(arm) } } - ExprFnBlock(_, ref function_declaration, ref body) => { - visitor.visit_fn(FkFnBlock, - &**function_declaration, - &**body, - expression.span, - expression.id) - } - ExprUnboxedFn(_, _, ref function_declaration, ref body) => { + ExprClosure(_, _, ref function_declaration, ref body) => { visitor.visit_fn(FkFnBlock, &**function_declaration, &**body, |
