diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2015-02-03 11:34:05 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2015-02-03 11:56:16 -0500 |
| commit | 04311341197ddabc420a8cffc0d26c12228d445b (patch) | |
| tree | 4c28b4373079ca63d53bfe6ee1250500113cf982 | |
| parent | 47f18659ff629792f49b5ed87e870687703831fe (diff) | |
| download | rust-04311341197ddabc420a8cffc0d26c12228d445b.tar.gz rust-04311341197ddabc420a8cffc0d26c12228d445b.zip | |
Remove the explicit closure kind syntax from the parser and AST;
upgrade the inference based on expected type so that it is able to infer the fn kind in isolation even if the full signature is not available (and we could perhaps do better still in some cases, such as extracting just the types of the arguments but not the return value).
| -rw-r--r-- | src/librustc/middle/check_loop.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/liveness.rs | 2 | ||||
| -rw-r--r-- | src/librustc/middle/mem_categorization.rs | 2 | ||||
| -rw-r--r-- | src/librustc_borrowck/borrowck/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_resolve/lib.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/save/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/base.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/debuginfo.rs | 4 | ||||
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/closure.rs | 151 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 4 | ||||
| -rw-r--r-- | src/librustc_typeck/check/regionck.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/upvar.rs | 2 | ||||
| -rw-r--r-- | src/librustc_typeck/check/writeback.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ast_map/blocks.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 62 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 2 |
23 files changed, 155 insertions, 136 deletions
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index 41ef55933cd..ea584407944 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -45,7 +45,7 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> { ast::ExprLoop(ref b, _) => { self.with_context(Loop, |v| v.visit_block(&**b)); } - ast::ExprClosure(_, _, _, ref b) => { + ast::ExprClosure(_, _, ref b) => { self.with_context(Closure, |v| v.visit_block(&**b)); } ast::ExprBreak(_) => self.require_loop("break", e.span), diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index e40e04bdee8..c0fabb2a348 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -959,7 +959,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&**e, succ) } - ast::ExprClosure(_, _, _, ref blk) => { + ast::ExprClosure(_, _, ref blk) => { debug!("{} is an ExprClosure", expr_to_string(expr)); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 1ae483be269..156ff43e2ba 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -739,7 +739,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> { }; match fn_expr.node { - ast::ExprClosure(_, _, _, ref body) => body.id, + ast::ExprClosure(_, _, ref body) => body.id, _ => unreachable!() } }; diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index e5271cfde5a..b9d2b9ec263 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -324,7 +324,7 @@ pub fn closure_to_block(closure_id: ast::NodeId, tcx: &ty::ctxt) -> ast::NodeId { match tcx.map.get(closure_id) { ast_map::NodeExpr(expr) => match expr.node { - ast::ExprClosure(_, _, _, ref block) => { + ast::ExprClosure(_, _, ref block) => { block.id } _ => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d87039cbaef..dd739059ed0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -4521,7 +4521,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { visit::walk_expr(self, expr); } - ExprClosure(_, _, ref fn_decl, ref block) => { + ExprClosure(_, ref fn_decl, ref block) => { self.resolve_function(ClosureRibKind(expr.id), Some(&**fn_decl), NoTypeParameters, &**block); diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 7758039e40a..b0ce9641cf4 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1394,7 +1394,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { type, found {:?}", ty)[]), } }, - ast::ExprClosure(_, _, ref decl, ref body) => { + ast::ExprClosure(_, ref decl, ref body) => { if generated_code(body.span) { return } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 9e561fc883b..6901eb25b31 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -1340,7 +1340,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) } Some(ast_map::NodeExpr(e)) => { match e.node { - ast::ExprClosure(_, _, _, ref blk) => { + ast::ExprClosure(_, _, ref blk) => { blk } _ => tcx.sess.bug("unexpected expr variant in has_nested_returns") diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 66bb299273d..172e105896c 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -1283,7 +1283,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ast_map::NodeExpr(ref expr) => { match expr.node { - ast::ExprClosure(_, _, 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 = token::str_to_ident(&name[]); (name, &**fn_decl, @@ -3595,7 +3595,7 @@ fn create_scope_map(cx: &CrateContext, }) } - ast::ExprClosure(_, _, ref decl, ref block) => { + ast::ExprClosure(_, ref decl, ref block) => { with_new_scope(cx, block.span, scope_stack, diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index bed43a5c838..df9e7225697 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -1094,7 +1094,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ast::ExprVec(..) | ast::ExprRepeat(..) => { tvec::trans_fixed_vstore(bcx, expr, dest) } - ast::ExprClosure(_, _, ref decl, ref body) => { + ast::ExprClosure(_, ref decl, ref body) => { closure::trans_closure_expr(bcx, &**decl, &**body, expr.id, dest) } ast::ExprCall(ref f, ref args) => { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 808dbd4b319..b2a676e878e 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -25,7 +25,6 @@ use util::ppaux::Repr; pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &ast::Expr, _capture: ast::CaptureClause, - opt_kind: Option<ast::ClosureKind>, decl: &'tcx ast::FnDecl, body: &'tcx ast::Block, expected: Expectation<'tcx>) { @@ -33,38 +32,14 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr.repr(fcx.tcx()), expected.repr(fcx.tcx())); - let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| { - deduce_expectations_from_expected_type(fcx, ty) - }); - - match opt_kind { - None => { - // If users didn't specify what sort of closure they want, - // examine the expected type. For now, if we see explicit - // evidence than an unboxed closure is desired, we'll use - // that. Otherwise, we leave it unspecified, to be filled - // in by upvar inference. - match expected_sig_and_kind { - None => { // don't have information about the kind, request explicit annotation - check_closure(fcx, expr, None, decl, body, None); - }, - Some((sig, kind)) => { - check_closure(fcx, expr, Some(kind), decl, body, Some(sig)); - } - } - } - - Some(kind) => { - let kind = match kind { - ast::FnClosureKind => ty::FnClosureKind, - ast::FnMutClosureKind => ty::FnMutClosureKind, - ast::FnOnceClosureKind => ty::FnOnceClosureKind, - }; - - let expected_sig = expected_sig_and_kind.map(|t| t.0); - check_closure(fcx, expr, Some(kind), decl, body, expected_sig); - } - } + // It's always helpful for inference if we know the kind of + // closure sooner rather than later, so first examine the expected + // type, and see if can glean a closure kind from there. + let (expected_sig,expected_kind) = match expected.to_option(fcx) { + Some(ty) => deduce_expectations_from_expected_type(fcx, ty), + None => (None, None) + }; + check_closure(fcx, expr, expected_kind, decl, body, expected_sig) } fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, @@ -133,21 +108,30 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fn deduce_expectations_from_expected_type<'a,'tcx>( fcx: &FnCtxt<'a,'tcx>, expected_ty: Ty<'tcx>) - -> Option<(ty::FnSig<'tcx>,ty::ClosureKind)> + -> (Option<ty::FnSig<'tcx>>,Option<ty::ClosureKind>) { + debug!("deduce_expectations_from_expected_type(expected_ty={})", + expected_ty.repr(fcx.tcx())); + match expected_ty.sty { ty::ty_trait(ref object_type) => { let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(), fcx.tcx().types.err); - proj_bounds.iter() - .filter_map(|pb| deduce_expectations_from_projection(fcx, pb)) - .next() + let expectations = + proj_bounds.iter() + .filter_map(|pb| deduce_expectations_from_projection(fcx, pb)) + .next(); + + match expectations { + Some((sig, kind)) => (Some(sig), Some(kind)), + None => (None, None) + } } ty::ty_infer(ty::TyVar(vid)) => { deduce_expectations_from_obligations(fcx, vid) } _ => { - None + (None, None) } } } @@ -155,33 +139,61 @@ fn deduce_expectations_from_expected_type<'a,'tcx>( fn deduce_expectations_from_obligations<'a,'tcx>( fcx: &FnCtxt<'a,'tcx>, expected_vid: ty::TyVid) - -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)> + -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>) { let fulfillment_cx = fcx.inh.fulfillment_cx.borrow(); // Here `expected_ty` is known to be a type inference variable. - fulfillment_cx.pending_obligations() - .iter() - .filter_map(|obligation| { - match obligation.predicate { - ty::Predicate::Projection(ref proj_predicate) => { - let trait_ref = proj_predicate.to_poly_trait_ref(); - let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty()); - match self_ty.sty { - ty::ty_infer(ty::TyVar(v)) if expected_vid == v => { - deduce_expectations_from_projection(fcx, proj_predicate) - } - _ => { - None - } - } - } - _ => { - None - } - } - }) - .next() + let expected_sig_and_kind = + fulfillment_cx + .pending_obligations() + .iter() + .filter_map(|obligation| { + debug!("deduce_expectations_from_obligations: obligation.predicate={}", + obligation.predicate.repr(fcx.tcx())); + + match obligation.predicate { + // Given a Projection predicate, we can potentially infer + // the complete signature. + ty::Predicate::Projection(ref proj_predicate) => { + let trait_ref = proj_predicate.to_poly_trait_ref(); + self_type_matches_expected_vid(fcx, trait_ref, expected_vid) + .and_then(|_| deduce_expectations_from_projection(fcx, proj_predicate)) + } + _ => { + None + } + } + }) + .next(); + + match expected_sig_and_kind { + Some((sig, kind)) => { return (Some(sig), Some(kind)); } + None => { } + } + + // Even if we can't infer the full signature, we may be able to + // infer the kind. This can occur if there is a trait-reference + // like `F : Fn<A>`. + let expected_kind = + fulfillment_cx + .pending_obligations() + .iter() + .filter_map(|obligation| { + let opt_trait_ref = match obligation.predicate { + ty::Predicate::Projection(ref data) => Some(data.to_poly_trait_ref()), + ty::Predicate::Trait(ref data) => Some(data.to_poly_trait_ref()), + ty::Predicate::Equate(..) => None, + ty::Predicate::RegionOutlives(..) => None, + ty::Predicate::TypeOutlives(..) => None, + }; + opt_trait_ref + .and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid)) + .and_then(|trait_ref| fcx.tcx().lang_items.fn_trait_kind(trait_ref.def_id())) + }) + .next(); + + (None, expected_kind) } /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce @@ -229,3 +241,20 @@ fn deduce_expectations_from_projection<'a,'tcx>( return Some((fn_sig, kind)); } +fn self_type_matches_expected_vid<'a,'tcx>( + fcx: &FnCtxt<'a,'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + expected_vid: ty::TyVid) + -> Option<ty::PolyTraitRef<'tcx>> +{ + let self_ty = fcx.infcx().shallow_resolve(trait_ref.self_ty()); + debug!("self_type_matches_expected_vid(trait_ref={}, self_ty={})", + trait_ref.repr(fcx.tcx()), + self_ty.repr(fcx.tcx())); + match self_ty.sty { + ty::ty_infer(ty::TyVar(v)) if expected_vid == v => Some(trait_ref), + _ => None, + } +} + + diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 07b67d543a8..adf15fbf28a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3736,8 +3736,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ast::ExprMatch(ref discrim, ref arms, match_src) => { _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src); } - ast::ExprClosure(capture, opt_kind, ref decl, ref body) => { - closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected); + ast::ExprClosure(capture, ref decl, ref body) => { + closure::check_expr_closure(fcx, expr, capture, &**decl, &**body, expected); } ast::ExprBlock(ref b) => { check_block_with_expected(fcx, &**b, expected); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index d5baff3a0c4..9df0403794d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -638,7 +638,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { visit::walk_expr(rcx, expr); } - ast::ExprClosure(_, _, _, ref body) => { + ast::ExprClosure(_, _, ref body) => { check_expr_fn_block(rcx, expr, &**body); } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index b52e01f9a7a..f452c8488ce 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -83,7 +83,7 @@ struct SeedBorrowKind<'a,'tcx:'a> { impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> { fn visit_expr(&mut self, expr: &ast::Expr) { match expr.node { - ast::ExprClosure(cc, _, _, ref body) => { + ast::ExprClosure(cc, _, ref body) => { self.check_closure(expr, cc, &**body); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 52b1eb490cc..f047a36c560 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -118,7 +118,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> { MethodCall::expr(e.id)); match e.node { - ast::ExprClosure(_, _, ref decl, _) => { + ast::ExprClosure(_, ref decl, _) => { for input in &decl.inputs { let _ = self.visit_node_id(ResolvingExpr(e.span), input.id); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d7283db25a5..34eeedeaa76 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -48,7 +48,6 @@ pub use self::TraitItem::*; pub use self::Ty_::*; pub use self::TyParamBound::*; pub use self::UintTy::*; -pub use self::ClosureKind::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; pub use self::VariantKind::*; @@ -736,7 +735,7 @@ 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), - ExprClosure(CaptureClause, Option<ClosureKind>, P<FnDecl>, P<Block>), + ExprClosure(CaptureClause, P<FnDecl>, P<Block>), ExprBlock(P<Block>), ExprAssign(P<Expr>, P<Expr>), @@ -1687,13 +1686,6 @@ impl ForeignItem_ { } } -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum ClosureKind { - FnClosureKind, - FnMutClosureKind, - FnOnceClosureKind, -} - /// The data we save and restore about an inlined item or method. This is not /// part of the AST that we parse from a file, but it becomes part of the tree /// that we trans. diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 53787d71eef..a85b87f47d6 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -218,7 +218,7 @@ impl<'a> FnLikeNode<'a> { } } ast_map::NodeExpr(e) => match e.node { - ast::ExprClosure(_, _, ref decl, ref block) => + ast::ExprClosure(_, ref decl, ref block) => closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), _ => panic!("expr FnLikeNode that is not fn-like"), }, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 2b3a7212683..53c35ef34cd 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -876,14 +876,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::ExprClosure(ast::CaptureByRef, None, fn_decl, blk)) + self.expr(span, ast::ExprClosure(ast::CaptureByRef, 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::ExprClosure(ast::CaptureByRef, None, fn_decl, blk)) + self.expr(span, ast::ExprClosure(ast::CaptureByRef, 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 6eacb344018..77440914342 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -322,11 +322,10 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { fld.cx.expr_match(span, into_iter_expr, vec![iter_arm]) } - ast::ExprClosure(capture_clause, opt_kind, fn_decl, block) => { + ast::ExprClosure(capture_clause, fn_decl, block) => { let (rewritten_fn_decl, rewritten_block) = expand_and_rename_fn_decl_and_block(fn_decl, block, fld); 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)}) diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 9012ec2114d..07b6af651f6 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -1325,9 +1325,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> arms.move_map(|x| folder.fold_arm(x)), source) } - ExprClosure(capture_clause, opt_kind, decl, body) => { + ExprClosure(capture_clause, decl, body) => { ExprClosure(capture_clause, - opt_kind, folder.fold_fn_decl(decl), folder.fold_block(body)) } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index a3600506057..60de6c909b7 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -27,6 +27,7 @@ pub enum ObsoleteSyntax { ProcType, ProcExpr, ClosureType, + ClosureKind, } pub trait ParserObsoleteMethods { @@ -65,6 +66,10 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { "`|usize| -> bool` closure type syntax", "use unboxed closures instead, no type annotation needed" ), + ObsoleteSyntax::ClosureKind => ( + "`:`, `&mut:`, or `&:` syntax", + "rely on inference instead" + ), ObsoleteSyntax::Sized => ( "`Sized? T` syntax for removing the `Sized` bound", "write `T: ?Sized` instead" diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c3182602a4b..385c0a48f87 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -28,8 +28,6 @@ use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; -use ast::{FnClosureKind, FnMutClosureKind}; -use ast::{FnOnceClosureKind}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; @@ -57,7 +55,7 @@ use ast::{TyFixedLengthVec, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; -use ast::{TypeImplItem, TypeTraitItem, Typedef, ClosureKind}; +use ast::{TypeImplItem, TypeTraitItem, Typedef,}; use ast::{UnnamedField, UnsafeBlock}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause}; @@ -1139,29 +1137,36 @@ impl<'a> Parser<'a> { TyInfer } - /// Parses an optional closure kind (`&:`, `&mut:`, or `:`). - pub fn parse_optional_closure_kind(&mut self) -> Option<ClosureKind> { - if self.check(&token::BinOp(token::And)) && - self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && - self.look_ahead(2, |t| *t == token::Colon) { + /// Parses an obsolete closure kind (`&:`, `&mut:`, or `:`). + pub fn parse_obsolete_closure_kind(&mut self) { + // let lo = self.span.lo; + if + self.check(&token::BinOp(token::And)) && + self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && + self.look_ahead(2, |t| *t == token::Colon) + { self.bump(); self.bump(); self.bump(); - return Some(FnMutClosureKind) - } - - if self.token == token::BinOp(token::And) && - self.look_ahead(1, |t| *t == token::Colon) { + } else if + self.token == token::BinOp(token::And) && + self.look_ahead(1, |t| *t == token::Colon) + { self.bump(); self.bump(); - return Some(FnClosureKind) - } - - if self.eat(&token::Colon) { - return Some(FnOnceClosureKind) + return; + } else if + self.eat(&token::Colon) + { + /* nothing */ + } else { + return; } - return None + // SNAP a45e117 + // Enable these obsolete errors after snapshot: + // let span = mk_sp(lo, self.span.hi); + // self.obsolete(span, ObsoleteSyntax::ClosureKind); } pub fn parse_ty_bare_fn_or_ty_closure(&mut self, lifetime_defs: Vec<LifetimeDef>) -> Ty_ { @@ -3047,7 +3052,7 @@ impl<'a> Parser<'a> { -> P<Expr> { let lo = self.span.lo; - let (decl, optional_closure_kind) = self.parse_fn_block_decl(); + let decl = self.parse_fn_block_decl(); let body = self.parse_expr(); let fakeblock = P(ast::Block { id: ast::DUMMY_NODE_ID, @@ -3060,7 +3065,7 @@ impl<'a> Parser<'a> { self.mk_expr( lo, fakeblock.span.hi, - ExprClosure(capture_clause, optional_closure_kind, decl, fakeblock)) + ExprClosure(capture_clause, decl, fakeblock)) } pub fn parse_else_expr(&mut self) -> P<Expr> { @@ -4529,30 +4534,29 @@ impl<'a> Parser<'a> { } // parse the |arg, arg| header on a lambda - fn parse_fn_block_decl(&mut self) -> (P<FnDecl>, Option<ClosureKind>) { - let (optional_closure_kind, inputs_captures) = { + fn parse_fn_block_decl(&mut self) -> P<FnDecl> { + let inputs_captures = { if self.eat(&token::OrOr) { - (None, Vec::new()) + Vec::new() } else { self.expect(&token::BinOp(token::Or)); - let optional_closure_kind = - self.parse_optional_closure_kind(); + self.parse_obsolete_closure_kind(); let args = self.parse_seq_to_before_end( &token::BinOp(token::Or), seq_sep_trailing_allowed(token::Comma), |p| p.parse_fn_block_arg() ); self.bump(); - (optional_closure_kind, args) + args } }; let output = self.parse_ret_ty(); - (P(FnDecl { + P(FnDecl { inputs: inputs_captures, output: output, variadic: false - }), optional_closure_kind) + }) } /// Parses the `(arg, arg) -> return_type` header on a procedure. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e6d895a49fc..ee8e207fa6c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -11,11 +11,9 @@ pub use self::AnnNode::*; use abi; -use ast::{self, FnClosureKind, FnMutClosureKind}; -use ast::{FnOnceClosureKind}; +use ast; use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem}; -use ast::{ClosureKind}; use ast_util; use owned_slice::OwnedSlice; use attr::{AttrMetaMethods, AttributeMethods}; @@ -350,7 +348,7 @@ pub fn method_to_string(p: &ast::Method) -> String { } pub fn fn_block_to_string(p: &ast::FnDecl) -> String { - $to_string(|s| s.print_fn_block_args(p, None)) + $to_string(|s| s.print_fn_block_args(p)) } pub fn path_to_string(p: &ast::Path) -> String { @@ -1747,10 +1745,10 @@ impl<'a> State<'a> { } try!(self.bclose_(expr.span, indent_unit)); } - ast::ExprClosure(capture_clause, opt_kind, ref decl, ref body) => { + ast::ExprClosure(capture_clause, ref decl, ref body) => { try!(self.print_capture_clause(capture_clause)); - try!(self.print_fn_block_args(&**decl, opt_kind)); + try!(self.print_fn_block_args(&**decl)); try!(space(&mut self.s)); if !body.stmts.is_empty() || !body.expr.is_some() { @@ -2350,16 +2348,9 @@ impl<'a> State<'a> { pub fn print_fn_block_args( &mut self, - decl: &ast::FnDecl, - closure_kind: Option<ClosureKind>) + decl: &ast::FnDecl) -> IoResult<()> { try!(word(&mut self.s, "|")); - match closure_kind { - None => {} - Some(FnClosureKind) => try!(self.word_space("&:")), - Some(FnMutClosureKind) => try!(self.word_space("&mut:")), - Some(FnOnceClosureKind) => try!(self.word_space(":")), - } try!(self.print_fn_args(decl, None)); try!(word(&mut self.s, "|")); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index bd84306fe17..fbcfcaadf12 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -836,7 +836,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_arm(arm) } } - ExprClosure(_, _, ref function_declaration, ref body) => { + ExprClosure(_, ref function_declaration, ref body) => { visitor.visit_fn(FkFnBlock, &**function_declaration, &**body, |
