]> git.lizzy.rs Git - rust.git/commitdiff
Remove the explicit closure kind syntax from the parser and AST;
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 3 Feb 2015 16:34:05 +0000 (11:34 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Tue, 3 Feb 2015 16:56:16 +0000 (11:56 -0500)
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).

23 files changed:
src/librustc/middle/check_loop.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_resolve/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/expr.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/writeback.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/blocks.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/fold.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs

index 41ef55933cda2e841f14d54f9af249fdf29b0fa8..ea584407944abeaa89d657e1cf47953fa62700ef 100644 (file)
@@ -45,7 +45,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
             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),
index e40e04bdee86acc308e66d45cf80fccbea0b78c7..c0fabb2a3481d7c622145e6ec939388e7f49ee40 100644 (file)
@@ -959,7 +959,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
               self.propagate_through_expr(&**e, succ)
           }
 
-          ast::ExprClosure(_, _, _, ref blk) => {
+          ast::ExprClosure(_, _, ref blk) => {
               debug!("{} is an ExprClosure",
                      expr_to_string(expr));
 
index 1ae483be2696d83a93183a58d73da756e7ada219..156ff43e2bab3c690e1e491c6d33ace9dfef276f 100644 (file)
@@ -739,7 +739,7 @@ fn env_deref(&self,
             };
 
             match fn_expr.node {
-                ast::ExprClosure(_, _, _, ref body) => body.id,
+                ast::ExprClosure(_, _, ref body) => body.id,
                 _ => unreachable!()
             }
         };
index e5271cfde5a447f63063c74076afef3d430c07cf..b9d2b9ec263ab450480bf3fa02db5c5505a6dd28 100644 (file)
@@ -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
             }
             _ => {
index d87039cbaefc18b4e3fabb0f8ee304ca57389f00..dd739059ed0ddf13c10d19ea06ce7a9aab9a90bb 100644 (file)
@@ -4521,7 +4521,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 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);
index 7758039e40a418ddbf2a522ee0c55ad68f53f75a..b0ce9641cf440e8a658e9bcb314d129720692fbe 100644 (file)
@@ -1394,7 +1394,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                                                       type, found {:?}", ty)[]),
                 }
             },
-            ast::ExprClosure(_, _, ref decl, ref body) => {
+            ast::ExprClosure(_, ref decl, ref body) => {
                 if generated_code(body.span) {
                     return
                 }
index 9e561fc883bb043366e5c7de7198d9863b5e3323..6901eb25b31feb1dda95147af59f7ec977ba1b13 100644 (file)
@@ -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")
index 66bb299273d9f86aa7aa4861f7468f3eddf783b0..172e105896c304e90c5964fe110c1ecd869325f8 100644 (file)
@@ -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 walk_expr(cx: &CrateContext,
                 })
             }
 
-            ast::ExprClosure(_, _, ref decl, ref block) => {
+            ast::ExprClosure(_, ref decl, ref block) => {
                 with_new_scope(cx,
                                block.span,
                                scope_stack,
index bed43a5c838823e36f062f1faeab10063ab48344..df9e722569701dacf4092b09f614eb07faaef5d2 100644 (file)
@@ -1094,7 +1094,7 @@ fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
         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) => {
index 808dbd4b319109d331678b40c15b71b1ca451d21..b2a676e878e6302e556e8aab29e462d8942da6fb 100644 (file)
@@ -25,7 +25,6 @@
 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,
+    }
+}
+
+
index 07b67d543a87e4f21243c9ca9b17a55bf0b6aeb0..adf15fbf28a8f040708e9e9aaea3b371558fdd9a 100644 (file)
@@ -3736,8 +3736,8 @@ fn check_struct_fields_on_error<'a,'tcx>(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);
index d5baff3a0c4a37a0ba1cad683c2d2200576d0ae4..9df0403794d7c8e8bd03087dda0a33a387ab2a47 100644 (file)
@@ -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);
         }
 
index b52e01f9a7a7684dd39b362ccac0d3c91aaeb7b6..f452c8488ce1c7eb2fe900db03205d06889460ac 100644 (file)
@@ -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);
             }
 
index 52b1eb490cc257c23204268dc6f581b41bbeff28..f047a36c56095fcc3433b872c2edb9480f1addb7 100644 (file)
@@ -118,7 +118,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
                                     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);
index d7283db25a5f2eedc23e4347b721e79716b599ce..34eeedeaa7650bba3e232b1f6fe901982fb1071e 100644 (file)
@@ -48,7 +48,6 @@
 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 @@ pub fn descriptive_variant(&self) -> &str {
     }
 }
 
-#[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.
index 53787d71eef800c72d23d424bf1f95c145486ed5..a85b87f47d6ee0d1a9338f262a8344bed2624ff9 100644 (file)
@@ -218,7 +218,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                 }
             }
             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"),
             },
index 2b3a72126831e7d8a3ae69def8692ade112586e5..53c35ef34cd0d4293ed2803b08a26af76a62f710 100644 (file)
@@ -876,14 +876,14 @@ 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> {
-        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)
index 6eacb3440189454f279f31b05b9a03e3ac16eed7..77440914342fb2ef4a60710bf3c16376db58934b 100644 (file)
@@ -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)})
index 9012ec2114d07462f6b3783183ba3dea8953df6c..07b6af651f610eec1e10c9744fcd64d725657dfd 100644 (file)
@@ -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))
             }
index a3600506057af8737ff9b1e3c7b73d73005f6bfb..60de6c909b78bfc2d8fb7371bea068650da2a536 100644 (file)
@@ -27,6 +27,7 @@ pub enum ObsoleteSyntax {
     ProcType,
     ProcExpr,
     ClosureType,
+    ClosureKind,
 }
 
 pub trait ParserObsoleteMethods {
@@ -65,6 +66,10 @@ fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
                 "`|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"
index c3182602a4b89672cab1ff008c7b0a569a6d5946..385c0a48f870f8142f96b42b201fce3c3f8573ca 100644 (file)
@@ -28,8 +28,6 @@
 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::{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 @@ pub fn parse_proc_type(&mut self, lifetime_defs: Vec<ast::LifetimeDef>) -> Ty_ {
         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 @@ pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause)
                              -> 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 @@ pub fn parse_lambda_expr(&mut self, capture_clause: CaptureClause)
         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 @@ macro_rules! parse_remaining_arguments {
     }
 
     // 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.
index e6d895a49fcd77896657f8e1bedfaf6527e73f0f..ee8e207fa6c059b909914232d1d501cda015a9f0 100644 (file)
 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 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                 }
                 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 @@ pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl,
 
     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, "|"));
 
index bd84306fe17e06047ea235ddbe00cad15af31093..fbcfcaadf12b71c29782e0ae4d5944b92043232a 100644 (file)
@@ -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,