about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-05 23:51:00 +0000
committerbors <bors@rust-lang.org>2015-01-05 23:51:00 +0000
commitc7dd3c4d69aee1c4ad8cc220c194b176bba2ab62 (patch)
tree437b342261834278ef6b45fde186c5944eb4819e /src/libsyntax
parentf11f3e7baeba3f5acf08cc6fbfee559c00e9f96e (diff)
parenteb2506cc1bcf2011d4e8ce99ff7cf74c2c1d1493 (diff)
downloadrust-c7dd3c4d69aee1c4ad8cc220c194b176bba2ab62.tar.gz
rust-c7dd3c4d69aee1c4ad8cc220c194b176bba2ab62.zip
auto merge of #20578 : japaric/rust/no-more-bc, r=nmatsakis
This PR removes boxed closures from the language, the closure type syntax (`let f: |int| -> bool = /* ... */`) has been obsoleted. Move all your uses of closures to the new unboxed closure system (i.e. `Fn*` traits).

[breaking-change] patterns

- `lef f = || {}`

This binding used to type check to a boxed closure. Now that boxed closures are gone, you need to annotate the "kind" of the unboxed closure, i.e. you need pick one of these: `|&:| {}`, `|&mut:| {}` or `|:| {}`.

In the (near) future we'll have closure "kind" inference, so the compiler will infer which `Fn*` trait to use based on how the closure is used. Once this inference machinery is in place, we'll be able to remove the kind annotation from most closures.

- `type Alias<'a> = |int|:'a -> bool`

Use a trait object: `type Alias<'a> = Box<FnMut(int) -> bool + 'a>`. Use the `Fn*` trait that makes sense for your use case.

- `fn foo(&self, f: |uint| -> bool)`

In this case you can use either a trait object or an unboxed closure:

``` rust
fn foo(&self, f: F) where F: FnMut(uint) -> bool;
// or
fn foo(&self, f: Box<FnMut(uint) -> bool>);
```

- `struct Struct<'a> { f: |uint|:'a -> bool }`

Again, you can use either a trait object or an unboxed closure:

``` rust
struct Struct<F> where F: FnMut(uint) -> bool { f: F }
// or
struct Struct<'a> { f: Box<FnMut(uint) -> bool + 'a> }
```

- Using `|x, y| f(x, y)` for closure "borrows"

This comes up in recursive functions, consider the following (contrived) example:

``` rust
fn foo(x: uint, f: |uint| -> bool) -> bool {
    //foo(x / 2, f) && f(x)  // can't use this because `f` gets moved away in the `foo` call
    foo(x / 2, |x| f(x)) && f(x)  // instead "borrow" `f` in the `foo` call
}
```

If you attempt to do the same with unboxed closures you'll hit ""error: reached the recursion limit during monomorphization" (see #19596):

``` rust
fn foo<F>(x: uint, mut f: F) -> bool where F: FnMut(uint) -> bool {
    foo(x / 2, |x| f(x)) && f(x)
    //~^ error: reached the recursion limit during monomorphization
}
```

Instead you *should* be able to write this:

``` rust
fn foo<F>(x: uint, mut f: F) -> bool where F: FnMut(uint) -> bool {
    foo(x / 2, &mut f) && f(x)
    //~^ error: the trait `FnMut` is not implemented for the type `&mut F`
}
```

But as you see above `&mut F` doesn't implement the `FnMut` trait. `&mut F` *should* implement the `FnMut` and the above code *should* work, but due to a bug (see #18835) it doesn't (for now).

You can work around the issue by rewriting the function to take `&mut F` instead of `F`:

``` rust
fn foo<F>(x: uint, f: &mut F) -> bool where F: FnMut(uint) -> bool {
    foo(x / 2, f) && (*f)(x)
}
```

This finally works! However writing `foo(0, &mut |x| x == 0)` is unergonomic. So you can use a private helper function to avoid this:

``` rust
// public API function
pub fn foo<F>(x: uint, mut f: F) -> bool where F: FnMut(uint) -> bool {
    foo_(x, &mut f)
}

// private helper function
fn foo_<F>(x: uint, f: &mut F) -> bool where F: FnMut(uint) -> bool {
    foo_(x / 2, f) && (*f)(x)
}
```

Closes #14798

---

There is more cleanup to do: like renaming functions/types from `unboxed_closure` to just `closure`, removing more dead code, simplify functions which now have unused arguments, update the documentation, etc. But that can be done in another PR.

r? @nikomatsakis @aturon (You probably want to focus on the deleted/modified tests.)
cc @eddyb 
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ast_map/mod.rs3
-rw-r--r--src/libsyntax/ext/deriving/clone.rs2
-rw-r--r--src/libsyntax/ext/deriving/cmp/eq.rs6
-rw-r--r--src/libsyntax/ext/deriving/cmp/ord.rs8
-rw-r--r--src/libsyntax/ext/deriving/cmp/totaleq.rs4
-rw-r--r--src/libsyntax/ext/deriving/cmp/totalord.rs4
-rw-r--r--src/libsyntax/ext/deriving/decodable.rs2
-rw-r--r--src/libsyntax/ext/deriving/default.rs2
-rw-r--r--src/libsyntax/ext/deriving/encodable.rs2
-rw-r--r--src/libsyntax/ext/deriving/generic/mod.rs22
-rw-r--r--src/libsyntax/ext/deriving/hash.rs2
-rw-r--r--src/libsyntax/ext/deriving/primitive.rs4
-rw-r--r--src/libsyntax/ext/deriving/rand.rs2
-rw-r--r--src/libsyntax/ext/deriving/show.rs2
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/libsyntax/fold.rs11
-rw-r--r--src/libsyntax/parse/obsolete.rs5
-rw-r--r--src/libsyntax/parse/parser.rs40
-rw-r--r--src/libsyntax/print/pprust.rs19
-rw-r--r--src/libsyntax/visit.rs8
21 files changed, 49 insertions, 107 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index c9d27e304ff..e779821342a 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1220,8 +1220,6 @@ pub enum Ty_ {
     TyPtr(MutTy),
     /// A reference (`&'a T` or `&'a mut T`)
     TyRptr(Option<Lifetime>, MutTy),
-    /// A closure (e.g. `|uint| -> bool`)
-    TyClosure(P<ClosureTy>),
     /// A bare function (e.g. `fn(uint) -> bool`)
     TyBareFn(P<BareFnTy>),
     /// A tuple (`(A, B, C, D,...)`)
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index ce7b964959f..cf09e2777f7 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -859,9 +859,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
 
     fn visit_ty(&mut self, ty: &'ast Ty) {
         match ty.node {
-            TyClosure(ref fd) => {
-                self.visit_fn_decl(&*fd.decl);
-            }
             TyBareFn(ref fd) => {
                 self.visit_fn_decl(&*fd.decl);
             }
diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs
index eedec6f37c8..3c74a9f4431 100644
--- a/src/libsyntax/ext/deriving/clone.rs
+++ b/src/libsyntax/ext/deriving/clone.rs
@@ -40,7 +40,7 @@ pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt,
                 args: Vec::new(),
                 ret_ty: Self,
                 attributes: attrs,
-                combine_substructure: combine_substructure(|c, s, sub| {
+                combine_substructure: combine_substructure(box |c, s, sub| {
                     cs_clone("Clone", c, s, sub)
                 }),
             }
diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs
index 7a67fab820d..84d30a99004 100644
--- a/src/libsyntax/ext/deriving/cmp/eq.rs
+++ b/src/libsyntax/ext/deriving/cmp/eq.rs
@@ -40,7 +40,7 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt,
                 cx.expr_binary(span, ast::BiAnd, subexpr, eq)
             },
             cx.expr_bool(span, true),
-            |cx, span, _, _| cx.expr_bool(span, false),
+            box |cx, span, _, _| cx.expr_bool(span, false),
             cx, span, substr)
     }
     fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
@@ -57,7 +57,7 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt,
                 cx.expr_binary(span, ast::BiOr, subexpr, eq)
             },
             cx.expr_bool(span, false),
-            |cx, span, _, _| cx.expr_bool(span, true),
+            box |cx, span, _, _| cx.expr_bool(span, true),
             cx, span, substr)
     }
 
@@ -72,7 +72,7 @@ pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     $f(a, b, c)
                 })
             }
diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs
index c02416bfbea..f9c8d95b308 100644
--- a/src/libsyntax/ext/deriving/cmp/ord.rs
+++ b/src/libsyntax/ext/deriving/cmp/ord.rs
@@ -38,7 +38,7 @@ pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(Path::new(vec!("bool"))),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|cx, span, substr| {
+                combine_substructure: combine_substructure(box |cx, span, substr| {
                     cs_op($op, $equal, cx, span, substr)
                 })
             }
@@ -61,7 +61,7 @@ pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt,
         args: vec![borrowed_self()],
         ret_ty: ret_ty,
         attributes: attrs,
-        combine_substructure: combine_substructure(|cx, span, substr| {
+        combine_substructure: combine_substructure(box |cx, span, substr| {
             cs_partial_cmp(cx, span, substr)
         })
     };
@@ -174,7 +174,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
             cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
         },
         equals_expr.clone(),
-        |cx, span, (self_args, tag_tuple), _non_self_args| {
+        box |cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `deriving(PartialOrd)`")
             } else {
@@ -222,7 +222,7 @@ fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt,
             cx.expr_binary(span, ast::BiOr, cmp, and)
         },
         cx.expr_bool(span, equal),
-        |cx, span, (self_args, tag_tuple), _non_self_args| {
+        box |cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `deriving(PartialOrd)`")
             } else {
diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs
index 2b986bea122..cdb36ede65d 100644
--- a/src/libsyntax/ext/deriving/cmp/totaleq.rs
+++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs
@@ -32,7 +32,7 @@ pub fn expand_deriving_totaleq<F>(cx: &mut ExtCtxt,
             let block = cx.block(span, stmts, None);
             cx.expr_block(block)
         },
-                       |cx, sp, _, _| cx.span_bug(sp, "non matching enums in deriving(Eq)?"),
+                       box |cx, sp, _, _| cx.span_bug(sp, "non matching enums in deriving(Eq)?"),
                        cx,
                        span,
                        substr)
@@ -57,7 +57,7 @@ pub fn expand_deriving_totaleq<F>(cx: &mut ExtCtxt,
                 args: vec!(),
                 ret_ty: nil_ty(),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     cs_total_eq_assert(a, b, c)
                 })
             }
diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs
index 65a4c569b44..10ecc86bda5 100644
--- a/src/libsyntax/ext/deriving/cmp/totalord.rs
+++ b/src/libsyntax/ext/deriving/cmp/totalord.rs
@@ -41,7 +41,7 @@ pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt,
                 args: vec!(borrowed_self()),
                 ret_ty: Literal(Path::new(vec!("std", "cmp", "Ordering"))),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     cs_cmp(a, b, c)
                 }),
             }
@@ -130,7 +130,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
             cx.expr_block(cx.block(span, vec!(assign), Some(if_)))
         },
         cx.expr_path(equals_path.clone()),
-        |cx, span, (self_args, tag_tuple), _non_self_args| {
+        box |cx, span, (self_args, tag_tuple), _non_self_args| {
             if self_args.len() != 2 {
                 cx.span_bug(span, "not exactly 2 arguments in `deriving(Ord)`")
             } else {
diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs
index c0631b8350b..8094f0d3de8 100644
--- a/src/libsyntax/ext/deriving/decodable.rs
+++ b/src/libsyntax/ext/deriving/decodable.rs
@@ -76,7 +76,7 @@ fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt,
                     true
                 )),
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     decodable_substructure(a, b, c, krate)
                 }),
             })
diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs
index 49bcb26a4c2..047c4fef3c4 100644
--- a/src/libsyntax/ext/deriving/default.rs
+++ b/src/libsyntax/ext/deriving/default.rs
@@ -40,7 +40,7 @@ pub fn expand_deriving_default<F>(cx: &mut ExtCtxt,
                 args: Vec::new(),
                 ret_ty: Self,
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     default_substructure(a, b, c)
                 })
             })
diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs
index 4323d2979cc..0fceb0fbfda 100644
--- a/src/libsyntax/ext/deriving/encodable.rs
+++ b/src/libsyntax/ext/deriving/encodable.rs
@@ -152,7 +152,7 @@ fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt,
                     true
                 )),
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     encodable_substructure(a, b, c)
                 }),
             })
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 459abf15b33..1fb8189c63c 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -312,7 +312,7 @@ pub enum SubstructureFields<'a> {
 /// Combine the values of all the fields together. The last argument is
 /// all the fields of all the structures.
 pub type CombineSubstructureFunc<'a> =
-    |&mut ExtCtxt, Span, &Substructure|: 'a -> P<Expr>;
+    Box<FnMut(&mut ExtCtxt, Span, &Substructure) -> P<Expr> + 'a>;
 
 /// Deal with non-matching enum variants.  The tuple is a list of
 /// identifiers (one for each `Self` argument, which could be any of the
@@ -320,11 +320,7 @@ pub type CombineSubstructureFunc<'a> =
 /// holding the variant index value for each of the `Self` arguments.  The
 /// last argument is all the non-`Self` args of the method being derived.
 pub type EnumNonMatchCollapsedFunc<'a> =
-    |&mut ExtCtxt,
-     Span,
-     (&[Ident], &[Ident]),
-     &[P<Expr>]|: 'a
-     -> P<Expr>;
+    Box<FnMut(&mut ExtCtxt, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
 
 pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
     -> RefCell<CombineSubstructureFunc<'a>> {
@@ -606,7 +602,7 @@ impl<'a> MethodDef<'a> {
         };
         let mut f = self.combine_substructure.borrow_mut();
         let f: &mut CombineSubstructureFunc = &mut *f;
-        (*f)(cx, trait_.span, &substructure)
+        f.call_mut((cx, trait_.span, &substructure))
     }
 
     fn get_ret_ty(&self,
@@ -1341,7 +1337,7 @@ impl<'a> TraitDef<'a> {
 pub fn cs_fold<F>(use_foldl: bool,
                   mut f: F,
                   base: P<Expr>,
-                  enum_nonmatch_f: EnumNonMatchCollapsedFunc,
+                  mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
                   cx: &mut ExtCtxt,
                   trait_span: Span,
                   substructure: &Substructure)
@@ -1369,8 +1365,8 @@ pub fn cs_fold<F>(use_foldl: bool,
             }
         },
         EnumNonMatchingCollapsed(ref all_args, _, tuple) =>
-            enum_nonmatch_f(cx, trait_span, (all_args[], tuple),
-                            substructure.nonself_args),
+            enum_nonmatch_f.call_mut((cx, trait_span, (all_args[], tuple),
+                                      substructure.nonself_args)),
         StaticEnum(..) | StaticStruct(..) => {
             cx.span_bug(trait_span, "static function in `derive`")
         }
@@ -1387,7 +1383,7 @@ pub fn cs_fold<F>(use_foldl: bool,
 /// ```
 #[inline]
 pub fn cs_same_method<F>(f: F,
-                         enum_nonmatch_f: EnumNonMatchCollapsedFunc,
+                         mut enum_nonmatch_f: EnumNonMatchCollapsedFunc,
                          cx: &mut ExtCtxt,
                          trait_span: Span,
                          substructure: &Substructure)
@@ -1409,8 +1405,8 @@ pub fn cs_same_method<F>(f: F,
             f(cx, trait_span, called)
         },
         EnumNonMatchingCollapsed(ref all_self_args, _, tuple) =>
-            enum_nonmatch_f(cx, trait_span, (all_self_args[], tuple),
-                            substructure.nonself_args),
+            enum_nonmatch_f.call_mut((cx, trait_span, (all_self_args[], tuple),
+                                     substructure.nonself_args)),
         StaticEnum(..) | StaticStruct(..) => {
             cx.span_bug(trait_span, "static function in `derive`")
         }
diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs
index 9ff42d85cfb..b9acde4bf6b 100644
--- a/src/libsyntax/ext/deriving/hash.rs
+++ b/src/libsyntax/ext/deriving/hash.rs
@@ -55,7 +55,7 @@ pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
                 args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
                 ret_ty: nil_ty(),
                 attributes: attrs,
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     hash_substructure(a, b, c)
                 })
             }
diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs
index 8abd846373a..d36bb2cd1c2 100644
--- a/src/libsyntax/ext/deriving/primitive.rs
+++ b/src/libsyntax/ext/deriving/primitive.rs
@@ -46,7 +46,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                                            true)),
                 // #[inline] liable to cause code-bloat
                 attributes: attrs.clone(),
-                combine_substructure: combine_substructure(|c, s, sub| {
+                combine_substructure: combine_substructure(box |c, s, sub| {
                     cs_from("i64", c, s, sub)
                 }),
             },
@@ -62,7 +62,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                                            true)),
                 // #[inline] liable to cause code-bloat
                 attributes: attrs,
-                combine_substructure: combine_substructure(|c, s, sub| {
+                combine_substructure: combine_substructure(box |c, s, sub| {
                     cs_from("u64", c, s, sub)
                 }),
             })
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index 1ddf5b2a5c3..5517019f804 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -45,7 +45,7 @@ pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt,
                 ),
                 ret_ty: Self,
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     rand_substructure(a, b, c)
                 })
             }
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
index 0513c75cf57..eceac4e9a83 100644
--- a/src/libsyntax/ext/deriving/show.rs
+++ b/src/libsyntax/ext/deriving/show.rs
@@ -46,7 +46,7 @@ pub fn expand_deriving_show<F>(cx: &mut ExtCtxt,
                 args: vec!(fmtr),
                 ret_ty: Literal(Path::new(vec!("std", "fmt", "Result"))),
                 attributes: Vec::new(),
-                combine_substructure: combine_substructure(|a, b, c| {
+                combine_substructure: combine_substructure(box |a, b, c| {
                     show_substructure(a, b, c)
                 })
             }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index f8ac34cfe29..cb6277069e1 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -364,12 +364,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
     }
 
     fn visit_ty(&mut self, t: &ast::Ty) {
-        if let ast::TyClosure(ref closure) =  t.node {
-            // this used to be blocked by a feature gate, but it should just
-            // be plain impossible right now
-            assert!(closure.onceness != ast::Once);
-        }
-
         visit::walk_ty(self, t);
     }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 35b2e5dbc53..396b0033b81 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -414,17 +414,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyRptr(region, mt) => {
                 TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
             }
-            TyClosure(f) => {
-                TyClosure(f.map(|ClosureTy {unsafety, onceness, bounds, decl, lifetimes}| {
-                    ClosureTy {
-                        unsafety: unsafety,
-                        onceness: onceness,
-                        bounds: fld.fold_bounds(bounds),
-                        decl: fld.fold_fn_decl(decl),
-                        lifetimes: fld.fold_lifetime_defs(lifetimes)
-                    }
-                }))
-            }
             TyBareFn(f) => {
                 TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
                     lifetimes: fld.fold_lifetime_defs(lifetimes),
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index e1e456f880e..75b2c17b81b 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -34,6 +34,7 @@ pub enum ObsoleteSyntax {
     ObsoleteExternCrateRenaming,
     ObsoleteProcType,
     ObsoleteProcExpr,
+    ObsoleteClosureType,
 }
 
 pub trait ParserObsoleteMethods {
@@ -94,6 +95,10 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
             ObsoleteExternCrateRenaming => (
                 "`extern crate foo = bar` syntax",
                 "write `extern crate bar as foo` instead"
+            ),
+            ObsoleteClosureType => (
+                "`|uint| -> bool` closure type syntax",
+                "use unboxed closures instead, no type annotation needed"
             )
         };
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cc67079e538..28c7293fc26 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -14,7 +14,7 @@ pub use self::PathParsingMode::*;
 use self::ItemOrViewItem::*;
 
 use abi;
-use ast::{AssociatedType, BareFnTy, ClosureTy};
+use ast::{AssociatedType, BareFnTy};
 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::{ProvidedMethod, Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
@@ -30,7 +30,6 @@ use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
 use ast::{ExprMethodCall, ExprParen, ExprPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
-use ast::{Many};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
@@ -55,7 +54,7 @@ use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
 use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
 use ast::{TtDelimited, TtSequence, TtToken};
 use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
-use ast::{TypeField, TyFixedLengthVec, TyClosure, TyBareFn};
+use ast::{TypeField, TyFixedLengthVec, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
 use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
@@ -1227,38 +1226,29 @@ impl<'a> Parser<'a> {
 
         */
 
-        let unsafety = self.parse_unsafety();
+        let ty_closure_span = self.last_span;
 
-        let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
+        // To be helpful, parse the closure type as ever
+        let _ = self.parse_unsafety();
 
-        let inputs = if self.eat(&token::OrOr) {
-            Vec::new()
-        } else {
+        let _ = self.parse_legacy_lifetime_defs(lifetime_defs);
+
+        if !self.eat(&token::OrOr) {
             self.expect_or();
 
-            let inputs = self.parse_seq_to_before_or(
+            let _ = self.parse_seq_to_before_or(
                 &token::Comma,
                 |p| p.parse_arg_general(false));
             self.expect_or();
-            inputs
-        };
+        }
 
-        let bounds = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
+        let _ = self.parse_colon_then_ty_param_bounds(BoundParsingMode::Bare);
 
-        let output = self.parse_ret_ty();
-        let decl = P(FnDecl {
-            inputs: inputs,
-            output: output,
-            variadic: false
-        });
+        let _ = self.parse_ret_ty();
 
-        TyClosure(P(ClosureTy {
-            unsafety: unsafety,
-            onceness: Many,
-            bounds: bounds,
-            decl: decl,
-            lifetimes: lifetime_defs,
-        }))
+        self.obsolete(ty_closure_span, ObsoleteClosureType);
+
+        TyInfer
     }
 
     pub fn parse_unsafety(&mut self) -> Unsafety {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 61b7aa408a8..e44cc2257c2 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -714,25 +714,6 @@ impl<'a> State<'a> {
                                       Some(&generics),
                                       None));
             }
-            ast::TyClosure(ref f) => {
-                let generics = ast::Generics {
-                    lifetimes: f.lifetimes.clone(),
-                    ty_params: OwnedSlice::empty(),
-                    where_clause: ast::WhereClause {
-                        id: ast::DUMMY_NODE_ID,
-                        predicates: Vec::new(),
-                    },
-                };
-                try!(self.print_ty_fn(None,
-                                      Some('&'),
-                                      f.unsafety,
-                                      f.onceness,
-                                      &*f.decl,
-                                      None,
-                                      &f.bounds,
-                                      Some(&generics),
-                                      None));
-            }
             ast::TyPath(ref path, _) => {
                 try!(self.print_path(path, false));
             }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 054a288a69e..737f1b73b32 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -404,14 +404,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
                 visitor.visit_ty(&**tuple_element_type)
             }
         }
-        TyClosure(ref function_declaration) => {
-            for argument in function_declaration.decl.inputs.iter() {
-                visitor.visit_ty(&*argument.ty)
-            }
-            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_ty_param_bounds_helper(visitor, &function_declaration.bounds);
-            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
-        }
         TyBareFn(ref function_declaration) => {
             for argument in function_declaration.decl.inputs.iter() {
                 visitor.visit_ty(&*argument.ty)