about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-01-31 17:12:29 -0800
committerNiko Matsakis <niko@alum.mit.edu>2013-02-07 05:53:30 -0800
commita32498d8464e0dfa4e2cb31967a66e076da40109 (patch)
tree62fc02049c4d06ccd64a704f6f9e3af53d2835e3 /src/libsyntax
parent82d73963334f01b818cda767b44cd0c8f3baf4cc (diff)
downloadrust-a32498d8464e0dfa4e2cb31967a66e076da40109.tar.gz
rust-a32498d8464e0dfa4e2cb31967a66e076da40109.zip
Make ~fn non-copyable, make &fn copyable, split barefn/closure types,
correct handling of moves for struct-record update.

Part of #3678.  Fixes #2828, #3904, #4719.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs82
-rw-r--r--src/libsyntax/attr.rs6
-rw-r--r--src/libsyntax/codemap.rs4
-rw-r--r--src/libsyntax/ext/auto_encode.rs2
-rw-r--r--src/libsyntax/ext/build.rs2
-rw-r--r--src/libsyntax/fold.rs15
-rw-r--r--src/libsyntax/parse/classify.rs6
-rw-r--r--src/libsyntax/parse/parser.rs170
-rw-r--r--src/libsyntax/print/pprust.rs110
-rw-r--r--src/libsyntax/syntax.rc1
-rw-r--r--src/libsyntax/visit.rs15
11 files changed, 243 insertions, 170 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bc808495ca3..574ce281e28 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -399,16 +399,46 @@ pub impl mutability : cmp::Eq {
 #[auto_encode]
 #[auto_decode]
 #[deriving_eq]
-pub enum Proto {
-    ProtoBare,     // bare functions (deprecated)
-    ProtoUniq,     // ~fn
-    ProtoBox,      // @fn
-    ProtoBorrowed, // &fn
+pub enum Abi {
+    RustAbi
 }
 
-pub impl Proto : to_bytes::IterBytes {
+pub impl Abi : to_bytes::IterBytes {
     pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
-        (*self as uint).iter_bytes(lsb0, f);
+        (*self as uint).iter_bytes(lsb0, f)
+    }
+}
+
+pub impl Abi : ToStr {
+    pure fn to_str(&self) -> ~str {
+        match *self {
+            RustAbi => ~"\"rust\""
+        }
+    }
+}
+
+#[auto_encode]
+#[auto_decode]
+#[deriving_eq]
+pub enum Sigil {
+    BorrowedSigil,
+    OwnedSigil,
+    ManagedSigil
+}
+
+pub impl Sigil : to_bytes::IterBytes {
+    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+        (*self as uint).iter_bytes(lsb0, f)
+    }
+}
+
+pub impl Sigil : ToStr {
+    pure fn to_str(&self) -> ~str {
+        match *self {
+            BorrowedSigil => ~"&",
+            OwnedSigil => ~"~",
+            ManagedSigil => ~"@"
+         }
     }
 }
 
@@ -434,13 +464,6 @@ pub enum expr_vstore {
     expr_vstore_mut_slice,             // &mut [1,2,3,4]
 }
 
-pub pure fn is_blockish(p: Proto) -> bool {
-    match p {
-        ProtoBorrowed => true,
-        ProtoBare | ProtoUniq | ProtoBox => false
-    }
-}
-
 #[auto_encode]
 #[auto_decode]
 pub enum binop {
@@ -673,12 +696,21 @@ pub enum log_level { error, debug, log_other }
 
 #[auto_encode]
 #[auto_decode]
+#[deriving_eq]
+pub enum CallSugar {
+    NoSugar,
+    DoSugar,
+    ForSugar
+}
+
+#[auto_encode]
+#[auto_decode]
 pub enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
     expr_rec(~[field], Option<@expr>),
-    expr_call(@expr, ~[@expr], bool), // True iff last argument is a block
-    expr_method_call(@expr, ident, ~[@Ty], ~[@expr], bool), // Ditto
+    expr_call(@expr, ~[@expr], CallSugar),
+    expr_method_call(@expr, ident, ~[@Ty], ~[@expr], CallSugar),
     expr_tup(~[@expr]),
     expr_binary(binop, @expr, @expr),
     expr_unary(unop, @expr),
@@ -693,7 +725,7 @@ pub enum expr_ {
     expr_match(@expr, ~[arm]),
 
     // FIXME(#4717) the @() is req'd on windows or else LLVM croaks
-    expr_fn(Proto, fn_decl, blk, @()),
+    expr_fn(Sigil, fn_decl, blk, @()),
 
     expr_fn_block(fn_decl, blk),
     // Inner expr is always an expr_fn_block. We need the wrapping node to
@@ -1112,12 +1144,19 @@ pub impl Onceness : to_bytes::IterBytes {
 
 #[auto_encode]
 #[auto_decode]
-pub struct TyFn {
-    proto: Proto,
+pub struct TyClosure {
+    sigil: Sigil,
     region: Option<@region>,
     purity: purity,
     onceness: Onceness,
-    bounds: @~[ty_param_bound],
+    decl: fn_decl
+}
+
+#[auto_encode]
+#[auto_decode]
+pub struct TyBareFn {
+    purity: purity,
+    abi: Abi,
     decl: fn_decl
 }
 
@@ -1133,7 +1172,8 @@ pub enum ty_ {
     ty_ptr(mt),
     ty_rptr(@region, mt),
     ty_rec(~[ty_field]),
-    ty_fn(@TyFn),
+    ty_closure(@TyClosure),
+    ty_bare_fn(@TyBareFn),
     ty_tup(~[@Ty]),
     ty_path(@path, node_id),
     ty_mac(mac),
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index ca28641c4a3..c347c04641f 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -154,7 +154,7 @@ pub fn find_attrs_by_name(attrs: &[ast::attribute], name: &str) ->
             option::None
         }
     };
-    return vec::filter_map(attrs, filter);
+    return vec::filter_mapped(attrs, filter);
 }
 
 /// Search a list of meta items and return only those with a specific name
@@ -277,9 +277,9 @@ pub fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
 pub fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: ~str) ->
    ~[@ast::meta_item] {
 
-    return vec::filter_map(items, |item| {
+    return vec::filter_mapped(items, |item| {
         if get_meta_item_name(*item) != name {
-            option::Some(/* FIXME (#2543) */ copy *item)
+            option::Some(*item)
         } else {
             option::None
         }
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 31ed65d8065..a509325face 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -76,7 +76,7 @@ pub impl BytePos: Sub<BytePos, BytePos> {
 }
 
 pub impl BytePos: to_bytes::IterBytes {
-    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+    pure fn iter_bytes(&self, +lsb0: bool, &&f: to_bytes::Cb) {
         (**self).iter_bytes(lsb0, f)
     }
 }
@@ -99,7 +99,7 @@ pub impl CharPos: cmp::Ord {
 }
 
 pub impl CharPos: to_bytes::IterBytes {
-    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+    pure fn iter_bytes(&self, +lsb0: bool, &&f: to_bytes::Cb) {
         (**self).iter_bytes(lsb0, f)
     }
 }
diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs
index 03aa0cde811..21154bff01e 100644
--- a/src/libsyntax/ext/auto_encode.rs
+++ b/src/libsyntax/ext/auto_encode.rs
@@ -392,7 +392,7 @@ priv impl ext_ctxt {
         expr: @ast::expr,
         args: ~[@ast::expr]
     ) -> @ast::expr {
-        self.expr(span, ast::expr_call(expr, args, false))
+        self.expr(span, ast::expr_call(expr, args, ast::NoSugar))
     }
 
     fn lambda_expr(expr: @ast::expr) -> @ast::expr {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 4d8fd39c960..a050b2316e8 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -103,7 +103,7 @@ pub fn mk_addr_of(cx: ext_ctxt, sp: span, e: @ast::expr) -> @ast::expr {
 }
 pub fn mk_call_(cx: ext_ctxt, sp: span, fn_expr: @ast::expr,
                 args: ~[@ast::expr]) -> @ast::expr {
-    mk_expr(cx, sp, ast::expr_call(fn_expr, args, false))
+    mk_expr(cx, sp, ast::expr_call(fn_expr, args, ast::NoSugar))
 }
 pub fn mk_call(cx: ext_ctxt, sp: span, fn_path: ~[ast::ident],
                args: ~[@ast::expr]) -> @ast::expr {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index cfa8a3c1153..8cecbfb1210 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -536,13 +536,18 @@ pub fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
       ty_rptr(region, mt) => ty_rptr(region, fold_mt(mt, fld)),
       ty_rec(ref fields) =>
         ty_rec(vec::map((*fields), |f| fold_field(*f, fld))),
-      ty_fn(f) =>
-        ty_fn(@TyFn {
-            proto: f.proto,
+      ty_closure(f) =>
+        ty_closure(@TyClosure {
+            sigil: f.sigil,
             purity: f.purity,
             region: f.region,
             onceness: f.onceness,
-            bounds: @vec::map(*f.bounds, |x| fold_ty_param_bound(*x, fld)),
+            decl: fold_fn_decl(f.decl, fld)
+        }),
+      ty_bare_fn(f) =>
+        ty_bare_fn(@TyBareFn {
+            purity: f.purity,
+            abi: f.abi,
             decl: fold_fn_decl(f.decl, fld)
         }),
       ty_tup(tys) => ty_tup(vec::map(tys, |ty| fld.fold_ty(*ty))),
@@ -557,7 +562,7 @@ pub fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
 pub fn noop_fold_mod(m: _mod, fld: ast_fold) -> _mod {
     ast::_mod {
         view_items: vec::map(m.view_items, |x| fld.fold_view_item(*x)),
-        items: vec::filter_map(m.items, |x| fld.fold_item(*x)),
+        items: vec::filter_mapped(m.items, |x| fld.fold_item(*x)),
     }
 }
 
diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs
index 4ceb04c55d0..64c4cb3c508 100644
--- a/src/libsyntax/parse/classify.rs
+++ b/src/libsyntax/parse/classify.rs
@@ -23,8 +23,10 @@ pub fn expr_requires_semi_to_be_stmt(e: @ast::expr) -> bool {
       | ast::expr_block(_)
       | ast::expr_while(*)
       | ast::expr_loop(*)
-      | ast::expr_call(_, _, true)
-      | ast::expr_method_call(_, _, _, _, true) => false,
+      | ast::expr_call(_, _, ast::DoSugar)
+      | ast::expr_call(_, _, ast::ForSugar)
+      | ast::expr_method_call(_, _, _, _, ast::DoSugar)
+      | ast::expr_method_call(_, _, _, _, ast::ForSugar) => false,
       _ => true
     }
 }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5cd78dd9049..7fb3064c388 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -10,7 +10,10 @@
 
 use core::prelude::*;
 
-use ast::{ProtoBox, ProtoUniq, RegionTyParamBound, TraitTyParamBound};
+use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil, RustAbi};
+use ast::{CallSugar, NoSugar, DoSugar, ForSugar};
+use ast::{TyBareFn, TyClosure};
+use ast::{RegionTyParamBound, TraitTyParamBound};
 use ast::{provided, public, pure_fn, purity, re_static};
 use ast::{_mod, add, arg, arm, attribute, bind_by_ref, bind_infer};
 use ast::{bind_by_copy, bitand, bitor, bitxor, blk};
@@ -27,7 +30,7 @@ use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
 use ast::{expr_vec, expr_vstore, expr_vstore_mut_box};
 use ast::{expr_vstore_fixed, expr_vstore_slice, expr_vstore_box};
 use ast::{expr_vstore_mut_slice, expr_while, extern_fn, field, fn_decl};
-use ast::{expr_vstore_uniq, TyFn, Onceness, Once, Many};
+use ast::{expr_vstore_uniq, TyClosure, TyBareFn, Onceness, Once, Many};
 use ast::{foreign_item, foreign_item_const, foreign_item_fn, foreign_mod};
 use ast::{ident, impure_fn, infer, inherited, item, item_, item_const};
 use ast::{item_const, item_enum, item_fn, item_foreign_mod, item_impl};
@@ -38,15 +41,16 @@ use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal};
 use ast::{match_seq, match_tok, method, mode, module_ns, mt, mul, mutability};
 use ast::{named_field, neg, node_id, noreturn, not, pat, pat_box, pat_enum};
 use ast::{pat_ident, pat_lit, pat_range, pat_rec, pat_region, pat_struct};
-use ast::{pat_tup, pat_uniq, pat_wild, path, private, Proto, ProtoBare};
-use ast::{ProtoBorrowed, re_self, re_anon, re_named, region, rem, required};
+use ast::{pat_tup, pat_uniq, pat_wild, path, private};
+use ast::{re_self, re_anon, re_named, region, rem, required};
 use ast::{ret_style, return_val, self_ty, shl, shr, stmt, stmt_decl};
 use ast::{stmt_expr, stmt_semi, stmt_mac, struct_def, struct_field};
 use ast::{struct_immutable, struct_mutable, struct_variant_kind, subtract};
 use ast::{sty_box, sty_by_ref, sty_region, sty_static, sty_uniq, sty_value};
 use ast::{token_tree, trait_method, trait_ref, tt_delim, tt_seq, tt_tok};
 use ast::{tt_nonterminal, tuple_variant_kind, Ty, ty_, ty_bot, ty_box};
-use ast::{ty_field, ty_fixed_length_vec, ty_fn, ty_infer, ty_mac, ty_method};
+use ast::{ty_field, ty_fixed_length_vec, ty_closure, ty_bare_fn};
+use ast::{ty_infer, ty_mac, ty_method};
 use ast::{ty_nil, ty_param, ty_param_bound, ty_path, ty_ptr, ty_rec, ty_rptr};
 use ast::{ty_tup, ty_u32, ty_uniq, ty_vec, type_value_ns, uniq};
 use ast::{unnamed_field, unsafe_blk, unsafe_fn, variant, view_item};
@@ -293,25 +297,49 @@ pub impl Parser {
 
     pure fn id_to_str(id: ident) -> @~str { self.sess.interner.get(id) }
 
-    fn token_is_fn_keyword(+tok: token::Token) -> bool {
+    fn token_is_closure_keyword(+tok: token::Token) -> bool {
         self.token_is_keyword(~"pure", tok) ||
             self.token_is_keyword(~"unsafe", tok) ||
             self.token_is_keyword(~"once", tok) ||
-            self.token_is_keyword(~"fn", tok) ||
-            self.token_is_keyword(~"extern", tok)
+            self.token_is_keyword(~"fn", tok)
     }
 
-    fn parse_ty_fn(pre_proto: Option<ast::Proto>,
-                       pre_region_name: Option<ident>) -> ty_
+    fn parse_ty_bare_fn() -> ty_
     {
         /*
 
-        (&|~|@) [r/] [pure|unsafe] [once] fn [:K] (S) -> T
-        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~~^ ^~^    ^
-           |     |     |             |        |    |     |
-           |     |     |             |        |    |   Return type
-           |     |     |             |        |  Argument types
-           |     |     |             |    Environment bounds
+        extern "ABI" [pure|unsafe] fn (S) -> T
+               ^~~~^ ^~~~~~~~~~~~^    ^~^    ^
+                 |     |               |     |
+                 |     |               |   Return type
+                 |     |             Argument types
+                 |     |
+                 |     |
+                 |   Purity
+                ABI
+
+        */
+
+        let purity = self.parse_purity();
+        self.expect_keyword(~"fn");
+        return ty_bare_fn(@TyBareFn {
+            abi: RustAbi,
+            purity: purity,
+            decl: self.parse_ty_fn_decl()
+        });
+    }
+
+    fn parse_ty_closure(pre_sigil: Option<ast::Sigil>,
+                        pre_region_name: Option<ident>) -> ty_
+    {
+        /*
+
+        (&|~|@) [r/] [pure|unsafe] [once] fn (S) -> T
+        ^~~~~~^ ^~~^ ^~~~~~~~~~~~^ ^~~~~^    ^~^    ^
+           |     |     |             |        |     |
+           |     |     |             |        |   Return type
+           |     |     |             |      Argument types
+           |     |     |             |
            |     |     |          Once-ness (a.k.a., affine)
            |     |   Purity
            | Lifetime bound
@@ -322,22 +350,13 @@ pub impl Parser {
         // At this point, the allocation type and lifetime bound have been
         // parsed.
 
-        let purity = parse_purity(&self);
+        let purity = self.parse_purity();
         let onceness = parse_onceness(&self);
+        self.expect_keyword(~"fn");
+        let post_sigil = self.parse_fn_ty_sigil();
 
-        let bounds, post_proto;
-        if self.eat_keyword(~"extern") {
-            self.expect_keyword(~"fn");
-            post_proto = Some(ast::ProtoBare);
-            bounds = @~[];
-        } else {
-            self.expect_keyword(~"fn");
-            post_proto = self.parse_fn_ty_proto();
-            bounds = self.parse_optional_ty_param_bounds();
-        };
-
-        let proto = match (pre_proto, post_proto) {
-            (None, None) => ast::ProtoBorrowed,
+        let sigil = match (pre_sigil, post_sigil) {
+            (None, None) => BorrowedSigil,
             (Some(p), None) | (None, Some(p)) => p,
             (Some(_), Some(_)) => {
                 self.fatal(~"cannot combine prefix and postfix \
@@ -352,30 +371,28 @@ pub impl Parser {
             None
         };
 
-        return ty_fn(@TyFn {
-            proto: proto,
+        return ty_closure(@TyClosure {
+            sigil: sigil,
             region: region,
             purity: purity,
             onceness: onceness,
-            bounds: bounds,
             decl: self.parse_ty_fn_decl()
         });
 
-        fn parse_purity(self: &Parser) -> purity {
-            if self.eat_keyword(~"pure") {
-                return pure_fn;
-            } else if self.eat_keyword(~"unsafe") {
-                return unsafe_fn;
-            } else {
-                return impure_fn;
-            }
-        }
-
         fn parse_onceness(self: &Parser) -> Onceness {
             if self.eat_keyword(~"once") {Once} else {Many}
         }
     }
 
+    fn parse_purity() -> purity {
+        if self.eat_keyword(~"pure") {
+            return pure_fn;
+        } else if self.eat_keyword(~"unsafe") {
+            return unsafe_fn;
+        } else {
+            return impure_fn;
+        }
+    }
 
     fn parse_ty_fn_decl() -> fn_decl {
         let inputs = do self.parse_unspanned_seq(
@@ -560,10 +577,10 @@ pub impl Parser {
             }
         } else if self.token == token::AT {
             self.bump();
-            self.parse_box_or_uniq_pointee(ast::ProtoBox, ty_box)
+            self.parse_box_or_uniq_pointee(ManagedSigil, ty_box)
         } else if self.token == token::TILDE {
             self.bump();
-            self.parse_box_or_uniq_pointee(ast::ProtoUniq, ty_uniq)
+            self.parse_box_or_uniq_pointee(OwnedSigil, ty_uniq)
         } else if self.token == token::BINOP(token::STAR) {
             self.bump();
             ty_ptr(self.parse_mt())
@@ -590,8 +607,10 @@ pub impl Parser {
         } else if self.token == token::BINOP(token::AND) {
             self.bump();
             self.parse_borrowed_pointee()
-        } else if self.token_is_fn_keyword(self.token) {
-            self.parse_ty_fn(None, None)
+        } else if self.eat_keyword(~"extern") {
+            self.parse_ty_bare_fn()
+        } else if self.token_is_closure_keyword(self.token) {
+            self.parse_ty_closure(None, None)
         } else if self.token == token::MOD_SEP
             || is_ident_or_path(self.token) {
             let path = self.parse_path_with_tps(colons_before_params);
@@ -603,19 +622,19 @@ pub impl Parser {
     }
 
     fn parse_box_or_uniq_pointee(
-        proto: ast::Proto,
+        sigil: ast::Sigil,
         ctor: &fn(+v: mt) -> ty_) -> ty_
     {
         // @foo/fn() or @fn() are parsed directly as fn types:
         match copy self.token {
             token::IDENT(rname, _) => {
                 if self.look_ahead(1u) == token::BINOP(token::SLASH) &&
-                    self.token_is_fn_keyword(self.look_ahead(2u))
+                    self.token_is_closure_keyword(self.look_ahead(2u))
                 {
                     self.bump(); self.bump();
-                    return self.parse_ty_fn(Some(proto), Some(rname));
-                } else if self.token_is_fn_keyword(self.token) {
-                    return self.parse_ty_fn(Some(proto), None);
+                    return self.parse_ty_closure(Some(sigil), Some(rname));
+                } else if self.token_is_closure_keyword(self.token) {
+                    return self.parse_ty_closure(Some(sigil), None);
                 }
             }
             _ => {}
@@ -643,8 +662,8 @@ pub impl Parser {
             _ => { None }
         };
 
-        if self.token_is_fn_keyword(self.token) {
-            return self.parse_ty_fn(Some(ProtoBorrowed), rname);
+        if self.token_is_closure_keyword(self.token) {
+            return self.parse_ty_closure(Some(BorrowedSigil), rname);
         }
 
         let r = self.region_from_name(rname);
@@ -981,9 +1000,11 @@ pub impl Parser {
         } else if self.eat_keyword(~"if") {
             return self.parse_if_expr();
         } else if self.eat_keyword(~"for") {
-            return self.parse_sugary_call_expr(~"for", expr_loop_body);
+            return self.parse_sugary_call_expr(~"for", ForSugar,
+                                               expr_loop_body);
         } else if self.eat_keyword(~"do") {
-            return self.parse_sugary_call_expr(~"do", expr_do_body);
+            return self.parse_sugary_call_expr(~"do", DoSugar,
+                                               expr_do_body);
         } else if self.eat_keyword(~"while") {
             return self.parse_while_expr();
         } else if self.eat_keyword(~"loop") {
@@ -991,14 +1012,14 @@ pub impl Parser {
         } else if self.eat_keyword(~"match") {
             return self.parse_match_expr();
         } else if self.eat_keyword(~"fn") {
-            let opt_proto = self.parse_fn_ty_proto();
-            let proto = match opt_proto {
-                None | Some(ast::ProtoBare) => {
+            let opt_sigil = self.parse_fn_ty_sigil();
+            let sigil = match opt_sigil {
+                None => {
                     self.fatal(~"fn expr are deprecated, use fn@")
                 }
                 Some(p) => { p }
             };
-            return self.parse_fn_expr(proto);
+            return self.parse_fn_expr(sigil);
         } else if self.eat_keyword(~"unsafe") {
             return self.parse_block_expr(lo, unsafe_blk);
         } else if self.token == token::LBRACKET {
@@ -1176,7 +1197,7 @@ pub impl Parser {
                                 |p| p.parse_expr());
                             hi = self.span.hi;
 
-                            let nd = expr_method_call(e, i, tys, es, false);
+                            let nd = expr_method_call(e, i, tys, es, NoSugar);
                             e = self.mk_expr(lo, hi, move nd);
                         }
                         _ => {
@@ -1198,7 +1219,7 @@ pub impl Parser {
                     |p| p.parse_expr());
                 hi = self.span.hi;
 
-                let nd = expr_call(e, es, false);
+                let nd = expr_call(e, es, NoSugar);
                 e = self.mk_expr(lo, hi, nd);
               }
 
@@ -1566,7 +1587,7 @@ pub impl Parser {
         self.mk_expr(q.lo, q.hi, expr_if(q.cond, q.then, q.els))
     }
 
-    fn parse_fn_expr(proto: Proto) -> @expr {
+    fn parse_fn_expr(sigil: Sigil) -> @expr {
         let lo = self.last_span.lo;
 
         // if we want to allow fn expression argument types to be inferred in
@@ -1576,7 +1597,7 @@ pub impl Parser {
         let body = self.parse_block();
 
         self.mk_expr(lo, body.span.hi,
-                            expr_fn(proto, decl, body, @()))
+                     expr_fn(sigil, decl, body, @()))
     }
 
     // `|args| { ... }` like in `do` expressions
@@ -1641,6 +1662,7 @@ pub impl Parser {
     }
 
     fn parse_sugary_call_expr(keyword: ~str,
+                              sugar: CallSugar,
                               ctor: fn(+v: @expr) -> expr_) -> @expr {
         let lo = self.last_span;
         // Parse the callee `foo` in
@@ -1654,27 +1676,27 @@ pub impl Parser {
         // them as the lambda arguments
         let e = self.parse_expr_res(RESTRICT_NO_BAR_OR_DOUBLEBAR_OP);
         match e.node {
-            expr_call(f, args, false) => {
+            expr_call(f, args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 let args = vec::append(args, ~[last_arg]);
-                self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, true))
+                self.mk_expr(lo.lo, block.span.hi, expr_call(f, args, sugar))
             }
-            expr_method_call(f, i, tps, args, false) => {
+            expr_method_call(f, i, tps, args, NoSugar) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 let args = vec::append(args, ~[last_arg]);
                 self.mk_expr(lo.lo, block.span.hi,
-                             expr_method_call(f, i, tps, args, true))
+                             expr_method_call(f, i, tps, args, sugar))
             }
             expr_field(f, i, tps) => {
                 let block = self.parse_lambda_block_expr();
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 self.mk_expr(lo.lo, block.span.hi,
-                             expr_method_call(f, i, tps, ~[last_arg], true))
+                             expr_method_call(f, i, tps, ~[last_arg], sugar))
             }
             expr_path(*) | expr_call(*) | expr_method_call(*) |
                 expr_paren(*) => {
@@ -1682,7 +1704,7 @@ pub impl Parser {
                 let last_arg = self.mk_expr(block.span.lo, block.span.hi,
                                             ctor(block));
                 self.mk_expr(lo.lo, last_arg.span.hi,
-                             expr_call(e, ~[last_arg], true))
+                             expr_call(e, ~[last_arg], sugar))
             }
             _ => {
                 // There may be other types of expressions that can
@@ -3592,19 +3614,19 @@ pub impl Parser {
         (id, item_enum(enum_definition, ty_params), None)
     }
 
-    fn parse_fn_ty_proto() -> Option<Proto> {
+    fn parse_fn_ty_sigil() -> Option<Sigil> {
         match self.token {
             token::AT => {
                 self.bump();
-                Some(ProtoBox)
+                Some(ManagedSigil)
             }
             token::TILDE => {
                 self.bump();
-                Some(ProtoUniq)
+                Some(OwnedSigil)
             }
             token::BINOP(token::AND) => {
                 self.bump();
-                Some(ProtoBorrowed)
+                Some(BorrowedSigil)
             }
             _ => {
                 None
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 5079766239b..bcbee7b2f24 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -404,9 +404,15 @@ pub fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) {
         commasep(s, inconsistent, elts, print_type);
         pclose(s);
       }
-      ast::ty_fn(f) => {
-        print_ty_fn(s, Some(f.proto), f.region, f.purity,
-                    f.onceness, f.bounds, f.decl, None, None, None);
+      ast::ty_bare_fn(f) => {
+          print_ty_fn(s, Some(f.abi), None, None,
+                      f.purity, ast::Many, f.decl, None,
+                      None, None);
+      }
+      ast::ty_closure(f) => {
+          print_ty_fn(s, None, Some(f.sigil), f.region,
+                      f.purity, f.onceness, f.decl, None,
+                      None, None);
       }
       ast::ty_path(path, _) => print_path(s, path, print_colons),
       ast::ty_fixed_length_vec(mt, v) => {
@@ -806,8 +812,8 @@ pub fn print_ty_method(s: ps, m: ast::ty_method) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, m.span.lo);
     print_outer_attributes(s, m.attrs);
-    print_ty_fn(s, None, None, m.purity, ast::Many,
-                @~[], m.decl, Some(m.ident), Some(m.tps),
+    print_ty_fn(s, None, None, None, m.purity, ast::Many,
+                m.decl, Some(m.ident), Some(m.tps),
                 Some(m.self_ty.node));
     word(s.s, ~";");
 }
@@ -1046,32 +1052,32 @@ pub fn print_expr_vstore(s: ps, t: ast::expr_vstore) {
 }
 
 pub fn print_call_pre(s: ps,
-                      has_block: bool,
+                      sugar: ast::CallSugar,
                       base_args: &mut ~[@ast::expr])
                    -> Option<@ast::expr> {
-    if has_block {
-        let blk_arg = base_args.pop();
-        match blk_arg.node {
-          ast::expr_loop_body(_) => { head(s, ~"for"); }
-          ast::expr_do_body(_) => { head(s, ~"do"); }
-          _ => {}
-        }
-        Some(blk_arg)
-    } else {
-        None
+    match sugar {
+        ast::DoSugar => {
+            head(s, ~"do");
+            Some(base_args.pop())
+        }
+        ast::ForSugar => {
+            head(s, ~"for");
+            Some(base_args.pop())
+        }
+        ast::NoSugar => None
     }
 }
 
 pub fn print_call_post(s: ps,
-                       has_block: bool,
+                       sugar: ast::CallSugar,
                        blk: &Option<@ast::expr>,
                        base_args: &mut ~[@ast::expr]) {
-    if !has_block || !base_args.is_empty() {
+    if sugar == ast::NoSugar || !base_args.is_empty() {
         popen(s);
         commasep_exprs(s, inconsistent, *base_args);
         pclose(s);
     }
-    if has_block {
+    if sugar != ast::NoSugar {
         nbsp(s);
         match blk.get().node {
           // need to handle closures specifically
@@ -1181,15 +1187,15 @@ pub fn print_expr(s: ps, &&expr: @ast::expr) {
         commasep_exprs(s, inconsistent, exprs);
         pclose(s);
       }
-      ast::expr_call(func, args, has_block) => {
+      ast::expr_call(func, args, sugar) => {
         let mut base_args = copy args;
-        let blk = print_call_pre(s, has_block, &mut base_args);
+        let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
-        print_call_post(s, has_block, &blk, &mut base_args);
+        print_call_post(s, sugar, &blk, &mut base_args);
       }
-      ast::expr_method_call(func, ident, tys, args, has_block) => {
+      ast::expr_method_call(func, ident, tys, args, sugar) => {
         let mut base_args = copy args;
-        let blk = print_call_pre(s, has_block, &mut base_args);
+        let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
         word(s.s, ~".");
         print_ident(s, ident);
@@ -1198,7 +1204,7 @@ pub fn print_expr(s: ps, &&expr: @ast::expr) {
             commasep(s, inconsistent, tys, print_type);
             word(s.s, ~">");
         }
-        print_call_post(s, has_block, &blk, &mut base_args);
+        print_call_post(s, sugar, &blk, &mut base_args);
       }
       ast::expr_binary(op, lhs, rhs) => {
         print_expr(s, lhs);
@@ -1305,13 +1311,13 @@ pub fn print_expr(s: ps, &&expr: @ast::expr) {
         }
         bclose_(s, expr.span, match_indent_unit);
       }
-      ast::expr_fn(proto, decl, ref body, _) => {
+      ast::expr_fn(sigil, decl, ref body, _) => {
         // containing cbox, will be closed by print-block at }
         cbox(s, indent_unit);
         // head-box, will be closed by print-block at start
         ibox(s, 0u);
         print_fn_header_info(s, None, None, ast::Many,
-                             Some(proto), ast::inherited);
+                             Some(sigil), ast::inherited);
         print_fn_args_and_ret(s, decl, None);
         space(s.s);
         print_block(s, (*body));
@@ -1900,33 +1906,32 @@ pub fn print_arg(s: ps, input: ast::arg) {
 }
 
 pub fn print_ty_fn(s: ps,
-                   opt_proto: Option<ast::Proto>,
+                   opt_abi: Option<ast::Abi>,
+                   opt_sigil: Option<ast::Sigil>,
                    opt_region: Option<@ast::region>,
                    purity: ast::purity,
                    onceness: ast::Onceness,
-                   bounds: @~[ast::ty_param_bound],
                    decl: ast::fn_decl, id: Option<ast::ident>,
                    tps: Option<~[ast::ty_param]>,
                    opt_self_ty: Option<ast::self_ty_>) {
     ibox(s, indent_unit);
 
     // Duplicates the logic in `print_fn_header_info()`.  This is because that
-    // function prints the proto in the wrong place.  That should be fixed.
+    // function prints the sigil in the wrong place.  That should be fixed.
     print_self_ty_if_static(s, opt_self_ty);
-    print_opt_proto(s, opt_proto);
+    print_opt_abi(s, opt_abi);
+    print_opt_sigil(s, opt_sigil);
     for opt_region.each |r| { print_region(s, ~"", *r, ~"/"); }
     print_purity(s, purity);
     print_onceness(s, onceness);
     word(s.s, ~"fn");
-    print_bounds(s, bounds);
     match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () }
     match tps { Some(tps) => print_type_params(s, tps), _ => () }
     zerobreak(s.s);
 
     popen(s);
-    // It is unfortunate to duplicate the commasep logic, but we
-    // we want the self type, the args, and the capture clauses all
-    // in the same box.
+    // It is unfortunate to duplicate the commasep logic, but we we want the
+    // self type and the args all in the same box.
     box(s, 0u, inconsistent);
     let mut first = true;
     for opt_self_ty.each |self_ty| {
@@ -2157,12 +2162,18 @@ pub fn print_opt_purity(s: ps, opt_purity: Option<ast::purity>) {
     }
 }
 
-pub fn print_opt_proto(s: ps, opt_proto: Option<ast::Proto>) {
-    match opt_proto {
-        Some(ast::ProtoBare) => { word(s.s, ~"extern "); }
-        Some(ast::ProtoBorrowed) => { word(s.s, ~"&"); }
-        Some(ast::ProtoUniq) => { word(s.s, ~"~"); }
-        Some(ast::ProtoBox) => { word(s.s, ~"@"); }
+pub fn print_opt_abi(s: ps, opt_abi: Option<ast::Abi>) {
+    match opt_abi {
+        Some(ast::RustAbi) => { word_nbsp(s, ~"extern"); }
+        None => {}
+    };
+}
+
+pub fn print_opt_sigil(s: ps, opt_sigil: Option<ast::Sigil>) {
+    match opt_sigil {
+        Some(ast::BorrowedSigil) => { word(s.s, ~"&"); }
+        Some(ast::OwnedSigil) => { word(s.s, ~"~"); }
+        Some(ast::ManagedSigil) => { word(s.s, ~"@"); }
         None => {}
     };
 }
@@ -2171,20 +2182,20 @@ pub fn print_fn_header_info(s: ps,
                             opt_sty: Option<ast::self_ty_>,
                             opt_purity: Option<ast::purity>,
                             onceness: ast::Onceness,
-                            opt_proto: Option<ast::Proto>,
+                            opt_sigil: Option<ast::Sigil>,
                             vis: ast::visibility) {
     print_self_ty_if_static(s, opt_sty);
     word(s.s, visibility_qualified(vis, ~""));
     print_opt_purity(s, opt_purity);
     print_onceness(s, onceness);
     word(s.s, ~"fn");
-    print_opt_proto(s, opt_proto);
+    print_opt_sigil(s, opt_sigil);
 }
 
-pub fn opt_proto_to_str(opt_p: Option<ast::Proto>) -> ~str {
+pub fn opt_sigil_to_str(opt_p: Option<ast::Sigil>) -> ~str {
     match opt_p {
       None => ~"fn",
-      Some(p) => proto_to_str(p)
+      Some(p) => fmt!("fn%s", p.to_str())
     }
 }
 
@@ -2218,15 +2229,6 @@ pub fn print_onceness(s: ps, o: ast::Onceness) {
     }
 }
 
-pub fn proto_to_str(p: ast::Proto) -> ~str {
-    return match p {
-      ast::ProtoBare => ~"extern fn",
-      ast::ProtoBorrowed => ~"fn&",
-      ast::ProtoUniq => ~"fn~",
-      ast::ProtoBox => ~"fn@"
-    };
-}
-
 #[cfg(test)]
 pub mod test {
     use ast;
diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc
index a6d50b9cf09..877817af06c 100644
--- a/src/libsyntax/syntax.rc
+++ b/src/libsyntax/syntax.rc
@@ -22,7 +22,6 @@
 #[allow(vecs_implicitly_copyable)];
 #[allow(non_camel_case_types)];
 #[allow(deprecated_mode)];
-#[warn(deprecated_pattern)];
 #[allow(deprecated_self)];
 
 #[no_core];
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index eea1a6906e4..37b96e05653 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -30,10 +30,10 @@ use core::vec;
 pub enum vt<E> { mk_vt(visitor<E>), }
 
 pub enum fn_kind {
-    fk_item_fn(ident, ~[ty_param], purity), //< an item declared with fn()
-    fk_method(ident, ~[ty_param], @method),
-    fk_anon(Proto),    //< an anonymous function like fn@(...)
-    fk_fn_block,       //< a block {||...}
+    fk_item_fn(ident, ~[ty_param], purity), // fn foo()
+    fk_method(ident, ~[ty_param], @method), // fn foo(&self)
+    fk_anon(ast::Sigil),                    // fn@(x, y) { ... }
+    fk_fn_block,                            // |x, y| ...
     fk_dtor(~[ty_param], ~[attribute], node_id /* self id */,
             def_id /* parent class id */) // class destructor
 
@@ -217,9 +217,12 @@ pub fn visit_ty<E>(t: @Ty, e: E, v: vt<E>) {
       ty_tup(ts) => for ts.each |tt| {
         (v.visit_ty)(*tt, e, v);
       },
-      ty_fn(f) => {
+      ty_closure(f) => {
+        for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); }
+        (v.visit_ty)(f.decl.output, e, v);
+      }
+      ty_bare_fn(f) => {
         for f.decl.inputs.each |a| { (v.visit_ty)(a.ty, e, v); }
-        visit_ty_param_bounds(f.bounds, e, v);
         (v.visit_ty)(f.decl.output, e, v);
       }
       ty_path(p, _) => visit_path(p, e, v),