about summary refs log tree commit diff
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
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.
-rw-r--r--src/compiletest/compiletest.rc15
-rw-r--r--src/libcore/at_vec.rs4
-rw-r--r--src/libcore/bool.rs4
-rw-r--r--src/libcore/cast.rs3
-rw-r--r--src/libcore/char.rs4
-rw-r--r--src/libcore/cleanup.rs4
-rw-r--r--src/libcore/cmp.rs4
-rw-r--r--src/libcore/container.rs3
-rw-r--r--src/libcore/core.rc2
-rw-r--r--src/libcore/dlist.rs4
-rw-r--r--src/libcore/dvec.rs4
-rw-r--r--src/libcore/either.rs4
-rw-r--r--src/libcore/extfmt.rs4
-rw-r--r--src/libcore/flate.rs4
-rw-r--r--src/libcore/from_str.rs4
-rw-r--r--src/libcore/gc.rs3
-rw-r--r--src/libcore/hash.rs4
-rw-r--r--src/libcore/hashmap.rs4
-rw-r--r--src/libcore/io.rs3
-rw-r--r--src/libcore/iter-trait.rs3
-rw-r--r--src/libcore/iter.rs3
-rw-r--r--src/libcore/libc.rs3
-rw-r--r--src/libcore/logging.rs4
-rw-r--r--src/libcore/managed.rs4
-rw-r--r--src/libcore/mutable.rs2
-rw-r--r--src/libcore/nil.rs4
-rw-r--r--src/libcore/num/cmath.rs3
-rw-r--r--src/libcore/num/f32.rs4
-rw-r--r--src/libcore/num/f64.rs4
-rw-r--r--src/libcore/num/float.rs4
-rw-r--r--src/libcore/num/int-template.rs4
-rw-r--r--src/libcore/num/uint-template.rs4
-rw-r--r--src/libcore/ops.rs3
-rw-r--r--src/libcore/option.rs3
-rw-r--r--src/libcore/os.rs3
-rw-r--r--src/libcore/owned.rs4
-rw-r--r--src/libcore/path.rs4
-rw-r--r--src/libcore/pipes.rs5
-rw-r--r--src/libcore/prelude.rs2
-rw-r--r--src/libcore/private.rs5
-rw-r--r--src/libcore/private/finally.rs22
-rw-r--r--src/libcore/ptr.rs3
-rw-r--r--src/libcore/rand.rs4
-rw-r--r--src/libcore/reflect.rs3
-rw-r--r--src/libcore/repr.rs3
-rw-r--r--src/libcore/result.rs3
-rw-r--r--src/libcore/rt.rs3
-rw-r--r--src/libcore/run.rs3
-rw-r--r--src/libcore/stackwalk.rs5
-rw-r--r--src/libcore/str.rs18
-rw-r--r--src/libcore/sys.rs4
-rw-r--r--src/libcore/task/mod.rs5
-rw-r--r--src/libcore/task/spawn.rs1
-rw-r--r--src/libcore/to_bytes.rs6
-rw-r--r--src/libcore/to_str.rs4
-rw-r--r--src/libcore/tuple.rs4
-rw-r--r--src/libcore/unicode.rs3
-rw-r--r--src/libcore/util.rs4
-rw-r--r--src/libcore/vec.rs104
-rw-r--r--src/librustc/front/config.rs25
-rw-r--r--src/librustc/front/test.rs113
-rw-r--r--src/librustc/metadata/decoder.rs24
-rw-r--r--src/librustc/metadata/encoder.rs10
-rw-r--r--src/librustc/metadata/tydecode.rs79
-rw-r--r--src/librustc/metadata/tyencode.rs54
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs60
-rw-r--r--src/librustc/middle/check_const.rs2
-rw-r--r--src/librustc/middle/check_loop.rs4
-rw-r--r--src/librustc/middle/check_match.rs14
-rw-r--r--src/librustc/middle/freevars.rs6
-rw-r--r--src/librustc/middle/kind.rs58
-rw-r--r--src/librustc/middle/lint.rs17
-rw-r--r--src/librustc/middle/mem_categorization.rs99
-rw-r--r--src/librustc/middle/moves.rs34
-rw-r--r--src/librustc/middle/region.rs12
-rw-r--r--src/librustc/middle/trans/_match.rs2
-rw-r--r--src/librustc/middle/trans/base.rs32
-rw-r--r--src/librustc/middle/trans/callee.rs9
-rw-r--r--src/librustc/middle/trans/closure.rs116
-rw-r--r--src/librustc/middle/trans/controlflow.rs12
-rw-r--r--src/librustc/middle/trans/expr.rs71
-rw-r--r--src/librustc/middle/trans/foreign.rs25
-rw-r--r--src/librustc/middle/trans/glue.rs15
-rw-r--r--src/librustc/middle/trans/inline.rs4
-rw-r--r--src/librustc/middle/trans/machine.rs7
-rw-r--r--src/librustc/middle/trans/meth.rs6
-rw-r--r--src/librustc/middle/trans/monomorphize.rs65
-rw-r--r--src/librustc/middle/trans/reflect.rs93
-rw-r--r--src/librustc/middle/trans/type_of.rs14
-rw-r--r--src/librustc/middle/trans/type_use.rs29
-rw-r--r--src/librustc/middle/ty.rs538
-rw-r--r--src/librustc/middle/typeck/astconv.rs146
-rw-r--r--src/librustc/middle/typeck/check/method.rs8
-rw-r--r--src/librustc/middle/typeck/check/mod.rs531
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs19
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs17
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs2
-rw-r--r--src/librustc/middle/typeck/coherence.rs6
-rw-r--r--src/librustc/middle/typeck/collect.rs186
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs43
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs78
-rw-r--r--src/librustc/middle/typeck/infer/glb.rs18
-rw-r--r--src/librustc/middle/typeck/infer/lattice.rs17
-rw-r--r--src/librustc/middle/typeck/infer/lub.rs18
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs4
-rw-r--r--src/librustc/middle/typeck/infer/region_inference.rs3
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs18
-rw-r--r--src/librustc/middle/typeck/infer/to_str.rs14
-rw-r--r--src/librustc/middle/typeck/mod.rs6
-rw-r--r--src/librustc/util/ppaux.rs159
-rw-r--r--src/librustdoc/astsrv.rs5
-rw-r--r--src/librustdoc/attr_parser.rs2
-rw-r--r--src/librustdoc/desc_to_brief_pass.rs4
-rw-r--r--src/librustdoc/doc.rs34
-rw-r--r--src/librustdoc/extract.rs2
-rw-r--r--src/librustdoc/fold.rs40
-rw-r--r--src/librustdoc/markdown_index_pass.rs8
-rw-r--r--src/librustdoc/markdown_pass.rs7
-rw-r--r--src/librustdoc/page_pass.rs4
-rw-r--r--src/librustdoc/pass.rs2
-rw-r--r--src/librustdoc/sectionalize_pass.rs4
-rw-r--r--src/librustdoc/sort_pass.rs6
-rw-r--r--src/librustdoc/text_pass.rs12
-rw-r--r--src/librustdoc/unindent_pass.rs2
-rw-r--r--src/libstd/arc.rs2
-rw-r--r--src/libstd/arena.rs2
-rw-r--r--src/libstd/base64.rs2
-rw-r--r--src/libstd/bitv.rs2
-rw-r--r--src/libstd/c_vec.rs1
-rw-r--r--src/libstd/cell.rs2
-rw-r--r--src/libstd/cmp.rs1
-rw-r--r--src/libstd/comm.rs3
-rw-r--r--src/libstd/dbg.rs1
-rw-r--r--src/libstd/deque.rs1
-rw-r--r--src/libstd/ebml.rs2
-rw-r--r--src/libstd/fun_treemap.rs2
-rw-r--r--src/libstd/getopts.rs1
-rw-r--r--src/libstd/json.rs1
-rw-r--r--src/libstd/list.rs1
-rw-r--r--src/libstd/md4.rs2
-rw-r--r--src/libstd/net_ip.rs1
-rw-r--r--src/libstd/net_tcp.rs1
-rw-r--r--src/libstd/net_url.rs3
-rw-r--r--src/libstd/oldmap.rs1
-rw-r--r--src/libstd/par.rs51
-rw-r--r--src/libstd/prettyprint.rs2
-rw-r--r--src/libstd/rl.rs4
-rw-r--r--src/libstd/rope.rs2
-rw-r--r--src/libstd/serialize.rs1
-rw-r--r--src/libstd/sha1.rs2
-rw-r--r--src/libstd/smallintmap.rs1
-rw-r--r--src/libstd/sort.rs14
-rw-r--r--src/libstd/std.rc4
-rw-r--r--src/libstd/sync.rs2
-rw-r--r--src/libstd/tempfile.rs2
-rw-r--r--src/libstd/term.rs1
-rw-r--r--src/libstd/test.rs209
-rw-r--r--src/libstd/time.rs2
-rw-r--r--src/libstd/timer.rs2
-rw-r--r--src/libstd/treemap.rs2
-rw-r--r--src/libstd/uv_global_loop.rs2
-rw-r--r--src/libstd/uv_iotask.rs1
-rw-r--r--src/libstd/workcache.rs2
-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
-rw-r--r--src/test/bench/graph500-bfs.rs44
-rw-r--r--src/test/bench/task-perf-alloc-unwind.rs9
-rw-r--r--src/test/compile-fail/bad-var-env-capture-in-block-arg.rs17
-rw-r--r--src/test/compile-fail/block-arg-used-as-lambda-with-illegal-cap.rs20
-rw-r--r--src/test/compile-fail/functional-struct-update.rs31
-rw-r--r--src/test/compile-fail/issue-3044.rs7
-rw-r--r--src/test/compile-fail/kindck-owned.rs4
-rw-r--r--src/test/compile-fail/moves-sru-moved-field.rs27
-rw-r--r--src/test/run-pass/bounded-fn-type.rs17
-rw-r--r--src/test/run-pass/morestack6.rs6
-rw-r--r--src/test/run-pass/newtype.rs1
-rw-r--r--src/test/run-pass/sendfn-deep-copy.rs36
-rw-r--r--src/test/run-pass/test-ignore-cfg.rs12
187 files changed, 2053 insertions, 2361 deletions
diff --git a/src/compiletest/compiletest.rc b/src/compiletest/compiletest.rc
index 8f5f9547c52..b63ac5e75a2 100644
--- a/src/compiletest/compiletest.rc
+++ b/src/compiletest/compiletest.rc
@@ -159,7 +159,7 @@ pub fn test_opts(config: config) -> test::TestOpts {
     }
 }
 
-pub fn make_tests(config: config) -> ~[test::TestDesc] {
+pub fn make_tests(config: config) -> ~[test::TestDescAndFn] {
     debug!("making tests from %s",
            config.src_base.to_str());
     let mut tests = ~[];
@@ -196,13 +196,14 @@ pub fn is_test(config: config, testfile: &Path) -> bool {
     return valid;
 }
 
-pub fn make_test(config: config, testfile: &Path) ->
-   test::TestDesc {
-    test::TestDesc {
-        name: make_test_name(config, testfile),
+pub fn make_test(config: config, testfile: &Path) -> test::TestDescAndFn {
+    test::TestDescAndFn {
+        desc: test::TestDesc {
+            name: make_test_name(config, testfile),
+            ignore: header::is_test_ignored(config, testfile),
+            should_fail: false
+        },
         testfn: make_test_closure(config, testfile),
-        ignore: header::is_test_ignored(config, testfile),
-        should_fail: false
     }
 }
 
diff --git a/src/libcore/at_vec.rs b/src/libcore/at_vec.rs
index be95148e554..75db5359e2e 100644
--- a/src/libcore/at_vec.rs
+++ b/src/libcore/at_vec.rs
@@ -10,10 +10,6 @@
 
 //! Managed vectors
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast::transmute;
 use kinds::Copy;
 use iter;
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
index 2f3a53ea504..1eebb716a59 100644
--- a/src/libcore/bool.rs
+++ b/src/libcore/bool.rs
@@ -9,10 +9,6 @@
 // except according to those terms.
 
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 //! Boolean logic
 
 use bool;
diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs
index 950a753d73f..14cc79ceaff 100644
--- a/src/libcore/cast.rs
+++ b/src/libcore/cast.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Unsafe operations
-#[forbid(deprecated_mode)]
-
 #[abi = "rust-intrinsic"]
 extern mod rusti {
     fn forget<T>(-x: T);
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index deecdc98ffa..f7a369489d1 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -10,10 +10,6 @@
 
 //! Utilities for manipulating the char type
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use char;
 use cmp::Eq;
 use option::{None, Option, Some};
diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs
index 1967f1771be..11a4cad5d1b 100644
--- a/src/libcore/cleanup.rs
+++ b/src/libcore/cleanup.rs
@@ -10,10 +10,6 @@
 
 #[doc(hidden)];
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use libc::{c_char, c_void, intptr_t, uintptr_t};
 use ptr::{mut_null, null, to_unsafe_ptr};
 use repr::BoxRepr;
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 038ea2ba675..e1ec8c7737c 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -20,10 +20,6 @@ and `Eq` to overload the `==` and `!=` operators.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 /**
 * Trait for values that can be compared for equality
 * and inequality.
diff --git a/src/libcore/container.rs b/src/libcore/container.rs
index c8be690a38c..2a5ca7d8dfa 100644
--- a/src/libcore/container.rs
+++ b/src/libcore/container.rs
@@ -10,9 +10,6 @@
 
 //! Container traits
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use option::Option;
 
 pub trait Container {
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index aece60652a2..64b480818b1 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -48,8 +48,6 @@ Implicitly, all crates behave as if they included the following prologue:
 // Don't link to core. We are core.
 #[no_core];
 
-#[warn(deprecated_mode)];
-#[warn(deprecated_pattern)];
 #[warn(vecs_implicitly_copyable)];
 #[deny(non_camel_case_types)];
 #[allow(deprecated_self)];
diff --git a/src/libcore/dlist.rs b/src/libcore/dlist.rs
index d4216b283a9..ed67e010b40 100644
--- a/src/libcore/dlist.rs
+++ b/src/libcore/dlist.rs
@@ -18,10 +18,6 @@ Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use kinds::Copy;
 use managed;
 use option::{None, Option, Some};
diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs
index 2fd7d71a7fc..fe36ed15960 100644
--- a/src/libcore/dvec.rs
+++ b/src/libcore/dvec.rs
@@ -19,10 +19,6 @@ Note that recursive use is not permitted.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast;
 use cast::reinterpret_cast;
 use prelude::*;
diff --git a/src/libcore/either.rs b/src/libcore/either.rs
index 5e9ccd84195..7efde62c4ca 100644
--- a/src/libcore/either.rs
+++ b/src/libcore/either.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 //! A type that represents one of two alternatives
 
 use cmp::Eq;
diff --git a/src/libcore/extfmt.rs b/src/libcore/extfmt.rs
index 259895da2a5..4d2a1b2afe0 100644
--- a/src/libcore/extfmt.rs
+++ b/src/libcore/extfmt.rs
@@ -51,10 +51,6 @@
 //! * s - str (any flavor)
 //! * ? - arbitrary type (does not use the to_str trait)
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 // Transitional
 #[allow(structural_records)]; // Macros -- needs a snapshot
 
diff --git a/src/libcore/flate.rs b/src/libcore/flate.rs
index 39a3aa890df..6b5c083662b 100644
--- a/src/libcore/flate.rs
+++ b/src/libcore/flate.rs
@@ -14,10 +14,6 @@ Simple compression
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use libc;
 use libc::{c_void, size_t, c_int};
 use ptr;
diff --git a/src/libcore/from_str.rs b/src/libcore/from_str.rs
index c3fda7eb8bd..9322c7e7cb8 100644
--- a/src/libcore/from_str.rs
+++ b/src/libcore/from_str.rs
@@ -10,10 +10,6 @@
 
 //! The trait for types that can be created from strings
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use option::Option;
 
 pub trait FromStr {
diff --git a/src/libcore/gc.rs b/src/libcore/gc.rs
index 8150bfbe0ee..d0c40ccf19a 100644
--- a/src/libcore/gc.rs
+++ b/src/libcore/gc.rs
@@ -35,9 +35,6 @@ with destructors.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 // Transitional
 #[allow(structural_records)];
 
diff --git a/src/libcore/hash.rs b/src/libcore/hash.rs
index d676570e1e6..692cfee5365 100644
--- a/src/libcore/hash.rs
+++ b/src/libcore/hash.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 /*!
  * Implementation of SipHash 2-4
  *
diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs
index 88981f514cf..be785863f71 100644
--- a/src/libcore/hashmap.rs
+++ b/src/libcore/hashmap.rs
@@ -10,10 +10,6 @@
 
 //! Sendable hash maps.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use container::{Container, Mutable, Map, Set};
 use cmp::Eq;
 use hash::Hash;
diff --git a/src/libcore/io.rs b/src/libcore/io.rs
index e7d568c5433..721a6584c65 100644
--- a/src/libcore/io.rs
+++ b/src/libcore/io.rs
@@ -14,9 +14,6 @@ Basic input/output
 
 */
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use result::Result;
 
 use cmp::Eq;
diff --git a/src/libcore/iter-trait.rs b/src/libcore/iter-trait.rs
index 942db1c5f29..df2aa6271d1 100644
--- a/src/libcore/iter-trait.rs
+++ b/src/libcore/iter-trait.rs
@@ -12,9 +12,6 @@
 // workaround our lack of traits and lack of macros.  See core.{rc,rs} for
 // how this file is used.
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::{Eq, Ord};
 use iter::BaseIter;
 use iter;
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 2ffa8702261..c414ab0f5f3 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -14,9 +14,6 @@ The iteration traits and common implementation
 
 */
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::{Eq, Ord};
 use kinds::Copy;
 use option::{None, Option, Some};
diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs
index a1107d49c0e..6976c83a6f4 100644
--- a/src/libcore/libc.rs
+++ b/src/libcore/libc.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 /*!
 * Bindings for libc.
 *
diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs
index 922995a5af7..357a3415ac2 100644
--- a/src/libcore/logging.rs
+++ b/src/libcore/logging.rs
@@ -10,10 +10,6 @@
 
 //! Logging
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast::transmute;
 use io;
 use libc;
diff --git a/src/libcore/managed.rs b/src/libcore/managed.rs
index 32fc5f527b7..700feee9839 100644
--- a/src/libcore/managed.rs
+++ b/src/libcore/managed.rs
@@ -10,10 +10,6 @@
 
 //! Operations on managed box types
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast::transmute;
 use cmp::{Eq, Ord};
 use managed::raw::BoxRepr;
diff --git a/src/libcore/mutable.rs b/src/libcore/mutable.rs
index 4623a3f4543..3c44c197f5e 100644
--- a/src/libcore/mutable.rs
+++ b/src/libcore/mutable.rs
@@ -18,8 +18,6 @@ dynamic checks: your program will fail if you attempt to perform
 mutation when the data structure should be immutable.
 
 */
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 
 use util::with;
 use cast::transmute_immut;
diff --git a/src/libcore/nil.rs b/src/libcore/nil.rs
index f3eb62a3a3a..8f03a1b6e34 100644
--- a/src/libcore/nil.rs
+++ b/src/libcore/nil.rs
@@ -14,10 +14,6 @@ Functions for the unit type.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::{Eq, Ord};
 
 #[cfg(notest)]
diff --git a/src/libcore/num/cmath.rs b/src/libcore/num/cmath.rs
index 6341481809e..c030dfc5899 100644
--- a/src/libcore/num/cmath.rs
+++ b/src/libcore/num/cmath.rs
@@ -9,9 +9,6 @@
 // except according to those terms.
 
 #[doc(hidden)]; // FIXME #3538
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 
 use libc::c_int;
 use libc::c_float;
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 24ad5c114af..738445b5cd9 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 //! Operations and constants for `f32`
 
 use cmath;
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 126a48cf280..f09d874803c 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 //! Operations and constants for `f64`
 
 use cmath;
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index 32cda029cd1..f5ae05ebffb 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 //! Operations and constants for `float`
 
 // Even though this module exports everything defined in it,
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs
index 8b02f3a94c5..1856781b1d7 100644
--- a/src/libcore/num/int-template.rs
+++ b/src/libcore/num/int-template.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use T = self::inst::T;
 
 use char;
diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs
index 82c6e017014..f8bbb35204a 100644
--- a/src/libcore/num/uint-template.rs
+++ b/src/libcore/num/uint-template.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use T = self::inst::T;
 use T_SIGNED = self::inst::T_SIGNED;
 
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 36293d6a1c0..aaa4ab3fecf 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -10,9 +10,6 @@
 
 // Core operators
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 #[lang="drop"]
 pub trait Drop {
     fn finalize(&self);  // FIXME(#4332): Rename to "drop"? --pcwalton
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 9cb955ad352..e5d703eec4a 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -41,9 +41,6 @@ let unwrapped_msg = match move msg {
 
 */
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::Eq;
 use kinds::Copy;
 use option;
diff --git a/src/libcore/os.rs b/src/libcore/os.rs
index af484454ef4..a14abd23cc3 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 #[allow(structural_records)];
 
 /*!
diff --git a/src/libcore/owned.rs b/src/libcore/owned.rs
index fb14820113e..d841188501d 100644
--- a/src/libcore/owned.rs
+++ b/src/libcore/owned.rs
@@ -10,10 +10,6 @@
 
 //! Operations on unique pointer types
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::{Eq, Ord};
 
 #[cfg(notest)]
diff --git a/src/libcore/path.rs b/src/libcore/path.rs
index 0b64df8c112..bf1f1c713a9 100644
--- a/src/libcore/path.rs
+++ b/src/libcore/path.rs
@@ -14,10 +14,6 @@ Cross-platform file path handling
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::Eq;
 use libc;
 use option::{None, Option, Some};
diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs
index 5f9eed70868..3f0aecb887d 100644
--- a/src/libcore/pipes.rs
+++ b/src/libcore/pipes.rs
@@ -82,11 +82,6 @@ bounded and unbounded protocols allows for less code duplication.
 
 */
 
-// NB: transitionary, de-mode-ing.
-// tjc: allowing deprecated modes due to function issue,
-// re-forbid after snapshot
-#[forbid(deprecated_pattern)];
-
 // Transitional -- needs snapshot
 #[allow(structural_records)];
 
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 4e6f209e79e..a798d8c866a 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -36,7 +36,7 @@ pub use path::PosixPath;
 pub use path::WindowsPath;
 pub use pipes::{GenericChan, GenericPort};
 pub use ptr::Ptr;
-pub use str::{StrSlice, Trimmable};
+pub use str::{StrSlice, Trimmable, OwnedStr};
 pub use to_bytes::IterBytes;
 pub use to_str::ToStr;
 pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
diff --git a/src/libcore/private.rs b/src/libcore/private.rs
index 40194713365..d4cf39ad262 100644
--- a/src/libcore/private.rs
+++ b/src/libcore/private.rs
@@ -8,11 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-// tjc: Re-forbid deprecated modes once a snapshot fixes the
-// function problem
-#[forbid(deprecated_pattern)];
-
 #[doc(hidden)];
 
 use cast;
diff --git a/src/libcore/private/finally.rs b/src/libcore/private/finally.rs
index 2c27b8ab3a2..50c5ea70cbb 100644
--- a/src/libcore/private/finally.rs
+++ b/src/libcore/private/finally.rs
@@ -26,10 +26,19 @@ do || {
 use ops::Drop;
 use task::{spawn, failing};
 
+#[cfg(stage0)]
 pub trait Finally<T> {
     fn finally(&self, +dtor: &fn()) -> T;
 }
 
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+pub trait Finally<T> {
+    fn finally(&self, dtor: &fn()) -> T;
+}
+
+#[cfg(stage0)]
 impl<T> &fn() -> T: Finally<T> {
     // FIXME #4518: Should not require a mode here
     fn finally(&self, +dtor: &fn()) -> T {
@@ -41,6 +50,19 @@ impl<T> &fn() -> T: Finally<T> {
     }
 }
 
+#[cfg(stage1)]
+#[cfg(stage2)]
+#[cfg(stage3)]
+impl<T> &fn() -> T: Finally<T> {
+    fn finally(&self, dtor: &fn()) -> T {
+        let _d = Finallyalizer {
+            dtor: dtor
+        };
+
+        (*self)()
+    }
+}
+
 struct Finallyalizer {
     dtor: &fn()
 }
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index fb82c07da04..ad0bcb5cff8 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -10,9 +10,6 @@
 
 //! Unsafe pointer utility functions
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast;
 use cmp::{Eq, Ord};
 use libc;
diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs
index 50232f99f85..452ab945251 100644
--- a/src/libcore/rand.rs
+++ b/src/libcore/rand.rs
@@ -10,10 +10,6 @@
 
 //! Random number generation
 
-// NB: transitional, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use int;
 use prelude::*;
 use str;
diff --git a/src/libcore/reflect.rs b/src/libcore/reflect.rs
index dcbb7067670..de94100d7a5 100644
--- a/src/libcore/reflect.rs
+++ b/src/libcore/reflect.rs
@@ -14,9 +14,6 @@ Runtime type reflection
 
 */
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use intrinsic::{TyDesc, get_tydesc, visit_tydesc, TyVisitor};
 use libc::c_void;
 use sys;
diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs
index 1f04f9e77a9..a47bad008b8 100644
--- a/src/libcore/repr.rs
+++ b/src/libcore/repr.rs
@@ -14,9 +14,6 @@ More runtime type reflection
 
 */
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast::transmute;
 use cast;
 use char;
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index d04667698fd..7f151317378 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -12,9 +12,6 @@
 
 // NB: transitionary, de-mode-ing.
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp;
 use cmp::Eq;
 use either;
diff --git a/src/libcore/rt.rs b/src/libcore/rt.rs
index f9de0bc91fd..33d76cb3c68 100644
--- a/src/libcore/rt.rs
+++ b/src/libcore/rt.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 //! Runtime calls emitted by the compiler.
 
 use cast::transmute;
diff --git a/src/libcore/run.rs b/src/libcore/run.rs
index c10eacc7a0a..e44bd2aab81 100644
--- a/src/libcore/run.rs
+++ b/src/libcore/run.rs
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 #[allow(structural_records)];
 
 //! Process spawning
diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs
index 17921a1a1b0..2e24df86c78 100644
--- a/src/libcore/stackwalk.rs
+++ b/src/libcore/stackwalk.rs
@@ -11,12 +11,7 @@
 #[doc(hidden)]; // FIXME #3538
 
 #[legacy_modes]; // tjc: remove after snapshot
-
-// NB: transitionary, de-mode-ing.
-// FIXME #4425: Can't forbid this because frame_address needs a deprecated
-// mode.
 #[allow(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 
 use cast::reinterpret_cast;
 use ptr::offset;
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 64695be21d5..9b25f92ede2 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -17,9 +17,6 @@
  * some heavy-duty uses, try std::rope.
  */
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use at_vec;
 use cast;
 use char;
@@ -2314,6 +2311,21 @@ impl &str: StrSlice {
     pure fn char_at(i: uint) -> char { char_at(self, i) }
 }
 
+pub trait OwnedStr {
+    fn push_str(&mut self, v: &str);
+    fn push_char(&mut self, c: char);
+}
+
+pub impl ~str : OwnedStr {
+    fn push_str(&mut self, v: &str) {
+        push_str(self, v);
+    }
+
+    fn push_char(&mut self, c: char) {
+        push_char(self, c);
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use char;
diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs
index 914eccd3d86..1571e645117 100644
--- a/src/libcore/sys.rs
+++ b/src/libcore/sys.rs
@@ -10,10 +10,6 @@
 
 //! Misc low level stuff
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cast;
 use cmp::{Eq, Ord};
 use gc;
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index d276f0c6ea9..9240a67c69a 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -8,11 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-// tjc: Deprecated modes allowed because of function arg issue
-// in task::spawn. Re-forbid after snapshot.
-#[forbid(deprecated_pattern)];
-
 /*!
  * Task management.
  *
diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs
index c88587067c1..22a0c870de6 100644
--- a/src/libcore/task/spawn.rs
+++ b/src/libcore/task/spawn.rs
@@ -71,7 +71,6 @@
  ****************************************************************************/
 
 #[doc(hidden)]; // FIXME #3538
-#[warn(deprecated_mode)];
 
 use cast;
 use container::Map;
diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs
index 84e5140d8ed..b4647d0c621 100644
--- a/src/libcore/to_bytes.rs
+++ b/src/libcore/to_bytes.rs
@@ -14,16 +14,12 @@ The `ToBytes` and `IterBytes` traits
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use io;
 use io::Writer;
 use option::{None, Option, Some};
 use str;
 
-pub type Cb = fn(buf: &[const u8]) -> bool;
+pub type Cb = &fn(buf: &[const u8]) -> bool;
 
 /**
  * A trait to implement in order to make a type hashable;
diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs
index 0e46b4fd004..d98e341eab8 100644
--- a/src/libcore/to_str.rs
+++ b/src/libcore/to_str.rs
@@ -14,10 +14,6 @@ The `ToStr` trait for converting to strings
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use kinds::Copy;
 use str;
 use vec;
diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs
index c497a2f3c7f..484fc1a5a27 100644
--- a/src/libcore/tuple.rs
+++ b/src/libcore/tuple.rs
@@ -8,10 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 //! Operations on tuples
 
 use cmp::{Eq, Ord};
diff --git a/src/libcore/unicode.rs b/src/libcore/unicode.rs
index dedd5d12c55..ff3b908186a 100644
--- a/src/libcore/unicode.rs
+++ b/src/libcore/unicode.rs
@@ -9,9 +9,6 @@
 // except according to those terms.
 
 #[doc(hidden)]; // FIXME #3538
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 
 pub mod general_category {
     pub pure fn Cc(c: char) -> bool {
diff --git a/src/libcore/util.rs b/src/libcore/util.rs
index 8dff492e634..3b6a134bc52 100644
--- a/src/libcore/util.rs
+++ b/src/libcore/util.rs
@@ -14,10 +14,6 @@ Miscellaneous helpers for common patterns.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
-
 use cmp::Eq;
 use prelude::*;
 
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 7846d3d0302..9ad5d9f32da 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -10,8 +10,6 @@
 
 //! Vectors
 
-#[forbid(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 #[warn(non_camel_case_types)];
 
 use container::{Container, Mutable};
@@ -841,14 +839,37 @@ pub pure fn map2<T: Copy, U: Copy, V>(v0: &[T], v1: &[U],
     u
 }
 
-/**
- * Apply a function to each element of a vector and return the results
- *
- * If function `f` returns `none` then that element is excluded from
- * the resulting vector.
- */
-pub pure fn filter_map<T, U: Copy>(v: &[T], f: fn(t: &T) -> Option<U>)
-    -> ~[U] {
+pub fn filter_map<T, U>(
+    v: ~[T],
+    f: fn(t: T) -> Option<U>) -> ~[U]
+{
+    /*!
+     *
+     * Apply a function to each element of a vector and return the results.
+     * Consumes the input vector.  If function `f` returns `None` then that
+     * element is excluded from the resulting vector.
+     */
+
+    let mut result = ~[];
+    do consume(v) |_, elem| {
+        match f(elem) {
+            None => {}
+            Some(result_elem) => { result.push(result_elem); }
+        }
+    }
+    result
+}
+
+pub pure fn filter_mapped<T, U: Copy>(
+    v: &[T],
+    f: fn(t: &T) -> Option<U>) -> ~[U]
+{
+    /*!
+     *
+     * Like `filter_map()`, but operates on a borrowed slice
+     * and does not consume the input.
+     */
+
     let mut result = ~[];
     for each(v) |elem| {
         match f(elem) {
@@ -1695,7 +1716,7 @@ pub trait ImmutableVector<T> {
     fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U];
     pure fn alli(&self, f: fn(uint, t: &T) -> bool) -> bool;
     pure fn flat_map<U>(&self, f: fn(t: &T) -> ~[U]) -> ~[U];
-    pure fn filter_map<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U];
+    pure fn filter_mapped<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U];
 }
 
 /// Extension methods for vectors
@@ -1758,8 +1779,8 @@ impl<T> &[T]: ImmutableVector<T> {
      * the resulting vector.
      */
     #[inline]
-    pure fn filter_map<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U] {
-        filter_map(*self, f)
+    pure fn filter_mapped<U: Copy>(&self, f: fn(t: &T) -> Option<U>) -> ~[U] {
+        filter_mapped(*self, f)
     }
 }
 
@@ -2439,10 +2460,14 @@ mod tests {
 
     pure fn is_equal(x: &uint, y:&uint) -> bool { return *x == *y; }
 
-    fn square_if_odd(n: &uint) -> Option<uint> {
+    fn square_if_odd_r(n: &uint) -> Option<uint> {
         return if *n % 2u == 1u { Some(*n * *n) } else { None };
     }
 
+    fn square_if_odd_v(n: uint) -> Option<uint> {
+        return if n % 2u == 1u { Some(n * n) } else { None };
+    }
+
     fn add(x: uint, y: &uint) -> uint { return x + *y; }
 
     #[test]
@@ -2775,17 +2800,17 @@ mod tests {
     }
 
     #[test]
-    fn test_filter_map() {
+    fn test_filter_mapped() {
         // Test on-stack filter-map.
         let mut v = ~[1u, 2u, 3u];
-        let mut w = filter_map(v, square_if_odd);
+        let mut w = filter_mapped(v, square_if_odd_r);
         assert (len(w) == 2u);
         assert (w[0] == 1u);
         assert (w[1] == 9u);
 
         // Test on-heap filter-map.
         v = ~[1u, 2u, 3u, 4u, 5u];
-        w = filter_map(v, square_if_odd);
+        w = filter_mapped(v, square_if_odd_r);
         assert (len(w) == 3u);
         assert (w[0] == 1u);
         assert (w[1] == 9u);
@@ -2804,7 +2829,46 @@ mod tests {
         let all_odd2: ~[int] = ~[];
         let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
         let mix_dest: ~[int] = ~[1, 3, 0, 0];
-        assert (filter_map(all_even, halve) == map(all_even, halve_for_sure));
+        assert (filter_mapped(all_even, halve) ==
+                map(all_even, halve_for_sure));
+        assert (filter_mapped(all_odd1, halve) == ~[]);
+        assert (filter_mapped(all_odd2, halve) == ~[]);
+        assert (filter_mapped(mix, halve) == mix_dest);
+    }
+
+    #[test]
+    fn test_filter_map() {
+        // Test on-stack filter-map.
+        let mut v = ~[1u, 2u, 3u];
+        let mut w = filter_map(v, square_if_odd_v);
+        assert (len(w) == 2u);
+        assert (w[0] == 1u);
+        assert (w[1] == 9u);
+
+        // Test on-heap filter-map.
+        v = ~[1u, 2u, 3u, 4u, 5u];
+        w = filter_map(v, square_if_odd_v);
+        assert (len(w) == 3u);
+        assert (w[0] == 1u);
+        assert (w[1] == 9u);
+        assert (w[2] == 25u);
+
+        fn halve(i: int) -> Option<int> {
+            if i % 2 == 0 {
+                return option::Some::<int>(i / 2);
+            } else {
+                return option::None::<int>;
+            }
+        }
+        fn halve_for_sure(i: &int) -> int { return *i / 2; }
+        let all_even: ~[int] = ~[0, 2, 8, 6];
+        let all_even0: ~[int] = copy all_even;
+        let all_odd1: ~[int] = ~[1, 7, 3];
+        let all_odd2: ~[int] = ~[];
+        let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
+        let mix_dest: ~[int] = ~[1, 3, 0, 0];
+        assert (filter_map(all_even, halve) ==
+                map(all_even0, halve_for_sure));
         assert (filter_map(all_odd1, halve) == ~[]);
         assert (filter_map(all_odd2, halve) == ~[]);
         assert (filter_map(mix, halve) == mix_dest);
@@ -3664,10 +3728,10 @@ mod tests {
     #[ignore(windows)]
     #[should_fail]
     #[allow(non_implicitly_copyable_typarams)]
-    fn test_filter_map_fail() {
+    fn test_filter_mapped_fail() {
         let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
         let mut i = 0;
-        do filter_map(v) |_elt| {
+        do filter_mapped(v) |_elt| {
             if i == 2 {
                 die!()
             }
diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs
index a7c071919ff..cf75db3a900 100644
--- a/src/librustc/front/config.rs
+++ b/src/librustc/front/config.rs
@@ -64,12 +64,13 @@ fn filter_view_item(cx: ctxt, &&view_item: @ast::view_item
 }
 
 fn fold_mod(cx: ctxt, m: ast::_mod, fld: fold::ast_fold) -> ast::_mod {
-    let filtered_items = vec::filter_map(m.items, |a| filter_item(cx, *a));
-    let filtered_view_items = vec::filter_map(m.view_items,
-                                              |a| filter_view_item(cx, *a));
+    let filtered_items =
+        m.items.filter_mapped(|a| filter_item(cx, *a));
+    let filtered_view_items =
+        m.view_items.filter_mapped(|a| filter_view_item(cx, *a));
     ast::_mod {
         view_items: filtered_view_items.map(|x| fld.fold_view_item(*x)),
-        items: filtered_items.filter_map(|x| fld.fold_item(*x)),
+        items: vec::filter_map(filtered_items, |x| fld.fold_item(x))
     }
 }
 
@@ -85,10 +86,10 @@ fn fold_foreign_mod(
     nm: ast::foreign_mod,
     fld: fold::ast_fold
 ) -> ast::foreign_mod {
-    let filtered_items = vec::filter_map(nm.items,
-                                         |a| filter_foreign_item(cx, *a));
-    let filtered_view_items = vec::filter_map(nm.view_items,
-                                              |a| filter_view_item(cx, *a));
+    let filtered_items =
+        nm.items.filter_mapped(|a| filter_foreign_item(cx, *a));
+    let filtered_view_items =
+        nm.view_items.filter_mapped(|a| filter_view_item(cx, *a));
     ast::foreign_mod {
         sort: nm.sort,
         abi: nm.abi,
@@ -136,7 +137,8 @@ fn fold_block(
     b: ast::blk_,
     fld: fold::ast_fold
 ) -> ast::blk_ {
-    let filtered_stmts = vec::filter_map(b.stmts, |a| filter_stmt(cx, *a));
+    let filtered_stmts =
+        b.stmts.filter_mapped(|a| filter_stmt(cx, *a));
     ast::blk_ {
         view_items: /*bad*/copy b.view_items,
         stmts: vec::map(filtered_stmts, |x| fld.fold_stmt(*x)),
@@ -183,8 +185,9 @@ pub fn metas_in_cfg(cfg: ast::crate_cfg,
     // Pull the inner meta_items from the #[cfg(meta_item, ...)]  attributes,
     // so we can match against them. This is the list of configurations for
     // which the item is valid
-    let cfg_metas = vec::concat(vec::filter_map(cfg_metas,
-        |i| attr::get_meta_item_list(*i)));
+    let cfg_metas =
+        vec::concat(
+            vec::filter_map(cfg_metas, |i| attr::get_meta_item_list(i)));
 
     let has_cfg_metas = vec::len(cfg_metas) > 0u;
     if !has_cfg_metas { return true; }
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 91eb8148bb7..9fa1cea3e10 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -168,9 +168,11 @@ fn is_test_fn(i: @ast::item) -> bool {
 fn is_ignored(cx: test_ctxt, i: @ast::item) -> bool {
     let ignoreattrs = attr::find_attrs_by_name(i.attrs, "ignore");
     let ignoreitems = attr::attr_metas(ignoreattrs);
-    let cfg_metas = vec::concat(vec::filter_map(ignoreitems,
-        |i| attr::get_meta_item_list(*i)));
     return if !ignoreitems.is_empty() {
+        let cfg_metas =
+            vec::concat(
+                vec::filter_map(ignoreitems,
+                                |i| attr::get_meta_item_list(i)));
         config::metas_in_cfg(/*bad*/copy cx.crate.node.config, cfg_metas)
     } else {
         false
@@ -277,7 +279,7 @@ fn mk_std(cx: test_ctxt) -> @ast::view_item {
 }
 
 fn mk_tests(cx: test_ctxt) -> @ast::item {
-    let ret_ty = mk_test_desc_vec_ty(cx);
+    let ret_ty = mk_test_desc_and_fn_vec_ty(cx);
 
     let decl = ast::fn_decl {
         inputs: ~[],
@@ -286,7 +288,7 @@ fn mk_tests(cx: test_ctxt) -> @ast::item {
     };
 
     // The vector of test_descs for this crate
-    let test_descs = mk_test_desc_vec(cx);
+    let test_descs = mk_test_desc_and_fn_vec(cx);
 
     let body_: ast::blk_ =
         default_block(~[], option::Some(test_descs), cx.sess.next_node_id());
@@ -327,19 +329,21 @@ fn mk_path(cx: test_ctxt, +path: ~[ast::ident]) -> @ast::path {
     }
 }
 
-// The ast::Ty of ~[std::test::test_desc]
-fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty {
-    let test_desc_ty_path =
+// The ast::Ty of ~[std::test::TestDescAndFn]
+fn mk_test_desc_and_fn_vec_ty(cx: test_ctxt) -> @ast::Ty {
+    let test_desc_and_fn_ty_path =
         mk_path(cx, ~[cx.sess.ident_of(~"test"),
-                      cx.sess.ident_of(~"TestDesc")]);
+                      cx.sess.ident_of(~"TestDescAndFn")]);
 
-    let test_desc_ty = ast::Ty {
+    let test_desc_and_fn_ty = ast::Ty {
         id: cx.sess.next_node_id(),
-        node: ast::ty_path(test_desc_ty_path, cx.sess.next_node_id()),
+        node: ast::ty_path(test_desc_and_fn_ty_path,
+                           cx.sess.next_node_id()),
         span: dummy_sp(),
     };
 
-    let vec_mt = ast::mt {ty: @test_desc_ty, mutbl: ast::m_imm};
+    let vec_mt = ast::mt {ty: @test_desc_and_fn_ty,
+                          mutbl: ast::m_imm};
 
     let inner_ty = @ast::Ty {
         id: cx.sess.next_node_id(),
@@ -354,11 +358,11 @@ fn mk_test_desc_vec_ty(cx: test_ctxt) -> @ast::Ty {
     }
 }
 
-fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
+fn mk_test_desc_and_fn_vec(cx: test_ctxt) -> @ast::expr {
     debug!("building test vector from %u tests", cx.testfns.len());
     let mut descs = ~[];
     for cx.testfns.each |test| {
-        descs.push(mk_test_desc_rec(cx, *test));
+        descs.push(mk_test_desc_and_fn_rec(cx, *test));
     }
 
     let inner_expr = @ast::expr {
@@ -376,7 +380,7 @@ fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
     }
 }
 
-fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
+fn mk_test_desc_and_fn_rec(cx: test_ctxt, test: test) -> @ast::expr {
     let span = test.span;
     let path = /*bad*/copy test.path;
 
@@ -407,23 +411,6 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
         expr: @name_expr,
     });
 
-    let fn_path = path_node_global(path);
-
-    let fn_expr = ast::expr {
-        id: cx.sess.next_node_id(),
-        callee_id: cx.sess.next_node_id(),
-        node: ast::expr_path(fn_path),
-        span: span,
-    };
-
-    let fn_wrapper_expr = mk_test_wrapper(cx, fn_expr, span);
-
-    let fn_field = nospan(ast::field_ {
-        mutbl: ast::m_imm,
-        ident: cx.sess.ident_of(~"testfn"),
-        expr: fn_wrapper_expr,
-    });
-
     let ignore_lit: ast::lit = nospan(ast::lit_bool(test.ignore));
 
     let ignore_expr = ast::expr {
@@ -460,62 +447,52 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
 
     let desc_rec_ = ast::expr_struct(
         test_desc_path,
-        ~[name_field, fn_field, ignore_field, fail_field],
+        ~[name_field, ignore_field, fail_field],
         option::None
     );
 
-    let desc_rec = ast::expr {
+    let desc_rec = @ast::expr {
         id: cx.sess.next_node_id(),
         callee_id: cx.sess.next_node_id(),
         node: desc_rec_,
         span: span,
     };
 
-    return @desc_rec;
-}
+    let desc_field = nospan(ast::field_ {
+        mutbl: ast::m_imm,
+        ident: cx.sess.ident_of(~"desc"),
+        expr: desc_rec
+    });
 
-// Produces a bare function that wraps the test function
+    let fn_path = path_node_global(path);
 
-// FIXME (#1281): This can go away once fn is the type of bare function.
-fn mk_test_wrapper(cx: test_ctxt,
-                   +fn_path_expr: ast::expr,
-                   span: span) -> @ast::expr {
-    let call_expr = ast::expr {
+    let fn_expr = @ast::expr {
         id: cx.sess.next_node_id(),
         callee_id: cx.sess.next_node_id(),
-        node: ast::expr_call(@fn_path_expr, ~[], false),
+        node: ast::expr_path(fn_path),
         span: span,
     };
 
-    let call_stmt: ast::stmt = nospan(
-        ast::stmt_semi(@call_expr, cx.sess.next_node_id()));
-
-    let wrapper_decl = ast::fn_decl {
-        inputs: ~[],
-        output: @ast::Ty {
-            id: cx.sess.next_node_id(),
-            node: ast::ty_nil,
-            span: span,
-        },
-        cf: ast::return_val
-    };
-
-    let wrapper_body = nospan(ast::blk_ {
-        view_items: ~[],
-        stmts: ~[@call_stmt],
-        expr: option::None,
-        id: cx.sess.next_node_id(),
-        rules: ast::default_blk
+    let fn_field = nospan(ast::field_ {
+        mutbl: ast::m_imm,
+        ident: cx.sess.ident_of(~"testfn"),
+        expr: fn_expr,
     });
 
-    let wrapper_expr = ast::expr  {
+    let test_desc_and_fn_path =
+        mk_path(cx, ~[cx.sess.ident_of(~"test"),
+                      cx.sess.ident_of(~"TestDescAndFn")]);
+
+    let desc_and_fn_rec = @ast::expr {
         id: cx.sess.next_node_id(),
         callee_id: cx.sess.next_node_id(),
-        node: ast::expr_fn(ast::ProtoBare, wrapper_decl, wrapper_body, @()),
-        span: span
+        node: ast::expr_struct(test_desc_and_fn_path,
+                               ~[fn_field, desc_field],
+                               option::None),
+        span: span,
     };
 
-    return @wrapper_expr;
+    return desc_and_fn_rec;
 }
 
 fn mk_main(cx: test_ctxt) -> @ast::item {
@@ -567,7 +544,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
     let args_call_expr = ast::expr {
         id: cx.sess.next_node_id(),
         callee_id: cx.sess.next_node_id(),
-        node: ast::expr_call(@args_path_expr, ~[], false),
+        node: ast::expr_call(@args_path_expr, ~[], ast::NoSugar),
         span: dummy_sp(),
     };
 
@@ -584,7 +561,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
     let test_call_expr = ast::expr {
         id: cx.sess.next_node_id(),
         callee_id: cx.sess.next_node_id(),
-        node: ast::expr_call(@test_path_expr, ~[], false),
+        node: ast::expr_call(@test_path_expr, ~[], ast::NoSugar),
         span: dummy_sp(),
     };
 
@@ -606,7 +583,7 @@ fn mk_test_main_call(cx: test_ctxt) -> @ast::expr {
         node: ast::expr_call(
             @test_main_path_expr,
             ~[@args_call_expr, @test_call_expr],
-            false
+            ast::NoSugar
         ),
         span: dummy_sp(),
     };
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 9a6a2f7e954..67498ad5aaf 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -586,10 +586,8 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
                                 item, tcx, cdata);
         let name = item_name(intr, item);
         let arg_tys = match ty::get(ctor_ty).sty {
-          ty::ty_fn(ref f) => (*f).sig.inputs.map(|a| a.ty),
-
-          // Nullary enum variant.
-          _ => ~[],
+          ty::ty_bare_fn(ref f) => f.sig.inputs.map(|a| a.ty),
+          _ => ~[], // Nullary enum variant.
         };
         match variant_disr_val(item) {
           Some(val) => { disr_val = val; }
@@ -705,11 +703,12 @@ pub fn get_trait_methods(intr: @ident_interner, cdata: cmd, id: ast::node_id,
         let ty = doc_type(mth, tcx, cdata);
         let def_id = item_def_id(mth, cdata);
         let fty = match ty::get(ty).sty {
-          ty::ty_fn(ref f) => (/*bad*/copy *f),
-          _ => {
-            tcx.diag.handler().bug(
-                ~"get_trait_methods: id has non-function type");
-        } };
+            ty::ty_bare_fn(ref f) => copy *f,
+            _ => {
+                tcx.diag.handler().bug(
+                    ~"get_trait_methods: id has non-function type");
+            }
+        };
         let self_ty = get_self_ty(mth);
         result.push({ident: name, tps: bounds, fty: fty, self_ty: self_ty,
                      vis: ast::public, def_id: def_id});
@@ -734,14 +733,13 @@ pub fn get_provided_trait_methods(intr: @ident_interner, cdata: cmd,
         let name = item_name(intr, mth);
         let ty = doc_type(mth, tcx, cdata);
 
-        let fty;
-        match ty::get(ty).sty {
-            ty::ty_fn(ref f) => fty = (/*bad*/copy *f),
+        let fty = match ty::get(ty).sty {
+            ty::ty_bare_fn(ref f) => copy *f,
             _ => {
                 tcx.diag.handler().bug(~"get_provided_trait_methods(): id \
                                          has non-function type");
             }
-        }
+        };
 
         let self_ty = get_self_ty(mth);
         let ty_method = {ident: name, tps: bounds, fty: fty, self_ty: self_ty,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 072b974d042..b0a424447b3 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -768,8 +768,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
                 encode_name(ecx, ebml_w, mty.ident);
                 encode_type_param_bounds(ebml_w, ecx,
                                          (*ty_m).tps);
-                encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty));
-                encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
+                encode_type(ecx, ebml_w,
+                            ty::mk_bare_fn(tcx, copy mty.fty));
+                encode_family(ebml_w, purity_fn_family(mty.fty.purity));
                 encode_self_type(ebml_w, mty.self_ty);
                 encode_method_sort(ebml_w, 'r');
                 ebml_w.end_tag();
@@ -781,8 +782,9 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
                 encode_def_id(ebml_w, local_def(m.id));
                 encode_name(ecx, ebml_w, mty.ident);
                 encode_type_param_bounds(ebml_w, ecx, m.tps);
-                encode_type(ecx, ebml_w, ty::mk_fn(tcx, /*bad*/copy mty.fty));
-                encode_family(ebml_w, purity_fn_family(mty.fty.meta.purity));
+                encode_type(ecx, ebml_w,
+                            ty::mk_bare_fn(tcx, copy mty.fty));
+                encode_family(ebml_w, purity_fn_family(mty.fty.purity));
                 encode_self_type(ebml_w, mty.self_ty);
                 encode_method_sort(ebml_w, 'p');
                 ebml_w.end_tag();
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index ea13325ad49..3f989339e27 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -17,8 +17,6 @@
 use core::prelude::*;
 
 use middle::ty;
-use middle::ty::{FnTyBase, FnMeta, FnSig, arg, creader_cache_key, field};
-use middle::ty::{substs};
 
 use core::io;
 use core::str;
@@ -124,17 +122,12 @@ fn parse_path(st: @pstate) -> @ast::path {
     };
 }
 
-fn parse_ty_rust_fn(st: @pstate, conv: conv_did) -> ty::t {
-    return ty::mk_fn(st.tcx, parse_ty_fn(st, conv));
-}
-
-fn parse_proto(st: @pstate) -> ast::Proto {
+fn parse_sigil(st: @pstate) -> ast::Sigil {
     match next(st) {
-        '_' => ast::ProtoBare,
-        '@' => ast::ProtoBox,
-        '~' => ast::ProtoUniq,
-        '&' => ast::ProtoBorrowed,
-        _ => die!(~"parse_proto(): bad input")
+        '@' => ast::ManagedSigil,
+        '~' => ast::OwnedSigil,
+        '&' => ast::BorrowedSigil,
+        c => st.tcx.sess.bug(fmt!("parse_sigil(): bad input '%c'", c))
     }
 }
 
@@ -152,7 +145,7 @@ fn parse_vstore(st: @pstate) -> ty::vstore {
       '~' => ty::vstore_uniq,
       '@' => ty::vstore_box,
       '&' => ty::vstore_slice(parse_region(st)),
-      _ => die!(~"parse_vstore: bad input")
+      c => st.tcx.sess.bug(fmt!("parse_vstore(): bad input '%c'", c))
     }
 }
 
@@ -166,7 +159,7 @@ fn parse_substs(st: @pstate, conv: conv_did) -> ty::substs {
     while peek(st) != ']' { params.push(parse_ty(st, conv)); }
     st.pos = st.pos + 1u;
 
-    return substs {
+    return ty::substs {
         self_r: self_r,
         self_ty: self_ty,
         tps: params
@@ -316,19 +309,24 @@ fn parse_ty(st: @pstate, conv: conv_did) -> ty::t {
         return ty::mk_tup(st.tcx, params);
       }
       'f' => {
-        parse_ty_rust_fn(st, conv)
+        return ty::mk_closure(st.tcx, parse_closure_ty(st, conv));
+      }
+      'F' => {
+        return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, conv));
       }
       'Y' => return ty::mk_type(st.tcx),
       'C' => {
-        let proto = parse_proto(st);
-        return ty::mk_opaque_closure_ptr(st.tcx, proto);
+        let sigil = parse_sigil(st);
+        return ty::mk_opaque_closure_ptr(st.tcx, sigil);
       }
       '#' => {
         let pos = parse_hex(st);
         assert (next(st) == ':');
         let len = parse_hex(st);
         assert (next(st) == '#');
-        let key = creader_cache_key { cnum: st.crate, pos: pos, len: len };
+        let key = ty::creader_cache_key {cnum: st.crate,
+                                         pos: pos,
+                                         len: len };
         match st.tcx.rcache.find(&key) {
           Some(tt) => return tt,
           None => {
@@ -408,6 +406,13 @@ fn parse_purity(c: char) -> purity {
     }
 }
 
+fn parse_abi(c: char) -> Abi {
+    match c {
+      'r' => ast::RustAbi,
+      _ => die!(fmt!("parse_abi: bad ABI '%c'", c))
+    }
+}
+
 fn parse_onceness(c: char) -> ast::Onceness {
     match c {
         'o' => ast::Once,
@@ -430,12 +435,33 @@ fn parse_mode(st: @pstate) -> ast::mode {
     return m;
 }
 
-fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
-    let proto = parse_proto(st);
+fn parse_closure_ty(st: @pstate, conv: conv_did) -> ty::ClosureTy {
+    let sigil = parse_sigil(st);
     let purity = parse_purity(next(st));
     let onceness = parse_onceness(next(st));
     let region = parse_region(st);
-    let bounds = parse_bounds(st, conv);
+    let sig = parse_sig(st, conv);
+    ty::ClosureTy {
+        purity: purity,
+        sigil: sigil,
+        onceness: onceness,
+        region: region,
+        sig: sig
+    }
+}
+
+fn parse_bare_fn_ty(st: @pstate, conv: conv_did) -> ty::BareFnTy {
+    let purity = parse_purity(next(st));
+    let abi = parse_abi(next(st));
+    let sig = parse_sig(st, conv);
+    ty::BareFnTy {
+        purity: purity,
+        abi: abi,
+        sig: sig
+    }
+}
+
+fn parse_sig(st: @pstate, conv: conv_did) -> ty::FnSig {
     assert (next(st) == '[');
     let mut inputs: ~[ty::arg] = ~[];
     while peek(st) != ']' {
@@ -444,18 +470,9 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
     }
     st.pos += 1u; // eat the ']'
     let ret_ty = parse_ty(st, conv);
-    return FnTyBase {
-        meta: FnMeta {purity: purity,
-                      proto: proto,
-                      onceness: onceness,
-                      bounds: bounds,
-                      region: region},
-        sig: FnSig {inputs: inputs,
-                    output: ret_ty}
-    };
+    ty::FnSig {inputs: inputs, output: ret_ty}
 }
 
-
 // Rust metadata parsing
 pub fn parse_def_id(buf: &[u8]) -> ast::def_id {
     let mut colon_idx = 0u;
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 0d66862c79f..a87ce02d5a3 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -288,8 +288,13 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
         }
         w.write_char(']');
       }
-      ty::ty_fn(ref f) => {
-        enc_ty_fn(w, cx, (*f));
+      ty::ty_closure(ref f) => {
+        w.write_char('f');
+        enc_closure_ty(w, cx, f);
+      }
+      ty::ty_bare_fn(ref f) => {
+        w.write_char('F');
+        enc_bare_fn_ty(w, cx, f);
       }
       ty::ty_infer(_) => {
         cx.diag.handler().bug(~"Cannot encode inference variable types");
@@ -306,7 +311,7 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
       ty::ty_type => w.write_char('Y'),
       ty::ty_opaque_closure_ptr(p) => {
           w.write_str(&"C&");
-          enc_proto(w, p);
+          enc_sigil(w, p);
       }
       ty::ty_opaque_box => w.write_char('B'),
       ty::ty_struct(def, ref substs) => {
@@ -325,13 +330,11 @@ fn enc_sty(w: io::Writer, cx: @ctxt, +st: ty::sty) {
     }
 }
 
-fn enc_proto(w: io::Writer, proto: Proto) {
-    w.write_str(&"f");
-    match proto {
-        ProtoBare => w.write_str(&"_"),
-        ProtoBox => w.write_str(&"@"),
-        ProtoUniq => w.write_str(&"~"),
-        ProtoBorrowed => w.write_str(&"&"),
+fn enc_sigil(w: io::Writer, sigil: Sigil) {
+    match sigil {
+        ManagedSigil => w.write_str("@"),
+        OwnedSigil => w.write_str("~"),
+        BorrowedSigil => w.write_str("&"),
     }
 }
 
@@ -357,6 +360,12 @@ fn enc_purity(w: io::Writer, p: purity) {
     }
 }
 
+fn enc_abi(w: io::Writer, a: Abi) {
+    match a {
+        RustAbi => w.write_char('r'),
+    }
+}
+
 fn enc_onceness(w: io::Writer, o: Onceness) {
     match o {
         Once => w.write_char('o'),
@@ -364,18 +373,27 @@ fn enc_onceness(w: io::Writer, o: Onceness) {
     }
 }
 
-fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) {
-    enc_proto(w, ft.meta.proto);
-    enc_purity(w, ft.meta.purity);
-    enc_onceness(w, ft.meta.onceness);
-    enc_region(w, cx, ft.meta.region);
-    enc_bounds(w, cx, ft.meta.bounds);
+fn enc_bare_fn_ty(w: io::Writer, cx: @ctxt, ft: &ty::BareFnTy) {
+    enc_purity(w, ft.purity);
+    enc_abi(w, ft.abi);
+    enc_fn_sig(w, cx, &ft.sig);
+}
+
+fn enc_closure_ty(w: io::Writer, cx: @ctxt, ft: &ty::ClosureTy) {
+    enc_sigil(w, ft.sigil);
+    enc_purity(w, ft.purity);
+    enc_onceness(w, ft.onceness);
+    enc_region(w, cx, ft.region);
+    enc_fn_sig(w, cx, &ft.sig);
+}
+
+fn enc_fn_sig(w: io::Writer, cx: @ctxt, fsig: &ty::FnSig) {
     w.write_char('[');
-    for ft.sig.inputs.each |arg| {
+    for fsig.inputs.each |arg| {
         enc_arg(w, cx, *arg);
     }
     w.write_char(']');
-    enc_ty(w, cx, ft.sig.output);
+    enc_ty(w, cx, fsig.output);
 }
 
 pub fn enc_bounds(w: io::Writer, cx: @ctxt, bs: @~[ty::param_bound]) {
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 9b2d51289ad..dfc26000116 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -221,18 +221,19 @@ impl check_loan_ctxt {
 
         let callee_ty = ty::node_id_to_type(tcx, callee_id);
         match ty::get(callee_ty).sty {
-          ty::ty_fn(ref fn_ty) => {
-            match fn_ty.meta.purity {
-              ast::pure_fn => return, // case (c) above
-              ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
-                self.report_purity_error(
-                    pc, callee_span,
-                    fmt!("access to %s function",
-                         fn_ty.meta.purity.to_str()));
-              }
+            ty::ty_bare_fn(ty::BareFnTy {purity: purity, _}) |
+            ty::ty_closure(ty::ClosureTy {purity: purity, _}) => {
+                match purity {
+                    ast::pure_fn => return, // case (c) above
+                    ast::impure_fn | ast::unsafe_fn | ast::extern_fn => {
+                        self.report_purity_error(
+                            pc, callee_span,
+                            fmt!("access to %s function",
+                                 purity.to_str()));
+                    }
+                }
             }
-          }
-          _ => return, // case (d) above
+            _ => return, // case (d) above
         }
     }
 
@@ -240,8 +241,11 @@ impl check_loan_ctxt {
     // The expression must be an expr_fn(*) or expr_fn_block(*)
     fn is_stack_closure(id: ast::node_id) -> bool {
         let fn_ty = ty::node_id_to_type(self.tcx(), id);
-        let proto = ty::ty_fn_proto(fn_ty);
-        return proto == ast::ProtoBorrowed;
+        match ty::get(fn_ty).sty {
+            ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
+                                          _}) => true,
+            _ => false
+        }
     }
 
     fn is_allowed_pure_arg(expr: @ast::expr) -> bool {
@@ -564,17 +568,27 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
 {
     let is_stack_closure = self.is_stack_closure(id);
     let fty = ty::node_id_to_type(self.tcx(), id);
-    let fty_proto = ty::ty_fn_proto(fty);
 
-    check_moves_from_captured_variables(self, id, fty_proto);
+    let declared_purity;
+    match fk {
+        visit::fk_item_fn(*) | visit::fk_method(*) |
+        visit::fk_dtor(*) => {
+            declared_purity = ty::ty_fn_purity(fty);
+        }
+
+        visit::fk_anon(*) | visit::fk_fn_block(*) => {
+            let fty_sigil = ty::ty_closure_sigil(fty);
+            check_moves_from_captured_variables(self, id, fty_sigil);
+            declared_purity = ty::determine_inherited_purity(
+                copy self.declared_purity, ty::ty_fn_purity(fty),
+                fty_sigil);
+        }
+    }
 
     debug!("purity on entry=%?", copy self.declared_purity);
     do save_and_restore(&mut(self.declared_purity)) {
         do save_and_restore(&mut(self.fn_args)) {
-            self.declared_purity = ty::determine_inherited_purity(
-                copy self.declared_purity,
-                ty::ty_fn_purity(fty),
-                fty_proto);
+            self.declared_purity = declared_purity;
 
             match fk {
                 visit::fk_anon(*) |
@@ -608,10 +622,10 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
 
     fn check_moves_from_captured_variables(&&self: check_loan_ctxt,
                                            id: ast::node_id,
-                                           fty_proto: ast::Proto)
+                                           fty_sigil: ast::Sigil)
     {
-        match fty_proto {
-            ast::ProtoBox | ast::ProtoUniq => {
+        match fty_sigil {
+            ast::ManagedSigil | ast::OwnedSigil => {
                 let cap_vars = self.bccx.capture_map.get(&id);
                 for cap_vars.each |cap_var| {
                     match cap_var.mode {
@@ -646,7 +660,7 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
                 }
             }
 
-            ast::ProtoBorrowed | ast::ProtoBare => {}
+            ast::BorrowedSigil => {}
         }
     }
 }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 69ace0d7797..ad46d3b6f4d 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -150,7 +150,7 @@ pub fn check_expr(sess: Session,
               }
             }
           }
-          expr_call(callee, _, false) => {
+          expr_call(callee, _, NoSugar) => {
             match def_map.find(&callee.id) {
                 Some(def_struct(*)) => {}    // OK.
                 Some(def_variant(*)) => {}    // OK.
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index 11c557f0249..38450de6b54 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -39,8 +39,8 @@ pub fn check_crate(tcx: ty::ctxt, crate: @crate) {
                 (v.visit_block)((*b), {in_loop: false, can_ret: false}, v);
               }
               expr_loop_body(@expr {node: expr_fn_block(_, ref b), _}) => {
-                let proto = ty::ty_fn_proto(ty::expr_ty(tcx, e));
-                let blk = (proto == ProtoBorrowed);
+                let sigil = ty::ty_closure_sigil(ty::expr_ty(tcx, e));
+                let blk = (sigil == BorrowedSigil);
                 (v.visit_block)((*b), {in_loop: true, can_ret: blk}, v);
               }
               expr_break(_) => {
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 978aaacb18a..6f9fe1edca5 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -100,7 +100,7 @@ pub fn check_expr(cx: @MatchCheckCtxt, ex: @expr, &&s: (), v: visit::vt<()>) {
           }
           _ => { /* We assume only enum types can be uninhabited */ }
        }
-       let arms = vec::concat(vec::filter_map((*arms), unguarded_pat));
+       let arms = vec::concat(arms.filter_mapped(unguarded_pat));
        check_exhaustive(cx, ex.span, arms);
      }
      _ => ()
@@ -255,7 +255,8 @@ pub fn is_useful(cx: @MatchCheckCtxt, +m: matrix, +v: &[@pat]) -> useful {
             }
           }
           Some(ref ctor) => {
-            match is_useful(cx, vec::filter_map(m, |r| default(cx, copy *r)),
+            match is_useful(cx,
+                            vec::filter_map(m, |r| default(cx, r)),
                             vec::tail(v)) {
               useful_ => useful(left_ty, (/*bad*/copy *ctor)),
               ref u => (/*bad*/copy *u)
@@ -277,8 +278,7 @@ pub fn is_useful_specialized(cx: @MatchCheckCtxt,
                              arity: uint,
                              lty: ty::t)
                           -> useful {
-    let ms = vec::filter_map(m, |r| specialize(cx, *r,
-                                               ctor, arity, lty));
+    let ms = m.filter_mapped(|r| specialize(cx, *r, ctor, arity, lty));
     let could_be_useful = is_useful(
         cx, ms, specialize(cx, v, ctor, arity, lty).get());
     match could_be_useful {
@@ -387,9 +387,9 @@ pub fn missing_ctor(cx: @MatchCheckCtxt,
       ty::ty_unboxed_vec(*) | ty::ty_evec(*) => {
 
         // Find the lengths and tails of all vector patterns.
-        let vec_pat_lens = do m.filter_map |r| {
-            match /*bad*/copy r[0].node {
-                pat_vec(elems, tail) => {
+        let vec_pat_lens = do m.filter_mapped |r| {
+            match r[0].node {
+                pat_vec(ref elems, ref tail) => {
                     Some((elems.len(), tail.is_some()))
                 }
                 _ => None
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index 5d65aba2a4d..e6091077210 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -48,10 +48,8 @@ fn collect_freevars(def_map: resolve::DefMap, blk: ast::blk)
 
     let walk_expr = fn@(expr: @ast::expr, &&depth: int, v: visit::vt<int>) {
             match expr.node {
-              ast::expr_fn(proto, _, _, _) => {
-                if proto != ast::ProtoBare {
-                    visit::visit_expr(expr, depth + 1, v);
-                }
+              ast::expr_fn(_, _, _, _) => {
+                visit::visit_expr(expr, depth + 1, v);
               }
               ast::expr_fn_block(*) => {
                 visit::visit_expr(expr, depth + 1, v);
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 8abafe6b079..35d5595fefd 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -150,11 +150,23 @@ fn with_appropriate_checker(cx: ctx, id: node_id, b: fn(check_fn)) {
     }
 
     let fty = ty::node_id_to_type(cx.tcx, id);
-    match ty::ty_fn_proto(fty) {
-        ProtoUniq => b(check_for_uniq),
-        ProtoBox => b(check_for_box),
-        ProtoBare => b(check_for_bare),
-        ProtoBorrowed => b(check_for_block),
+    match ty::get(fty).sty {
+        ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, _}) => {
+            b(check_for_uniq)
+        }
+        ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, _}) => {
+            b(check_for_box)
+        }
+        ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, _}) => {
+            b(check_for_block)
+        }
+        ty::ty_bare_fn(_) => {
+            b(check_for_bare)
+        }
+        ref s => {
+            cx.tcx.sess.bug(
+                fmt!("expect fn type in kind checker, not %?", s));
+        }
     }
 }
 
@@ -240,42 +252,6 @@ pub fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
                        expr.span,
                        "explicit copy requires a copyable argument");
         }
-        expr_rec(ref fields, def) | expr_struct(_, ref fields, def) => {
-            match def {
-                Some(ex) => {
-                    // All noncopyable fields must be overridden
-                    let t = ty::expr_ty(cx.tcx, ex);
-                    let ty_fields = match ty::get(t).sty {
-                        ty::ty_rec(ref f) => {
-                            copy *f
-                        }
-                        ty::ty_struct(did, ref substs) => {
-                            ty::struct_fields(cx.tcx, did, substs)
-                        }
-                        _ => {
-                            cx.tcx.sess.span_bug(
-                                ex.span,
-                                ~"bad base expr type in record")
-                        }
-                    };
-                    for ty_fields.each |tf| {
-                        // If this field would not be copied, ok.
-                        if fields.any(|f| f.node.ident == tf.ident) { loop; }
-
-                        // If this field is copyable, ok.
-                        let kind = ty::type_kind(cx.tcx, tf.mt.ty);
-                        if ty::kind_can_be_copied(kind) { loop; }
-
-                        cx.tcx.sess.span_err(
-                            e.span,
-                            fmt!("cannot copy field `%s` of base expression, \
-                                  which has a noncopyable type",
-                                 *cx.tcx.sess.intr().get(tf.ident)));
-                    }
-                }
-                _ => {}
-            }
-        }
         expr_repeat(element, count_expr, _) => {
             let count = ty::eval_repeat_count(cx.tcx, count_expr, e.span);
             if count > 1 {
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 4601941f73a..51bbdfdc19c 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -897,9 +897,10 @@ fn check_fn(tcx: ty::ctxt, fk: visit::fn_kind, decl: ast::fn_decl,
 fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
                              span: span, id: ast::node_id) {
     match ty::get(fn_ty).sty {
-        ty::ty_fn(ref fn_ty) => {
+        ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) |
+        ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) => {
             let mut counter = 0;
-            for vec::each2(fn_ty.sig.inputs, decl.inputs) |arg_ty, arg_ast| {
+            for vec::each2(sig.inputs, decl.inputs) |arg_ty, arg_ast| {
                 counter += 1;
                 debug!("arg %d, ty=%s, mode=%s",
                        counter,
@@ -938,13 +939,14 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
                 }
 
                 match ty::get(arg_ty.ty).sty {
-                    ty::ty_fn(*) => {
+                    ty::ty_closure(*) | ty::ty_bare_fn(*) => {
                         let span = arg_ast.ty.span;
                         // Recurse to check fn-type argument
                         match arg_ast.ty.node {
-                            ast::ty_fn(f) => {
+                            ast::ty_closure(@ast::TyClosure{decl: ref d, _}) |
+                            ast::ty_bare_fn(@ast::TyBareFn{decl: ref d, _})=>{
                                 check_fn_deprecated_modes(tcx, arg_ty.ty,
-                                                          f.decl, span, id);
+                                                          *d, span, id);
                             }
                             ast::ty_path(*) => {
                                 // This is probably a typedef, so we can't
@@ -976,10 +978,11 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) {
     match it.node {
         ast::item_ty(ty, _) => {
             match ty.node {
-                ast::ty_fn(f) => {
+                ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) |
+                ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
                     let fn_ty = ty::node_id_to_type(tcx, it.id);
                     check_fn_deprecated_modes(
-                        tcx, fn_ty, f.decl, ty.span, it.id)
+                        tcx, fn_ty, *decl, ty.span, it.id)
                 }
                 _ => ()
             }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index abe8a64fea5..07de9987096 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -146,63 +146,55 @@ pub enum deref_kind {deref_ptr(ptr_kind), deref_comp(comp_kind)}
 // pointer adjustment).
 pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
     match ty::get(t).sty {
-      ty::ty_uniq(*) |
-      ty::ty_evec(_, ty::vstore_uniq) |
-      ty::ty_estr(ty::vstore_uniq) => {
-        Some(deref_ptr(uniq_ptr))
-      }
-
-      ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoUniq => {
-        Some(deref_ptr(uniq_ptr))
-      }
-
-      ty::ty_rptr(r, mt) |
-      ty::ty_evec(mt, ty::vstore_slice(r)) => {
-        Some(deref_ptr(region_ptr(mt.mutbl, r)))
-      }
-
-      ty::ty_estr(ty::vstore_slice(r)) => {
-        Some(deref_ptr(region_ptr(ast::m_imm, r)))
-      }
+        ty::ty_uniq(*) |
+        ty::ty_evec(_, ty::vstore_uniq) |
+        ty::ty_estr(ty::vstore_uniq) |
+        ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
+            Some(deref_ptr(uniq_ptr))
+        }
 
-      ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBorrowed => {
-        Some(deref_ptr(region_ptr(ast::m_imm, (*f).meta.region)))
-      }
+        ty::ty_rptr(r, mt) |
+        ty::ty_evec(mt, ty::vstore_slice(r)) => {
+            Some(deref_ptr(region_ptr(mt.mutbl, r)))
+        }
 
-      ty::ty_box(mt) |
-      ty::ty_evec(mt, ty::vstore_box) => {
-        Some(deref_ptr(gc_ptr(mt.mutbl)))
-      }
+        ty::ty_estr(ty::vstore_slice(r)) |
+        ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
+                                      region: r, _}) => {
+            Some(deref_ptr(region_ptr(ast::m_imm, r)))
+        }
 
-      ty::ty_estr(ty::vstore_box) => {
-        Some(deref_ptr(gc_ptr(ast::m_imm)))
-      }
+        ty::ty_box(mt) |
+        ty::ty_evec(mt, ty::vstore_box) => {
+            Some(deref_ptr(gc_ptr(mt.mutbl)))
+        }
 
-      ty::ty_fn(ref f) if (*f).meta.proto == ast::ProtoBox => {
-        Some(deref_ptr(gc_ptr(ast::m_imm)))
-      }
+        ty::ty_estr(ty::vstore_box) |
+        ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
+            Some(deref_ptr(gc_ptr(ast::m_imm)))
+        }
 
-      ty::ty_ptr(*) => {
-        Some(deref_ptr(unsafe_ptr))
-      }
+        ty::ty_ptr(*) => {
+            Some(deref_ptr(unsafe_ptr))
+        }
 
-      ty::ty_enum(did, _) => {
-        Some(deref_comp(comp_variant(did)))
-      }
+        ty::ty_enum(did, _) => {
+            Some(deref_comp(comp_variant(did)))
+        }
 
-      ty::ty_struct(_, _) => {
-        Some(deref_comp(comp_anon_field))
-      }
+        ty::ty_struct(_, _) => {
+            Some(deref_comp(comp_anon_field))
+        }
 
-      ty::ty_evec(mt, ty::vstore_fixed(_)) => {
-        Some(deref_comp(comp_index(t, mt.mutbl)))
-      }
+        ty::ty_evec(mt, ty::vstore_fixed(_)) => {
+            Some(deref_comp(comp_index(t, mt.mutbl)))
+        }
 
-      ty::ty_estr(ty::vstore_fixed(_)) => {
-        Some(deref_comp(comp_index(t, m_imm)))
-      }
+        ty::ty_estr(ty::vstore_fixed(_)) => {
+            Some(deref_comp(comp_index(t, m_imm)))
+        }
 
-      _ => None
+        _ => None
     }
 }
 
@@ -473,9 +465,9 @@ pub impl &mem_categorization_ctxt {
 
           ast::def_upvar(_, inner, fn_node_id, _) => {
             let ty = ty::node_id_to_type(self.tcx, fn_node_id);
-            let proto = ty::ty_fn_proto(ty);
-            match proto {
-                ast::ProtoBorrowed => {
+            let sigil = ty::ty_closure_sigil(ty);
+            match sigil {
+                ast::BorrowedSigil => {
                     let upcmt = self.cat_def(id, span, expr_ty, *inner);
                     @cmt_ {
                         id:id,
@@ -486,7 +478,7 @@ pub impl &mem_categorization_ctxt {
                         ty:upcmt.ty
                     }
                 }
-                ast::ProtoUniq | ast::ProtoBox => {
+                ast::OwnedSigil | ast::ManagedSigil => {
                     // FIXME #2152 allow mutation of moved upvars
                     @cmt_ {
                         id:id,
@@ -497,11 +489,6 @@ pub impl &mem_categorization_ctxt {
                         ty:expr_ty
                     }
                 }
-                ast::ProtoBare => {
-                    self.tcx.sess.span_bug(
-                        span,
-                        fmt!("Upvar in a bare closure?"));
-                }
             }
           }
 
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index f7943d6edc0..aaa3156e27c 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -474,7 +474,35 @@ impl VisitContext {
                 }
 
                 for opt_with.each |with_expr| {
-                    self.consume_expr(*with_expr, visitor);
+                    // If there are any fields whose type is move-by-default,
+                    // then `with` is consumed, otherwise it is only read
+                    let with_ty = ty::expr_ty(self.tcx, *with_expr);
+                    let with_fields = match ty::get(with_ty).sty {
+                        ty::ty_rec(ref f) => copy *f,
+                        ty::ty_struct(did, ref substs) => {
+                            ty::struct_fields(self.tcx, did, substs)
+                        }
+                        ref r => {
+                           self.tcx.sess.span_bug(
+                                with_expr.span,
+                                fmt!("bad base expr type in record: %?", r))
+                        }
+                    };
+
+                    // The `with` expr must be consumed if it contains
+                    // any fields which (1) were not explicitly
+                    // specified and (2) have a type that
+                    // moves-by-default:
+                    let consume_with = with_fields.any(|tf| {
+                        !fields.any(|f| f.node.ident == tf.ident) &&
+                            ty::type_implicitly_moves(self.tcx, tf.mt.ty)
+                    });
+
+                    if consume_with {
+                        self.consume_expr(*with_expr, visitor);
+                    } else {
+                        self.use_expr(*with_expr, Read, visitor);
+                    }
                 }
             }
 
@@ -786,9 +814,9 @@ impl VisitContext {
         let _indenter = indenter();
 
         let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id);
-        let proto = ty::ty_fn_proto(fn_ty);
+        let sigil = ty::ty_closure_sigil(fn_ty);
         let freevars = freevars::get_freevars(self.tcx, fn_expr_id);
-        if proto == ProtoBorrowed {
+        if sigil == BorrowedSigil {
             // &fn() captures everything by ref
             at_vec::from_fn(freevars.len(), |i| {
                 let fvar = &freevars[i];
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 867cc7c686f..68e41b329e3 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -657,7 +657,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
             }
         }
 
-        ast::ty_fn(f) => {
+        ast::ty_closure(ref f) => {
             debug!("referenced fn type: %s",
                    pprust::ty_to_str(ty, cx.sess.intr()));
             match f.region {
@@ -668,7 +668,7 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
                     }
                 }
                 None => {
-                    if f.proto == ast::ProtoBorrowed && cx.anon_implies_rp {
+                    if f.sigil == ast::BorrowedSigil && cx.anon_implies_rp {
                         cx.add_rp(cx.item_id,
                                   cx.add_variance(rv_contravariant));
                     }
@@ -732,18 +732,18 @@ pub fn determine_rp_in_ty(ty: @ast::Ty,
         }
       }
 
-      ast::ty_fn(f) => {
+      ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) |
+      ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => {
         // fn() binds the & region, so do not consider &T types that
         // appear *inside* a fn() type to affect the enclosing item:
         do cx.with(cx.item_id, false) {
             // parameters are contravariant
             do cx.with_ambient_variance(rv_contravariant) {
-                for f.decl.inputs.each |a| {
+                for decl.inputs.each |a| {
                     (visitor.visit_ty)(a.ty, cx, visitor);
                 }
             }
-            visit::visit_ty_param_bounds(f.bounds, cx, visitor);
-            (visitor.visit_ty)(f.decl.output, cx, visitor);
+            (visitor.visit_ty)(decl.output, cx, visitor);
         }
       }
 
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 99b5641ac6a..ebd6d9f9056 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -1652,7 +1652,7 @@ pub fn trans_match_inner(scope_cx: block,
         // insert bindings into the lllocals map and add cleanups
         bcx = insert_lllocals(bcx, *arm_data, true);
 
-        bcx = controlflow::trans_block(bcx, arm_data.arm.body, dest);
+        bcx = controlflow::trans_block(bcx, &arm_data.arm.body, dest);
         bcx = trans_block_cleanups(bcx, block_cleanups(arm_data.bodycx));
         arm_cxs.push(bcx);
     }
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index a1f863332bd..588e2916e47 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -613,7 +613,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
         let ccx = cx.ccx();
         let mut cx = cx;
         match ty::get(fn_ty).sty {
-          ty::ty_fn(ref fn_ty) => {
+          ty::ty_bare_fn(ref fn_ty) => {
             let mut j = 0u;
             let v_id = variant.id;
             for vec::each(fn_ty.sig.inputs) |a| {
@@ -777,10 +777,10 @@ pub fn trans_external_path(ccx: @crate_ctxt, did: ast::def_id, t: ty::t)
     -> ValueRef {
     let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad
     match ty::get(t).sty {
-      ty::ty_fn(_) => {
+      ty::ty_bare_fn(_) | ty::ty_closure(_) => {
         let llty = type_of_fn_from_ty(ccx, t);
         return get_extern_fn(ccx.externs, ccx.llmod, name,
-                          lib::llvm::CCallConv, llty);
+                             lib::llvm::CCallConv, llty);
       }
       _ => {
         let llty = type_of(ccx, t);
@@ -1363,7 +1363,7 @@ pub fn with_scope_datumblock(bcx: block, opt_node_info: Option<node_info>,
     DatumBlock {bcx: leave_block(bcx, scope_cx), datum: datum}
 }
 
-pub fn block_locals(b: ast::blk, it: fn(@ast::local)) {
+pub fn block_locals(b: &ast::blk, it: fn(@ast::local)) {
     for vec::each(b.node.stmts) |s| {
         match s.node {
           ast::stmt_decl(d, _) => {
@@ -1727,8 +1727,8 @@ pub enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, }
 // returned.
 pub fn trans_closure(ccx: @crate_ctxt,
                      +path: path,
-                     decl: ast::fn_decl,
-                     body: ast::blk,
+                     decl: &ast::fn_decl,
+                     body: &ast::blk,
                      llfndecl: ValueRef,
                      ty_self: self_arg,
                      +param_substs: Option<param_substs>,
@@ -1791,8 +1791,8 @@ pub fn trans_closure(ccx: @crate_ctxt,
 // function.
 pub fn trans_fn(ccx: @crate_ctxt,
                 +path: path,
-                decl: ast::fn_decl,
-                body: ast::blk,
+                decl: &ast::fn_decl,
+                body: &ast::blk,
                 llfndecl: ValueRef,
                 ty_self: self_arg,
                 +param_substs: Option<param_substs>,
@@ -1935,7 +1935,7 @@ pub fn trans_tuple_struct(ccx: @crate_ctxt,
 
 pub fn trans_struct_dtor(ccx: @crate_ctxt,
                          +path: path,
-                         body: ast::blk,
+                         body: &ast::blk,
                          dtor_id: ast::node_id,
                          +psubsts: Option<param_substs>,
                          hash_id: Option<mono_id>,
@@ -1966,8 +1966,9 @@ pub fn trans_struct_dtor(ccx: @crate_ctxt,
     ccx.monomorphized.insert(*h_id, lldecl);
   }
   /* Translate the dtor body */
-  trans_fn(ccx, path, ast_util::dtor_dec(),
-           body, lldecl, impl_self(class_ty), psubsts, dtor_id, None);
+  let decl = ast_util::dtor_dec();
+  trans_fn(ccx, path, &decl, body, lldecl,
+           impl_self(class_ty), psubsts, dtor_id, None);
   lldecl
 }
 
@@ -2013,20 +2014,19 @@ pub fn trans_item(ccx: @crate_ctxt, item: ast::item) {
         _ => die!(~"trans_item"),
     };
     match /*bad*/copy item.node {
-      // XXX: Bad copies.
-      ast::item_fn(copy decl, purity, copy tps, ref body) => {
+      ast::item_fn(ref decl, purity, ref tps, ref body) => {
         if purity == ast::extern_fn  {
             let llfndecl = get_item_val(ccx, item.id);
             foreign::trans_foreign_fn(ccx,
                                      vec::append(
                                          /*bad*/copy *path,
                                          ~[path_name(item.ident)]),
-                                     decl, (*body), llfndecl, item.id);
+                                      decl, body, llfndecl, item.id);
         } else if tps.is_empty() {
             let llfndecl = get_item_val(ccx, item.id);
             trans_fn(ccx,
                      vec::append(/*bad*/copy *path, ~[path_name(item.ident)]),
-                     decl, (*body), llfndecl, no_self, None, item.id, None);
+                     decl, body, llfndecl, no_self, None, item.id, None);
         } else {
             for vec::each((*body).node.stmts) |stmt| {
                 match stmt.node {
@@ -2078,7 +2078,7 @@ pub fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
                         id: ast::node_id) {
     // Translate the destructor.
     do option::iter(&struct_def.dtor) |dtor| {
-        trans_struct_dtor(ccx, /*bad*/copy *path, dtor.node.body,
+        trans_struct_dtor(ccx, /*bad*/copy *path, &dtor.node.body,
                          dtor.node.id, None, None, local_def(id));
     };
 
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 4bd5ae969f2..4af74b3623f 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -627,18 +627,17 @@ pub fn trans_arg_expr(bcx: block,
         Some(_) => {
             match arg_expr.node {
                 ast::expr_loop_body(
-                    // XXX: Bad copy.
-                    blk@@ast::expr {
-                        node: ast::expr_fn_block(copy decl, ref body),
+                    blk @ @ast::expr {
+                        node: ast::expr_fn_block(ref decl, ref body),
                         _
                     }) =>
                 {
                     let scratch_ty = expr_ty(bcx, arg_expr);
                     let scratch = alloc_ty(bcx, scratch_ty);
                     let arg_ty = expr_ty(bcx, arg_expr);
-                    let proto = ty::ty_fn_proto(arg_ty);
+                    let sigil = ty::ty_closure_sigil(arg_ty);
                     let bcx = closure::trans_expr_fn(
-                        bcx, proto, decl, /*bad*/copy *body, arg_expr.id,
+                        bcx, sigil, decl, body, arg_expr.id,
                         blk.id, Some(ret_flag), expr::SaveIn(scratch));
                     DatumBlock {bcx: bcx,
                                 datum: Datum {val: scratch,
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 62e00100d6c..c70425da9fa 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -160,7 +160,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
     return cdata_ty;
 }
 
-pub fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t)
+pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t)
                   -> Result {
     let _icx = bcx.insn_ctxt("closure::allocate_cbox");
     let ccx = bcx.ccx(), tcx = ccx.tcx;
@@ -176,23 +176,19 @@ pub fn allocate_cbox(bcx: block, proto: ast::Proto, cdata_ty: ty::t)
     }
 
     // Allocate and initialize the box:
-    match proto {
-        ast::ProtoBox => {
+    match sigil {
+        ast::ManagedSigil => {
             malloc_raw(bcx, cdata_ty, heap_shared)
         }
-        ast::ProtoUniq => {
+        ast::OwnedSigil => {
             malloc_raw(bcx, cdata_ty, heap_exchange)
         }
-        ast::ProtoBorrowed => {
+        ast::BorrowedSigil => {
             let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
             let llbox = base::alloc_ty(bcx, cbox_ty);
             nuke_ref_count(bcx, llbox);
             rslt(bcx, llbox)
         }
-        ast::ProtoBare => {
-            let cdata_llty = type_of(bcx.ccx(), cdata_ty);
-            rslt(bcx, C_null(cdata_llty))
-        }
     }
 }
 
@@ -208,7 +204,7 @@ pub type closure_result = {
 // Otherwise, it is stack allocated and copies pointers to the upvars.
 pub fn store_environment(bcx: block,
                          bound_values: ~[EnvValue],
-                         proto: ast::Proto) -> closure_result {
+                         sigil: ast::Sigil) -> closure_result {
     let _icx = bcx.insn_ctxt("closure::store_environment");
     let ccx = bcx.ccx(), tcx = ccx.tcx;
 
@@ -217,7 +213,7 @@ pub fn store_environment(bcx: block,
     let cdata_ty = mk_closure_tys(tcx, copy bound_values);
 
     // allocate closure in the heap
-    let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, proto, cdata_ty);
+    let Result {bcx: bcx, val: llbox} = allocate_cbox(bcx, sigil, cdata_ty);
     let mut temp_cleanups = ~[];
 
     // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a
@@ -265,7 +261,7 @@ pub fn store_environment(bcx: block,
 // collects the upvars and packages them up for store_environment.
 pub fn build_closure(bcx0: block,
                      cap_vars: &[moves::CaptureVar],
-                     proto: ast::Proto,
+                     sigil: ast::Sigil,
                      include_ret_handle: Option<ValueRef>) -> closure_result {
     let _icx = bcx0.insn_ctxt("closure::build_closure");
     // If we need to, package up the iterator body to call
@@ -279,7 +275,7 @@ pub fn build_closure(bcx0: block,
         let datum = expr::trans_local_var(bcx, cap_var.def);
         match cap_var.mode {
             moves::CapRef => {
-                assert proto == ast::ProtoBorrowed;
+                assert sigil == ast::BorrowedSigil;
                 env_vals.push(EnvValue {action: EnvRef,
                                         datum: datum});
             }
@@ -316,7 +312,7 @@ pub fn build_closure(bcx0: block,
                                 datum: ret_datum});
     }
 
-    return store_environment(bcx, env_vals, proto);
+    return store_environment(bcx, env_vals, sigil);
 }
 
 // Given an enclosing block context, a new function context, a closure type,
@@ -326,7 +322,7 @@ pub fn load_environment(fcx: fn_ctxt,
                         cdata_ty: ty::t,
                         cap_vars: &[moves::CaptureVar],
                         load_ret_handle: bool,
-                        proto: ast::Proto) {
+                        sigil: ast::Sigil) {
     let _icx = fcx.insn_ctxt("closure::load_environment");
 
     let llloadenv = match fcx.llloadenv {
@@ -352,9 +348,9 @@ pub fn load_environment(fcx: fn_ctxt,
     let mut i = 0u;
     for cap_vars.each |cap_var| {
         let mut upvarptr = GEPi(bcx, llcdata, [0u, i]);
-        match proto {
-            ast::ProtoBorrowed => { upvarptr = Load(bcx, upvarptr); }
-            ast::ProtoBox | ast::ProtoUniq | ast::ProtoBare => {}
+        match sigil {
+            ast::BorrowedSigil => { upvarptr = Load(bcx, upvarptr); }
+            ast::ManagedSigil | ast::OwnedSigil => {}
         }
         let def_id = ast_util::def_id_of_def(cap_var.def);
         fcx.llupvars.insert(def_id.node, upvarptr);
@@ -369,9 +365,9 @@ pub fn load_environment(fcx: fn_ctxt,
 }
 
 pub fn trans_expr_fn(bcx: block,
-                     proto: ast::Proto,
-                     +decl: ast::fn_decl,
-                     +body: ast::blk,
+                     sigil: ast::Sigil,
+                     decl: &ast::fn_decl,
+                     body: &ast::blk,
                      outer_id: ast::node_id,
                      user_id: ast::node_id,
                      is_loop_body: Option<Option<ValueRef>>,
@@ -381,7 +377,7 @@ pub fn trans_expr_fn(bcx: block,
      *
      * Translates the body of a closure expression.
      *
-     * - `proto`
+     * - `sigil`
      * - `decl`
      * - `body`
      * - `outer_id`: The id of the closure expression with the correct
@@ -417,18 +413,18 @@ pub fn trans_expr_fn(bcx: block,
                                                  ~"expr_fn");
     let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
 
-    let Result {bcx: bcx, val: closure} = match proto {
-        ast::ProtoBorrowed | ast::ProtoBox | ast::ProtoUniq => {
+    let Result {bcx: bcx, val: closure} = match sigil {
+        ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => {
             let cap_vars = ccx.maps.capture_map.get(&user_id);
             let ret_handle = match is_loop_body {Some(x) => x,
                                                  None => None};
-            let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, proto,
+            let {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil,
                                                        ret_handle);
             trans_closure(ccx, sub_path, decl,
                           body, llfn, no_self,
                           /*bad*/ copy bcx.fcx.param_substs, user_id, None,
                           |fcx| load_environment(fcx, cdata_ty, cap_vars,
-                                                 ret_handle.is_some(), proto),
+                                                 ret_handle.is_some(), sigil),
                           |bcx| {
                               if is_loop_body.is_some() {
                                   Store(bcx, C_bool(true), bcx.fcx.llretptr);
@@ -436,34 +432,30 @@ pub fn trans_expr_fn(bcx: block,
                           });
             rslt(bcx, llbox)
         }
-        ast::ProtoBare => {
-            trans_closure(ccx, sub_path, decl, body, llfn, no_self, None,
-                          user_id, None, |_fcx| { }, |_bcx| { });
-            rslt(bcx, C_null(T_opaque_box_ptr(ccx)))
-        }
     };
     fill_fn_pair(bcx, dest_addr, llfn, closure);
 
     return bcx;
 }
 
-pub fn make_fn_glue(cx: block,
-                    v: ValueRef,
-                    t: ty::t,
-                    glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block)
-                 -> block {
-    let _icx = cx.insn_ctxt("closure::make_fn_glue");
+pub fn make_closure_glue(
+    cx: block,
+    v: ValueRef,
+    t: ty::t,
+    glue_fn: fn@(block, v: ValueRef, t: ty::t) -> block) -> block
+{
+    let _icx = cx.insn_ctxt("closure::make_closure_glue");
     let bcx = cx;
     let tcx = cx.tcx();
 
-    let proto = ty::ty_fn_proto(t);
-    match proto {
-        ast::ProtoBare | ast::ProtoBorrowed => bcx,
-        ast::ProtoUniq | ast::ProtoBox => {
+    let sigil = ty::ty_closure_sigil(t);
+    match sigil {
+        ast::BorrowedSigil => bcx,
+        ast::OwnedSigil | ast::ManagedSigil => {
             let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]);
             let box_ptr_v = Load(cx, box_cell_v);
             do with_cond(cx, IsNotNull(cx, box_ptr_v)) |bcx| {
-                let closure_ty = ty::mk_opaque_closure_ptr(tcx, proto);
+                let closure_ty = ty::mk_opaque_closure_ptr(tcx, sigil);
                 glue_fn(bcx, box_cell_v, closure_ty)
             }
         }
@@ -472,20 +464,20 @@ pub fn make_fn_glue(cx: block,
 
 pub fn make_opaque_cbox_take_glue(
     bcx: block,
-    proto: ast::Proto,
+    sigil: ast::Sigil,
     cboxptr: ValueRef)     // ptr to ptr to the opaque closure
     -> block {
     // Easy cases:
     let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue");
-    match proto {
-        ast::ProtoBare | ast::ProtoBorrowed => {
+    match sigil {
+        ast::BorrowedSigil => {
             return bcx;
         }
-        ast::ProtoBox => {
+        ast::ManagedSigil => {
             glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr));
             return bcx;
         }
-        ast::ProtoUniq => {
+        ast::OwnedSigil => {
             /* hard case: fallthrough to code below */
         }
     }
@@ -531,36 +523,36 @@ pub fn make_opaque_cbox_take_glue(
 
 pub fn make_opaque_cbox_drop_glue(
     bcx: block,
-    proto: ast::Proto,
+    sigil: ast::Sigil,
     cboxptr: ValueRef)     // ptr to the opaque closure
     -> block {
     let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue");
-    match proto {
-        ast::ProtoBare | ast::ProtoBorrowed => bcx,
-        ast::ProtoBox => {
+    match sigil {
+        ast::BorrowedSigil => bcx,
+        ast::ManagedSigil => {
             glue::decr_refcnt_maybe_free(
                 bcx, Load(bcx, cboxptr),
-                ty::mk_opaque_closure_ptr(bcx.tcx(), proto))
+                ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
         }
-        ast::ProtoUniq => {
+        ast::OwnedSigil => {
             glue::free_ty(
                 bcx, cboxptr,
-                ty::mk_opaque_closure_ptr(bcx.tcx(), proto))
+                ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
         }
     }
 }
 
 pub fn make_opaque_cbox_free_glue(
     bcx: block,
-    proto: ast::Proto,
+    sigil: ast::Sigil,
     cbox: ValueRef)     // ptr to ptr to the opaque closure
     -> block {
     let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue");
-    match proto {
-        ast::ProtoBare | ast::ProtoBorrowed => {
+    match sigil {
+        ast::BorrowedSigil => {
             return bcx;
         }
-        ast::ProtoBox | ast::ProtoUniq => {
+        ast::ManagedSigil | ast::OwnedSigil => {
             /* hard cases: fallthrough to code below */
         }
     }
@@ -580,10 +572,10 @@ pub fn make_opaque_cbox_free_glue(
                                     abi::tydesc_field_drop_glue, None);
 
         // Free the ty descr (if necc) and the box itself
-        match proto {
-            ast::ProtoBox => glue::trans_free(bcx, cbox),
-            ast::ProtoUniq => glue::trans_unique_free(bcx, cbox),
-            ast::ProtoBare | ast::ProtoBorrowed => {
+        match sigil {
+            ast::ManagedSigil => glue::trans_free(bcx, cbox),
+            ast::OwnedSigil => glue::trans_unique_free(bcx, cbox),
+            ast::BorrowedSigil => {
                 bcx.sess().bug(~"impossible")
             }
         }
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index a1505dd2f11..0933eedd5e4 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -23,7 +23,7 @@ pub fn macros() {
     include!("macros.rs");
 }
 
-pub fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block {
+pub fn trans_block(bcx: block, b: &ast::blk, dest: expr::Dest) -> block {
     let _icx = bcx.insn_ctxt("trans_block");
     let mut bcx = bcx;
     do block_locals(b) |local| {
@@ -47,7 +47,7 @@ pub fn trans_block(bcx: block, b: ast::blk, dest: expr::Dest) -> block {
 
 pub fn trans_if(bcx: block,
             cond: @ast::expr,
-            thn: ast::blk,
+            thn: &ast::blk,
             els: Option<@ast::expr>,
             dest: expr::Dest)
          -> block {
@@ -82,10 +82,10 @@ pub fn trans_if(bcx: block,
         match elexpr.node {
           ast::expr_if(_, _, _) => {
             let elseif_blk = ast_util::block_from_expr(elexpr);
-            trans_block(else_bcx_in, elseif_blk, dest)
+            trans_block(else_bcx_in, &elseif_blk, dest)
           }
           ast::expr_block(ref blk) => {
-            trans_block(else_bcx_in, (*blk), dest)
+            trans_block(else_bcx_in, blk, dest)
           }
           // would be nice to have a constraint on ifs
           _ => bcx.tcx().sess.bug(~"strange alternative in if")
@@ -114,7 +114,7 @@ pub fn join_blocks(parent_bcx: block, in_cxs: ~[block]) -> block {
     return out;
 }
 
-pub fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) -> block {
+pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::blk) -> block {
     let _icx = bcx.insn_ctxt("trans_while");
     let next_bcx = sub_block(bcx, ~"while next");
 
@@ -154,7 +154,7 @@ pub fn trans_while(bcx: block, cond: @ast::expr, body: ast::blk) -> block {
 }
 
 pub fn trans_loop(bcx:block,
-                  body: ast::blk,
+                  body: &ast::blk,
                   opt_label: Option<ident>)
                -> block {
     let _icx = bcx.insn_ctxt("trans_loop");
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 56833d373c5..f2da47eb0ec 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -475,10 +475,10 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
             return controlflow::trans_check_expr(bcx, expr, a, ~"Assertion");
         }
         ast::expr_while(cond, ref body) => {
-            return controlflow::trans_while(bcx, cond, (*body));
+            return controlflow::trans_while(bcx, cond, body);
         }
         ast::expr_loop(ref body, opt_label) => {
-            return controlflow::trans_loop(bcx, (*body), opt_label);
+            return controlflow::trans_loop(bcx, body, opt_label);
         }
         ast::expr_assign(dst, src) => {
             let src_datum = unpack_datum!(
@@ -530,7 +530,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
                                             bcx.def(expr.id), dest);
         }
         ast::expr_if(cond, ref thn, els) => {
-            return controlflow::trans_if(bcx, cond, *thn, els, dest);
+            return controlflow::trans_if(bcx, cond, thn, els, dest);
         }
         ast::expr_match(discr, ref arms) => {
             return _match::trans_match(bcx, expr, discr, /*bad*/copy *arms,
@@ -539,7 +539,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
         ast::expr_block(ref blk) => {
             return do base::with_scope(bcx, blk.info(),
                                        ~"block-expr body") |bcx| {
-                controlflow::trans_block(bcx, (*blk), dest)
+                controlflow::trans_block(bcx, blk, dest)
             };
         }
         ast::expr_rec(ref fields, base) |
@@ -562,58 +562,31 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
         ast::expr_vec(*) | ast::expr_repeat(*) => {
             return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
         }
-        // XXX: Bad copy.
-        ast::expr_fn(proto, copy decl, ref body, _) => {
-            // Don't use this function for anything real. Use the one in
-            // astconv instead.
-            return closure::trans_expr_fn(bcx, proto, decl,
-                                          /*bad*/copy *body,
-                                          expr.id, expr.id,
-                                          None, dest);
-        }
+        ast::expr_fn(_, ref decl, ref body, _) |
         ast::expr_fn_block(ref decl, ref body) => {
             let expr_ty = expr_ty(bcx, expr);
-            match ty::get(expr_ty).sty {
-                ty::ty_fn(ref fn_ty) => {
-                    debug!("translating fn_block %s with type %s",
-                           expr_to_str(expr, tcx.sess.intr()),
-                           ty_to_str(tcx, expr_ty));
-                    return closure::trans_expr_fn(
-                        bcx, fn_ty.meta.proto, /*bad*/copy *decl,
-                        /*bad*/copy *body, expr.id, expr.id,
-                        None, dest);
-                }
-                _ => {
-                    bcx.sess().impossible_case(
-                        expr.span, "fn_block has body with a non-fn type");
-                }
-            }
+            let sigil = ty::ty_closure_sigil(expr_ty);
+            debug!("translating fn_block %s with type %s",
+                   expr_to_str(expr, tcx.sess.intr()),
+                   ty_to_str(tcx, expr_ty));
+            return closure::trans_expr_fn(bcx, sigil, decl, body,
+                                          expr.id, expr.id,
+                                          None, dest);
         }
         ast::expr_loop_body(blk) => {
-            match ty::get(expr_ty(bcx, expr)).sty {
-                ty::ty_fn(ref fn_ty) => {
-                    match blk.node {
-                        ast::expr_fn_block(copy decl, ref body) => {
-                            return closure::trans_expr_fn(
-                                bcx,
-                                fn_ty.meta.proto,
-                                decl,
-                                /*bad*/copy *body,
-                                expr.id,
-                                blk.id,
-                                Some(None),
-                                dest);
-                        }
-                        _ => {
-                            bcx.sess().impossible_case(
-                                expr.span,
-                                "loop_body has the wrong kind of contents")
-                        }
-                    }
+            let expr_ty = expr_ty(bcx, expr);
+            let sigil = ty::ty_closure_sigil(expr_ty);
+            match blk.node {
+                ast::expr_fn_block(ref decl, ref body) => {
+                    return closure::trans_expr_fn(bcx, sigil,
+                                                  decl, body,
+                                                  expr.id, blk.id,
+                                                  Some(None), dest);
                 }
                 _ => {
                     bcx.sess().impossible_case(
-                        expr.span, "loop_body has body with a non-fn type")
+                        expr.span,
+                        "loop_body has the wrong kind of contents")
                 }
             }
         }
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index ae05ceb1ec5..bb14fce8053 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -31,7 +31,7 @@ use middle::trans::machine;
 use middle::trans::shape;
 use middle::trans::type_of::*;
 use middle::trans::type_of;
-use middle::ty::{FnTyBase, FnMeta, FnSig, arg};
+use middle::ty::{FnSig, arg};
 use util::ppaux::ty_to_str;
 
 use core::libc::c_uint;
@@ -66,10 +66,8 @@ type c_stack_tys = {
 fn c_arg_and_ret_lltys(ccx: @crate_ctxt,
                        id: ast::node_id) -> (~[TypeRef], TypeRef, ty::t) {
     match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
-        ty::ty_fn(ref fn_ty) => {
-            let llargtys = type_of_explicit_args(
-                ccx,
-                fn_ty.sig.inputs);
+        ty::ty_bare_fn(ref fn_ty) => {
+            let llargtys = type_of_explicit_args(ccx, fn_ty.sig.inputs);
             let llretty = type_of::type_of(ccx, fn_ty.sig.output);
             (llargtys, llretty, fn_ty.sig.output)
         }
@@ -541,12 +539,11 @@ pub fn trans_intrinsic(ccx: @crate_ctxt,
             let star_u8 = ty::mk_imm_ptr(
                 bcx.tcx(),
                 ty::mk_mach_uint(bcx.tcx(), ast::ty_u8));
-            let fty = ty::mk_fn(bcx.tcx(), FnTyBase {
-                meta: FnMeta {purity: ast::impure_fn,
-                              proto: ast::ProtoBorrowed,
-                              onceness: ast::Many,
-                              region: ty::re_bound(ty::br_anon(0)),
-                              bounds: @~[]},
+            let fty = ty::mk_closure(bcx.tcx(), ty::ClosureTy {
+                purity: ast::impure_fn,
+                sigil: ast::BorrowedSigil,
+                onceness: ast::Many,
+                region: ty::re_bound(ty::br_anon(0)),
                 sig: FnSig {inputs: ~[arg {mode: ast::expl(ast::by_copy),
                                            ty: star_u8}],
                             output: ty::mk_nil(bcx.tcx())}
@@ -843,14 +840,14 @@ pub fn trans_intrinsic(ccx: @crate_ctxt,
 
 pub fn trans_foreign_fn(ccx: @crate_ctxt,
                         +path: ast_map::path,
-                        decl: ast::fn_decl,
-                        body: ast::blk,
+                        decl: &ast::fn_decl,
+                        body: &ast::blk,
                         llwrapfn: ValueRef,
                         id: ast::node_id) {
     let _icx = ccx.insn_ctxt("foreign::build_foreign_fn");
 
     fn build_rust_fn(ccx: @crate_ctxt, +path: ast_map::path,
-                     decl: ast::fn_decl, body: ast::blk,
+                     decl: &ast::fn_decl, body: &ast::blk,
                      id: ast::node_id) -> ValueRef {
         let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn");
         let t = ty::node_id_to_type(ccx.tcx, id);
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 9909980fb7e..564460fd88e 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -172,7 +172,8 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
 
     if field == abi::tydesc_field_free_glue {
         match ty::get(t).sty {
-          ty::ty_fn(*) |
+          ty::ty_bare_fn(*) |
+          ty::ty_closure(*) |
           ty::ty_box(*) |
           ty::ty_opaque_box |
           ty::ty_uniq(*) |
@@ -419,8 +420,8 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
                        tvec::expand_boxed_vec_ty(bcx.tcx(), t));
         return;
       }
-      ty::ty_fn(_) => {
-        closure::make_fn_glue(bcx, v, t, free_ty)
+      ty::ty_closure(_) => {
+        closure::make_closure_glue(bcx, v, t, free_ty)
       }
       ty::ty_opaque_closure_ptr(ck) => {
         closure::make_opaque_cbox_free_glue(bcx, ck, v)
@@ -528,8 +529,8 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
           }
         }
       }
-      ty::ty_fn(_) => {
-        closure::make_fn_glue(bcx, v0, t, drop_ty)
+      ty::ty_closure(_) => {
+        closure::make_closure_glue(bcx, v0, t, drop_ty)
       }
       ty::ty_trait(_, _, ty::vstore_box) => {
         let llbox = Load(bcx, GEPi(bcx, v0, [0u, 1u]));
@@ -594,8 +595,8 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
       | ty::ty_estr(ty::vstore_slice(_)) => {
         bcx
       }
-      ty::ty_fn(_) => {
-        closure::make_fn_glue(bcx, v, t, take_ty)
+      ty::ty_closure(_) => {
+        closure::make_closure_glue(bcx, v, t, take_ty)
       }
       ty::ty_trait(_, _, ty::vstore_box) => {
         let llbox = Load(bcx, GEPi(bcx, v, [0u, 1u]));
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index 4466e4e1b28..c094db4ecca 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -108,8 +108,8 @@ pub fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id,
                 };
                 trans_fn(ccx,
                          path,
-                         mth.decl,
-                         mth.body,
+                         &mth.decl,
+                         &mth.body,
                          llfn,
                          self_kind,
                          None,
diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs
index e76176218b7..828b5619390 100644
--- a/src/librustc/middle/trans/machine.rs
+++ b/src/librustc/middle/trans/machine.rs
@@ -34,8 +34,11 @@ pub fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
           ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) |
           ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) |
           ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
-          ty::ty_ptr(_) | ty::ty_rptr(_,_) => nilptr(tcx),
-          ty::ty_fn(_) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
+          ty::ty_ptr(_) | ty::ty_rptr(*) => nilptr(tcx),
+
+          ty::ty_bare_fn(*) | // FIXME(#4804) Bare fn repr
+          ty::ty_closure(*) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
+
           ty::ty_evec(_, ty::vstore_slice(_)) |
           ty::ty_estr(ty::vstore_slice(_)) => {
             ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)])
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index d751b8f9208..1d48d2dde6b 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -142,8 +142,8 @@ pub fn trans_method(ccx: @crate_ctxt,
     // generate the actual code
     trans_fn(ccx,
              path,
-             method.decl,
-             method.body,
+             &method.decl,
+             &method.body,
              llfn,
              self_arg,
              param_substs,
@@ -822,7 +822,7 @@ pub fn make_impl_vtable(ccx: @crate_ctxt,
     let has_tps = (*ty::lookup_item_type(ccx.tcx, impl_id).bounds).len() > 0u;
     make_vtable(ccx, vec::map(*ty::trait_methods(tcx, trt_id), |im| {
         let fty = ty::subst_tps(tcx, substs, None,
-                                ty::mk_fn(tcx, copy im.fty));
+                                ty::mk_bare_fn(tcx, copy im.fty));
         if (*im.tps).len() > 0u || ty::type_has_self(fty) {
             debug!("(making impl vtable) method has self or type params: %s",
                    tcx.sess.str_of(im.ident));
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 5873d0a76d9..b09a41f2b7f 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -26,7 +26,7 @@ use middle::trans::shape;
 use middle::trans::type_of::type_of_fn_from_ty;
 use middle::trans::type_of;
 use middle::trans::type_use;
-use middle::ty::{FnTyBase, FnMeta, FnSig};
+use middle::ty::{FnSig};
 use middle::typeck;
 
 use core::option;
@@ -166,12 +166,12 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
     let lldecl = match map_node {
       ast_map::node_item(i@@ast::item {
                 // XXX: Bad copy.
-                node: ast::item_fn(copy decl, _, _, ref body),
+                node: ast::item_fn(ref decl, _, _, ref body),
                 _
             }, _) => {
         let d = mk_lldecl();
         set_inline_hint_if_appr(/*bad*/copy i.attrs, d);
-        trans_fn(ccx, pt, decl, *body, d, no_self, psubsts, fn_id.node, None);
+        trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None);
         d
       }
       ast_map::node_item(*) => {
@@ -224,7 +224,7 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
                 None      => ccx.sess.span_bug(dtor.span, ~"Bad self ty in \
                                                             dtor")
         };
-        trans_struct_dtor(ccx, /*bad*/copy *pt, dtor.node.body,
+        trans_struct_dtor(ccx, /*bad*/copy *pt, &dtor.node.body,
           dtor.node.id, psubsts, Some(hash_id), parent_id)
       }
       ast_map::node_trait_method(@ast::provided(mth), _, pt) => {
@@ -267,31 +267,34 @@ pub fn monomorphic_fn(ccx: @crate_ctxt,
 pub fn normalize_for_monomorphization(tcx: ty::ctxt,
                                       ty: ty::t) -> Option<ty::t> {
     // FIXME[mono] could do this recursively. is that worthwhile? (#2529)
-    match ty::get(ty).sty {
+    return match ty::get(ty).sty {
         ty::ty_box(*) => {
             Some(ty::mk_opaque_box(tcx))
         }
-        ty::ty_fn(ref fty) => {
-            Some(ty::mk_fn(
+        ty::ty_bare_fn(_) => {
+            Some(ty::mk_bare_fn(
                 tcx,
-                FnTyBase {meta: FnMeta {purity: ast::impure_fn,
-                                        proto: fty.meta.proto,
-                                        onceness: ast::Many,
-                                        region: ty::re_static,
-                                        bounds: @~[]},
-                          sig: FnSig {inputs: ~[],
-                                      output: ty::mk_nil(tcx)}}))
+                ty::BareFnTy {
+                    purity: ast::impure_fn,
+                    abi: ast::RustAbi,
+                    sig: FnSig {inputs: ~[],
+                                output: ty::mk_nil(tcx)}}))
         }
-        ty::ty_trait(_, _, _) => {
-            Some(ty::mk_fn(
-                tcx,
-                FnTyBase {meta: FnMeta {purity: ast::impure_fn,
-                                        proto: ast::ProtoBox,
-                                        onceness: ast::Many,
-                                        region: ty::re_static,
-                                        bounds: @~[]},
-                          sig: FnSig {inputs: ~[],
-                                      output: ty::mk_nil(tcx)}}))
+        ty::ty_closure(ref fty) => {
+            Some(normalized_closure_ty(tcx, fty.sigil))
+        }
+        ty::ty_trait(_, _, ref vstore) => {
+            let sigil = match *vstore {
+                ty::vstore_uniq => ast::OwnedSigil,
+                ty::vstore_box => ast::ManagedSigil,
+                ty::vstore_slice(_) => ast::BorrowedSigil,
+                ty::vstore_fixed(*) => {
+                    tcx.sess.bug(fmt!("ty_trait with vstore_fixed"));
+                }
+            };
+
+            // Traits have the same runtime representation as closures.
+            Some(normalized_closure_ty(tcx, sigil))
         }
         ty::ty_ptr(_) => {
             Some(ty::mk_uint(tcx))
@@ -299,6 +302,20 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt,
         _ => {
             None
         }
+    };
+
+    fn normalized_closure_ty(tcx: ty::ctxt,
+                             sigil: ast::Sigil) -> ty::t
+    {
+        ty::mk_closure(
+            tcx,
+            ty::ClosureTy {
+                purity: ast::impure_fn,
+                sigil: sigil,
+                onceness: ast::Many,
+                region: ty::re_static,
+                sig: ty::FnSig {inputs: ~[],
+                                output: ty::mk_nil(tcx)}})
     }
 }
 
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 7380fa2e562..9466099904c 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -86,9 +86,8 @@ pub impl reflector {
             tcx.sess.ident_of(~"visit_" + ty_name),
             *self.visitor_methods).expect(fmt!("Couldn't find visit method \
                                                 for %s", ty_name));
-        let mth_ty = ty::mk_fn(
-            tcx,
-            /*bad*/copy self.visitor_methods[mth_idx].fty);
+        let mth_ty =
+            ty::mk_bare_fn(tcx, copy self.visitor_methods[mth_idx].fty);
         let v = self.visitor_val;
         debug!("passing %u args:", vec::len(args));
         let bcx = self.bcx;
@@ -211,39 +210,33 @@ pub impl reflector {
             }
           }
 
+          // FIXME (#2594): fetch constants out of intrinsic
+          // FIXME (#4809): visitor should break out bare fns from other fns
+          ty::ty_closure(ref fty) => {
+            let pureval = ast_purity_constant(fty.purity);
+            let sigilval = ast_sigil_constant(fty.sigil);
+            let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
+            let extra = ~[self.c_uint(pureval),
+                          self.c_uint(sigilval),
+                          self.c_uint(vec::len(fty.sig.inputs)),
+                          self.c_uint(retval)];
+            self.visit(~"enter_fn", copy extra);    // XXX: Bad copy.
+            self.visit_sig(retval, &fty.sig);
+            self.visit(~"leave_fn", extra);
+          }
+
           // FIXME (#2594): fetch constants out of intrinsic:: for the
           // numbers.
-          ty::ty_fn(ref fty) => {
-            let pureval = match fty.meta.purity {
-              ast::pure_fn => 0u,
-              ast::unsafe_fn => 1u,
-              ast::impure_fn => 2u,
-              ast::extern_fn => 3u
-            };
-            let protoval = ast_proto_constant(fty.meta.proto);
+          ty::ty_bare_fn(ref fty) => {
+            let pureval = ast_purity_constant(fty.purity);
+            let sigilval = 0u;
             let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u};
             let extra = ~[self.c_uint(pureval),
-                          self.c_uint(protoval),
+                          self.c_uint(sigilval),
                           self.c_uint(vec::len(fty.sig.inputs)),
                           self.c_uint(retval)];
             self.visit(~"enter_fn", copy extra);    // XXX: Bad copy.
-            for fty.sig.inputs.eachi |i, arg| {
-                let modeval = match arg.mode {
-                  ast::infer(_) => 0u,
-                  ast::expl(e) => match e {
-                    ast::by_ref => 1u,
-                    ast::by_val => 2u,
-                    ast::by_copy => 5u
-                  }
-                };
-                self.visit(~"fn_input",
-                           ~[self.c_uint(i),
-                             self.c_uint(modeval),
-                             self.c_tydesc(arg.ty)]);
-            }
-            self.visit(~"fn_output",
-                       ~[self.c_uint(retval),
-                         self.c_tydesc(fty.sig.output)]);
+            self.visit_sig(retval, &fty.sig);
             self.visit(~"leave_fn", extra);
           }
 
@@ -302,11 +295,31 @@ pub impl reflector {
           ty::ty_type => self.leaf(~"type"),
           ty::ty_opaque_box => self.leaf(~"opaque_box"),
           ty::ty_opaque_closure_ptr(ck) => {
-            let ckval = ast_proto_constant(ck);
+            let ckval = ast_sigil_constant(ck);
             self.visit(~"closure_ptr", ~[self.c_uint(ckval)])
           }
         }
     }
+
+    fn visit_sig(&self, retval: uint, sig: &ty::FnSig) {
+        for sig.inputs.eachi |i, arg| {
+            let modeval = match arg.mode {
+                ast::infer(_) => 0u,
+                ast::expl(e) => match e {
+                    ast::by_ref => 1u,
+                    ast::by_val => 2u,
+                    ast::by_copy => 5u
+                }
+            };
+            self.visit(~"fn_input",
+                       ~[self.c_uint(i),
+                         self.c_uint(modeval),
+                         self.c_tydesc(arg.ty)]);
+        }
+        self.visit(~"fn_output",
+                   ~[self.c_uint(retval),
+                     self.c_tydesc(sig.output)]);
+    }
 }
 
 // Emit a sequence of calls to visit_ty::visit_foo
@@ -332,12 +345,20 @@ pub fn emit_calls_to_trait_visit_ty(bcx: block,
     return final;
 }
 
-pub fn ast_proto_constant(proto: ast::Proto) -> uint {
-    match proto {
-        ast::ProtoBare => 0u,
-        ast::ProtoUniq => 2u,
-        ast::ProtoBox => 3u,
-        ast::ProtoBorrowed => 4u,
+pub fn ast_sigil_constant(sigil: ast::Sigil) -> uint {
+    match sigil {
+        ast::OwnedSigil => 2u,
+        ast::ManagedSigil => 3u,
+        ast::BorrowedSigil => 4u,
+    }
+}
+
+pub fn ast_purity_constant(purity: ast::purity) -> uint {
+    match purity {
+        ast::pure_fn => 0u,
+        ast::unsafe_fn => 1u,
+        ast::impure_fn => 2u,
+        ast::extern_fn => 3u
     }
 }
 
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 99c47997df0..f727b5a2de0 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -59,7 +59,13 @@ pub fn type_of_fn(cx: @crate_ctxt, inputs: &[ty::arg],
 
 // Given a function type and a count of ty params, construct an llvm type
 pub fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
-    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
+    match ty::get(fty).sty {
+        ty::ty_closure(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
+        ty::ty_bare_fn(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
+        _ => {
+            cx.sess.bug(~"type_of_fn_from_ty given non-closure, non-bare-fn")
+        }
+    }
 }
 
 pub fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
@@ -170,7 +176,11 @@ pub fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
         // structs
         T_struct(~[T_struct(tys)])
       }
-      ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
+
+      // FIXME(#4804) Bare fn repr
+      // ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)),
+      ty::ty_bare_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
+      ty::ty_closure(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
       ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
       ty::ty_type => T_ptr(cx.tydesc_type),
       ty::ty_tup(elts) => {
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 6b0d4e17c74..3fd334c2d15 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -69,8 +69,9 @@ pub fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
 
     let cx = {ccx: ccx, uses: vec::cast_to_mut(vec::from_elem(n_tps, 0u))};
     match ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).sty {
-        ty::ty_fn(ref fn_ty) => {
-            for vec::each(fn_ty.sig.inputs) |arg| {
+        ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
+        ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
+            for vec::each(sig.inputs) |arg| {
                 match ty::resolved_mode(ccx.tcx, arg.mode) {
                     by_val | by_copy => {
                         type_needs(cx, use_repr, arg.ty);
@@ -197,8 +198,12 @@ pub fn type_needs_inner(cx: ctx,
                  it, we depend on the drop glue for T (we have to write the
                  right tydesc into the result)
                  */
-              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _)
-               | ty::ty_trait(_, _, _) => false,
+                ty::ty_closure(*) |
+                ty::ty_bare_fn(*) |
+                ty::ty_ptr(_) |
+                ty::ty_rptr(_, _) |
+                ty::ty_trait(_, _, _) => false,
+
               ty::ty_enum(did, ref substs) => {
                 if option::is_none(&list::find(enums_seen, |id| *id == did)) {
                     let seen = @Cons(did, enums_seen);
@@ -287,15 +292,15 @@ pub fn mark_for_expr(cx: ctx, e: @expr) {
         }
       }
       expr_fn(*) | expr_fn_block(*) => {
-        match ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) {
-          ast::ProtoBare | ast::ProtoUniq => {}
-          ast::ProtoBox | ast::ProtoBorrowed => {
-            for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) |fv| {
-                let node_id = ast_util::def_id_of_def(fv.def).node;
-                node_type_needs(cx, use_repr, node_id);
-            }
+          match ty::ty_closure_sigil(ty::expr_ty(cx.ccx.tcx, e)) {
+              ast::OwnedSigil => {}
+              ast::BorrowedSigil | ast::ManagedSigil => {
+                  for freevars::get_freevars(cx.ccx.tcx, e.id).each |fv| {
+                      let node_id = ast_util::def_id_of_def(fv.def).node;
+                      node_type_needs(cx, use_repr, node_id);
+                  }
+              }
           }
-        }
       }
       expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
       expr_ret(Some(val)) => {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 9905701e058..ef62fb3caf1 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[warn(deprecated_pattern)];
-
 use core::prelude::*;
 
 use driver::session;
@@ -27,7 +25,7 @@ use middle;
 use session::Session;
 use util::ppaux::{note_and_explain_region, bound_region_to_str};
 use util::ppaux::{region_to_str, explain_region, vstore_to_str};
-use util::ppaux::{ty_to_str, proto_ty_to_str, tys_to_str};
+use util::ppaux::{ty_to_str, tys_to_str};
 
 use core::cast;
 use core::cmp;
@@ -73,7 +71,7 @@ pub type param_bounds = @~[param_bound];
 pub type method = {
     ident: ast::ident,
     tps: @~[param_bounds],
-    fty: FnTy,
+    fty: BareFnTy,
     self_ty: ast::self_ty_,
     vis: ast::visibility,
     def_id: ast::def_id
@@ -344,22 +342,20 @@ pub pure fn type_contains_err(t: t) -> bool {
 pub pure fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
 pub pure fn type_id(t: t) -> uint { get(t).id }
 
-/**
- * Meta information about a closure.
- *
- * - `purity` is the function's effect (pure, impure, unsafe).
- * - `proto` is the protocol (fn@, fn~, etc).
- * - `onceness` indicates whether the function can be called one time or many
- *   times.
- * - `region` is the region bound on the function's upvars (often &static).
- * - `bounds` is the parameter bounds on the function's upvars. */
 #[deriving_eq]
-pub struct FnMeta {
+pub struct BareFnTy {
+    purity: ast::purity,
+    abi: Abi,
+    sig: FnSig
+}
+
+#[deriving_eq]
+pub struct ClosureTy {
     purity: ast::purity,
-    proto: ast::Proto,
+    sigil: ast::Sigil,
     onceness: ast::Onceness,
     region: Region,
-    bounds: @~[param_bound]
+    sig: FnSig
 }
 
 /**
@@ -374,25 +370,19 @@ pub struct FnSig {
     output: t
 }
 
-/**
- * Function type: combines the meta information and the
- * type signature.  This particular type is parameterized
- * by the meta information because, in some cases, the
- * meta information is inferred. */
-#[deriving_eq]
-pub struct FnTyBase<M> {
-    meta: M,        // Either FnMeta or FnVid
-    sig: FnSig      // Types of arguments/return type
+impl BareFnTy : to_bytes::IterBytes {
+    pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
+        to_bytes::iter_bytes_3(&self.purity, &self.abi, &self.sig, lsb0, f)
+    }
 }
 
-impl<M: to_bytes::IterBytes> FnTyBase<M> : to_bytes::IterBytes {
+impl ClosureTy : to_bytes::IterBytes {
     pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
-        to_bytes::iter_bytes_2(&self.meta, &self.sig, lsb0, f)
+        to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness,
+                               &self.region, &self.sig, lsb0, f)
     }
 }
 
-pub type FnTy = FnTyBase<FnMeta>;
-
 #[deriving_eq]
 pub struct param_ty {
     idx: uint,
@@ -491,6 +481,7 @@ pub struct substs {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
+#[deriving_eq]
 pub enum sty {
     ty_nil,
     ty_bot,
@@ -506,7 +497,8 @@ pub enum sty {
     ty_ptr(mt),
     ty_rptr(Region, mt),
     ty_rec(~[field]),
-    ty_fn(FnTy),
+    ty_bare_fn(BareFnTy),
+    ty_closure(ClosureTy),
     ty_trait(def_id, substs, vstore),
     ty_struct(def_id, substs),
     ty_tup(~[t]),
@@ -522,7 +514,7 @@ pub enum sty {
     // "Fake" types, used for trans purposes
     ty_type, // type_desc*
     ty_opaque_box, // used by monomorphizer to represent any @ box
-    ty_opaque_closure_ptr(ast::Proto), // ptr to env for fn, fn@, fn~
+    ty_opaque_closure_ptr(Sigil), // ptr to env for fn, fn@, fn~
     ty_unboxed_vec(mt),
 }
 
@@ -546,8 +538,9 @@ pub enum type_err {
     terr_mismatch,
     terr_purity_mismatch(expected_found<purity>),
     terr_onceness_mismatch(expected_found<Onceness>),
+    terr_abi_mismatch(expected_found<ast::Abi>),
     terr_mutability,
-    terr_proto_mismatch(expected_found<ast::Proto>),
+    terr_sigil_mismatch(expected_found<ast::Sigil>),
     terr_box_mutability,
     terr_ptr_mutability,
     terr_ref_mutability,
@@ -744,6 +737,15 @@ pub impl RegionVid : to_bytes::IterBytes {
     }
 }
 
+pub fn kind_to_param_bounds(kind: Kind) -> param_bounds {
+    let mut bounds = ~[];
+    if kind_can_be_copied(kind) { bounds.push(bound_copy); }
+    if kind_can_be_sent(kind) { bounds.push(bound_owned); }
+    else if kind_is_durable(kind) { bounds.push(bound_durable); }
+    if kind_is_const(kind) { bounds.push(bound_const); }
+    return @bounds;
+}
+
 pub fn param_bounds_to_kind(bounds: param_bounds) -> Kind {
     let mut kind = kind_noncopyable();
     for vec::each(*bounds) |bound| {
@@ -925,8 +927,12 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
       }
       &ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
       &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
-      &ty_fn(ref f) => {
-        flags |= rflags(f.meta.region);
+      &ty_bare_fn(ref f) => {
+        for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
+        flags |= get(f.sig.output).flags;
+      }
+      &ty_closure(ref f) => {
+        flags |= rflags(f.region);
         for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
         flags |= get(f.sig.output).flags;
       }
@@ -1044,8 +1050,25 @@ pub fn mk_rec(cx: ctxt, +fs: ~[field]) -> t { mk_t(cx, ty_rec(fs)) }
 
 pub fn mk_tup(cx: ctxt, +ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
 
-// take a copy because we want to own the various vectors inside
-pub fn mk_fn(cx: ctxt, +fty: FnTy) -> t { mk_t(cx, ty_fn(fty)) }
+pub fn mk_closure(cx: ctxt, +fty: ClosureTy) -> t {
+    mk_t(cx, ty_closure(fty))
+}
+
+pub fn mk_bare_fn(cx: ctxt, +fty: BareFnTy) -> t {
+    mk_t(cx, ty_bare_fn(fty))
+}
+
+pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
+    let input_args = input_tys.map(|t| arg {mode: ast::expl(ast::by_copy),
+                                            ty: *t});
+    mk_bare_fn(cx,
+               BareFnTy {
+                   purity: ast::pure_fn,
+                   abi: ast::RustAbi,
+                   sig: FnSig {inputs: input_args,
+                               output: output}})
+}
+
 
 pub fn mk_trait(cx: ctxt, did: ast::def_id, +substs: substs, vstore: vstore)
          -> t {
@@ -1074,8 +1097,8 @@ pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
 
 pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
 
-pub fn mk_opaque_closure_ptr(cx: ctxt, proto: ast::Proto) -> t {
-    mk_t(cx, ty_opaque_closure_ptr(proto))
+pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
+    mk_t(cx, ty_opaque_closure_ptr(sigil))
 }
 
 pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
@@ -1097,13 +1120,11 @@ pub pure fn mach_sty(cfg: @session::config, t: t) -> sty {
 pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
         // FIXME(#2202) --- We retain by-ref for fn& things to workaround a
         // memory leak that otherwise results when @fn is upcast to &fn.
-    if type_is_fn(ty) {
-        match ty_fn_proto(ty) {
-            ast::ProtoBorrowed => {
-                return ast::by_ref;
-            }
-            _ => {}
+    match ty::get(ty).sty {
+        ty::ty_closure(ClosureTy {sigil: ast::BorrowedSigil, _}) => {
+            return ast::by_ref;
         }
+        _ => {}
     }
     return if tcx.legacy_modes {
         if type_is_borrowed(ty) {
@@ -1119,13 +1140,6 @@ pub fn default_arg_mode_for_ty(tcx: ctxt, ty: ty::t) -> ast::rmode {
         ast::by_copy
     };
 
-    fn type_is_fn(ty: t) -> bool {
-        match get(ty).sty {
-            ty_fn(*) => true,
-            _ => false
-        }
-    }
-
     fn type_is_borrowed(ty: t) -> bool {
         match ty::get(ty).sty {
             ty::ty_rptr(*) => true,
@@ -1171,7 +1185,11 @@ pub fn maybe_walk_ty(ty: t, f: fn(t) -> bool) {
         for fields.each |fl| { maybe_walk_ty(fl.mt.ty, f); }
       }
       ty_tup(ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
-      ty_fn(ref ft) => {
+      ty_bare_fn(ref ft) => {
+        for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
+        maybe_walk_ty(ft.sig.output, f);
+      }
+      ty_closure(ref ft) => {
         for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
         maybe_walk_ty(ft.sig.output, f);
       }
@@ -1235,9 +1253,13 @@ fn fold_sty(sty: &sty, fldop: fn(t) -> t) -> sty {
             let new_ts = vec::map(ts, |tt| fldop(*tt));
             ty_tup(new_ts)
         }
-        ty_fn(ref f) => {
+        ty_bare_fn(ref f) => {
+            let sig = fold_sig(&f.sig, fldop);
+            ty_bare_fn(BareFnTy {sig: sig, abi: f.abi, purity: f.purity})
+        }
+        ty_closure(ref f) => {
             let sig = fold_sig(&f.sig, fldop);
-            ty_fn(FnTyBase {meta: f.meta, sig: sig})
+            ty_closure(ClosureTy {sig: sig, ..copy *f})
         }
         ty_rptr(r, tm) => {
             ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
@@ -1318,10 +1340,14 @@ pub fn fold_regions_and_ty(
       ty_trait(def_id, ref substs, vst) => {
         ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), vst)
       }
-      ty_fn(ref f) => {
-          ty::mk_fn(cx, FnTyBase {meta: FnMeta {region: fldr(f.meta.region),
-                                                ..f.meta},
-                                  sig: fold_sig(&f.sig, fldfnt)})
+      ty_bare_fn(ref f) => {
+          ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
+                                       ..copy *f})
+      }
+      ty_closure(ref f) => {
+          ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
+                                        sig: fold_sig(&f.sig, fldfnt),
+                                        ..copy *f})
       }
       ref sty => {
         fold_sty_to_ty(cx, sty, |t| fldt(t))
@@ -1329,30 +1355,6 @@ pub fn fold_regions_and_ty(
     }
 }
 
-/* A little utility: it often happens that I have a `fn_ty`,
- * but I want to use some function like `fold_regions_and_ty()`
- * that is defined over all types.  This utility converts to
- * a full type and back.  It's not the best way to do this (somewhat
- * inefficient to do the conversion), it would be better to refactor
- * all this folding business.  However, I've been waiting on that
- * until trait support is improved. */
-pub fn apply_op_on_t_to_ty_fn(
-    cx: ctxt,
-    f: &FnTy,
-    t_op: fn(t) -> t) -> FnTy
-{
-    let t0 = ty::mk_fn(cx, /*bad*/copy *f);
-    let t1 = t_op(t0);
-    match ty::get(t1).sty {
-        ty::ty_fn(copy f) => {
-            move f
-        }
-        _ => {
-            cx.sess.bug(~"`t_op` did not return a function type");
-        }
-    }
-}
-
 // n.b. this function is intended to eventually replace fold_region() below,
 // that is why its name is so similar.
 pub fn fold_regions(
@@ -1372,41 +1374,6 @@ pub fn fold_regions(
     do_fold(cx, ty, false, fldr)
 }
 
-pub fn fold_region(cx: ctxt, t0: t, fldop: fn(Region, bool) -> Region) -> t {
-    fn do_fold(cx: ctxt, t0: t, under_r: bool,
-               fldop: fn(Region, bool) -> Region) -> t {
-        let tb = get(t0);
-        if !tbox_has_flag(tb, has_regions) { return t0; }
-        match tb.sty {
-          ty_rptr(r, mt {ty: t1, mutbl: m}) => {
-            let m_r = fldop(r, under_r);
-            let m_t1 = do_fold(cx, t1, true, fldop);
-            ty::mk_rptr(cx, m_r, mt {ty: m_t1, mutbl: m})
-          }
-          ty_estr(vstore_slice(r)) => {
-            let m_r = fldop(r, under_r);
-            ty::mk_estr(cx, vstore_slice(m_r))
-          }
-          ty_evec(mt {ty: t1, mutbl: m}, vstore_slice(r)) => {
-            let m_r = fldop(r, under_r);
-            let m_t1 = do_fold(cx, t1, true, fldop);
-            ty::mk_evec(cx, mt {ty: m_t1, mutbl: m}, vstore_slice(m_r))
-          }
-          ty_fn(_) => {
-            // do not recurse into functions, which introduce fresh bindings
-            t0
-          }
-          ref sty => {
-            do fold_sty_to_ty(cx, sty) |t| {
-                do_fold(cx, t, under_r, fldop)
-            }
-          }
-      }
-    }
-
-    do_fold(cx, t0, false, fldop)
-}
-
 // Substitute *only* type parameters.  Used in trans where regions are erased.
 pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
     if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
@@ -1529,7 +1496,9 @@ pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
 
 pub fn type_is_structural(ty: t) -> bool {
     match get(ty).sty {
-      ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_fn(_) |
+      ty_rec(_) | ty_struct(*) | ty_tup(_) | ty_enum(*) |
+      ty_closure(_) |
+      ty_bare_fn(_) | // FIXME(#4804) Bare fn repr
       ty_trait(*) |
       ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
       ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
@@ -1715,10 +1684,11 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
         }
         accum
       }
-      ty_fn(ref fty) => {
-        match fty.meta.proto {
-          ast::ProtoBare | ast::ProtoBorrowed => false,
-          ast::ProtoBox | ast::ProtoUniq => true,
+      ty_bare_fn(*) => false,
+      ty_closure(ref fty) => {
+        match fty.sigil {
+          ast::BorrowedSigil => false,
+          ast::ManagedSigil | ast::OwnedSigil => true,
         }
       }
     };
@@ -1813,7 +1783,7 @@ pub enum Kind { kind_(u32) }
 const KIND_MASK_COPY         : u32 = 0b000000000000000000000000001_u32;
 
 /// no shared box, borrowed ptr (must imply DURABLE)
-const KIND_MASK_OWNED         : u32 = 0b000000000000000000000000010_u32;
+const KIND_MASK_OWNED        : u32 = 0b000000000000000000000000010_u32;
 
 /// is durable (no borrowed ptrs)
 const KIND_MASK_DURABLE      : u32 = 0b000000000000000000000000100_u32;
@@ -1942,20 +1912,25 @@ pub pure fn kind_is_durable(k: Kind) -> bool {
     *k & KIND_MASK_DURABLE == KIND_MASK_DURABLE
 }
 
-pub fn meta_kind(p: FnMeta) -> Kind {
-    match p.proto { // XXX consider the kind bounds!
-        ast::ProtoBare => {
-            kind_safe_for_default_mode_send() | kind_const() | kind_durable()
-        }
-        ast::ProtoBorrowed => {
-            kind_noncopyable() | kind_(KIND_MASK_DEFAULT_MODE)
-        }
-        ast::ProtoBox => {
-            kind_safe_for_default_mode() | kind_durable()
-        }
-        ast::ProtoUniq => {
-            kind_owned_copy() | kind_durable()
-        }
+pure fn kind_is_const(k: Kind) -> bool {
+    *k & KIND_MASK_CONST == KIND_MASK_CONST
+}
+
+fn closure_kind(cty: &ClosureTy) -> Kind {
+    let kind = match cty.sigil {
+        ast::BorrowedSigil => kind_implicitly_copyable(),
+        ast::ManagedSigil => kind_implicitly_copyable(),
+        ast::OwnedSigil => kind_owned_only() | kind_durable(),
+    };
+
+    let kind = match cty.region {
+        re_static => kind | kind_durable(),
+        _ => kind - kind_owned_only() - kind_durable()
+    };
+
+    match cty.onceness {
+        ast::Once => kind - kind_implicitly_copyable(),
+        ast::Many => kind
     }
 }
 
@@ -2022,7 +1997,7 @@ pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
     let mut result = match /*bad*/copy get(ty).sty {
       // Scalar and unique types are sendable, constant, and owned
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
-      ty_ptr(_) => {
+      ty_bare_fn(_) | ty_ptr(_) => {
         kind_safe_for_default_mode_send() | kind_const() | kind_durable()
       }
 
@@ -2035,8 +2010,9 @@ pub fn type_kind_ext(cx: ctxt, ty: t, allow_ty_var: bool) -> Kind {
         }
       }
 
-      // functions depend on the protocol
-      ty_fn(ref f) => meta_kind(f.meta),
+      ty_closure(ref c) => {
+          closure_kind(c)
+      }
 
       // Those with refcounts raise noncopyable to copyable,
       // lower sendable to copyable. Therefore just set result to copyable.
@@ -2215,7 +2191,8 @@ fn type_size(cx: ctxt, ty: t) -> uint {
 
       ty_evec(_, vstore_slice(_)) |
       ty_estr(vstore_slice(_)) |
-      ty_fn(_) => {
+      ty_bare_fn(*) |
+      ty_closure(*) => {
         2
       }
 
@@ -2297,7 +2274,8 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
           ty_uint(_) |
           ty_float(_) |
           ty_estr(_) |
-          ty_fn(_) |
+          ty_bare_fn(_) |
+          ty_closure(_) |
           ty_infer(_) |
           ty_err |
           ty_param(_) |
@@ -2472,9 +2450,9 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
     match /*bad*/copy get(ty).sty {
       // Scalar types
       ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
-      ty_type | ty_ptr(_) => result = true,
+      ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
       // Boxed types
-      ty_box(_) | ty_uniq(_) | ty_fn(_) |
+      ty_box(_) | ty_uniq(_) | ty_closure(_) |
       ty_estr(vstore_uniq) | ty_estr(vstore_box) |
       ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
       ty_trait(_, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
@@ -2700,14 +2678,9 @@ impl arg : to_bytes::IterBytes {
     }
 }
 
-impl FnMeta : to_bytes::IterBytes {
+impl Kind : to_bytes::IterBytes {
     pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
-        to_bytes::iter_bytes_5(&self.purity,
-                               &self.proto,
-                               &self.onceness,
-                               &self.region,
-                               &self.bounds,
-                               lsb0, f);
+        (**self).iter_bytes(lsb0, f)
     }
 }
 
@@ -2755,7 +2728,7 @@ impl sty : to_bytes::IterBytes {
           ty_rec(ref fs) =>
           to_bytes::iter_bytes_2(&11u8, fs, lsb0, f),
 
-          ty_fn(ref ft) =>
+          ty_bare_fn(ref ft) =>
           to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
 
           ty_self => 13u8.iter_bytes(lsb0, f),
@@ -2789,7 +2762,10 @@ impl sty : to_bytes::IterBytes {
           ty_rptr(ref r, ref mt) =>
           to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
 
-          ty_err => 25u8.iter_bytes(lsb0, f)
+          ty_err => 25u8.iter_bytes(lsb0, f),
+
+          ty_closure(ref ct) =>
+          to_bytes::iter_bytes_2(&26u8, ct, lsb0, f),
         }
     }
 }
@@ -2823,36 +2799,48 @@ fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
 // Type accessors for substructures of types
 pub fn ty_fn_args(fty: t) -> ~[arg] {
     match get(fty).sty {
-      ty_fn(ref f) => /*bad*/copy f.sig.inputs,
-      _ => die!(~"ty_fn_args() called on non-fn type")
+        ty_bare_fn(ref f) => copy f.sig.inputs,
+        ty_closure(ref f) => copy f.sig.inputs,
+        ref s => {
+            die!(fmt!("ty_fn_args() called on non-fn type: %?", s))
+        }
     }
 }
 
-pub fn ty_fn_proto(fty: t) -> Proto {
+pub fn ty_closure_sigil(fty: t) -> Sigil {
     match get(fty).sty {
-      ty_fn(ref f) => f.meta.proto,
-      _ => die!(~"ty_fn_proto() called on non-fn type")
+        ty_closure(ref f) => f.sigil,
+        ref s => {
+            die!(fmt!("ty_closure_sigil() called on non-closure type: %?", s))
+        }
     }
 }
 
 pub fn ty_fn_purity(fty: t) -> ast::purity {
     match get(fty).sty {
-      ty_fn(ref f) => f.meta.purity,
-      _ => die!(~"ty_fn_purity() called on non-fn type")
+        ty_bare_fn(ref f) => f.purity,
+        ty_closure(ref f) => f.purity,
+        ref s => {
+            die!(fmt!("ty_fn_purity() called on non-fn type: %?", s))
+        }
     }
 }
 
 pub pure fn ty_fn_ret(fty: t) -> t {
     match get(fty).sty {
-        ty_fn(ref f) => f.sig.output,
-        _ => die!(~"ty_fn_ret() called on non-fn type")
+        ty_bare_fn(ref f) => f.sig.output,
+        ty_closure(ref f) => f.sig.output,
+        ref s => {
+            die!(fmt!("ty_fn_ret() called on non-fn type: %?", s))
+        }
     }
 }
 
 fn is_fn_ty(fty: t) -> bool {
     match get(fty).sty {
-      ty_fn(_) => true,
-      _ => false
+        ty_bare_fn(_) => true,
+        ty_closure(_) => true,
+        _ => false
     }
 }
 
@@ -2874,17 +2862,17 @@ pub fn ty_region(ty: t) -> Region {
     }
 }
 
-pub fn replace_fn_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
+pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
     /*!
      *
      * Returns a new function type based on `fn_type` but returning a value of
      * type `ret_type` instead. */
 
     match ty::get(fn_type).sty {
-        ty::ty_fn(ref fty) => {
-            ty::mk_fn(tcx, FnTyBase {
-                meta: fty.meta,
-                sig: FnSig {output: ret_type, ..copy fty.sig}
+        ty::ty_closure(ref fty) => {
+            ty::mk_closure(tcx, ClosureTy {
+                sig: FnSig {output: ret_type, ..copy fty.sig},
+                ..copy *fty
             })
         }
         _ => {
@@ -2900,12 +2888,6 @@ pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
     vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
 }
 
-// Just checks whether it's a fn that returns bool,
-// not its purity.
-pub fn is_pred_ty(fty: t) -> bool {
-    is_fn_ty(fty) && type_is_bool(ty_fn_ret(fty))
-}
-
 // Type accessors for AST nodes
 pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
     return node_id_to_type(cx, b.node.id);
@@ -3023,11 +3005,12 @@ pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
     fn borrow_fn(cx: ctxt, expr: @ast::expr,
                  autoref: &AutoRef, ty: ty::t) -> ty::t {
         match get(ty).sty {
-            ty_fn(ref fty) => {
-                ty::mk_fn(cx, FnTyBase {meta: FnMeta {proto: ProtoBorrowed,
-                                                      region: autoref.region,
-                                                      ..copy fty.meta},
-                                        sig: copy fty.sig})
+            ty_closure(ref fty) => {
+                ty::mk_closure(cx, ClosureTy {
+                    sigil: BorrowedSigil,
+                    region: autoref.region,
+                    ..copy *fty
+                })
             }
 
             ref s => {
@@ -3417,7 +3400,8 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
       ty_ptr(_) => ~"*-ptr",
       ty_rptr(_, _) => ~"&-ptr",
       ty_rec(_) => ~"record",
-      ty_fn(_) => ~"fn",
+      ty_bare_fn(_) => ~"extern fn",
+      ty_closure(_) => ~"fn",
       ty_trait(id, _, _) => fmt!("trait %s", item_path_str(cx, id)),
       ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
       ty_tup(_) => ~"tuple",
@@ -3455,14 +3439,18 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
             fmt!("expected %s fn but found %s fn",
                  values.expected.to_str(), values.found.to_str())
         }
+        terr_abi_mismatch(values) => {
+            fmt!("expected %s fn but found %s fn",
+                 values.expected.to_str(), values.found.to_str())
+        }
         terr_onceness_mismatch(values) => {
             fmt!("expected %s fn but found %s fn",
                  values.expected.to_str(), values.found.to_str())
         }
-        terr_proto_mismatch(values) => {
+        terr_sigil_mismatch(values) => {
             fmt!("expected %s closure, found %s closure",
-                 proto_ty_to_str(cx, values.expected, false),
-                 proto_ty_to_str(cx, values.found, false))
+                 values.expected.to_str(),
+                 values.found.to_str())
         }
         terr_mutability => ~"values differ in mutability",
         terr_box_mutability => ~"boxed values differ in mutability",
@@ -4232,13 +4220,10 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
             // This type has a region. Get rid of it
             mk_rptr(cx, re_static, normalize_mt(cx, mt)),
 
-        ty_fn(ref fn_ty) => {
-            mk_fn(cx, FnTyBase {
-                meta: FnMeta {
-                    region: ty::re_static,
-                    ..fn_ty.meta
-                },
-                sig: /*bad*/copy fn_ty.sig
+        ty_closure(ref closure_ty) => {
+            mk_closure(cx, ClosureTy {
+                region: ty::re_static,
+                ..copy *closure_ty
             })
         }
 
@@ -4310,13 +4295,13 @@ pub fn eval_repeat_count(tcx: ctxt,
 // Determine what purity to check a nested function under
 pub pure fn determine_inherited_purity(parent_purity: ast::purity,
                                        child_purity: ast::purity,
-                                       child_proto: ast::Proto)
+                                       child_sigil: ast::Sigil)
                                     -> ast::purity {
     // If the closure is a stack closure and hasn't had some non-standard
     // purity inferred for it, then check it under its parent's purity.
     // Otherwise, use its own
-    match child_proto {
-        ast::ProtoBorrowed if child_purity == ast::impure_fn => parent_purity,
+    match child_sigil {
+        ast::BorrowedSigil if child_purity == ast::impure_fn => parent_purity,
         _ => child_purity
     }
 }
@@ -4526,171 +4511,6 @@ impl bound_region : cmp::Eq {
     pure fn ne(&self, other: &bound_region) -> bool { !(*self).eq(other) }
 }
 
-impl sty : cmp::Eq {
-    pure fn eq(&self, other: &sty) -> bool {
-        match (/*bad*/copy *self) {
-            ty_nil => {
-                match (*other) {
-                    ty_nil => true,
-                    _ => false
-                }
-            }
-            ty_bot => {
-                match (*other) {
-                    ty_bot => true,
-                    _ => false
-                }
-            }
-            ty_bool => {
-                match (*other) {
-                    ty_bool => true,
-                    _ => false
-                }
-            }
-            ty_int(e0a) => {
-                match (*other) {
-                    ty_int(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_uint(e0a) => {
-                match (*other) {
-                    ty_uint(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_float(e0a) => {
-                match (*other) {
-                    ty_float(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_estr(e0a) => {
-                match (*other) {
-                    ty_estr(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_enum(e0a, ref e1a) => {
-                match (*other) {
-                    ty_enum(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
-                    _ => false
-                }
-            }
-            ty_box(e0a) => {
-                match (*other) {
-                    ty_box(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_uniq(e0a) => {
-                match (*other) {
-                    ty_uniq(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_evec(e0a, e1a) => {
-                match (*other) {
-                    ty_evec(e0b, e1b) => e0a == e0b && e1a == e1b,
-                    _ => false
-                }
-            }
-            ty_ptr(e0a) => {
-                match (*other) {
-                    ty_ptr(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_rptr(e0a, e1a) => {
-                match (*other) {
-                    ty_rptr(e0b, e1b) => e0a == e0b && e1a == e1b,
-                    _ => false
-                }
-            }
-            ty_rec(e0a) => {
-                match (/*bad*/copy *other) {
-                    ty_rec(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_fn(ref e0a) => {
-                match (*other) {
-                    ty_fn(ref e0b) => (*e0a) == (*e0b),
-                    _ => false
-                }
-            }
-            ty_trait(e0a, ref e1a, e2a) => {
-                match (*other) {
-                    ty_trait(e0b, ref e1b, e2b) =>
-                        e0a == e0b && (*e1a) == (*e1b) && e2a == e2b,
-                    _ => false
-                }
-            }
-            ty_struct(e0a, ref e1a) => {
-                match (*other) {
-                    ty_struct(e0b, ref e1b) => e0a == e0b && (*e1a) == (*e1b),
-                    _ => false
-                }
-            }
-            ty_tup(e0a) => {
-                match (/*bad*/copy *other) {
-                    ty_tup(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_infer(ref e0a) => {
-                match (*other) {
-                    ty_infer(ref e0b) => *e0a == *e0b,
-                    _ => false
-                }
-            }
-            ty_err => {
-                match (*other) {
-                    ty_err => true,
-                    _ => false
-                }
-            }
-            ty_param(e0a) => {
-                match (*other) {
-                    ty_param(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_self => {
-                match (*other) {
-                    ty_self => true,
-                    _ => false
-                }
-            }
-            ty_type => {
-                match (*other) {
-                    ty_type => true,
-                    _ => false
-                }
-            }
-            ty_opaque_box => {
-                match (*other) {
-                    ty_opaque_box => true,
-                    _ => false
-                }
-            }
-            ty_opaque_closure_ptr(e0a) => {
-                match (*other) {
-                    ty_opaque_closure_ptr(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-            ty_unboxed_vec(e0a) => {
-                match (*other) {
-                    ty_unboxed_vec(e0b) => e0a == e0b,
-                    _ => false
-                }
-            }
-        }
-    }
-    pure fn ne(&self, other: &sty) -> bool { !(*self).eq(other) }
-}
-
 impl param_bound : cmp::Eq {
     pure fn eq(&self, other: &param_bound) -> bool {
         match (*self) {
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 070360ce32f..0aafeac265a 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -55,7 +55,7 @@
 use core::prelude::*;
 
 use middle::pat_util::pat_id_map;
-use middle::ty::{FnTyBase, FnMeta, FnSig, arg, field, substs};
+use middle::ty::{arg, field, substs};
 use middle::ty::{ty_param_substs_and_ty};
 use middle::ty;
 use middle::typeck::check::fn_ctxt;
@@ -70,7 +70,7 @@ use core::vec;
 use syntax::ast;
 use syntax::codemap::span;
 use syntax::print::pprust::path_to_str;
-use util::common::indent;
+use util::common::indenter;
 
 pub trait ast_conv {
     fn tcx() -> ty::ctxt;
@@ -321,13 +321,16 @@ pub fn ast_ty_to_ty<AC: ast_conv, RS: region_scope Copy Durable>(
         };
         ty::mk_rec(tcx, flds)
       }
-      ast::ty_fn(f) => {
-        let bounds = collect::compute_bounds(self.ccx(), f.bounds);
-        let fn_decl = ty_of_fn_decl(self, rscope, f.proto,
-                                    f.purity, f.onceness,
-                                    bounds, f.region, f.decl, None,
-                                    ast_ty.span);
-        ty::mk_fn(tcx, fn_decl)
+      ast::ty_bare_fn(bf) => {
+          ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity,
+                                            bf.abi, bf.decl))
+      }
+      ast::ty_closure(f) => {
+          let fn_decl = ty_of_closure(self, rscope, f.sigil,
+                                      f.purity, f.onceness,
+                                      f.region, f.decl, None,
+                                      ast_ty.span);
+          ty::mk_closure(tcx, fn_decl)
       }
       ast::ty_path(path, id) => {
         let a_def = match tcx.def_map.find(&id) {
@@ -452,71 +455,92 @@ pub fn ty_of_arg<AC: ast_conv, RS: region_scope Copy Durable>(
     arg {mode: mode, ty: ty}
 }
 
-pub type expected_tys = Option<{inputs: ~[ty::arg],
-                                output: ty::t}>;
+pub fn ty_of_bare_fn<AC: ast_conv, RS: region_scope Copy Durable>(
+    self: AC, rscope: RS,
+    purity: ast::purity,
+    abi: ast::Abi,
+    decl: ast::fn_decl) -> ty::BareFnTy
+{
+    debug!("ty_of_fn_decl");
+
+    // new region names that appear inside of the fn decl are bound to
+    // that function type
+    let rb = in_binding_rscope(rscope);
+
+    let input_tys = decl.inputs.map(|a| ty_of_arg(self, rb, *a, None));
+    let output_ty = match decl.output.node {
+        ast::ty_infer => self.ty_infer(decl.output.span),
+        _ => ast_ty_to_ty(self, rb, decl.output)
+    };
+
+    ty::BareFnTy {
+        purity: purity,
+        abi: abi,
+        sig: ty::FnSig {inputs: input_tys, output: output_ty}
+    }
+}
 
-pub fn ty_of_fn_decl<AC: ast_conv, RS: region_scope Copy Durable>(
+pub fn ty_of_closure<AC: ast_conv, RS: region_scope Copy Durable>(
     self: AC, rscope: RS,
-    ast_proto: ast::Proto,
+    sigil: ast::Sigil,
     purity: ast::purity,
     onceness: ast::Onceness,
-    bounds: @~[ty::param_bound],
     opt_region: Option<@ast::region>,
     decl: ast::fn_decl,
-    expected_tys: expected_tys,
-    span: span) -> ty::FnTy {
+    expected_tys: Option<ty::FnSig>,
+    span: span) -> ty::ClosureTy
+{
     debug!("ty_of_fn_decl");
-    do indent {
-        // resolve the function bound region in the original region
-        // scope `rscope`, not the scope of the function parameters
-        let bound_region = match opt_region {
-            Some(region) => {
-                ast_region_to_region(self, rscope, span, region)
-            }
-            None => {
-                match ast_proto {
-                    ast::ProtoBare | ast::ProtoUniq | ast::ProtoBox => {
-                        // @fn(), ~fn() default to static as the bound
-                        // on their upvars:
-                        ty::re_static
-                    }
-                    ast::ProtoBorrowed => {
-                        // &fn() defaults to an anonymous region:
-                        let r_result = rscope.anon_region(span);
-                        get_region_reporting_err(self.tcx(), span, r_result)
-                    }
+    let _i = indenter();
+
+    // resolve the function bound region in the original region
+    // scope `rscope`, not the scope of the function parameters
+    let bound_region = match opt_region {
+        Some(region) => {
+            ast_region_to_region(self, rscope, span, region)
+        }
+        None => {
+            match sigil {
+                ast::OwnedSigil | ast::ManagedSigil => {
+                    // @fn(), ~fn() default to static as the bound
+                    // on their upvars:
+                    ty::re_static
+                }
+                ast::BorrowedSigil => {
+                    // &fn() defaults to an anonymous region:
+                    let r_result = rscope.anon_region(span);
+                    get_region_reporting_err(self.tcx(), span, r_result)
                 }
             }
-        };
+        }
+    };
 
-        // new region names that appear inside of the fn decl are bound to
-        // that function type
-        let rb = in_binding_rscope(rscope);
-
-        let input_tys = do decl.inputs.mapi |i, a| {
-            let expected_arg_ty = do expected_tys.chain_ref |e| {
-                // no guarantee that the correct number of expected args
-                // were supplied
-                if i < e.inputs.len() {Some(e.inputs[i])} else {None}
-            };
-            ty_of_arg(self, rb, *a, expected_arg_ty)
-        };
+    // new region names that appear inside of the fn decl are bound to
+    // that function type
+    let rb = in_binding_rscope(rscope);
 
-        let expected_ret_ty = expected_tys.map(|e| e.output);
-        let output_ty = match decl.output.node {
-          ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
-          ast::ty_infer => self.ty_infer(decl.output.span),
-          _ => ast_ty_to_ty(self, rb, decl.output)
+    let input_tys = do decl.inputs.mapi |i, a| {
+        let expected_arg_ty = do expected_tys.chain_ref |e| {
+            // no guarantee that the correct number of expected args
+            // were supplied
+            if i < e.inputs.len() {Some(e.inputs[i])} else {None}
         };
+        ty_of_arg(self, rb, *a, expected_arg_ty)
+    };
 
-        FnTyBase {
-            meta: FnMeta {purity: purity,
-                          proto: ast_proto,
-                          onceness: onceness,
-                          region: bound_region,
-                          bounds: bounds},
-            sig: FnSig {inputs: input_tys,
+    let expected_ret_ty = expected_tys.map(|e| e.output);
+    let output_ty = match decl.output.node {
+        ast::ty_infer if expected_ret_ty.is_some() => expected_ret_ty.get(),
+        ast::ty_infer => self.ty_infer(decl.output.span),
+        _ => ast_ty_to_ty(self, rb, decl.output)
+    };
+
+    ty::ClosureTy {
+        purity: purity,
+        sigil: sigil,
+        onceness: onceness,
+        region: bound_region,
+        sig: ty::FnSig {inputs: input_tys,
                         output: output_ty}
-        }
     }
 }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index b86f8f26c25..f5faa968791 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -883,7 +883,7 @@ pub impl LookupContext {
                     })
             }
 
-            ty_trait(*) | ty_fn(*) => {
+            ty_trait(*) | ty_closure(*) => {
                 // NDM---eventually these should be some variant of autoref
                 None
             }
@@ -906,14 +906,14 @@ pub impl LookupContext {
 
         let tcx = self.tcx();
         match ty::get(self_ty).sty {
-            ty_box(*) | ty_uniq(*) | ty_rptr(*) |
+            ty_bare_fn(*) | ty_box(*) | ty_uniq(*) | ty_rptr(*) |
             ty_infer(IntVar(_)) |
             ty_infer(FloatVar(_)) |
             ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool |
             ty_int(*) | ty_uint(*) |
             ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) |
             ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) |
-            ty_trait(*) | ty_fn(*) => {
+            ty_trait(*) | ty_closure(*) => {
                 self.search_for_some_kind_of_autorefd_method(
                     AutoPtr, autoderefs, [m_const, m_imm, m_mutbl],
                     |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m}))
@@ -1212,7 +1212,7 @@ pub impl LookupContext {
                                 trait_did: def_id,
                                 method_num: uint) -> ty::t {
             let trait_methods = ty::trait_methods(tcx, trait_did);
-            ty::mk_fn(tcx, /*bad*/copy trait_methods[method_num].fty)
+            ty::mk_bare_fn(tcx, copy trait_methods[method_num].fty)
         }
     }
 
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 1c0881b6ed5..074a0a565ae 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -81,7 +81,7 @@ use core::prelude::*;
 use middle::const_eval;
 use middle::pat_util::pat_id_map;
 use middle::pat_util;
-use middle::ty::{TyVid, Vid, FnTyBase, FnMeta, FnSig, VariantInfo_, field};
+use middle::ty::{TyVid, Vid, FnSig, VariantInfo_, field};
 use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
 use middle::ty::{re_bound, br_cap_avoid, substs, arg, param_ty};
 use middle::ty;
@@ -90,7 +90,6 @@ use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
 use middle::typeck::astconv;
 use middle::typeck::check::_match::pat_ctxt;
 use middle::typeck::check::method::TransformTypeNormally;
-use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_ty;
 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
 use middle::typeck::check::vtable::{LocationInfo, VtableContext};
 use middle::typeck::crate_ctxt;
@@ -248,8 +247,9 @@ pub fn check_bare_fn(ccx: @crate_ctxt,
                      self_info: Option<self_info>) {
     let fty = ty::node_id_to_type(ccx.tcx, id);
     match ty::get(fty).sty {
-        ty::ty_fn(ref fn_ty) => {
-            check_fn(ccx, self_info, fn_ty, decl, body, Vanilla, None)
+        ty::ty_bare_fn(ref fn_ty) => {
+            check_fn(ccx, self_info, fn_ty.purity, None,
+                     &fn_ty.sig, decl, body, Vanilla, None)
         }
         _ => ccx.tcx.sess.impossible_case(body.span,
                                  "check_bare_fn: function type expected")
@@ -258,12 +258,14 @@ pub fn check_bare_fn(ccx: @crate_ctxt,
 
 pub fn check_fn(ccx: @crate_ctxt,
                 self_info: Option<self_info>,
-                fn_ty: &ty::FnTy,
+                purity: ast::purity,
+                sigil: Option<ast::Sigil>,
+                fn_sig: &ty::FnSig,
                 decl: &ast::fn_decl,
                 body: ast::blk,
                 fn_kind: FnKind,
-                old_fcx: Option<@fn_ctxt>) {
-
+                old_fcx: Option<@fn_ctxt>)
+{
     let tcx = ccx.tcx;
     let indirect_ret = match fn_kind {
         ForLoop => true, _ => false
@@ -277,7 +279,7 @@ pub fn check_fn(ccx: @crate_ctxt,
     let {isr, self_info, fn_sig} = {
         let old_isr = option::map_default(&old_fcx, @Nil,
                                           |fcx| fcx.in_scope_regions);
-        replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, &fn_ty.sig,
+        replace_bound_regions_in_fn_sig(tcx, old_isr, self_info, fn_sig,
                                         |br| ty::re_free(body.node.id, br))
     };
 
@@ -294,13 +296,10 @@ pub fn check_fn(ccx: @crate_ctxt,
     // in the case of function expressions, based on the outer context.
     let fcx: @fn_ctxt = {
         let (purity, inherited) = match old_fcx {
-            None => {
-                (fn_ty.meta.purity,
-                 blank_inherited(ccx))
-            }
+            None => (purity, blank_inherited(ccx)),
             Some(fcx) => {
-                (ty::determine_inherited_purity(fcx.purity, fn_ty.meta.purity,
-                                                fn_ty.meta.proto),
+                (ty::determine_inherited_purity(fcx.purity, purity,
+                                                sigil.get()),
                  fcx.inh)
             }
         };
@@ -1092,8 +1091,9 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
         in_fty: ty::t,
         callee_expr: @ast::expr,
         args: ~[@ast::expr],
-        deref_args: DerefArgs) -> {fty: ty::t, bot: bool} {
-
+        sugar: ast::CallSugar,
+        deref_args: DerefArgs) -> (ty::t, bool)
+    {
         let tcx = fcx.ccx.tcx;
         let mut bot = false;
 
@@ -1103,62 +1103,72 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
         debug!("check_call_inner: before universal quant., in_fty=%s",
                fcx.infcx().ty_to_str(in_fty));
 
-        let mut formal_tys;
+        let formal_tys;
 
         // This is subtle: we expect `fty` to be a function type, which
         // normally introduce a level of binding.  In this case, we want to
         // process the types bound by the function but not by any nested
         // functions.  Therefore, we match one level of structure.
-        let fty =
-            match structure_of(fcx, sp, in_fty) {
-              ty::ty_fn(ref fn_ty) => {
-                  let fn_ty =
-                    /*bad*/copy replace_bound_regions_in_fn_ty(tcx, @Nil,
-                      None, fn_ty, |_br| fcx.infcx().next_region_var(sp,
-                                                      call_expr_id)).fn_ty;
-
-                  let supplied_arg_count = args.len();
-
-                  bot |= ty::type_is_bot(fn_ty.sig.output);
-
-                  // Grab the argument types, supplying fresh type variables
-                  // if the wrong number of arguments were supplied
-                  let expected_arg_count = fn_ty.sig.inputs.len();
-                  formal_tys = if expected_arg_count == supplied_arg_count {
-                      fn_ty.sig.inputs.map(|a| a.ty)
-                  } else {
-                      tcx.sess.span_err(
-                          sp, fmt!("this function takes %u parameter%s but \
-                                    %u parameter%s supplied",
+        let ret_ty = match structure_of(fcx, sp, in_fty) {
+            ty::ty_bare_fn(ty::BareFnTy {sig: ref sig, _}) |
+            ty::ty_closure(ty::ClosureTy {sig: ref sig, _}) => {
+                let {fn_sig: sig, _} =
+                    replace_bound_regions_in_fn_sig(
+                        tcx, @Nil, None, sig,
+                        |_br| fcx.infcx().next_region_var(
+                            sp, call_expr_id));
+
+                let supplied_arg_count = args.len();
+
+                bot |= ty::type_is_bot(sig.output);
+
+                // Grab the argument types, supplying fresh type variables
+                // if the wrong number of arguments were supplied
+                let expected_arg_count = sig.inputs.len();
+                formal_tys = if expected_arg_count == supplied_arg_count {
+                    sig.inputs.map(|a| a.ty)
+                } else {
+                    let suffix = match sugar {
+                        ast::NoSugar => "",
+                        ast::DoSugar => " (including the closure passed by \
+                                         the `do` keyword)",
+                        ast::ForSugar => " (including the closure passed by \
+                                          the `for` keyword)"
+                    };
+                    let msg = fmt!("this function takes %u parameter%s but \
+                                    %u parameter%s supplied%s",
                                    expected_arg_count,
-                                   if expected_arg_count == 1 {
-                                       ~""
-                                   } else {
-                                       ~"s"
-                                   },
+                                   if expected_arg_count == 1 {""}
+                                   else {"s"},
                                    supplied_arg_count,
-                                   if supplied_arg_count == 1 {
-                                       ~" was"
-                                   } else {
-                                       ~"s were"
-                                   }));
-                      fcx.infcx().next_ty_vars(supplied_arg_count)
-                  };
-                  ty::mk_fn(tcx, fn_ty)
-              }
-              _ => {
-                  fcx.type_error_message(sp, |actual| {
-                      fmt!("expected function or foreign function but \
-                            found `%s`", actual) }, in_fty, None);
-                  // check each arg against "error", in order to set up
-                  // all the node type bindings
-                  formal_tys = args.map(|_x| ty::mk_err(tcx));
-                  ty::mk_err(tcx)
-              }
-            };
+                                   if supplied_arg_count == 1 {" was"}
+                                   else {"s were"},
+                                   suffix);
 
-        debug!("check_call_inner: after universal quant., fty=%s",
-               fcx.infcx().ty_to_str(fty));
+                    tcx.sess.span_err(sp, msg);
+
+                    vec::from_fn(expected_arg_count, |_| ty::mk_err(tcx))
+                };
+
+                sig.output
+            }
+
+            _ => {
+                fcx.type_error_message(sp, |actual| {
+                    fmt!("expected function or foreign function but \
+                          found `%s`", actual) }, in_fty, None);
+
+                // check each arg against "error", in order to set up
+                // all the node type bindings
+                formal_tys = args.map(|_x| ty::mk_err(tcx));
+                ty::mk_err(tcx)
+            }
+        };
+
+        debug!("check_call_inner: after universal quant., \
+                formal_tys=%? ret_ty=%s",
+               formal_tys.map(|t| fcx.infcx().ty_to_str(*t)),
+               fcx.infcx().ty_to_str(ret_ty));
 
         // Check the arguments.
         // We do this in a pretty awful way: first we typecheck any arguments
@@ -1209,7 +1219,7 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
             }
         }
 
-        {fty: fty, bot: bot}
+        (ret_ty, bot)
     }
 
     // A generic function for checking assignment expressions
@@ -1233,36 +1243,26 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
                             fn_ty: ty::t,
                             expr: @ast::expr,
                             +args: ~[@ast::expr],
-                            bot: bool)
-                         -> bool {
+                            bot: bool,
+                            sugar: ast::CallSugar) -> bool
+    {
         let mut bot = bot;
 
         // Call the generic checker.
-        let fty = {
-            let r = check_call_inner(fcx, sp, call_expr_id,
-                                     fn_ty, expr, args, DontDerefArgs);
-            bot |= r.bot;
-            r.fty
-        };
+        let (ret_ty, b) = check_call_inner(fcx, sp, call_expr_id,
+                                           fn_ty, expr, args, sugar,
+                                           DontDerefArgs);
+        bot |= b;
 
         // Pull the return type out of the type of the function.
-        match structure_of(fcx, sp, fty) {
-          ty::ty_fn(ref f) => {
-              fcx.write_ty(call_expr_id, f.sig.output);
-              return bot;
-          }
-          _ => {
-              fcx.write_ty(call_expr_id, ty::mk_err(fcx.ccx.tcx));
-              fcx.type_error_message(sp, |_actual| {
-                  ~"expected function"}, fty, None);
-              return bot;
-          }
-        }
+        fcx.write_ty(call_expr_id, ret_ty);
+        return bot;
     }
 
     // A generic function for doing all of the checking for call expressions
     fn check_call(fcx: @fn_ctxt, sp: span, call_expr_id: ast::node_id,
-                  f: @ast::expr, +args: ~[@ast::expr]) -> bool {
+                  f: @ast::expr, +args: ~[@ast::expr],
+                  sugar: ast::CallSugar) -> bool {
         // Index expressions need to be handled separately, to inform them
         // that they appear in call position.
         let mut bot = match /*bad*/copy f.node {
@@ -1278,7 +1278,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
                              fcx.expr_ty(f),
                              f,
                              args,
-                             bot)
+                             bot,
+                             sugar)
     }
 
     // Checks a method call.
@@ -1287,7 +1288,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
                          rcvr: @ast::expr,
                          method_name: ast::ident,
                          +args: ~[@ast::expr],
-                         tps: ~[@ast::Ty])
+                         tps: ~[@ast::Ty],
+                         sugar: ast::CallSugar)
                       -> bool {
         let bot = check_expr(fcx, rcvr);
         let expr_t = structurally_resolved_type(fcx,
@@ -1329,7 +1331,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
                              fcx.node_ty(expr.callee_id),
                              expr,
                              args,
-                             bot)
+                             bot,
+                             sugar)
     }
 
     // A generic function for checking for or for-each loops
@@ -1378,13 +1381,11 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
                              op_ex.callee_id, opname, self_t, ~[],
                              deref_args) {
           Some(ref origin) => {
-            let {fty: method_ty, bot: bot} = {
-                let method_ty = fcx.node_ty(op_ex.callee_id);
-                check_call_inner(fcx, op_ex.span, op_ex.id,
-                                 method_ty, op_ex, args, deref_args)
-            };
-            fcx.ccx.method_map.insert(op_ex.id, (*origin));
-            Some((ty::ty_fn_ret(method_ty), bot))
+              let method_ty = fcx.node_ty(op_ex.callee_id);
+              fcx.ccx.method_map.insert(op_ex.id, *origin);
+              Some(check_call_inner(fcx, op_ex.span, op_ex.id,
+                                    method_ty, op_ex, args,
+                                    ast::NoSugar, deref_args))
           }
           _ => None
         }
@@ -1472,13 +1473,14 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
         // If the or operator is used it might be that the user forgot to
         // supply the do keyword.  Let's be more helpful in that situation.
         if op == ast::or {
-          match ty::get(lhs_resolved_t).sty {
-            ty::ty_fn(_) => {
-              tcx.sess.span_note(
-                  ex.span, ~"did you forget the `do` keyword for the call?");
+            match ty::get(lhs_resolved_t).sty {
+                ty::ty_bare_fn(_) | ty::ty_closure(_) => {
+                    tcx.sess.span_note(
+                        ex.span, ~"did you forget the `do` keyword \
+                                   for the call?");
+                }
+                _ => ()
             }
-            _ => ()
-          }
         }
 
         (lhs_resolved_t, false)
@@ -1523,7 +1525,7 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
 
     fn check_expr_fn(fcx: @fn_ctxt,
                      expr: @ast::expr,
-                     ast_proto_opt: Option<ast::Proto>,
+                     ast_sigil_opt: Option<ast::Sigil>,
                      decl: &ast::fn_decl,
                      body: ast::blk,
                      fn_kind: FnKind,
@@ -1534,50 +1536,44 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
         // avoid capture of bound regions in the expected type.  See
         // def'n of br_cap_avoid() for a more lengthy explanation of
         // what's going on here.
-        // Also try to pick up inferred purity and proto, defaulting
+        // Also try to pick up inferred purity and sigil, defaulting
         // to impure and block. Note that we only will use those for
         // block syntax lambdas; that is, lambdas without explicit
-        // protos.
+        // sigils.
         let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
         let (expected_tys,
              expected_purity,
-             expected_proto,
+             expected_sigil,
              expected_onceness) = {
             match expected_sty {
-                Some(ty::ty_fn(ref fn_ty)) => {
+                Some(ty::ty_closure(ref cenv)) => {
                     let id = expr.id;
-                    let {fn_ty: fn_ty, _} =
-                        replace_bound_regions_in_fn_ty(
-                            tcx, @Nil, None, fn_ty,
+                    let {fn_sig: sig, _} =
+                        replace_bound_regions_in_fn_sig(
+                            tcx, @Nil, None, &cenv.sig,
                             |br| ty::re_bound(ty::br_cap_avoid(id, @br)));
-                    (Some({inputs: /*bad*/copy fn_ty.sig.inputs,
-                           output: fn_ty.sig.output}),
-                     fn_ty.meta.purity,
-                     fn_ty.meta.proto,
-                     fn_ty.meta.onceness)
+                    (Some(sig), cenv.purity, cenv.sigil, cenv.onceness)
                 }
                 _ => {
-                    (None, ast::impure_fn, ast::ProtoBorrowed, ast::Many)
+                    (None, ast::impure_fn, ast::BorrowedSigil, ast::Many)
                 }
             }
         };
 
         // If the proto is specified, use that, otherwise select a
         // proto based on inference.
-        let (proto, purity) = match ast_proto_opt {
+        let (sigil, purity) = match ast_sigil_opt {
             Some(p) => (p, ast::impure_fn),
-            None => (expected_proto, expected_purity)
+            None => (expected_sigil, expected_purity)
         };
 
         // construct the function type
-        let mut fn_ty = astconv::ty_of_fn_decl(
+        let mut fn_ty = astconv::ty_of_closure(
             fcx, fcx,
-            proto, purity, expected_onceness,
-            /*bounds:*/ @~[], /*opt_region:*/ None,
-            *decl, expected_tys, expr.span);
+            sigil, purity, expected_onceness,
+            None, *decl, expected_tys, expr.span);
 
-        // XXX: Bad copy.
-        let fty = ty::mk_fn(tcx, copy fn_ty);
+        let fty = ty::mk_closure(tcx, copy fn_ty);
 
         debug!("check_expr_fn_with_unifier %s fty=%s",
                fcx.expr_to_str(expr),
@@ -1587,8 +1583,8 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
 
         // We inherit the same self info as the enclosing scope,
         // since the function we're checking might capture `self`
-        check_fn(fcx.ccx, fcx.self_info, &fn_ty, decl, body,
-                 fn_kind, Some(fcx));
+        check_fn(fcx.ccx, fcx.self_info, fn_ty.purity, Some(fn_ty.sigil),
+                 &fn_ty.sig, decl, body, fn_kind, Some(fcx));
     }
 
 
@@ -1913,6 +1909,119 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
         return bot;
     }
 
+    fn check_loop_body(fcx: @fn_ctxt,
+                       expr: @ast::expr,
+                       expected: Option<ty::t>,
+                       loop_body: @ast::expr)
+    {
+        // a loop body is the special argument to a `for` loop.  We know that
+        // there will be an expected type in this context because it can only
+        // appear in the context of a call, so we get the expected type of the
+        // parameter. The catch here is that we need to validate two things:
+        // 1. a closure that returns a bool is expected
+        // 2. the closure that was given returns unit
+        let tcx = fcx.tcx();
+        let mut err_happened = false;
+        let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
+        let inner_ty = match expected_sty {
+            Some(ty::ty_closure(ref fty)) => {
+                match fcx.mk_subty(false, expr.span,
+                                   fty.sig.output, ty::mk_bool(tcx)) {
+                    result::Ok(_) => {
+                        ty::mk_closure(tcx, ty::ClosureTy {
+                            sig: FnSig {output: ty::mk_nil(tcx),
+                                        ..copy fty.sig},
+                            ..copy *fty
+                        })
+                    }
+                    result::Err(_) => {
+                        fcx.type_error_message(
+                            expr.span,
+                            |actual| {
+                                let did_you_mean = {
+                                    if ty::type_is_nil(fty.sig.output) {
+                                        "\nDid you mean to use \
+                                             `do` instead of `for`?"
+                                     } else {
+                                         ""
+                                     }
+                                };
+                                fmt!("A `for` loop iterator should expect a \
+                                      closure that returns `bool`. This \
+                                      iterator expects a closure that \
+                                      returns `%s`.%s",
+                                     actual, did_you_mean)
+                            },
+                            fty.sig.output,
+                            None);
+                        err_happened = true;
+
+                        // Kind of a hack: create a function type with
+                        // the result replaced with ty_err, to
+                        // suppress derived errors.
+                        let t = ty::replace_closure_return_type(
+                            tcx, ty::mk_closure(tcx, copy *fty),
+                            ty::mk_err(tcx));
+                        fcx.write_ty(expr.id, ty::mk_err(tcx));
+                        t
+                    }
+                }
+            }
+            _ => {
+                match expected {
+                    Some(expected_t) => {
+                        fcx.type_error_message(
+                            expr.span,
+                            |actual| {
+                                fmt!("last argument in `for` call \
+                                      has non-closure type: %s",
+                                     actual)
+                            },
+                            expected_t, None);
+                        let err_ty = ty::mk_err(tcx);
+                        fcx.write_ty(expr.id, err_ty);
+                        err_happened = true;
+                        err_ty
+                    }
+                    None => fcx.tcx().sess.impossible_case(
+                        expr.span,
+                        ~"loop body must have an expected type")
+                }
+            }
+        };
+
+        match loop_body.node {
+            ast::expr_fn_block(ref decl, ref body) => {
+                // If an error occurred, we pretend this isn't a for
+                // loop, so as to assign types to all nodes while also
+                // propagating ty_err throughout so as to suppress
+                // derived errors. If we passed in ForLoop in the
+                // error case, we'd potentially emit a spurious error
+                // message because of the indirect_ret_ty.
+                let fn_kind = if err_happened {Vanilla} else {ForLoop};
+                check_expr_fn(fcx, loop_body, None,
+                              decl, *body, fn_kind, Some(inner_ty));
+                demand::suptype(fcx, loop_body.span,
+                                inner_ty, fcx.expr_ty(loop_body));
+            }
+            ref n => {
+                die!(fmt!(
+                    "check_loop_body expected expr_fn_block, not %?", n))
+            }
+        }
+
+        let block_ty = structurally_resolved_type(
+            fcx, expr.span, fcx.node_ty(loop_body.id));
+        if err_happened {
+            fcx.write_ty(expr.id, ty::mk_err(fcx.tcx()));
+        } else {
+            let loop_body_ty =
+                ty::replace_closure_return_type(
+                    tcx, block_ty, ty::mk_bool(tcx));
+            fcx.write_ty(expr.id, loop_body_ty);
+        }
+    }
+
     let tcx = fcx.ccx.tcx;
     let id = expr.id;
     let mut bot = false;
@@ -2153,121 +2262,38 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
       ast::expr_match(discrim, ref arms) => {
         bot = _match::check_match(fcx, expr, discrim, (/*bad*/copy *arms));
       }
-      ast::expr_fn(proto, ref decl, ref body, _) => {
-        check_expr_fn(fcx, expr, Some(proto),
+      ast::expr_fn(sigil, ref decl, ref body, _) => {
+        check_expr_fn(fcx, expr, Some(sigil),
                       decl, (*body), Vanilla, expected);
       }
       ast::expr_fn_block(ref decl, ref body) => {
         check_expr_fn(fcx, expr, None,
                       decl, (*body), Vanilla, expected);
       }
-      ast::expr_loop_body(b) => {
-        // a loop body is the special argument to a `for` loop.  We know that
-        // there will be an expected type in this context because it can only
-        // appear in the context of a call, so we get the expected type of the
-        // parameter. The catch here is that we need to validate two things:
-        // 1. a closure that returns a bool is expected
-        // 2. the closure that was given returns unit
-        let mut err_happened = false;
-        let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
-        let inner_ty = match expected_sty {
-          Some(ty::ty_fn(ref fty)) => {
-            match fcx.mk_subty(false, expr.span,
-                               (*fty).sig.output, ty::mk_bool(tcx)) {
-              result::Ok(_) =>
-                  ty::mk_fn(tcx, FnTyBase {
-                      meta: (*fty).meta,
-                      sig: FnSig {output: ty::mk_nil(tcx),
-                                  ../*bad*/copy (*fty).sig}
-                  }),
-              result::Err(_) => {
-                   fcx.type_error_message(expr.span,
-                      |actual| {
-                          fmt!("A `for` loop iterator should expect a \
-                                closure that returns `bool`. This iterator \
-                                expects a closure that returns `%s`. %s",
-                               actual, if ty::type_is_nil((*fty).sig.output) {
-                                   "\nDid you mean to use `do` instead of \
-                                        `for`?" } else { "" } )
-                      },
-                      (*fty).sig.output, None);
-                err_happened = true;
-                // Kind of a hack: create a function type with the result
-                // replaced with ty_err, to suppress derived errors.
-                let t = ty::replace_fn_return_type(tcx, ty::mk_fn(tcx,
-                                                                  copy *fty),
-                                                   ty::mk_err(tcx));
-                fcx.write_ty(id, ty::mk_err(tcx));
-                t
-              }
-            }
-          }
-          _ =>
-              match expected {
-                  Some(expected_t) => {
-                      fcx.type_error_message(expr.span, |actual| {
-                          fmt!("a `loop` function's last \
-                                argument should be of function \
-                                type, not `%s`",
-                               actual)
-                      },
-                                             expected_t, None);
-                      let err_ty = ty::mk_err(tcx);
-                      fcx.write_ty(id, err_ty);
-                      err_happened = true;
-                      err_ty
-                  }
-                  None => fcx.tcx().sess.impossible_case(expr.span,
-                            ~"loop body must have an expected type")
-              }
-        };
-        match b.node {
-                ast::expr_fn_block(ref decl, ref body) => {
-                    // If an error occurred, we pretend this isn't a for
-                    // loop, so as to assign types to all nodes while also
-                    // propagating ty_err throughout so as to suppress
-                    // derived errors. If we passed in ForLoop in the
-                    // error case, we'd potentially emit a spurious error
-                    // message because of the indirect_ret_ty.
-                    let fn_kind = if err_happened { Vanilla }
-                                  else { ForLoop };
-                    check_expr_fn(fcx, b, None,
-                                  decl, *body, fn_kind, Some(inner_ty));
-                    demand::suptype(fcx, b.span, inner_ty, fcx.expr_ty(b));
-                }
-                // argh
-                _ => die!(~"expr_fn_block")
-        }
-        let block_ty = structurally_resolved_type(
-            fcx, expr.span, fcx.node_ty(b.id));
-        if err_happened {
-            fcx.write_ty(expr.id, ty::mk_err(fcx.tcx()));
-        } else {
-            let loop_body_ty = ty::replace_fn_return_type(tcx, block_ty,
-                                                          ty::mk_bool(tcx));
-            fcx.write_ty(expr.id, loop_body_ty);
-        }
+      ast::expr_loop_body(loop_body) => {
+          check_loop_body(fcx, expr, expected, loop_body);
       }
       ast::expr_do_body(b) => {
         let expected_sty = unpack_expected(fcx, expected, |x| Some(copy *x));
         let inner_ty = match expected_sty {
-          Some(ty::ty_fn(ref fty)) => {
-              ty::mk_fn(tcx, (/*bad*/copy *fty))
-          }
-          _ => match expected {
-                  Some(expected_t) => {
-                      fcx.type_error_message(expr.span, |_actual| {
-                          ~"Non-function passed to a `do` \
-                            function as its last argument, or wrong number \
-                            of arguments passed to a `do` function"
-                      }, expected_t, None);
-                      let err_ty = ty::mk_err(tcx);
-                      fcx.write_ty(id, err_ty);
-                      err_ty
-                  }
-                  None => fcx.tcx().sess.impossible_case(expr.span,
-                              ~"do body must have expected type")
-              }
+            Some(ty::ty_closure(_)) => expected.get(),
+            _ => match expected {
+                Some(expected_t) => {
+                    fcx.type_error_message(expr.span, |actual| {
+                        fmt!("last argument in `do` call \
+                              has non-closure type: %s",
+                             actual)
+                    }, expected_t, None);
+                    let err_ty = ty::mk_err(tcx);
+                    fcx.write_ty(id, err_ty);
+                    err_ty
+                }
+                None => {
+                    fcx.tcx().sess.impossible_case(
+                        expr.span,
+                        ~"do body must have expected type")
+                }
+            }
         };
         match b.node {
           ast::expr_fn_block(ref decl, ref body) => {
@@ -2290,11 +2316,11 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
             };
         fcx.write_ty(id, typ);
       }
-      ast::expr_call(f, args, _) => {
-        bot = check_call(fcx, expr.span, expr.id, f, args);
+      ast::expr_call(f, args, sugar) => {
+        bot = check_call(fcx, expr.span, expr.id, f, args, sugar);
       }
-      ast::expr_method_call(rcvr, ident, tps, args, _) => {
-        bot = check_method_call(fcx, expr, rcvr, ident, args, tps);
+      ast::expr_method_call(rcvr, ident, tps, args, sugar) => {
+        bot = check_method_call(fcx, expr, rcvr, ident, args, tps, sugar);
       }
       ast::expr_cast(e, t) => {
         bot = check_expr(fcx, e);
@@ -3088,20 +3114,18 @@ pub fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
                  arg(ast::by_ref, visitor_trait)], ty::mk_nil(tcx))
       }
       ~"frame_address" => {
-        let fty = ty::mk_fn(ccx.tcx, FnTyBase {
-            meta: FnMeta {purity: ast::impure_fn,
-                          proto: ast::ProtoBorrowed,
-                          onceness: ast::Once,
-                          region: ty::re_bound(ty::br_anon(0)),
-                          bounds: @~[]},
-            sig: FnSig {
-                inputs: ~[arg {
-                    mode: ast::expl(ast::by_val),
-                    ty: ty::mk_imm_ptr(
-                        ccx.tcx,
-                        ty::mk_mach_uint(ccx.tcx, ast::ty_u8))
-                }],
-                output: ty::mk_nil(ccx.tcx)}
+        let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
+            purity: ast::impure_fn,
+            sigil: ast::BorrowedSigil,
+            onceness: ast::Once,
+            region: ty::re_bound(ty::br_anon(0)),
+            sig: ty::FnSig {
+                inputs: ~[arg {mode: ast::expl(ast::by_val),
+                               ty: ty::mk_imm_ptr(
+                                   ccx.tcx,
+                                   ty::mk_mach_uint(ccx.tcx, ast::ty_u8))}],
+                output: ty::mk_nil(ccx.tcx)
+            }
         });
         (0u, ~[arg(ast::by_ref, fty)], ty::mk_nil(tcx))
       }
@@ -3324,12 +3348,9 @@ pub fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
         return;
       }
     };
-    let fty = ty::mk_fn(tcx, FnTyBase {
-        meta: FnMeta {purity: ast::unsafe_fn,
-                      proto: ast::ProtoBare,
-                      onceness: ast::Many,
-                      region: ty::re_static,
-                      bounds: @~[]},
+    let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
+        purity: ast::unsafe_fn,
+        abi: ast::RustAbi,
         sig: FnSig {inputs: inputs,
                     output: output}
     });
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 952c1a9fcd8..9dfaaeebc8f 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -32,7 +32,7 @@ use core::prelude::*;
 use middle::freevars::get_freevars;
 use middle::pat_util::{pat_bindings, pat_is_binding};
 use middle::ty::{encl_region, re_scope};
-use middle::ty::{ty_fn_proto, vstore_box, vstore_fixed, vstore_slice};
+use middle::ty::{vstore_box, vstore_fixed, vstore_slice};
 use middle::ty::{vstore_uniq};
 use middle::ty;
 use middle::typeck::check::fn_ctxt;
@@ -42,7 +42,7 @@ use middle::typeck::infer::{resolve_type};
 use util::ppaux::{note_and_explain_region, ty_to_str};
 
 use core::result;
-use syntax::ast::{ProtoBare, ProtoBox, ProtoUniq, ProtoBorrowed};
+use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil};
 use syntax::ast::{def_arg, def_binding, def_local, def_self, def_upvar};
 use syntax::ast;
 use syntax::codemap::span;
@@ -59,10 +59,9 @@ pub fn encl_region_of_def(fcx: @fn_ctxt, def: ast::def) -> ty::Region {
         def_self(node_id, _) | def_binding(node_id, _) =>
             return encl_region(tcx, node_id),
         def_upvar(_, subdef, closure_id, body_id) => {
-            match ty_fn_proto(fcx.node_ty(closure_id)) {
-                ProtoBare => tcx.sess.bug(~"ProtoBare with upvars?!"),
-                ProtoBorrowed => encl_region_of_def(fcx, *subdef),
-                ProtoBox | ProtoUniq => re_scope(body_id)
+            match ty::ty_closure_sigil(fcx.node_ty(closure_id)) {
+                BorrowedSigil => encl_region_of_def(fcx, *subdef),
+                ManagedSigil | OwnedSigil => re_scope(body_id)
             }
         }
         _ => {
@@ -278,11 +277,9 @@ pub fn visit_expr(expr: @ast::expr, &&rcx: @rcx, v: rvt) {
         ast::expr_fn(*) | ast::expr_fn_block(*) => {
             let function_type = rcx.resolve_node_type(expr.id);
             match ty::get(function_type).sty {
-                ty::ty_fn(ref fn_ty) => {
-                    if fn_ty.meta.proto == ast::ProtoBorrowed {
-                        constrain_free_variables(
-                            rcx, fn_ty.meta.region, expr);
-                    }
+                ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
+                                              region: region, _}) => {
+                    constrain_free_variables(rcx, region, expr);
                 }
                 _ => ()
             }
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index 8ea35824e32..f0956df545c 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -12,7 +12,6 @@
 
 use core::prelude::*;
 
-use middle::ty::{FnTyBase};
 use middle::ty;
 use middle::typeck::check::self_info;
 use middle::typeck::isr_alist;
@@ -27,22 +26,6 @@ use syntax::print::pprust::{expr_to_str};
 
 // Helper functions related to manipulating region types.
 
-pub fn replace_bound_regions_in_fn_ty(
-    tcx: ty::ctxt,
-    isr: isr_alist,
-    self_info: Option<self_info>,
-    fn_ty: &ty::FnTy,
-    mapf: fn(ty::bound_region) -> ty::Region) ->
-    {isr: isr_alist, self_info: Option<self_info>, fn_ty: ty::FnTy} {
-    let {isr, self_info, fn_sig} =
-        replace_bound_regions_in_fn_sig(
-            tcx, isr, self_info, &fn_ty.sig, mapf);
-    {isr: isr,
-     self_info: self_info,
-     fn_ty: FnTyBase {meta: fn_ty.meta,
-                      sig: fn_sig}}
-}
-
 pub fn replace_bound_regions_in_fn_sig(
     tcx: ty::ctxt,
     isr: isr_alist,
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 9f2af3ec003..abd4697eb31 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -233,7 +233,7 @@ pub fn lookup_vtable(vcx: &VtableContext,
             relate_trait_tys(vcx, location_info, trait_ty, ty);
             if !allow_unsafe && !is_early {
                 for vec::each(*ty::trait_methods(tcx, did)) |m| {
-                    if ty::type_has_self(ty::mk_fn(tcx, /*bad*/copy m.fty)) {
+                    if ty::type_has_self(ty::mk_bare_fn(tcx, copy m.fty)) {
                         tcx.sess.span_err(
                             location_info.span,
                             ~"a boxed trait with self types may not be \
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 324cdcc261f..8fc8c4f6cbb 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -26,10 +26,10 @@ use middle::resolve::{Impl, MethodInfo};
 use middle::ty::{ProvidedMethodSource, ProvidedMethodInfo, bound_copy, get};
 use middle::ty::{kind_can_be_copied, lookup_item_type, param_bounds, subst};
 use middle::ty::{substs, t, ty_bool, ty_bot, ty_box, ty_enum, ty_err};
-use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_infer, ty_int, ty_nil};
+use middle::ty::{ty_estr, ty_evec, ty_float, ty_infer, ty_int, ty_nil};
 use middle::ty::{ty_opaque_box, ty_param, ty_param_bounds_and_ty, ty_ptr};
 use middle::ty::{ty_rec, ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
-use middle::ty::{ty_type, ty_uint, ty_uniq};
+use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure};
 use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec, type_kind_ext};
 use middle::ty::{type_is_ty_var};
 use middle::ty;
@@ -108,7 +108,7 @@ pub fn get_base_type(inference_context: @InferCtxt,
 
         ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) |
         ty_estr(*) | ty_evec(*) | ty_rec(*) |
-        ty_fn(*) | ty_tup(*) | ty_infer(*) |
+        ty_bare_fn(*) | ty_closure(*) | ty_tup(*) | ty_infer(*) |
         ty_param(*) | ty_self | ty_type | ty_opaque_box |
         ty_opaque_closure_ptr(*) | ty_unboxed_vec(*) | ty_err => {
             debug!("(getting base type) no base type; found %?",
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index b7b7899883b..120fd89e5eb 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -33,10 +33,10 @@ are represented as `ty_param()` instances.
 use core::prelude::*;
 
 use metadata::csearch;
-use middle::ty::{FnMeta, FnSig, FnTyBase, InstantiatedTraitRef, arg};
+use middle::ty::{InstantiatedTraitRef, arg};
 use middle::ty::{substs, ty_param_substs_and_ty};
 use middle::ty;
-use middle::typeck::astconv::{ast_conv, ty_of_fn_decl, ty_of_arg};
+use middle::typeck::astconv::{ast_conv, ty_of_arg};
 use middle::typeck::astconv::{ast_ty_to_ty};
 use middle::typeck::astconv;
 use middle::typeck::infer;
@@ -153,9 +153,10 @@ pub impl @crate_ctxt: ast_conv {
 
 pub fn get_enum_variant_types(ccx: @crate_ctxt,
                               enum_ty: ty::t,
-                              variants: ~[ast::variant],
-                              ty_params: ~[ast::ty_param],
-                              rp: Option<ty::region_variance>) {
+                              variants: &[ast::variant],
+                              ty_params: &[ast::ty_param],
+                              rp: Option<ty::region_variance>)
+{
     let tcx = ccx.tcx;
 
     // Create a set of parameter types shared among all the variants.
@@ -166,58 +167,35 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt,
         match variant.node.kind {
             ast::tuple_variant_kind(ref args) if args.len() > 0 => {
                 let rs = type_rscope(rp);
-                let args = args.map(|va| {
-                    let arg_ty = ccx.to_ty(rs, va.ty);
-                    arg { mode: ast::expl(ast::by_copy), ty: arg_ty }
-                });
-                result_ty = Some(ty::mk_fn(tcx, FnTyBase {
-                    meta: FnMeta {purity: ast::pure_fn,
-                                  proto: ast::ProtoBare,
-                                  onceness: ast::Many,
-                                  bounds: @~[],
-                                  region: ty::re_static},
-                    sig: FnSig {inputs: args,
-                                output: enum_ty}
-                }));
+                let input_tys = args.map(|va| ccx.to_ty(rs, va.ty));
+                result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
             }
+
             ast::tuple_variant_kind(_) => {
                 result_ty = Some(enum_ty);
             }
+
             ast::struct_variant_kind(struct_def) => {
-                // XXX: Merge with computation of the the same value below?
-                let tpt = {
-                    bounds: ty_param_bounds(ccx, /*bad*/copy ty_params),
-                    region_param: rp,
-                    ty: enum_ty
-                };
-                convert_struct(
-                    ccx,
-                    rp,
-                    struct_def,
-                    /*bad*/copy ty_params,
-                    tpt,
-                    variant.node.id);
-                // Compute the ctor arg types from the struct fields
-                let struct_fields = do struct_def.fields.map |struct_field| {
-                    arg {
-                        mode: ast::expl(ast::by_val),
-                        ty: ty::node_id_to_type(ccx.tcx, struct_field.node.id)
-                    }
-                };
-                result_ty = Some(ty::mk_fn(tcx, FnTyBase {
-                    meta: FnMeta {purity: ast::pure_fn,
-                                  proto: ast::ProtoBare,
-                                  onceness: ast::Many,
-                                  bounds: @~[],
-                                  region: ty::re_static},
-                    sig: FnSig {inputs: struct_fields, output: enum_ty }}));
+                let tpt = {bounds: ty_param_bounds(ccx, ty_params),
+                           region_param: rp,
+                           ty: enum_ty};
+
+                convert_struct(ccx,
+                               rp,
+                               struct_def,
+                               ty_params.to_vec(),
+                               tpt,
+                               variant.node.id);
+
+                let input_tys = struct_def.fields.map(
+                    |f| ty::node_id_to_type(ccx.tcx, f.node.id));
+                result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
             }
+
             ast::enum_variant_kind(ref enum_definition) => {
-                get_enum_variant_types(ccx,
-                                       enum_ty,
-                                       /*bad*/copy enum_definition.variants,
-                                       /*bad*/copy ty_params,
-                                       rp);
+                get_enum_variant_types(ccx, enum_ty,
+                                       enum_definition.variants,
+                                       ty_params, rp);
                 result_ty = None;
             }
         };
@@ -225,11 +203,9 @@ pub fn get_enum_variant_types(ccx: @crate_ctxt,
         match result_ty {
             None => {}
             Some(result_ty) => {
-                let tpt = {
-                    bounds: ty_param_bounds(ccx, /*bad*/copy ty_params),
-                    region_param: rp,
-                    ty: result_ty
-                };
+                let tpt = {bounds: ty_param_bounds(ccx, ty_params),
+                           region_param: rp,
+                           ty: result_ty};
                 tcx.tcache.insert(local_def(variant.node.id), tpt);
                 write_ty_to_tcx(tcx, variant.node.id, result_ty);
             }
@@ -279,7 +255,7 @@ pub fn ensure_trait_methods(ccx: @crate_ctxt,
         };
         let ty = ty::subst(ccx.tcx,
                            &substs,
-                           ty::mk_fn(ccx.tcx, /*bad*/copy m.fty));
+                           ty::mk_bare_fn(ccx.tcx, copy m.fty));
         let bounds = @(*trait_bounds + ~[@~[ty::bound_trait(trait_ty)]]
                        + *m.tps);
         ccx.tcx.tcache.insert(local_def(am.id),
@@ -305,7 +281,7 @@ pub fn ensure_trait_methods(ccx: @crate_ctxt,
                 ast::provided(method) => def_id = local_def(method.id)
             }
 
-            let trait_bounds = ty_param_bounds(ccx, copy *params);
+            let trait_bounds = ty_param_bounds(ccx, *params);
             let ty_m = trait_method_to_ty_method(*m);
             let method_ty = ty_of_ty_method(ccx, ty_m, region_paramd, def_id);
             if ty_m.self_ty.node == ast::sty_static {
@@ -458,7 +434,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
     //   that correspond to the parameters we will find on the impl
     // - replace self region with a fresh, dummy region
     let impl_fty = {
-        let impl_fty = ty::mk_fn(tcx, /*bad*/copy impl_m.fty);
+        let impl_fty = ty::mk_bare_fn(tcx, copy impl_m.fty);
         debug!("impl_fty (pre-subst): %s", ppaux::ty_to_str(tcx, impl_fty));
         replace_bound_self(tcx, impl_fty, dummy_self_r)
     };
@@ -476,7 +452,7 @@ pub fn compare_impl_method(tcx: ty::ctxt,
             self_ty: Some(self_ty),
             tps: vec::append(trait_tps, dummy_tps)
         };
-        let trait_fty = ty::mk_fn(tcx, /*bad*/copy trait_m.fty);
+        let trait_fty = ty::mk_bare_fn(tcx, copy trait_m.fty);
         debug!("trait_fty (pre-subst): %s", ppaux::ty_to_str(tcx, trait_fty));
         ty::subst(tcx, &substs, trait_fty)
     };
@@ -583,9 +559,9 @@ pub fn convert_methods(ccx: @crate_ctxt,
 
     let tcx = ccx.tcx;
     do vec::map(ms) |m| {
-        let bounds = ty_param_bounds(ccx, /*bad*/copy m.tps);
+        let bounds = ty_param_bounds(ccx, m.tps);
         let mty = ty_of_method(ccx, *m, rp);
-        let fty = ty::mk_fn(tcx, /*bad*/copy mty.fty);
+        let fty = ty::mk_bare_fn(tcx, copy mty.fty);
         tcx.tcache.insert(
             local_def(m.id),
 
@@ -626,13 +602,11 @@ pub fn convert(ccx: @crate_ctxt, it: @ast::item) {
         ensure_no_ty_param_bounds(ccx, it.span, *ty_params, "enumeration");
         let tpt = ty_of_item(ccx, it);
         write_ty_to_tcx(tcx, it.id, tpt.ty);
-        get_enum_variant_types(ccx,
-                               tpt.ty,
-                               /*bad*/copy (*enum_definition).variants,
-                               /*bad*/copy *ty_params, rp);
+        get_enum_variant_types(ccx, tpt.ty, enum_definition.variants,
+                               *ty_params, rp);
       }
       ast::item_impl(ref tps, trait_ref, selfty, ref ms) => {
-        let i_bounds = ty_param_bounds(ccx, /*bad*/copy *tps);
+        let i_bounds = ty_param_bounds(ccx, *tps);
         let selfty = ccx.to_ty(type_rscope(rp), selfty);
         write_ty_to_tcx(tcx, it.id, selfty);
         tcx.tcache.insert(local_def(it.id),
@@ -695,13 +669,12 @@ pub fn convert_struct(ccx: @crate_ctxt,
 
     do option::iter(&struct_def.dtor) |dtor| {
         // Write the dtor type
-        let t_dtor = ty::mk_fn(
+        let t_dtor = ty::mk_bare_fn(
             tcx,
-            ty_of_fn_decl(
-                ccx, type_rscope(rp), ast::ProtoBare,
-                ast::impure_fn, ast::Many,
-                /*bounds:*/ @~[], /*opt_region:*/ None,
-                ast_util::dtor_dec(), None, dtor.span));
+            astconv::ty_of_bare_fn(
+                ccx, type_rscope(rp),
+                ast::impure_fn, ast::RustAbi,
+                ast_util::dtor_dec()));
         write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
         tcx.tcache.insert(local_def(dtor.node.id),
                           {bounds: tpt.bounds,
@@ -727,25 +700,11 @@ pub fn convert_struct(ccx: @crate_ctxt,
                 tcx.tcache.insert(local_def(ctor_id), tpt);
             } else if struct_def.fields[0].node.kind == ast::unnamed_field {
                 // Tuple-like.
-                let ctor_fn_ty = ty::mk_fn(tcx, FnTyBase {
-                    meta: FnMeta {
-                        purity: ast::pure_fn,
-                        proto: ast::ProtoBare,
-                        onceness: ast::Many,
-                        bounds: @~[],
-                        region: ty::re_static
-                    },
-                    sig: FnSig {
-                        inputs: do struct_def.fields.map |field| {
-                            arg {
-                                mode: ast::expl(ast::by_copy),
-                                ty: ccx.tcx.tcache.get
-                                        (&local_def(field.node.id)).ty
-                            }
-                        },
-                        output: selfty
-                    }
-                });
+                let inputs =
+                    struct_def.fields.map(
+                        |field| ccx.tcx.tcache.get(
+                            &local_def(field.node.id)).ty);
+                let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty);
                 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
                 tcx.tcache.insert(local_def(ctor_id), {
                     bounds: tpt.bounds,
@@ -770,11 +729,9 @@ pub fn ty_of_method(ccx: @crate_ctxt,
                     m: @ast::method,
                     rp: Option<ty::region_variance>) -> ty::method {
     {ident: m.ident,
-     tps: ty_param_bounds(ccx, /*bad*/copy m.tps),
-     fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::ProtoBare,
-                        m.purity, ast::Many,
-                        /*bounds:*/ @~[], /*opt_region:*/ None,
-                        m.decl, None, m.span),
+     tps: ty_param_bounds(ccx, m.tps),
+     fty: astconv::ty_of_bare_fn(ccx, type_rscope(rp), m.purity,
+                                 ast::RustAbi, m.decl),
      self_ty: m.self_ty.node,
      vis: m.vis,
      def_id: local_def(m.id)}
@@ -785,11 +742,9 @@ pub fn ty_of_ty_method(self: @crate_ctxt,
                        rp: Option<ty::region_variance>,
                        id: ast::def_id) -> ty::method {
     {ident: m.ident,
-     tps: ty_param_bounds(self, /*bad*/copy m.tps),
-     fty: ty_of_fn_decl(self, type_rscope(rp), ast::ProtoBare,
-                        m.purity, ast::Many,
-                        /*bounds:*/ @~[], /*opt_region:*/ None,
-                        m.decl, None, m.span),
+     tps: ty_param_bounds(self, m.tps),
+     fty: astconv::ty_of_bare_fn(self, type_rscope(rp), m.purity,
+                                 ast::RustAbi, m.decl),
      // assume public, because this is only invoked on trait methods
      self_ty: m.self_ty.node,
      vis: ast::public,
@@ -844,13 +799,11 @@ pub fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
       }
       ast::item_fn(decl, purity, tps, _) => {
         let bounds = ty_param_bounds(ccx, tps);
-        let tofd = ty_of_fn_decl(ccx, empty_rscope,
-                                 ast::ProtoBare, purity, ast::Many,
-                                 /*bounds:*/ @~[], /*opt_region:*/ None,
-                                 decl, None, it.span);
+        let tofd = astconv::ty_of_bare_fn(ccx, empty_rscope, purity,
+                                          ast::RustAbi, decl);
         let tpt = {bounds: bounds,
                    region_param: None,
-                   ty: ty::mk_fn(ccx.tcx, tofd)};
+                   ty: ty::mk_bare_fn(ccx.tcx, tofd)};
         debug!("type of %s (id %d) is %s",
                tcx.sess.str_of(it.ident),
                it.id,
@@ -976,7 +929,7 @@ pub fn compute_bounds(ccx: @crate_ctxt,
 }
 
 pub fn ty_param_bounds(ccx: @crate_ctxt,
-                       params: ~[ast::ty_param]) -> @~[ty::param_bounds] {
+                       params: &[ast::ty_param]) -> @~[ty::param_bounds] {
     @do params.map |param| {
         match ccx.tcx.ty_param_bounds.find(&param.id) {
           Some(bs) => bs,
@@ -999,15 +952,13 @@ pub fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
     let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, rb, *a, None) );
     let output_ty = ast_ty_to_ty(ccx, rb, decl.output);
 
-    let t_fn = ty::mk_fn(ccx.tcx, FnTyBase {
-        meta: FnMeta {purity: ast::unsafe_fn,
-                      onceness: ast::Many,
-                      proto: ast::ProtoBare,
-                      bounds: @~[],
-                      region: ty::re_static},
-        sig: FnSig {inputs: input_tys,
-                    output: output_ty}
-    });
+    let t_fn = ty::mk_bare_fn(
+        ccx.tcx,
+        ty::BareFnTy {
+            abi: ast::RustAbi,
+            purity: ast::unsafe_fn,
+            sig: ty::FnSig {inputs: input_tys, output: output_ty}
+        });
     let tpt = {bounds: bounds, region_param: None, ty: t_fn};
     ccx.tcx.tcache.insert(def_id, tpt);
     return tpt;
@@ -1017,8 +968,7 @@ pub fn mk_ty_params(ccx: @crate_ctxt, atps: ~[ast::ty_param])
     -> {bounds: @~[ty::param_bounds], params: ~[ty::t]} {
 
     let mut i = 0u;
-    // XXX: Bad copy.
-    let bounds = ty_param_bounds(ccx, copy atps);
+    let bounds = ty_param_bounds(ccx, atps);
     {bounds: bounds,
      params: vec::map(atps, |atp| {
          let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index f0fe2deffdf..5d291fdde77 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -69,7 +69,7 @@ use core::prelude::*;
 use middle::ty::{TyVar, AutoPtr, AutoBorrowVec, AutoBorrowFn};
 use middle::ty::{AutoAdjustment, AutoRef};
 use middle::ty::{vstore_slice, vstore_box, vstore_uniq, vstore_fixed};
-use middle::ty::{FnMeta, FnTyBase, mt};
+use middle::ty::{mt};
 use middle::ty;
 use middle::typeck::infer::{CoerceResult, resolve_type};
 use middle::typeck::infer::combine::CombineFields;
@@ -117,7 +117,7 @@ impl Coerce {
                 };
             }
 
-            ty::ty_fn(ref b_f) if b_f.meta.proto == ast::ProtoBorrowed => {
+            ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil, _}) => {
                 return do self.unpack_actual_value(a) |sty_a| {
                     self.coerce_borrowed_fn(a, sty_a, b)
                 };
@@ -134,7 +134,7 @@ impl Coerce {
 
         do self.unpack_actual_value(a) |sty_a| {
             match *sty_a {
-                ty::ty_fn(ref a_f) if a_f.meta.proto == ast::ProtoBare => {
+                ty::ty_bare_fn(ref a_f) => {
                     // Bare functions are coercable to any closure type.
                     //
                     // FIXME(#3320) this should go away and be
@@ -289,9 +289,9 @@ impl Coerce {
                b.inf_str(self.infcx));
 
         let fn_ty = match *sty_a {
-            ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBox => {f}
-            ty::ty_fn(ref f) if f.meta.proto == ast::ProtoUniq => {f}
-            ty::ty_fn(ref f) if f.meta.proto == ast::ProtoBare => {
+            ty::ty_closure(ref f) if f.sigil == ast::ManagedSigil => copy *f,
+            ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => copy *f,
+            ty::ty_bare_fn(ref f) => {
                 return self.coerce_from_bare_fn(a, f, b);
             }
             _ => {
@@ -300,12 +300,13 @@ impl Coerce {
         };
 
         let r_borrow = self.infcx.next_region_var_nb(self.span);
-        let meta = FnMeta {proto: ast::ProtoBorrowed,
-                           region: r_borrow,
-                           ..fn_ty.meta};
-        let a_borrowed = ty::mk_fn(self.infcx.tcx,
-                                   FnTyBase {meta: meta,
-                                             sig: copy fn_ty.sig});
+        let a_borrowed = ty::mk_closure(
+            self.infcx.tcx,
+            ty::ClosureTy {
+                sigil: ast::BorrowedSigil,
+                region: r_borrow,
+                ..fn_ty
+            });
 
         if_ok!(self.subtype(a_borrowed, b));
         Ok(Some(@AutoAdjustment {
@@ -320,7 +321,7 @@ impl Coerce {
 
     fn coerce_from_bare_fn(&self,
                            a: ty::t,
-                           fn_ty_a: &ty::FnTy,
+                           fn_ty_a: &ty::BareFnTy,
                            b: ty::t) -> CoerceResult
     {
         do self.unpack_actual_value(b) |sty_b| {
@@ -330,7 +331,7 @@ impl Coerce {
 
     fn coerce_from_bare_fn_post_unpack(&self,
                                        a: ty::t,
-                                       fn_ty_a: &ty::FnTy,
+                                       fn_ty_a: &ty::BareFnTy,
                                        b: ty::t,
                                        sty_b: &ty::sty) -> CoerceResult
     {
@@ -338,18 +339,18 @@ impl Coerce {
                a.inf_str(self.infcx), b.inf_str(self.infcx));
 
         let fn_ty_b = match *sty_b {
-            ty::ty_fn(ref f) if f.meta.proto != ast::ProtoBare => {f}
+            ty::ty_closure(ref f) => {copy *f}
             _ => {
                 return self.subtype(a, b);
             }
         };
 
-            // for now, bare fn and closures have the same
-            // representation
-        let a_adapted = ty::mk_fn(self.infcx.tcx,
-                                  FnTyBase {meta: copy fn_ty_b.meta,
-                                            sig: copy fn_ty_a.sig});
-        self.subtype(a_adapted, b)
+        // for now, bare fn and closures have the same
+        // representation
+        let a_closure = ty::mk_closure(
+            self.infcx.tcx,
+            ty::ClosureTy {sig: copy fn_ty_a.sig, ..fn_ty_b});
+        self.subtype(a_closure, b)
     }
 
     fn coerce_unsafe_ptr(&self,
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index 819348e744e..7737327bc0c 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -56,7 +56,7 @@
 
 use core::prelude::*;
 
-use middle::ty::{FloatVar, FnTyBase, FnMeta, FnSig, IntVar, TyVar};
+use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
 use middle::ty::{IntType, UintType, arg, substs};
 use middle::ty;
 use middle::typeck::infer::glb::Glb;
@@ -94,14 +94,17 @@ pub trait Combine {
     fn self_tys(a: Option<ty::t>, b: Option<ty::t>) -> cres<Option<ty::t>>;
     fn substs(did: ast::def_id, as_: &ty::substs,
               bs: &ty::substs) -> cres<ty::substs>;
-    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy>;
+    fn bare_fn_tys(a: &ty::BareFnTy,
+                   b: &ty::BareFnTy) -> cres<ty::BareFnTy>;
+    fn closure_tys(a: &ty::ClosureTy,
+                   b: &ty::ClosureTy) -> cres<ty::ClosureTy>;
     fn fn_sigs(a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
-    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta>;
     fn flds(a: ty::field, b: ty::field) -> cres<ty::field>;
     fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode>;
     fn args(a: ty::arg, b: ty::arg) -> cres<ty::arg>;
-    fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto>;
+    fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil>;
     fn purities(a: purity, b: purity) -> cres<purity>;
+    fn abis(a: ast::Abi, b: ast::Abi) -> cres<ast::Abi>;
     fn oncenesses(a: Onceness, b: Onceness) -> cres<Onceness>;
     fn contraregions(a: ty::Region, b: ty::Region) -> cres<ty::Region>;
     fn regions(a: ty::Region, b: ty::Region) -> cres<ty::Region>;
@@ -287,12 +290,12 @@ pub fn super_self_tys<C:Combine>(
     }
 }
 
-pub fn super_protos<C: Combine>(
-    self: &C, p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
+pub fn super_sigils<C: Combine>(
+    self: &C, p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
     if p1 == p2 {
         Ok(p1)
     } else {
-        Err(ty::terr_proto_mismatch(expected_found(self, p1, p2)))
+        Err(ty::terr_sigil_mismatch(expected_found(self, p1, p2)))
     }
 }
 
@@ -350,21 +353,45 @@ pub fn super_vstores<C:Combine>(
     }
 }
 
-pub fn super_fn_metas<C:Combine>(
-    self: &C, a_f: &ty::FnMeta, b_f: &ty::FnMeta) -> cres<ty::FnMeta> {
-    let p = if_ok!(self.protos(a_f.proto, b_f.proto));
+pub fn super_closure_tys<C:Combine>(
+    self: &C, a_f: &ty::ClosureTy, b_f: &ty::ClosureTy) -> cres<ty::ClosureTy>
+{
+    let p = if_ok!(self.sigils(a_f.sigil, b_f.sigil));
     let r = if_ok!(self.contraregions(a_f.region, b_f.region));
     let purity = if_ok!(self.purities(a_f.purity, b_f.purity));
     let onceness = if_ok!(self.oncenesses(a_f.onceness, b_f.onceness));
-    Ok(FnMeta {purity: purity,
-               proto: p,
-               onceness: onceness,
-               region: r,
-               bounds: a_f.bounds}) // XXX: This is wrong!
+    let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig));
+    Ok(ty::ClosureTy {purity: purity,
+                      sigil: p,
+                      onceness: onceness,
+                      region: r,
+                      sig: sig})
+}
+
+pub fn super_abis<C:Combine>(
+    self: &C, a: ast::Abi, b: ast::Abi) -> cres<ast::Abi>
+{
+    if a == b {
+        Ok(a)
+    } else {
+        Err(ty::terr_abi_mismatch(expected_found(self, a, b)))
+    }
+}
+
+pub fn super_bare_fn_tys<C:Combine>(
+    self: &C, a_f: &ty::BareFnTy, b_f: &ty::BareFnTy) -> cres<ty::BareFnTy>
+{
+    let purity = if_ok!(self.purities(a_f.purity, b_f.purity));
+    let abi = if_ok!(self.abis(a_f.abi, b_f.abi));
+    let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig));
+    Ok(ty::BareFnTy {purity: purity,
+                     abi: abi,
+                     sig: sig})
 }
 
 pub fn super_fn_sigs<C:Combine>(
-    self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig> {
+    self: &C, a_f: &ty::FnSig, b_f: &ty::FnSig) -> cres<ty::FnSig>
+{
     fn argvecs<C:Combine>(self: &C,
                           +a_args: ~[ty::arg],
                           +b_args: ~[ty::arg]) -> cres<~[ty::arg]>
@@ -384,13 +411,6 @@ pub fn super_fn_sigs<C:Combine>(
     }
 }
 
-pub fn super_fns<C:Combine>(
-    self: &C, a_f: &ty::FnTy, b_f: &ty::FnTy) -> cres<ty::FnTy> {
-    let m = if_ok!(self.fn_metas(&a_f.meta, &b_f.meta));
-    let s = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig));
-    Ok(FnTyBase {meta: m, sig: s})
-}
-
 pub fn super_tys<C:Combine>(
     self: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
     let tcx = self.infcx().tcx;
@@ -551,9 +571,15 @@ pub fn super_tys<C:Combine>(
         }
       }
 
-      (ty::ty_fn(ref a_fty), ty::ty_fn(ref b_fty)) => {
-        do self.fns(a_fty, b_fty).chain |fty| {
-            Ok(ty::mk_fn(tcx, fty))
+      (ty::ty_bare_fn(ref a_fty), ty::ty_bare_fn(ref b_fty)) => {
+        do self.bare_fn_tys(a_fty, b_fty).chain |fty| {
+            Ok(ty::mk_bare_fn(tcx, fty))
+        }
+      }
+
+      (ty::ty_closure(ref a_fty), ty::ty_closure(ref b_fty)) => {
+        do self.closure_tys(a_fty, b_fty).chain |fty| {
+            Ok(ty::mk_closure(tcx, fty))
         }
       }
 
diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs
index 58d9f1019ae..382d5f24cc7 100644
--- a/src/librustc/middle/typeck/infer/glb.rs
+++ b/src/librustc/middle/typeck/infer/glb.rs
@@ -267,16 +267,22 @@ pub impl Glb: Combine {
         }
     }
 
-    fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
-        super_protos(&self, p1, p2)
+    fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
+        super_sigils(&self, p1, p2)
     }
 
-    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
-        super_fns(&self, a, b)
+    fn abis(p1: ast::Abi, p2: ast::Abi) -> cres<ast::Abi> {
+        super_abis(&self, p1, p2)
     }
 
-    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
-        super_fn_metas(&self, a, b)
+    fn bare_fn_tys(a: &ty::BareFnTy,
+                   b: &ty::BareFnTy) -> cres<ty::BareFnTy> {
+        super_bare_fn_tys(&self, a, b)
+    }
+
+    fn closure_tys(a: &ty::ClosureTy,
+                   b: &ty::ClosureTy) -> cres<ty::ClosureTy> {
+        super_closure_tys(&self, a, b)
     }
 
     fn substs(did: ast::def_id,
diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs
index 4f7bedd8149..4bf8a0bae86 100644
--- a/src/librustc/middle/typeck/infer/lattice.rs
+++ b/src/librustc/middle/typeck/infer/lattice.rs
@@ -71,23 +71,6 @@ pub impl ty::t: LatticeValue {
     }
 }
 
-pub impl FnMeta: LatticeValue {
-    static fn sub(cf: &CombineFields,
-                  a: &FnMeta, b: &FnMeta) -> ures {
-        Sub(*cf).fn_metas(a, b).to_ures()
-    }
-
-    static fn lub(cf: &CombineFields,
-                  a: &FnMeta, b: &FnMeta) -> cres<FnMeta> {
-        Lub(*cf).fn_metas(a, b)
-    }
-
-    static fn glb(cf: &CombineFields,
-                  a: &FnMeta, b: &FnMeta) -> cres<FnMeta> {
-        Glb(*cf).fn_metas(a, b)
-    }
-}
-
 pub impl CombineFields {
     fn var_sub_var<T:Copy InferStr LatticeValue,
                    V:Copy Eq ToStr Vid UnifyVid<Bounds<T>>>(
diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs
index f24d245db58..44ad367c9dc 100644
--- a/src/librustc/middle/typeck/infer/lub.rs
+++ b/src/librustc/middle/typeck/infer/lub.rs
@@ -191,18 +191,24 @@ pub impl Lub: Combine {
         }
     }
 
-    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
-        super_fns(&self, a, b)
+    fn bare_fn_tys(a: &ty::BareFnTy,
+                   b: &ty::BareFnTy) -> cres<ty::BareFnTy> {
+        super_bare_fn_tys(&self, a, b)
     }
 
-    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
-        super_fn_metas(&self, a, b)
+    fn closure_tys(a: &ty::ClosureTy,
+                   b: &ty::ClosureTy) -> cres<ty::ClosureTy> {
+        super_closure_tys(&self, a, b)
     }
 
     // Traits please (FIXME: #2794):
 
-    fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
-        super_protos(&self, p1, p2)
+    fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
+        super_sigils(&self, p1, p2)
+    }
+
+    fn abis(p1: ast::Abi, p2: ast::Abi) -> cres<ast::Abi> {
+        super_abis(&self, p1, p2)
     }
 
     fn tys(a: ty::t, b: ty::t) -> cres<ty::t> {
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index 6140390a24e..d6ecf11ef26 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -242,9 +242,6 @@ section on "Type Combining" below for details.
 
 */
 
-#[warn(deprecated_mode)];
-#[warn(deprecated_pattern)];
-
 use core::prelude::*;
 
 pub use middle::ty::IntVarValue;
@@ -257,7 +254,6 @@ pub use middle::typeck::infer::resolve::{resolve_nested_tvar};
 pub use middle::typeck::infer::resolve::{resolve_rvar};
 
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, Vid};
-use middle::ty::{mk_fn, type_is_bot};
 use middle::ty::{ty_int, ty_uint, get, terr_fn, TyVar, IntVar, FloatVar};
 use middle::ty;
 use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig};
diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs
index 0d4e520122f..afb18888cd9 100644
--- a/src/librustc/middle/typeck/infer/region_inference.rs
+++ b/src/librustc/middle/typeck/infer/region_inference.rs
@@ -536,9 +536,6 @@ more convincing in the future.
 
 */
 
-#[warn(deprecated_mode)];
-#[warn(deprecated_pattern)];
-
 use core::prelude::*;
 
 use middle::region::is_subregion_of;
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 2e30bdc5888..bc834ef0289 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -212,20 +212,26 @@ pub impl Sub: Combine {
 
     // Traits please (FIXME: #2794):
 
-    fn protos(p1: ast::Proto, p2: ast::Proto) -> cres<ast::Proto> {
-        super_protos(&self, p1, p2)
+    fn sigils(p1: ast::Sigil, p2: ast::Sigil) -> cres<ast::Sigil> {
+        super_sigils(&self, p1, p2)
+    }
+
+    fn abis(p1: ast::Abi, p2: ast::Abi) -> cres<ast::Abi> {
+        super_abis(&self, p1, p2)
     }
 
     fn flds(a: ty::field, b: ty::field) -> cres<ty::field> {
         super_flds(&self, a, b)
     }
 
-    fn fns(a: &ty::FnTy, b: &ty::FnTy) -> cres<ty::FnTy> {
-        super_fns(&self, a, b)
+    fn bare_fn_tys(a: &ty::BareFnTy,
+                   b: &ty::BareFnTy) -> cres<ty::BareFnTy> {
+        super_bare_fn_tys(&self, a, b)
     }
 
-    fn fn_metas(a: &ty::FnMeta, b: &ty::FnMeta) -> cres<ty::FnMeta> {
-        super_fn_metas(&self, a, b)
+    fn closure_tys(a: &ty::ClosureTy,
+                   b: &ty::ClosureTy) -> cres<ty::ClosureTy> {
+        super_closure_tys(&self, a, b)
     }
 
     fn vstores(vk: ty::terr_vstore_kind,
diff --git a/src/librustc/middle/typeck/infer/to_str.rs b/src/librustc/middle/typeck/infer/to_str.rs
index 57e05926173..bade7639e4b 100644
--- a/src/librustc/middle/typeck/infer/to_str.rs
+++ b/src/librustc/middle/typeck/infer/to_str.rs
@@ -10,7 +10,7 @@
 
 use core::prelude::*;
 
-use middle::ty::{FnMeta, FnTyBase, FnSig, Vid};
+use middle::ty::{FnSig, Vid};
 use middle::ty::{IntVarValue, IntType, UintType};
 use middle::ty;
 use middle::typeck::infer::{Bound, Bounds};
@@ -34,12 +34,6 @@ pub impl ty::t : InferStr {
     }
 }
 
-pub impl FnMeta : InferStr {
-    fn inf_str(&self, _cx: &InferCtxt) -> ~str {
-        fmt!("%?", *self)
-    }
-}
-
 pub impl FnSig : InferStr {
     fn inf_str(&self, cx: &InferCtxt) -> ~str {
         fmt!("(%s) -> %s",
@@ -48,12 +42,6 @@ pub impl FnSig : InferStr {
     }
 }
 
-pub impl<M:InferStr> FnTyBase<M> : InferStr {
-    fn inf_str(&self, cx: &InferCtxt) -> ~str {
-        fmt!("%s%s", self.meta.inf_str(cx), self.sig.inf_str(cx))
-    }
-}
-
 pub impl ty::mt : InferStr {
     fn inf_str(&self, cx: &InferCtxt) -> ~str {
         mt_to_str(cx.tcx, *self)
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 742646618bd..3d9e2e7b86a 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -324,7 +324,7 @@ fn check_main_fn_ty(ccx: @crate_ctxt,
     let tcx = ccx.tcx;
     let main_t = ty::node_id_to_type(tcx, main_id);
     match ty::get(main_t).sty {
-        ty::ty_fn(ref fn_ty) => {
+        ty::ty_bare_fn(ref fn_ty) => {
             match tcx.items.find(&main_id) {
                 Some(ast_map::node_item(it,_)) => {
                     match it.node {
@@ -341,8 +341,8 @@ fn check_main_fn_ty(ccx: @crate_ctxt,
                 }
                 _ => ()
             }
-            let mut ok = ty::type_is_nil((*fn_ty).sig.output);
-            let num_args = vec::len((*fn_ty).sig.inputs);
+            let mut ok = ty::type_is_nil(fn_ty.sig.output);
+            let num_args = vec::len(fn_ty.sig.inputs);
             ok &= num_args == 0u;
             if !ok {
                 tcx.sess.span_err(
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 9e70a6ab130..43d12c95c4d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -21,7 +21,8 @@ use middle::ty::{mt, t, param_bound, param_ty};
 use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region};
 use middle::ty::{ReSkolemized, ReVar};
 use middle::ty::{ty_bool, ty_bot, ty_box, ty_struct, ty_enum};
-use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int};
+use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
+use middle::ty::{ty_trait, ty_int};
 use middle::ty::{ty_nil, ty_opaque_box, ty_opaque_closure_ptr, ty_param};
 use middle::ty::{ty_ptr, ty_rec, ty_rptr, ty_self, ty_tup};
 use middle::ty::{ty_type, ty_uniq, ty_uint, ty_infer};
@@ -30,7 +31,7 @@ use metadata::encoder;
 use syntax::codemap;
 use syntax::codemap::span;
 use syntax::print::pprust;
-use syntax::print::pprust::{path_to_str, proto_to_str, mode_to_str};
+use syntax::print::pprust::{path_to_str, mode_to_str};
 use syntax::{ast, ast_util};
 use syntax::ast_map;
 
@@ -252,17 +253,6 @@ pub fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str {
     }
 }
 
-pub fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto,
-                       followed_by_word: bool) -> &static/str {
-    match proto {
-        ast::ProtoBare if followed_by_word => "extern ",
-        ast::ProtoBare => "extern",
-        ast::ProtoBox => "@",
-        ast::ProtoBorrowed => "&",
-        ast::ProtoUniq => "~",
-    }
-}
-
 pub fn expr_repr(cx: ctxt, expr: @ast::expr) -> ~str {
     fmt!("expr(%d: %s)",
          expr.id,
@@ -306,69 +296,95 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
         };
         fmt!("%s%s", modestr, ty_to_str(cx, ty))
     }
-    fn fn_to_str(cx: ctxt,
-                 proto: ast::Proto,
-                 region: ty::Region,
-                 purity: ast::purity,
-                 onceness: ast::Onceness,
-                 ident: Option<ast::ident>,
-                 inputs: &[arg],
-                 output: t) -> ~str {
-        let mut s;
-
-        s = match purity {
-            ast::impure_fn => ~"",
-            _ => purity.to_str() + ~" "
-        };
+    fn bare_fn_to_str(cx: ctxt,
+                      purity: ast::purity,
+                      abi: ast::Abi,
+                      ident: Option<ast::ident>,
+                      sig: &ty::FnSig) -> ~str
+    {
+        let mut s = ~"extern ";
 
-        s += match onceness {
-            ast::Many => ~"",
-            ast::Once => onceness.to_str() + ~" "
+        match abi {
+            ast::RustAbi => {}
+        }
+
+        match purity {
+            ast::impure_fn => {}
+            _ => {
+                s.push_str(purity.to_str());
+                s.push_char(' ');
+            }
         };
 
-        s += proto_ty_to_str(cx, proto, true);
+        s.push_str("fn");
 
-        match (proto, region) {
-            (ast::ProtoBox, ty::re_static) |
-            (ast::ProtoUniq, ty::re_static) |
-            (ast::ProtoBare, ty::re_static) => {
-            }
+        match ident {
+          Some(i) => {
+              s.push_char(' ');
+              s.push_str(cx.sess.str_of(i));
+          }
+          _ => { }
+        }
+
+        push_sig_to_str(cx, &mut s, sig);
+
+        return s;
+    }
+    fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str
+    {
+        let mut s = cty.sigil.to_str();
+
+        match (cty.sigil, cty.region) {
+            (ast::ManagedSigil, ty::re_static) |
+            (ast::OwnedSigil, ty::re_static) => {}
 
             (_, region) => {
-                s += region_to_str_adorned(cx, ~"", region, ~"/");
+                s.push_str(region_to_str_adorned(cx, "", region, "/"));
             }
         }
 
-        s += ~"fn";
+        match cty.purity {
+            ast::impure_fn => {}
+            _ => {
+                s.push_str(cty.purity.to_str());
+                s.push_char(' ');
+            }
+        };
 
-        match ident {
-          Some(i) => { s += ~" "; s += cx.sess.str_of(i); }
-          _ => { }
-        }
-        s += ~"(";
-        let strs = inputs.map(|a| fn_input_to_str(cx, *a));
-        s += str::connect(strs, ~", ");
-        s += ~")";
-        if ty::get(output).sty != ty_nil {
-            s += ~" -> ";
-            if ty::type_is_bot(output) {
-                s += ~"!";
+        match cty.onceness {
+            ast::Many => {}
+            ast::Once => {
+                s.push_str(cty.onceness.to_str());
+                s.push_char(' ');
+            }
+        };
+
+        s.push_str("fn");
+
+        push_sig_to_str(cx, &mut s, &cty.sig);
+
+        return s;
+    }
+    fn push_sig_to_str(cx: ctxt, s: &mut ~str, sig: &ty::FnSig) {
+        s.push_char('(');
+        let strs = sig.inputs.map(|a| fn_input_to_str(cx, *a));
+        s.push_str(str::connect(strs, ", "));
+        s.push_char(')');
+        if ty::get(sig.output).sty != ty_nil {
+            s.push_str(" -> ");
+            if ty::type_is_bot(sig.output) {
+                s.push_char('!');
             } else {
-                s += ty_to_str(cx, output);
+                s.push_str(ty_to_str(cx, sig.output));
             }
         }
-        return s;
     }
     fn method_to_str(cx: ctxt, m: method) -> ~str {
-        return fn_to_str(
-            cx,
-            m.fty.meta.proto,
-            m.fty.meta.region,
-            m.fty.meta.purity,
-            m.fty.meta.onceness,
-            Some(m.ident),
-            m.fty.sig.inputs,
-            m.fty.sig.output) + ~";";
+        bare_fn_to_str(cx,
+                       m.fty.purity,
+                       m.fty.abi,
+                       Some(m.ident),
+                       &m.fty.sig) + ~";"
     }
     fn field_to_str(cx: ctxt, f: field) -> ~str {
         return cx.sess.str_of(f.ident) + ~": " + mt_to_str(cx, f.mt);
@@ -409,15 +425,11 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
         let strs = elems.map(|elem| ty_to_str(cx, *elem));
         ~"(" + str::connect(strs, ~",") + ~")"
       }
-      ty_fn(ref f) => {
-        fn_to_str(cx,
-                  f.meta.proto,
-                  f.meta.region,
-                  f.meta.purity,
-                  f.meta.onceness,
-                  None,
-                  f.sig.inputs,
-                  f.sig.output)
+      ty_closure(ref f) => {
+          closure_to_str(cx, f)
+      }
+      ty_bare_fn(ref f) => {
+          bare_fn_to_str(cx, f.purity, f.abi, None, &f.sig)
       }
       ty_infer(infer_ty) => infer_ty.to_str(),
       ty_err => ~"[type error]",
@@ -448,10 +460,9 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
       }
       ty_estr(vs) => vstore_ty_to_str(cx, ~"str", vs),
       ty_opaque_box => ~"@?",
-      ty_opaque_closure_ptr(ast::ProtoBorrowed) => ~"closure&",
-      ty_opaque_closure_ptr(ast::ProtoBox) => ~"closure@",
-      ty_opaque_closure_ptr(ast::ProtoUniq) => ~"closure~",
-      ty_opaque_closure_ptr(ast::ProtoBare) => ~"closure"
+      ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"closure&",
+      ty_opaque_closure_ptr(ast::ManagedSigil) => ~"closure@",
+      ty_opaque_closure_ptr(ast::OwnedSigil) => ~"closure~",
     }
 }
 
diff --git a/src/librustdoc/astsrv.rs b/src/librustdoc/astsrv.rs
index dd6e889008f..1d629467a42 100644
--- a/src/librustdoc/astsrv.rs
+++ b/src/librustdoc/astsrv.rs
@@ -21,6 +21,7 @@ use core::prelude::*;
 
 use parse;
 use util;
+use std::cell::Cell;
 
 use core::pipes::{stream, Chan, SharedChan, Port};
 use core::vec;
@@ -78,8 +79,10 @@ fn run<T>(owner: SrvOwner<T>, source: ~str, parse: Parser) -> T {
 
     let (po, ch) = stream();
 
+    let source = Cell(source);
+    let parse = Cell(parse);
     do task::spawn {
-        act(&po, copy source, copy parse);
+        act(&po, source.take(), parse.take());
     }
 
     let srv_ = Srv {
diff --git a/src/librustdoc/attr_parser.rs b/src/librustdoc/attr_parser.rs
index afbb10f2cbb..0beb651afc4 100644
--- a/src/librustdoc/attr_parser.rs
+++ b/src/librustdoc/attr_parser.rs
@@ -96,7 +96,7 @@ fn should_not_extract_crate_name_if_no_name_value_in_link_attribute() {
 }
 
 pub fn parse_desc(attrs: ~[ast::attribute]) -> Option<~str> {
-    let doc_strs = do doc_metas(attrs).filter_map |meta| {
+    let doc_strs = do doc_metas(attrs).filter_mapped |meta| {
         attr::get_meta_item_value_str(*meta)
     };
     if doc_strs.is_empty() {
diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs
index 225b62f72cb..2d0969562a0 100644
--- a/src/librustdoc/desc_to_brief_pass.rs
+++ b/src/librustdoc/desc_to_brief_pass.rs
@@ -62,7 +62,7 @@ fn fold_trait(fold: &fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc {
     let doc =fold::default_seq_fold_trait(fold, doc);
 
     doc::TraitDoc {
-        methods: par::map(doc.methods, |doc| doc::MethodDoc {
+        methods: doc.methods.map(|doc| doc::MethodDoc {
             brief: extract(copy doc.desc),
             .. copy *doc
         }),
@@ -74,7 +74,7 @@ fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc {
     let doc =fold::default_seq_fold_impl(fold, doc);
 
     doc::ImplDoc {
-        methods: par::map(doc.methods, |doc| doc::MethodDoc {
+        methods: doc.methods.map(|doc| doc::MethodDoc {
             brief: extract(copy doc.desc),
             .. copy *doc
         }),
diff --git a/src/librustdoc/doc.rs b/src/librustdoc/doc.rs
index e51c8106f3d..2eb4ed97871 100644
--- a/src/librustdoc/doc.rs
+++ b/src/librustdoc/doc.rs
@@ -192,7 +192,7 @@ impl Doc {
 /// Some helper methods on ModDoc, mostly for testing
 impl ModDoc {
     fn mods(&self) -> ~[ModDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               ModTag(ModDoc) => Some(ModDoc),
               _ => None
@@ -201,7 +201,7 @@ impl ModDoc {
     }
 
     fn nmods(&self) -> ~[NmodDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               NmodTag(nModDoc) => Some(nModDoc),
               _ => None
@@ -210,7 +210,7 @@ impl ModDoc {
     }
 
     fn fns(&self) -> ~[FnDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               FnTag(FnDoc) => Some(FnDoc),
               _ => None
@@ -219,7 +219,7 @@ impl ModDoc {
     }
 
     fn consts(&self) -> ~[ConstDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               ConstTag(ConstDoc) => Some(ConstDoc),
               _ => None
@@ -228,7 +228,7 @@ impl ModDoc {
     }
 
     fn enums(&self) -> ~[EnumDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               EnumTag(EnumDoc) => Some(EnumDoc),
               _ => None
@@ -237,7 +237,7 @@ impl ModDoc {
     }
 
     fn traits(&self) -> ~[TraitDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               TraitTag(TraitDoc) => Some(TraitDoc),
               _ => None
@@ -246,7 +246,7 @@ impl ModDoc {
     }
 
     fn impls(&self) -> ~[ImplDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               ImplTag(ImplDoc) => Some(ImplDoc),
               _ => None
@@ -255,7 +255,7 @@ impl ModDoc {
     }
 
     fn types(&self) -> ~[TyDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
               TyTag(TyDoc) => Some(TyDoc),
               _ => None
@@ -264,7 +264,7 @@ impl ModDoc {
     }
 
     fn structs(&self) -> ~[StructDoc] {
-        do vec::filter_map(self.items) |itemtag| {
+        do vec::filter_mapped(self.items) |itemtag| {
             match copy *itemtag {
                 StructTag(StructDoc) => Some(StructDoc),
                 _ => None
@@ -287,7 +287,7 @@ pub trait PageUtils {
 impl ~[Page]: PageUtils {
 
     fn mods(&self) -> ~[ModDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(ModTag(ModDoc)) => Some(ModDoc),
               _ => None
@@ -296,7 +296,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn nmods(&self) -> ~[NmodDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(NmodTag(nModDoc)) => Some(nModDoc),
               _ => None
@@ -305,7 +305,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn fns(&self) -> ~[FnDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(FnTag(FnDoc)) => Some(FnDoc),
               _ => None
@@ -314,7 +314,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn consts(&self) -> ~[ConstDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(ConstTag(ConstDoc)) => Some(ConstDoc),
               _ => None
@@ -323,7 +323,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn enums(&self) -> ~[EnumDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(EnumTag(EnumDoc)) => Some(EnumDoc),
               _ => None
@@ -332,7 +332,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn traits(&self) -> ~[TraitDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(TraitTag(TraitDoc)) => Some(TraitDoc),
               _ => None
@@ -341,7 +341,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn impls(&self) -> ~[ImplDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(ImplTag(ImplDoc)) => Some(ImplDoc),
               _ => None
@@ -350,7 +350,7 @@ impl ~[Page]: PageUtils {
     }
 
     fn types(&self) -> ~[TyDoc] {
-        do vec::filter_map(*self) |page| {
+        do vec::filter_mapped(*self) |page| {
             match copy *page {
               ItemPage(TyTag(TyDoc)) => Some(TyDoc),
               _ => None
diff --git a/src/librustdoc/extract.rs b/src/librustdoc/extract.rs
index fc572e3da2c..822a423eae4 100644
--- a/src/librustdoc/extract.rs
+++ b/src/librustdoc/extract.rs
@@ -92,7 +92,7 @@ fn moddoc_from_mod(
 ) -> doc::ModDoc {
     doc::ModDoc {
         item: itemdoc,
-        items: do vec::filter_map(module_.items) |item| {
+        items: do vec::filter_mapped(module_.items) |item| {
             let ItemDoc = mk_itemdoc(item.id, to_str(item.ident));
             match copy item.node {
               ast::item_mod(m) => {
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index c93d9f3d7c1..e9b25b07de1 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -55,23 +55,23 @@ impl<T: Clone> Fold<T>: Clone {
     }
 }
 
-type FoldDoc<T> = fn~(fold: &Fold<T>, doc: doc::Doc) -> doc::Doc;
-type FoldCrate<T> = fn~(fold: &Fold<T>, doc: doc::CrateDoc) -> doc::CrateDoc;
-type FoldItem<T> = fn~(fold: &Fold<T>, doc: doc::ItemDoc) -> doc::ItemDoc;
-type FoldMod<T> = fn~(fold: &Fold<T>, doc: doc::ModDoc) -> doc::ModDoc;
-type FoldNmod<T> = fn~(fold: &Fold<T>, doc: doc::NmodDoc) -> doc::NmodDoc;
-type FoldFn<T> = fn~(fold: &Fold<T>, doc: doc::FnDoc) -> doc::FnDoc;
-type FoldConst<T> = fn~(fold: &Fold<T>, doc: doc::ConstDoc) -> doc::ConstDoc;
-type FoldEnum<T> = fn~(fold: &Fold<T>, doc: doc::EnumDoc) -> doc::EnumDoc;
-type FoldTrait<T> = fn~(fold: &Fold<T>, doc: doc::TraitDoc) -> doc::TraitDoc;
-type FoldImpl<T> = fn~(fold: &Fold<T>, doc: doc::ImplDoc) -> doc::ImplDoc;
-type FoldType<T> = fn~(fold: &Fold<T>, doc: doc::TyDoc) -> doc::TyDoc;
-type FoldStruct<T> = fn~(fold: &Fold<T>,
+type FoldDoc<T> = @fn(fold: &Fold<T>, doc: doc::Doc) -> doc::Doc;
+type FoldCrate<T> = @fn(fold: &Fold<T>, doc: doc::CrateDoc) -> doc::CrateDoc;
+type FoldItem<T> = @fn(fold: &Fold<T>, doc: doc::ItemDoc) -> doc::ItemDoc;
+type FoldMod<T> = @fn(fold: &Fold<T>, doc: doc::ModDoc) -> doc::ModDoc;
+type FoldNmod<T> = @fn(fold: &Fold<T>, doc: doc::NmodDoc) -> doc::NmodDoc;
+type FoldFn<T> = @fn(fold: &Fold<T>, doc: doc::FnDoc) -> doc::FnDoc;
+type FoldConst<T> = @fn(fold: &Fold<T>, doc: doc::ConstDoc) -> doc::ConstDoc;
+type FoldEnum<T> = @fn(fold: &Fold<T>, doc: doc::EnumDoc) -> doc::EnumDoc;
+type FoldTrait<T> = @fn(fold: &Fold<T>, doc: doc::TraitDoc) -> doc::TraitDoc;
+type FoldImpl<T> = @fn(fold: &Fold<T>, doc: doc::ImplDoc) -> doc::ImplDoc;
+type FoldType<T> = @fn(fold: &Fold<T>, doc: doc::TyDoc) -> doc::TyDoc;
+type FoldStruct<T> = @fn(fold: &Fold<T>,
                          doc: doc::StructDoc) -> doc::StructDoc;
 
 // This exists because fn types don't infer correctly as record
 // initializers, but they do as function arguments
-fn mk_fold<T:Clone>(
+fn mk_fold<T>(
     ctxt: T,
     fold_doc: FoldDoc<T>,
     fold_crate: FoldCrate<T>,
@@ -103,7 +103,7 @@ fn mk_fold<T:Clone>(
     }
 }
 
-pub fn default_any_fold<T:Owned Clone>(ctxt: T) -> Fold<T> {
+pub fn default_any_fold<T: Clone>(ctxt: T) -> Fold<T> {
     mk_fold(
         move ctxt,
         |f, d| default_seq_fold_doc(f, d),
@@ -121,7 +121,7 @@ pub fn default_any_fold<T:Owned Clone>(ctxt: T) -> Fold<T> {
     )
 }
 
-pub fn default_seq_fold<T:Clone>(ctxt: T) -> Fold<T> {
+pub fn default_seq_fold<T: Clone>(ctxt: T) -> Fold<T> {
     mk_fold(
         move ctxt,
         |f, d| default_seq_fold_doc(f, d),
@@ -139,7 +139,7 @@ pub fn default_seq_fold<T:Clone>(ctxt: T) -> Fold<T> {
     )
 }
 
-pub fn default_par_fold<T:Owned Clone>(ctxt: T) -> Fold<T> {
+pub fn default_par_fold<T: Clone>(ctxt: T) -> Fold<T> {
     mk_fold(
         move ctxt,
         |f, d| default_seq_fold_doc(f, d),
@@ -189,7 +189,7 @@ pub fn default_seq_fold_item<T>(
     doc
 }
 
-pub fn default_any_fold_mod<T:Owned Clone>(
+pub fn default_any_fold_mod<T:Clone>(
     fold: &Fold<T>,
     doc: doc::ModDoc
 ) -> doc::ModDoc {
@@ -215,7 +215,7 @@ pub fn default_seq_fold_mod<T>(
     }
 }
 
-pub fn default_par_fold_mod<T:Owned Clone>(
+pub fn default_par_fold_mod<T:Clone>(
     fold: &Fold<T>,
     doc: doc::ModDoc
 ) -> doc::ModDoc {
@@ -228,7 +228,7 @@ pub fn default_par_fold_mod<T:Owned Clone>(
     }
 }
 
-pub fn default_any_fold_nmod<T:Owned Clone>(
+pub fn default_any_fold_nmod<T:Clone>(
     fold: &Fold<T>,
     doc: doc::NmodDoc
 ) -> doc::NmodDoc {
@@ -254,7 +254,7 @@ pub fn default_seq_fold_nmod<T>(
     }
 }
 
-pub fn default_par_fold_nmod<T:Owned Clone>(
+pub fn default_par_fold_nmod<T:Clone>(
     fold: &Fold<T>,
     doc: doc::NmodDoc
 ) -> doc::NmodDoc {
diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs
index 776d2fe9083..42a7d0006db 100644
--- a/src/librustdoc/markdown_index_pass.rs
+++ b/src/librustdoc/markdown_index_pass.rs
@@ -28,9 +28,7 @@ use std::par;
 pub fn mk_pass(config: config::Config) -> Pass {
     Pass {
         name: ~"markdown_index",
-        f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
-            run(srv, doc, copy config)
-        }
+        f: |srv, doc| run(srv, doc, copy config)
     }
 }
 
@@ -78,7 +76,7 @@ fn build_mod_index(
     config: config::Config
 ) -> doc::Index {
     doc::Index {
-        entries: par::map(doc.items, |doc| {
+        entries: doc.items.map(|doc| {
             item_to_entry(copy *doc, copy config)
         })
     }
@@ -89,7 +87,7 @@ fn build_nmod_index(
     config: config::Config
 ) -> doc::Index {
     doc::Index {
-        entries: par::map(doc.fns, |doc| {
+        entries: doc.fns.map(|doc| {
             item_to_entry(doc::FnTag(copy *doc), copy config)
         })
     }
diff --git a/src/librustdoc/markdown_pass.rs b/src/librustdoc/markdown_pass.rs
index fc13af8a221..161642a2f3d 100644
--- a/src/librustdoc/markdown_pass.rs
+++ b/src/librustdoc/markdown_pass.rs
@@ -43,14 +43,9 @@ use syntax;
 
 pub fn mk_pass(writer_factory: WriterFactory) -> Pass {
     let writer_factory = Cell(writer_factory);
-    let f = fn~(move writer_factory,
-                srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
-        run(srv, doc, writer_factory.take())
-    };
-
     Pass {
         name: ~"markdown",
-        f: move f
+        f: |srv, doc| run(srv, doc, writer_factory.take())
     }
 }
 
diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs
index c8509826fdb..08abe4b351b 100644
--- a/src/librustdoc/page_pass.rs
+++ b/src/librustdoc/page_pass.rs
@@ -36,9 +36,7 @@ use syntax::ast;
 pub fn mk_pass(output_style: config::OutputStyle) -> Pass {
     Pass {
         name: ~"page",
-        f: fn~(srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
-            run(srv, doc, output_style)
-        }
+        f: |srv, doc| run(srv, doc, output_style)
     }
 }
 
diff --git a/src/librustdoc/pass.rs b/src/librustdoc/pass.rs
index 91e3264db1c..e78c7d54019 100644
--- a/src/librustdoc/pass.rs
+++ b/src/librustdoc/pass.rs
@@ -20,7 +20,7 @@ use core::vec;
 /// A single operation on the document model
 pub struct Pass {
     name: ~str,
-    f: fn~(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc
+    f: @fn(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc
 }
 
 pub fn run_passes(
diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs
index d6455c4c783..205fc0aa86d 100644
--- a/src/librustdoc/sectionalize_pass.rs
+++ b/src/librustdoc/sectionalize_pass.rs
@@ -57,7 +57,7 @@ fn fold_trait(fold: &fold::Fold<()>, doc: doc::TraitDoc) -> doc::TraitDoc {
     let doc = fold::default_seq_fold_trait(fold, doc);
 
     doc::TraitDoc {
-        methods: do par::map(doc.methods) |method| {
+        methods: do doc.methods.map |method| {
             let (desc, sections) = sectionalize(copy method.desc);
 
             doc::MethodDoc {
@@ -74,7 +74,7 @@ fn fold_impl(fold: &fold::Fold<()>, doc: doc::ImplDoc) -> doc::ImplDoc {
     let doc = fold::default_seq_fold_impl(fold, doc);
 
     doc::ImplDoc {
-        methods: do par::map(doc.methods) |method| {
+        methods: do doc.methods.map |method| {
             let (desc, sections) = sectionalize(copy method.desc);
 
             doc::MethodDoc {
diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs
index 2792508483c..b7614a785c7 100644
--- a/src/librustdoc/sort_pass.rs
+++ b/src/librustdoc/sort_pass.rs
@@ -23,16 +23,14 @@ use util::NominalOp;
 
 use std::sort;
 
-pub type ItemLtEqOp = pure fn~(v1: &doc::ItemTag, v2:  &doc::ItemTag) -> bool;
+pub type ItemLtEqOp = @pure fn(v1: &doc::ItemTag, v2:  &doc::ItemTag) -> bool;
 
 type ItemLtEq = NominalOp<ItemLtEqOp>;
 
 pub fn mk_pass(name: ~str, lteq: ItemLtEqOp) -> Pass {
     Pass {
         name: copy name,
-        f: fn~(move lteq, srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
-            run(srv, doc, NominalOp { op: copy lteq })
-        }
+        f: |srv, doc| run(srv, doc, NominalOp { op: lteq })
     }
 }
 
diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs
index aec8b56341f..79ba8f0684a 100644
--- a/src/librustdoc/text_pass.rs
+++ b/src/librustdoc/text_pass.rs
@@ -23,17 +23,17 @@ use util::NominalOp;
 use std::par;
 use std::cell::Cell;
 
-pub fn mk_pass(name: ~str, op: fn~(&str) -> ~str) -> Pass {
+pub fn mk_pass(name: ~str, op: @fn(&str) -> ~str) -> Pass {
     let op = Cell(op);
     Pass {
         name: copy name,
-        f: fn~(move op, srv: astsrv::Srv, doc: doc::Doc) -> doc::Doc {
+        f: |srv: astsrv::Srv, doc: doc::Doc| -> doc::Doc {
             run(srv, doc, op.take())
         }
     }
 }
 
-type Op = fn~(&str) -> ~str;
+type Op = @fn(&str) -> ~str;
 
 #[allow(non_implicitly_copyable_typarams)]
 fn run(
@@ -76,7 +76,7 @@ fn apply_to_sections(
     op: NominalOp<Op>,
     sections: ~[doc::Section]
 ) -> ~[doc::Section] {
-    par::map(sections, |section, copy op| doc::Section {
+    sections.map(|section, copy op| doc::Section {
         header: (op.op)(copy section.header),
         body: (op.op)(copy section.body)
     })
@@ -89,7 +89,7 @@ fn fold_enum(
     let fold_copy = copy *fold;
 
     doc::EnumDoc {
-        variants: do par::map(doc.variants) |variant, copy fold_copy| {
+        variants: do doc.variants.map |variant, copy fold_copy| {
             doc::VariantDoc {
                 desc: maybe_apply_op(copy fold_copy.ctxt, &variant.desc),
                 .. copy *variant
@@ -116,7 +116,7 @@ fn apply_to_methods(
     docs: ~[doc::MethodDoc]
 ) -> ~[doc::MethodDoc] {
     let op = copy op;
-    do par::map(docs) |doc| {
+    do docs.map |doc| {
         doc::MethodDoc {
             brief: maybe_apply_op(copy op, &doc.brief),
             desc: maybe_apply_op(copy op, &doc.desc),
diff --git a/src/librustdoc/unindent_pass.rs b/src/librustdoc/unindent_pass.rs
index 1c53ed5dcce..fa8c2dd93c0 100644
--- a/src/librustdoc/unindent_pass.rs
+++ b/src/librustdoc/unindent_pass.rs
@@ -80,7 +80,7 @@ fn unindent(s: &str) -> ~str {
 
     if !lines.is_empty() {
         let unindented = ~[str::trim(vec::head(lines))]
-            + do par::map(vec::tail(lines)) |line| {
+            + do vec::tail(lines).map |line| {
             if str::is_whitespace(*line) {
                 copy *line
             } else {
diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs
index a8d3f156104..a1fd7a66f7e 100644
--- a/src/libstd/arc.rs
+++ b/src/libstd/arc.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
 /**
  * Concurrency-enabled mechanisms for sharing mutable and/or immutable state
  * between tasks.
diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs
index 3e21a320d44..a2cbe27ea90 100644
--- a/src/libstd/arena.rs
+++ b/src/libstd/arena.rs
@@ -32,8 +32,6 @@
 // overhead when initializing plain-old-data and means we don't need
 // to waste time running the destructors of POD.
 
-#[forbid(deprecated_mode)];
-
 use arena;
 use list;
 use list::{List, Cons, Nil};
diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs
index 5813e0919d9..d9e121798f1 100644
--- a/src/libstd/base64.rs
+++ b/src/libstd/base64.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use core::io::Reader;
 use core::iter;
 use core::str;
diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs
index 244d388bffe..a94c4f79064 100644
--- a/src/libstd/bitv.rs
+++ b/src/libstd/bitv.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use core::ops;
 use core::prelude::*;
 use core::uint;
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
index 17920f5de3f..5ea5418d988 100644
--- a/src/libstd/c_vec.rs
+++ b/src/libstd/c_vec.rs
@@ -35,7 +35,6 @@
  * great care must be taken to ensure that a reference to the c_vec::t is
  * still held if needed.
  */
-#[forbid(deprecated_mode)];
 
 use core::libc;
 use core::option;
diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs
index aae84a86957..10a896a4089 100644
--- a/src/libstd/cell.rs
+++ b/src/libstd/cell.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use core::option;
 use core::prelude::*;
 
diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs
index 0bd7538d947..110559ddcef 100644
--- a/src/libstd/cmp.rs
+++ b/src/libstd/cmp.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
 //! Additional general-purpose comparison functionality.
 
 use core::f32;
diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs
index dc0fbbac641..71eb29e26eb 100644
--- a/src/libstd/comm.rs
+++ b/src/libstd/comm.rs
@@ -14,9 +14,6 @@ Higher level communication abstractions.
 
 */
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
-
 use core::pipes::{GenericChan, GenericSmartChan, GenericPort};
 use core::pipes::{Chan, Port, Selectable, Peekable};
 use core::pipes;
diff --git a/src/libstd/dbg.rs b/src/libstd/dbg.rs
index cf1b816f238..7813357caf2 100644
--- a/src/libstd/dbg.rs
+++ b/src/libstd/dbg.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
 //! Unsafe debugging functions for inspecting values.
 
 use core::cast::reinterpret_cast;
diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs
index 2f001ae866c..465c5d8f8fe 100644
--- a/src/libstd/deque.rs
+++ b/src/libstd/deque.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 //! A deque. Untested as of yet. Likely buggy
-#[forbid(deprecated_mode)];
 #[forbid(non_camel_case_types)];
 
 use core::cmp::Eq;
diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs
index aaeecfb3302..768d2dbf2d4 100644
--- a/src/libstd/ebml.rs
+++ b/src/libstd/ebml.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use serialize;
 
 use core::io;
diff --git a/src/libstd/fun_treemap.rs b/src/libstd/fun_treemap.rs
index e0d4b95a7e4..d6c2cf5a265 100644
--- a/src/libstd/fun_treemap.rs
+++ b/src/libstd/fun_treemap.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 /*!
  * A functional key,value store that works on anything.
  *
diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs
index 6e1a0861035..fa8fdf56428 100644
--- a/src/libstd/getopts.rs
+++ b/src/libstd/getopts.rs
@@ -72,7 +72,6 @@
  *         do_work(input, output);
  *     }
  */
-#[forbid(deprecated_mode)];
 
 use core::cmp::Eq;
 use core::prelude::*;
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
index 13b58c43300..99c6c2f008d 100644
--- a/src/libstd/json.rs
+++ b/src/libstd/json.rs
@@ -10,7 +10,6 @@
 
 // Rust JSON serialization library
 // Copyright (c) 2011 Google Inc.
-#[forbid(deprecated_mode)];
 #[forbid(non_camel_case_types)];
 
 //! json serialization
diff --git a/src/libstd/list.rs b/src/libstd/list.rs
index 3016abee464..140c2013738 100644
--- a/src/libstd/list.rs
+++ b/src/libstd/list.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 //! A standard linked list
-#[forbid(deprecated_mode)];
 
 use core::cmp::Eq;
 use core::option;
diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs
index 718e805b5d9..1d831af0e29 100644
--- a/src/libstd/md4.rs
+++ b/src/libstd/md4.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use core::str;
 use core::uint;
 use core::vec;
diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs
index f4fd69aae1e..511e80b0160 100644
--- a/src/libstd/net_ip.rs
+++ b/src/libstd/net_ip.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 //! Types/fns concerning Internet Protocol (IP), versions 4 & 6
-#[forbid(deprecated_mode)];
 
 use core::libc;
 use core::prelude::*;
diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs
index 429bd6ae474..c90518f1692 100644
--- a/src/libstd/net_tcp.rs
+++ b/src/libstd/net_tcp.rs
@@ -10,6 +10,7 @@
 
 //! High-level interface to libuv's TCP functionality
 // FIXME #4425: Need FFI fixes
+
 #[allow(deprecated_mode)];
 
 use future;
diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs
index b32c97c6998..9403438dde0 100644
--- a/src/libstd/net_url.rs
+++ b/src/libstd/net_url.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 //! Types/fns concerning URLs (see RFC 3986)
-#[forbid(deprecated_mode)];
+
+#[allow(deprecated_mode)];
 
 use core::cmp::Eq;
 use core::dvec::DVec;
diff --git a/src/libstd/oldmap.rs b/src/libstd/oldmap.rs
index 18cfc8d4a2d..ad7e8e50e38 100644
--- a/src/libstd/oldmap.rs
+++ b/src/libstd/oldmap.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 //! A map type - **deprecated**, use `core::hashmap` instead
-#[forbid(deprecated_mode)];
 
 use core::container::{Container, Mutable, Map};
 use core::cmp::Eq;
diff --git a/src/libstd/par.rs b/src/libstd/par.rs
index 779dda0ab29..8293ff1c2af 100644
--- a/src/libstd/par.rs
+++ b/src/libstd/par.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use core::cast;
 use core::prelude::*;
 use core::ptr;
@@ -38,7 +36,7 @@ const min_granularity : uint = 1024u;
  */
 fn map_slices<A: Copy Owned, B: Copy Owned>(
     xs: &[A],
-    f: fn() -> fn~(uint, v: &[A]) -> B)
+    f: &fn() -> ~fn(uint, v: &[A]) -> B)
     -> ~[B] {
 
     let len = xs.len();
@@ -93,9 +91,9 @@ fn map_slices<A: Copy Owned, B: Copy Owned>(
 
 /// A parallel version of map.
 pub fn map<A: Copy Owned, B: Copy Owned>(
-    xs: &[A], f: fn~(&A) -> B) -> ~[B] {
+    xs: &[A], fn_factory: &fn() -> ~fn(&A) -> B) -> ~[B] {
     vec::concat(map_slices(xs, || {
-        let f = copy f;
+        let f = fn_factory();
         fn~(_base: uint, slice : &[A]) -> ~[B] {
             vec::map(slice, |x| f(x))
         }
@@ -103,10 +101,12 @@ pub fn map<A: Copy Owned, B: Copy Owned>(
 }
 
 /// A parallel version of mapi.
-pub fn mapi<A: Copy Owned, B: Copy Owned>(xs: &[A],
-                                    f: fn~(uint, &A) -> B) -> ~[B] {
+pub fn mapi<A: Copy Owned, B: Copy Owned>(
+    xs: &[A],
+    fn_factory: &fn() -> ~fn(uint, &A) -> B) -> ~[B]
+{
     let slices = map_slices(xs, || {
-        let f = copy f;
+        let f = fn_factory();
         fn~(base: uint, slice : &[A], copy f) -> ~[B] {
             vec::mapi(slice, |i, x| {
                 f(i + base, x)
@@ -119,32 +119,13 @@ pub fn mapi<A: Copy Owned, B: Copy Owned>(xs: &[A],
     r
 }
 
-/**
- * A parallel version of mapi.
- *
- * In this case, f is a function that creates functions to run over the
- * inner elements. This is to skirt the need for copy constructors.
- */
-pub fn mapi_factory<A: Copy Owned, B: Copy Owned>(
-    xs: &[A], f: fn() -> fn~(uint, A) -> B) -> ~[B] {
-    let slices = map_slices(xs, || {
-        let f = f();
-        fn~(base: uint, slice : &[A], move f) -> ~[B] {
-            vec::mapi(slice, |i, x| {
-                f(i + base, *x)
-            })
-        }
-    });
-    let r = vec::concat(slices);
-    log(info, (r.len(), xs.len()));
-    assert(r.len() == xs.len());
-    r
-}
-
 /// Returns true if the function holds for all elements in the vector.
-pub fn alli<A: Copy Owned>(xs: &[A], f: fn~(uint, &A) -> bool) -> bool {
+pub fn alli<A: Copy Owned>(
+    xs: &[A],
+    fn_factory: &fn() -> ~fn(uint, &A) -> bool) -> bool
+{
     do vec::all(map_slices(xs, || {
-        let f = copy f;
+        let f = fn_factory();
         fn~(base: uint, slice : &[A], copy f) -> bool {
             vec::alli(slice, |i, x| {
                 f(i + base, x)
@@ -154,9 +135,11 @@ pub fn alli<A: Copy Owned>(xs: &[A], f: fn~(uint, &A) -> bool) -> bool {
 }
 
 /// Returns true if the function holds for any elements in the vector.
-pub fn any<A: Copy Owned>(xs: &[A], f: fn~(&A) -> bool) -> bool {
+pub fn any<A: Copy Owned>(
+    xs: &[A],
+    fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
     do vec::any(map_slices(xs, || {
-        let f = copy f;
+        let f = fn_factory();
         fn~(_base : uint, slice: &[A], copy f) -> bool {
             vec::any(slice, |x| f(x))
         }
diff --git a/src/libstd/prettyprint.rs b/src/libstd/prettyprint.rs
index d07c29d624c..dc2e3d3da2b 100644
--- a/src/libstd/prettyprint.rs
+++ b/src/libstd/prettyprint.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use serialize;
 
 use core::io::Writer;
diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs
index 5dd2a056327..30baa3cc5f1 100644
--- a/src/libstd/rl.rs
+++ b/src/libstd/rl.rs
@@ -64,7 +64,7 @@ pub unsafe fn read(prompt: ~str) -> Option<~str> {
     }
 }
 
-pub type CompletionCb = fn~(~str, fn(~str));
+pub type CompletionCb = @fn(~str, fn(~str));
 
 fn complete_key(_v: @CompletionCb) {}
 
@@ -75,7 +75,7 @@ pub unsafe fn complete(cb: CompletionCb) {
 
         extern fn callback(line: *c_char, completions: *()) {
             unsafe {
-                let cb = copy *task::local_data::local_data_get(complete_key)
+                let cb = *task::local_data::local_data_get(complete_key)
                     .get();
 
                 do cb(str::raw::from_c_str(line)) |suggestion| {
diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs
index c7601f6b6b5..f8aef2c5f1e 100644
--- a/src/libstd/rope.rs
+++ b/src/libstd/rope.rs
@@ -33,8 +33,6 @@
  * * access to a character by index is logarithmic (linear in strings);
  */
 
-#[forbid(deprecated_mode)];
-
 use core::cast;
 use core::char;
 use core::option;
diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs
index 4938ead9ea8..972df73d216 100644
--- a/src/libstd/serialize.rs
+++ b/src/libstd/serialize.rs
@@ -14,7 +14,6 @@
 Core encoding and decoding interfaces.
 */
 
-#[forbid(deprecated_mode)];
 #[forbid(non_camel_case_types)];
 
 use core::at_vec;
diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs
index 5fb7d892c58..6209170ac3d 100644
--- a/src/libstd/sha1.rs
+++ b/src/libstd/sha1.rs
@@ -22,8 +22,6 @@
  * the `reset` method.
  */
 
-#[forbid(deprecated_mode)];
-
 use core::str;
 use core::uint;
 use core::vec;
diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs
index 1cd35722ab4..9af596eb1f5 100644
--- a/src/libstd/smallintmap.rs
+++ b/src/libstd/smallintmap.rs
@@ -12,7 +12,6 @@
  * A simple map based on a vector for small integer keys. Space requirements
  * are O(highest integer key).
  */
-#[forbid(deprecated_mode)];
 
 use core::container::{Container, Mutable, Map, Set};
 use core::option::{Some, None};
diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs
index 6e89cd9e24f..680a2b99c4a 100644
--- a/src/libstd/sort.rs
+++ b/src/libstd/sort.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 //! Sorting methods
-#[forbid(deprecated_mode)];
 
 use core::cmp::{Eq, Ord};
 use core::dvec::DVec;
@@ -64,14 +63,13 @@ pub pure fn merge_sort<T: Copy>(v: &[const T], le: Le<T>) -> ~[T] {
     }
 }
 
-fn part<T: Copy>(arr: &mut [T], left: uint,
-                right: uint, pivot: uint, compare_func: Le<T>) -> uint {
-    let pivot_value = arr[pivot];
+fn part<T>(arr: &mut [T], left: uint,
+           right: uint, pivot: uint, compare_func: Le<T>) -> uint {
     arr[pivot] <-> arr[right];
     let mut storage_index: uint = left;
     let mut i: uint = left;
     while i < right {
-        if compare_func(&arr[i], &pivot_value) {
+        if compare_func(&arr[i], &arr[right]) {
             arr[i] <-> arr[storage_index];
             storage_index += 1;
         }
@@ -81,8 +79,8 @@ fn part<T: Copy>(arr: &mut [T], left: uint,
     return storage_index;
 }
 
-fn qsort<T: Copy>(arr: &mut [T], left: uint,
-             right: uint, compare_func: Le<T>) {
+fn qsort<T>(arr: &mut [T], left: uint,
+            right: uint, compare_func: Le<T>) {
     if right > left {
         let pivot = (left + right) / 2u;
         let new_pivot = part::<T>(arr, left, right, pivot, compare_func);
@@ -100,7 +98,7 @@ fn qsort<T: Copy>(arr: &mut [T], left: uint,
  * Has worst case O(n^2) performance, average case O(n log n).
  * This is an unstable sort.
  */
-pub fn quick_sort<T: Copy>(arr: &mut [T], compare_func: Le<T>) {
+pub fn quick_sort<T>(arr: &mut [T], compare_func: Le<T>) {
     if len::<T>(arr) == 0u { return; }
     qsort::<T>(arr, 0u, len::<T>(arr) - 1u, compare_func);
 }
diff --git a/src/libstd/std.rc b/src/libstd/std.rc
index a2fbc8b1db1..8c142908d10 100644
--- a/src/libstd/std.rc
+++ b/src/libstd/std.rc
@@ -28,10 +28,6 @@ not required in or otherwise suitable for the core library.
 
 #[allow(vecs_implicitly_copyable)];
 #[deny(non_camel_case_types)];
-// XXX this is set to allow because there are two methods in encoding
-// that can't be silenced otherwise. Most every module is set to forbid
-#[allow(deprecated_mode)];
-#[forbid(deprecated_pattern)];
 #[allow(deprecated_self)];
 
 #[no_core];
diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs
index 31c596c5038..b7e75897bf1 100644
--- a/src/libstd/sync.rs
+++ b/src/libstd/sync.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// NB: transitionary, de-mode-ing.
-#[forbid(deprecated_mode)];
 /**
  * The concurrency primitives you know and love.
  *
diff --git a/src/libstd/tempfile.rs b/src/libstd/tempfile.rs
index f10d54f3271..b786d913639 100644
--- a/src/libstd/tempfile.rs
+++ b/src/libstd/tempfile.rs
@@ -10,8 +10,6 @@
 
 //! Temporary files and directories
 
-#[forbid(deprecated_mode)];
-
 use core::os;
 use core::prelude::*;
 use core::rand;
diff --git a/src/libstd/term.rs b/src/libstd/term.rs
index ae5949e6f18..5616c7211c1 100644
--- a/src/libstd/term.rs
+++ b/src/libstd/term.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 //! Simple ANSI color library
-#[forbid(deprecated_mode)];
 
 use core::i32;
 use core::io;
diff --git a/src/libstd/test.rs b/src/libstd/test.rs
index 4f0b7da89aa..e83b759f901 100644
--- a/src/libstd/test.rs
+++ b/src/libstd/test.rs
@@ -15,8 +15,6 @@
 // simplest interface possible for representing and running tests
 // while providing a base that other test frameworks may build off of.
 
-#[forbid(deprecated_mode)];
-
 use getopts;
 use sort;
 use term;
@@ -51,20 +49,24 @@ pub type TestName = ~str;
 // the test succeeds; if the function fails then the test fails. We
 // may need to come up with a more clever definition of test in order
 // to support isolation of tests into tasks.
-pub type TestFn = fn~();
+pub type TestFn = ~fn();
 
 // The definition of a single test. A test runner will run a list of
 // these.
 pub struct TestDesc {
     name: TestName,
-    testfn: TestFn,
     ignore: bool,
     should_fail: bool
 }
 
+pub struct TestDescAndFn {
+    desc: TestDesc,
+    testfn: TestFn,
+}
+
 // The default console test runner. It accepts the command line
 // arguments and a vector of test_descs (generated at compile time).
-pub fn test_main(args: &[~str], tests: &[TestDesc]) {
+pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
     let opts =
         match parse_opts(args) {
           either::Left(move o) => o,
@@ -124,7 +126,7 @@ struct ConsoleTestState {
 
 // A simple console test runner
 pub fn run_tests_console(opts: &TestOpts,
-                     tests: &[TestDesc]) -> bool {
+                         tests: ~[TestDescAndFn]) -> bool {
 
     fn callback(event: &TestEvent, st: @ConsoleTestState) {
         debug!("callback(event=%?)", event);
@@ -247,17 +249,17 @@ fn print_failures(st: @ConsoleTestState) {
 
 #[test]
 fn should_sort_failures_before_printing_them() {
+    fn dummy() {}
+
     let s = do io::with_str_writer |wr| {
         let test_a = TestDesc {
             name: ~"a",
-            testfn: fn~() { },
             ignore: false,
             should_fail: false
         };
 
         let test_b = TestDesc {
             name: ~"b",
-            testfn: fn~() { },
             ignore: false,
             should_fail: false
         };
@@ -291,45 +293,44 @@ enum TestEvent {
 type MonitorMsg = (TestDesc, TestResult);
 
 fn run_tests(opts: &TestOpts,
-             tests: &[TestDesc],
+             tests: ~[TestDescAndFn],
              callback: fn@(e: TestEvent)) {
     let mut filtered_tests = filter_tests(opts, tests);
-    callback(TeFiltered(copy filtered_tests));
+
+    let filtered_descs = filtered_tests.map(|t| t.desc);
+    callback(TeFiltered(filtered_descs));
 
     // It's tempting to just spawn all the tests at once, but since we have
     // many tests that run in other processes we would be making a big mess.
     let concurrency = get_concurrency();
     debug!("using %u test tasks", concurrency);
 
-    let total = vec::len(filtered_tests);
-    let mut run_idx = 0;
-    let mut wait_idx = 0;
-    let mut done_idx = 0;
+    let mut remaining = filtered_tests;
+    vec::reverse(remaining);
+    let mut pending = 0;
 
     let (p, ch) = stream();
     let ch = SharedChan(ch);
 
-    while done_idx < total {
-        while wait_idx < concurrency && run_idx < total {
-            let test = copy filtered_tests[run_idx];
+    while pending > 0 || !remaining.is_empty() {
+        while pending < concurrency && !remaining.is_empty() {
+            let test = remaining.pop();
             if concurrency == 1 {
                 // We are doing one test at a time so we can print the name
                 // of the test before we run it. Useful for debugging tests
                 // that hang forever.
-                callback(TeWait(copy test));
+                callback(TeWait(test.desc));
             }
-            run_test(move test, ch.clone());
-            wait_idx += 1;
-            run_idx += 1;
+            run_test(test, ch.clone());
+            pending += 1;
         }
 
-        let (test, result) = p.recv();
+        let (desc, result) = p.recv();
         if concurrency != 1 {
-            callback(TeWait(copy test));
+            callback(TeWait(desc));
         }
-        callback(TeResult(move test, result));
-        wait_idx -= 1;
-        done_idx += 1;
+        callback(TeResult(desc, result));
+        pending -= 1;
     }
 }
 
@@ -349,10 +350,11 @@ fn get_concurrency() -> uint {
 }
 
 #[allow(non_implicitly_copyable_typarams)]
-pub fn filter_tests(opts: &TestOpts,
-                    tests: &[TestDesc])
-                 -> ~[TestDesc] {
-    let mut filtered = vec::slice(tests, 0, tests.len());
+pub fn filter_tests(
+    opts: &TestOpts,
+    tests: ~[TestDescAndFn]) -> ~[TestDescAndFn]
+{
+    let mut filtered = tests;
 
     // Remove tests that don't match the test filter
     filtered = if opts.filter.is_none() {
@@ -364,10 +366,10 @@ pub fn filter_tests(opts: &TestOpts,
           option::None => ~""
         };
 
-        fn filter_fn(test: &TestDesc, filter_str: &str) ->
-            Option<TestDesc> {
-            if str::contains(test.name, filter_str) {
-                return option::Some(copy *test);
+        fn filter_fn(test: TestDescAndFn, filter_str: &str) ->
+            Option<TestDescAndFn> {
+            if str::contains(test.desc.name, filter_str) {
+                return option::Some(test);
             } else { return option::None; }
         }
 
@@ -378,26 +380,26 @@ pub fn filter_tests(opts: &TestOpts,
     filtered = if !opts.run_ignored {
         move filtered
     } else {
-        fn filter(test: &TestDesc) -> Option<TestDesc> {
-            if test.ignore {
-                return option::Some(TestDesc {
-                    name: test.name,
-                    testfn: copy test.testfn,
-                    ignore: false,
-                    should_fail: test.should_fail});
-            } else { return option::None; }
+        fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
+            if test.desc.ignore {
+                let TestDescAndFn {desc, testfn} = test;
+                Some(TestDescAndFn {
+                    desc: TestDesc {ignore: false, ..desc},
+                    testfn: testfn
+                })
+            } else {
+                None
+            }
         };
 
         vec::filter_map(filtered, |x| filter(x))
     };
 
     // Sort the tests alphabetically
-    filtered = {
-        pure fn lteq(t1: &TestDesc, t2: &TestDesc) -> bool {
-            str::le(t1.name, t2.name)
-        }
-        sort::merge_sort(filtered, lteq)
-    };
+    pure fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool {
+        str::le(t1.desc.name, t2.desc.name)
+    }
+    sort::quick_sort(filtered, lteq);
 
     move filtered
 }
@@ -407,37 +409,40 @@ struct TestFuture {
     wait: fn@() -> TestResult,
 }
 
-pub fn run_test(test: TestDesc, monitor_ch: SharedChan<MonitorMsg>) {
-    if test.ignore {
-        monitor_ch.send((copy test, TrIgnored));
+pub fn run_test(test: TestDescAndFn, monitor_ch: SharedChan<MonitorMsg>) {
+    let TestDescAndFn {desc, testfn} = test;
+
+    if desc.ignore {
+        monitor_ch.send((desc, TrIgnored));
         return;
     }
 
-    do task::spawn |move test| {
-        let testfn = copy test.testfn;
+    let testfn_cell = ::cell::Cell(testfn);
+    do task::spawn {
         let mut result_future = None; // task::future_result(builder);
         task::task().unlinked().future_result(|+r| {
             result_future = Some(move r);
-        }).spawn(move testfn);
+        }).spawn(testfn_cell.take());
         let task_result = option::unwrap(move result_future).recv();
-        let test_result = calc_result(&test, task_result == task::Success);
-        monitor_ch.send((copy test, test_result));
+        let test_result = calc_result(&desc, task_result == task::Success);
+        monitor_ch.send((desc, test_result));
     };
 }
 
-fn calc_result(test: &TestDesc, task_succeeded: bool) -> TestResult {
+fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult {
     if task_succeeded {
-        if test.should_fail { TrFailed }
+        if desc.should_fail { TrFailed }
         else { TrOk }
     } else {
-        if test.should_fail { TrOk }
+        if desc.should_fail { TrOk }
         else { TrFailed }
     }
 }
 
 #[cfg(test)]
 mod tests {
-    use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc};
+    use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts,
+               TestDesc, TestDescAndFn};
     use test::{TestOpts, run_test};
 
     use core::either;
@@ -448,11 +453,13 @@ mod tests {
     #[test]
     pub fn do_not_run_ignored_tests() {
         fn f() { die!(); }
-        let desc = TestDesc {
-            name: ~"whatever",
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: ~"whatever",
+                ignore: true,
+                should_fail: false
+            },
             testfn: f,
-            ignore: true,
-            should_fail: false
         };
         let (p, ch) = stream();
         let ch = SharedChan(ch);
@@ -464,11 +471,13 @@ mod tests {
     #[test]
     pub fn ignored_tests_result_in_ignored() {
         fn f() { }
-        let desc = TestDesc {
-            name: ~"whatever",
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: ~"whatever",
+                ignore: true,
+                should_fail: false
+            },
             testfn: f,
-            ignore: true,
-            should_fail: false
         };
         let (p, ch) = stream();
         let ch = SharedChan(ch);
@@ -481,11 +490,13 @@ mod tests {
     #[ignore(cfg(windows))]
     pub fn test_should_fail() {
         fn f() { die!(); }
-        let desc = TestDesc {
-            name: ~"whatever",
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: ~"whatever",
+                ignore: false,
+                should_fail: true
+            },
             testfn: f,
-            ignore: false,
-            should_fail: true
         };
         let (p, ch) = stream();
         let ch = SharedChan(ch);
@@ -497,11 +508,13 @@ mod tests {
     #[test]
     pub fn test_should_fail_but_succeeds() {
         fn f() { }
-        let desc = TestDesc {
-            name: ~"whatever",
+        let desc = TestDescAndFn {
+            desc: TestDesc {
+                name: ~"whatever",
+                ignore: false,
+                should_fail: true
+            },
             testfn: f,
-            ignore: false,
-            should_fail: true
         };
         let (p, ch) = stream();
         let ch = SharedChan(ch);
@@ -532,6 +545,8 @@ mod tests {
 
     #[test]
     pub fn filter_for_ignored_option() {
+        fn dummy() {}
+
         // When we run ignored tests the test filter should filter out all the
         // unignored tests and flip the ignore flag on the rest to false
 
@@ -542,24 +557,28 @@ mod tests {
         };
 
         let tests = ~[
-            TestDesc {
-                name: ~"1",
-                testfn: fn~() { },
-                ignore: true,
-                should_fail: false,
+            TestDescAndFn {
+                desc: TestDesc {
+                    name: ~"1",
+                    ignore: true,
+                    should_fail: false,
+                },
+                testfn: dummy,
             },
-            TestDesc {
-                name: ~"2",
-                testfn: fn~() { },
-                ignore: false,
-                should_fail: false,
+            TestDescAndFn {
+                desc: TestDesc {
+                    name: ~"2",
+                    ignore: false,
+                    should_fail: false
+                },
+                testfn: dummy,
             },
         ];
         let filtered = filter_tests(&opts, tests);
 
         assert (vec::len(filtered) == 1);
-        assert (filtered[0].name == ~"1");
-        assert (filtered[0].ignore == false);
+        assert (filtered[0].desc.name == ~"1");
+        assert (filtered[0].desc.ignore == false);
     }
 
     #[test]
@@ -579,12 +598,16 @@ mod tests {
              ~"test::sort_tests"];
         let tests =
         {
-            let testfn = fn~() { };
+            fn testfn() { }
             let mut tests = ~[];
             for vec::each(names) |name| {
-                let test = TestDesc {
-                    name: *name, testfn: copy testfn, ignore: false,
-                    should_fail: false};
+                let test = TestDescAndFn {
+                    desc: TestDesc {
+                        name: *name, ignore: false,
+                        should_fail: false
+                    },
+                    testfn: testfn,
+                };
                 tests.push(move test);
             }
             move tests
@@ -604,7 +627,7 @@ mod tests {
 
         for vec::each(pairs) |p| {
             match *p {
-                (ref a, ref b) => { assert (*a == b.name); }
+                (ref a, ref b) => { assert (*a == b.desc.name); }
             }
         }
     }
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index dd25fc36d2d..f696d239d30 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
 use core::cmp::{Eq, Ord};
 use core::int;
 use core::libc::{c_char, c_int, c_long, size_t, time_t};
diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs
index f89830ed12a..1da1bc60314 100644
--- a/src/libstd/timer.rs
+++ b/src/libstd/timer.rs
@@ -10,8 +10,6 @@
 
 //! Utilities that leverage libuv's `uv_timer_*` API
 
-#[forbid(deprecated_mode)];
-
 use uv;
 use uv::iotask;
 use uv::iotask::IoTask;
diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs
index 3cc287b16a3..1e90abcc03d 100644
--- a/src/libstd/treemap.rs
+++ b/src/libstd/treemap.rs
@@ -12,8 +12,6 @@
 //! trees. The only requirement for the types is that the key implements
 //! `Ord`, and that the `lt` method provides a total ordering.
 
-#[forbid(deprecated_mode)];
-
 use core::container::{Container, Mutable, Map, Set};
 use core::cmp::{Eq, Ord};
 use core::option::{Option, Some, None};
diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs
index 736954f6b22..9763f655a6f 100644
--- a/src/libstd/uv_global_loop.rs
+++ b/src/libstd/uv_global_loop.rs
@@ -10,8 +10,6 @@
 
 //! A process-wide libuv event loop for library use.
 
-#[forbid(deprecated_mode)];
-
 use ll = uv_ll;
 use iotask = uv_iotask;
 use get_gl = get;
diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs
index fe4137f76be..a44fef54b72 100644
--- a/src/libstd/uv_iotask.rs
+++ b/src/libstd/uv_iotask.rs
@@ -14,7 +14,6 @@
  * The I/O task runs in its own single-threaded scheduler.  By using the
  * `interact` function you can execute code in a uv callback.
  */
-#[forbid(deprecated_mode)];
 
 use ll = uv_ll;
 
diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs
index 4e9df14419b..b828c4ef629 100644
--- a/src/libstd/workcache.rs
+++ b/src/libstd/workcache.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[allow(deprecated_mode)];
+
 use json;
 use sha1;
 use serialize::{Encoder, Encodable, Decoder, Decodable};
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),
diff --git a/src/test/bench/graph500-bfs.rs b/src/test/bench/graph500-bfs.rs
index 5ade0c9ed25..222307bd240 100644
--- a/src/test/bench/graph500-bfs.rs
+++ b/src/test/bench/graph500-bfs.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #[legacy_modes];
+#[allow(deprecated_mode)];
 
 /*!
 
@@ -247,8 +248,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
         }
     }
 
+    fn is_gray_factory() -> ~fn(c: &color) -> bool {
+        let r: ~fn(c: &color) -> bool = is_gray;
+        r
+    }
+
     let mut i = 0;
-    while par::any(colors, is_gray) {
+    while par::any(colors, is_gray_factory) {
         // Do the BFS.
         log(info, fmt!("PBFS iteration %?", i));
         i += 1;
@@ -257,14 +263,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
         let color = arc::ARC(move colors);
 
         let color_vec = arc::get(&color); // FIXME #3387 requires this temp
-        colors = do par::mapi_factory(*color_vec) {
+        colors = do par::mapi(*color_vec) {
             let colors = arc::clone(&color);
             let graph = arc::clone(&graph);
-            fn~(move graph, move colors, +i: uint, +c: color) -> color {
-                let c : color = c;
+            fn~(+i: uint, +c: &color) -> color {
                 let colors = arc::get(&colors);
                 let graph = arc::get(&graph);
-                match c {
+                match *c {
                   white => {
                     let i = i as node_id;
 
@@ -290,11 +295,13 @@ fn pbfs(&&graph: arc::ARC<graph>, key: node_id) -> bfs_result {
     }
 
     // Convert the results.
-    do par::map(colors) |c| {
-        match *c {
-          white => { -1i64 }
-          black(parent) => { parent }
-          _ => { die!(~"Found remaining gray nodes in BFS") }
+    do par::map(colors) {
+        fn~(c: &color) -> i64 {
+            match *c {
+                white => { -1i64 }
+                black(parent) => { parent }
+                _ => { die!(~"Found remaining gray nodes in BFS") }
+            }
         }
     }
 }
@@ -377,14 +384,15 @@ fn validate(edges: ~[(node_id, node_id)],
 
     log(info, ~"Verifying tree and graph edges...");
 
-    let edges = copy edges;
-    let status = do par::alli(tree) |u, v| {
-        let u = u as node_id;
-        if *v == -1i64 || u == root {
-            true
-        }
-        else {
-            edges.contains(&(u, *v)) || edges.contains(&(*v, u))
+    let status = do par::alli(tree) {
+        let edges = copy edges;
+        fn~(+u: uint, v: &i64) -> bool {
+            let u = u as node_id;
+            if *v == -1i64 || u == root {
+                true
+            } else {
+                edges.contains(&(u, *v)) || edges.contains(&(*v, u))
+            }
         }
     };
 
diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs
index 20dcb079597..8e5ab45bae8 100644
--- a/src/test/bench/task-perf-alloc-unwind.rs
+++ b/src/test/bench/task-perf-alloc-unwind.rs
@@ -15,6 +15,10 @@ extern mod std;
 use std::list::{List, Cons, Nil};
 use std::time::precise_time_s;
 
+enum UniqueList {
+    ULNil, ULCons(~UniqueList)
+}
+
 fn main() {
     let (repeat, depth) = if os::getenv(~"RUST_BENCH").is_some() {
         (50, 1000)
@@ -43,7 +47,6 @@ struct State {
     box: @nillist,
     unique: ~nillist,
     fn_box: fn@() -> @nillist,
-    fn_unique: fn~() -> ~nillist,
     tuple: (@nillist, ~nillist),
     vec: ~[@nillist],
     res: r
@@ -76,7 +79,6 @@ fn recurse_or_fail(depth: int, st: Option<State>) {
                 box: @Nil,
                 unique: ~Nil,
                 fn_box: fn@() -> @nillist { @Nil::<()> },
-                fn_unique: fn~() -> ~nillist { ~Nil::<()> },
                 tuple: (@Nil, ~Nil),
                 vec: ~[@Nil],
                 res: r(@Nil)
@@ -84,14 +86,11 @@ fn recurse_or_fail(depth: int, st: Option<State>) {
           }
           Some(st) => {
             let fn_box = st.fn_box;
-            let fn_unique = copy st.fn_unique;
 
             State {
                 box: @Cons((), st.box),
                 unique: ~Cons((), @*st.unique),
                 fn_box: fn@() -> @nillist { @Cons((), fn_box()) },
-                fn_unique: fn~(move fn_unique) -> ~nillist
-                    { ~Cons((), @*fn_unique()) },
                 tuple: (@Cons((), st.tuple.first()),
                         ~Cons((), @*st.tuple.second())),
                 vec: st.vec + ~[@Cons((), st.vec.last())],
diff --git a/src/test/compile-fail/bad-var-env-capture-in-block-arg.rs b/src/test/compile-fail/bad-var-env-capture-in-block-arg.rs
deleted file mode 100644
index b093af6e80c..00000000000
--- a/src/test/compile-fail/bad-var-env-capture-in-block-arg.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let x = 3;
-    fn blah(_a: extern fn()) {}
-    blah(|| {
-        log(debug, x); //~ ERROR attempted dynamic environment capture
-    });
-}
\ No newline at end of file
diff --git a/src/test/compile-fail/block-arg-used-as-lambda-with-illegal-cap.rs b/src/test/compile-fail/block-arg-used-as-lambda-with-illegal-cap.rs
deleted file mode 100644
index 0671e804601..00000000000
--- a/src/test/compile-fail/block-arg-used-as-lambda-with-illegal-cap.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn to_lambda1(f: fn@(uint) -> uint) -> fn@(uint) -> uint {
-    return f;
-}
-
-fn to_lambda2(b: fn(uint) -> uint) -> fn@(uint) -> uint {
-    return to_lambda1(|x| b(x)); //~ ERROR illegal move from argument `b`
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/functional-struct-update.rs b/src/test/compile-fail/functional-struct-update.rs
deleted file mode 100644
index c0430a6a8bb..00000000000
--- a/src/test/compile-fail/functional-struct-update.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-struct Bar {
-    x: int,
-}
-
-impl Bar : Drop {
-    fn finalize(&self) {
-        io::println("Goodbye, cruel world");
-    }
-}
-
-struct Foo {
-    x: int,
-    y: Bar
-}
-
-fn main() {
-    let a = Foo { x: 1, y: Bar { x: 5 } };
-    let c = Foo { x: 4, .. a}; //~ ERROR cannot copy field `y` of base expression, which has a noncopyable type
-    io::println(fmt!("%?", c));
-}
-
diff --git a/src/test/compile-fail/issue-3044.rs b/src/test/compile-fail/issue-3044.rs
index 2a5785b23b7..46ad7f64589 100644
--- a/src/test/compile-fail/issue-3044.rs
+++ b/src/test/compile-fail/issue-3044.rs
@@ -8,12 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: Non-function passed to a `do` function as its last argument, or wrong number of arguments passed to a `do` function
 fn main() {
     let needlesArr: ~[char] = ~['a', 'f'];
     do vec::foldr(needlesArr) |x, y| {
+        //~^ ERROR 2 parameters were supplied (including the closure passed by the `do` keyword)
+        //~^^ ERROR Unconstrained region variable #2
+        //
+        // this last error is, um, non-ideal.
     }
-// for some reason if I use the new error syntax for the two error messages this generates,
-// the test runner gets confused -- tjc
 }
 
diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs
index 52031c900a2..bc6dd8f5dc9 100644
--- a/src/test/compile-fail/kindck-owned.rs
+++ b/src/test/compile-fail/kindck-owned.rs
@@ -24,6 +24,6 @@ fn main() {
     copy2(@&x); //~ ERROR missing `&static`
 
     copy2(fn@() {});
-    copy2(fn~() {}); //~ WARNING instantiating copy type parameter with a not implicitly copyable type
-    copy2(fn&() {}); //~ ERROR missing `copy &static`
+    copy2(fn~() {}); //~ ERROR missing `copy`
+    copy2(fn&() {}); //~ ERROR missing `&static`
 }
diff --git a/src/test/compile-fail/moves-sru-moved-field.rs b/src/test/compile-fail/moves-sru-moved-field.rs
new file mode 100644
index 00000000000..660e5596ca5
--- /dev/null
+++ b/src/test/compile-fail/moves-sru-moved-field.rs
@@ -0,0 +1,27 @@
+type Noncopyable = ~fn();
+
+struct Foo {
+    copied: int,
+    moved: ~int,
+    noncopyable: Noncopyable
+}
+
+fn test0(f: Foo, g: Noncopyable, h: Noncopyable) {
+    // just copy implicitly copyable fields from `f`, no moves:
+    let _b = Foo {moved: ~1, noncopyable: g, ..f};
+    let _c = Foo {moved: ~2, noncopyable: h, ..f};
+}
+
+fn test1(f: Foo, g: Noncopyable, h: Noncopyable) {
+    // copying move-by-default fields from `f`, so move:
+    let _b = Foo {noncopyable: g, ..f};
+    let _c = Foo {noncopyable: h, ..f}; //~ ERROR use of moved value: `f`
+}
+
+fn test2(f: Foo, g: Noncopyable) {
+    // move non-copyable field
+    let _b = Foo {copied: 22, moved: ~23, ..f};
+    let _c = Foo {noncopyable: g, ..f}; //~ ERROR use of moved value: `f`
+}
+
+fn main() {}
diff --git a/src/test/run-pass/bounded-fn-type.rs b/src/test/run-pass/bounded-fn-type.rs
deleted file mode 100644
index 5f4a88375a4..00000000000
--- a/src/test/run-pass/bounded-fn-type.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn ignore<T>(_x: T) {}
-
-pub fn main() {
-    let f: fn@:Owned() = ||();
-    ignore(f);
-}
-
diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs
index 4a254f6a7eb..9b852cbc635 100644
--- a/src/test/run-pass/morestack6.rs
+++ b/src/test/run-pass/morestack6.rs
@@ -29,11 +29,11 @@ fn calllink08() { unsafe { rustrt::get_task_id(); } }
 fn calllink09() { unsafe { rustrt::rust_sched_threads(); } }
 fn calllink10() { unsafe { rustrt::rust_get_task(); } }
 
-fn runtest(f: fn~(), frame_backoff: u32) {
+fn runtest(f: extern fn(), frame_backoff: u32) {
     runtest2(f, frame_backoff, 0 as *u8);
 }
 
-fn runtest2(f: fn~(), frame_backoff: u32, last_stk: *u8) -> u32 {
+fn runtest2(f: extern fn(), frame_backoff: u32, last_stk: *u8) -> u32 {
     unsafe {
         let curr_stk = rustrt::debug_get_stk_seg();
         if (last_stk != curr_stk && last_stk != 0 as *u8) {
@@ -67,6 +67,6 @@ pub fn main() {
         let f = *f;
         let sz = rng.next() % 256u32 + 256u32;
         let frame_backoff = rng.next() % 10u32 + 1u32;
-        task::try(|move f| runtest(f, frame_backoff) );
+        task::try(|| runtest(f, frame_backoff) );
     }
 }
diff --git a/src/test/run-pass/newtype.rs b/src/test/run-pass/newtype.rs
index 697a579f4bc..18c446fe350 100644
--- a/src/test/run-pass/newtype.rs
+++ b/src/test/run-pass/newtype.rs
@@ -16,5 +16,6 @@ fn compute(i: mytype) -> int { return i.val + 20; }
 
 pub fn main() {
     let myval = mytype(Mytype{compute: compute, val: 30});
+    io::println(fmt!("%d", compute(myval)));
     assert ((myval.compute)(myval) == 50);
 }
diff --git a/src/test/run-pass/sendfn-deep-copy.rs b/src/test/run-pass/sendfn-deep-copy.rs
deleted file mode 100644
index 520ddf3f73a..00000000000
--- a/src/test/run-pass/sendfn-deep-copy.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-pub fn main() { test05(); }
-
-fn mk_counter<A:Copy>() -> fn~(A) -> (A,uint) {
-    // The only reason that the counter is generic is so that it closes
-    // over both a type descriptor and some data.
-    let v = ~[mut 0u];
-    return fn~(a: A) -> (A,uint) {
-        let n = v[0];
-        v[0] = n + 1u;
-        (a, n)
-    };
-}
-
-fn test05() {
-    let fp0 = mk_counter::<float>();
-
-    assert (5.3f, 0u) == fp0(5.3f);
-    assert (5.5f, 1u) == fp0(5.5f);
-
-    let fp1 = copy fp0;
-
-    assert (5.3f, 2u) == fp0(5.3f);
-    assert (5.3f, 2u) == fp1(5.3f);
-    assert (5.5f, 3u) == fp0(5.5f);
-    assert (5.5f, 3u) == fp1(5.5f);
-}
diff --git a/src/test/run-pass/test-ignore-cfg.rs b/src/test/run-pass/test-ignore-cfg.rs
index 589b9794f64..1f4df7be1f3 100644
--- a/src/test/run-pass/test-ignore-cfg.rs
+++ b/src/test/run-pass/test-ignore-cfg.rs
@@ -28,11 +28,11 @@ fn checktests() {
     // Pull the tests out of the secreturn test module
     let tests = __test::tests();
 
-    let shouldignore = option::get(
-        vec::find(tests, |t| t.name == ~"shouldignore" ));
-    assert shouldignore.ignore == true;
+    assert vec::any(
+        tests,
+        |t| t.desc.name == ~"shouldignore" && t.desc.ignore);
 
-    let shouldnotignore = option::get(
-        vec::find(tests, |t| t.name == ~"shouldnotignore" ));
-    assert shouldnotignore.ignore == false;
+    assert vec::any(
+        tests,
+        |t| t.desc.name == ~"shouldnotignore" && !t.desc.ignore);
 }
\ No newline at end of file