about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-23 19:20:58 -0700
committerbors <bors@rust-lang.org>2013-09-23 19:20:58 -0700
commitd062de8aa48083439237cb338b38c25306bf6c94 (patch)
tree1ced905a1f2255a3f5207ed6c70fbe5e80cf4b41
parent348d8446739f9633897a3d728d265ee6ac59c8fb (diff)
parent3b1d3e5bf8e2f288147fd879b37bc5e6f8c5528f (diff)
downloadrust-d062de8aa48083439237cb338b38c25306bf6c94.tar.gz
rust-d062de8aa48083439237cb338b38c25306bf6c94.zip
auto merge of #9310 : pcwalton/rust/at-fn, r=pcwalton
r? @brson
-rw-r--r--doc/tutorial.md28
-rw-r--r--src/libextra/c_vec.rs59
-rw-r--r--src/libextra/rl.rs52
-rw-r--r--src/libextra/test.rs5
-rw-r--r--src/librustc/driver/driver.rs155
-rw-r--r--src/librustc/front/assign_node_ids.rs17
-rw-r--r--src/librustc/front/config.rs136
-rw-r--r--src/librustc/front/std_inject.rs179
-rw-r--r--src/librustc/front/test.rs177
-rw-r--r--src/librustc/metadata/tydecode.rs3
-rw-r--r--src/librustc/metadata/tyencode.rs2
-rw-r--r--src/librustc/middle/astencode.rs124
-rw-r--r--src/librustc/middle/dataflow.rs79
-rw-r--r--src/librustc/middle/kind.rs21
-rw-r--r--src/librustc/middle/lint.rs22
-rw-r--r--src/librustc/middle/mem_categorization.rs6
-rw-r--r--src/librustc/middle/stack_check.rs3
-rw-r--r--src/librustc/middle/trans/_match.rs102
-rw-r--r--src/librustc/middle/trans/base.rs2
-rw-r--r--src/librustc/middle/trans/closure.rs40
-rw-r--r--src/librustc/middle/trans/common.rs141
-rw-r--r--src/librustc/middle/trans/debuginfo.rs330
-rw-r--r--src/librustc/middle/trans/glue.rs10
-rw-r--r--src/librustc/middle/ty.rs7
-rw-r--r--src/librustc/middle/typeck/astconv.rs5
-rw-r--r--src/librustc/rustc.rs42
-rw-r--r--src/librustc/util/common.rs28
-rw-r--r--src/librustdoc/core.rs13
-rw-r--r--src/librusti/rusti.rs71
-rw-r--r--src/librusti/utils.rs8
-rw-r--r--src/librustpkg/rustpkg.rs4
-rw-r--r--src/librustpkg/tests.rs7
-rw-r--r--src/librustpkg/util.rs135
-rw-r--r--src/libstd/io.rs32
-rw-r--r--src/libstd/reflect.rs8
-rw-r--r--src/libstd/routine.rs (renamed from src/test/run-pass/fn-assign-managed-to-bare-2.rs)28
-rw-r--r--src/libstd/std.rs2
-rw-r--r--src/libstd/unstable/extfmt.rs22
-rw-r--r--src/libstd/unstable/finally.rs12
-rw-r--r--src/libsyntax/ast_util.rs93
-rw-r--r--src/libsyntax/diagnostic.rs79
-rw-r--r--src/libsyntax/ext/base.rs239
-rw-r--r--src/libsyntax/ext/build.rs30
-rw-r--r--src/libsyntax/ext/expand.rs489
-rw-r--r--src/libsyntax/ext/fmt.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs141
-rw-r--r--src/libsyntax/fold.rs1455
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/print/pprust.rs58
-rw-r--r--src/test/auxiliary/cci_nested_lib.rs2
-rw-r--r--src/test/auxiliary/issue4516_ty_param_lib.rs14
-rw-r--r--src/test/bench/task-perf-alloc-unwind.rs5
-rw-r--r--src/test/compile-fail/borrowck-addr-of-upvar.rs27
-rw-r--r--src/test/compile-fail/borrowck-move-by-capture.rs4
-rw-r--r--src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs4
-rw-r--r--src/test/compile-fail/dead-code-ret.rs5
-rw-r--r--src/test/compile-fail/do2.rs2
-rw-r--r--src/test/compile-fail/fn-variance-2.rs30
-rw-r--r--src/test/compile-fail/fn-variance-3.rs32
-rw-r--r--src/test/compile-fail/issue-1451.rs8
-rw-r--r--src/test/compile-fail/issue-1896-1.rs26
-rw-r--r--src/test/compile-fail/issue-2074.rs4
-rw-r--r--src/test/compile-fail/issue-897-2.rs4
-rw-r--r--src/test/compile-fail/issue-897.rs2
-rw-r--r--src/test/compile-fail/kindck-owned.rs28
-rw-r--r--src/test/compile-fail/lambda-mutate-nested.rs25
-rw-r--r--src/test/compile-fail/lambda-mutate.rs22
-rw-r--r--src/test/compile-fail/liveness-init-in-called-fn-expr.rs2
-rw-r--r--src/test/compile-fail/liveness-init-in-fn-expr.rs2
-rw-r--r--src/test/compile-fail/regions-fn-subtyping.rs16
-rw-r--r--src/test/compile-fail/regions-fns.rs2
-rw-r--r--src/test/compile-fail/regions-infer-at-fn-not-param.rs4
-rw-r--r--src/test/compile-fail/regions-infer-contravariance-due-to-ret.rs2
-rw-r--r--src/test/compile-fail/regions-infer-covariance-due-to-arg.rs2
-rw-r--r--src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs2
-rw-r--r--src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs2
-rw-r--r--src/test/compile-fail/regions-infer-not-param.rs4
-rw-r--r--src/test/compile-fail/sendfn-is-not-a-lambda.rs18
-rw-r--r--src/test/debug-info/lexical-scope-in-managed-closure.rs77
-rw-r--r--src/test/debug-info/var-captured-in-managed-closure.rs56
-rw-r--r--src/test/pretty/block-arg-disambig.rs12
-rw-r--r--src/test/pretty/do1.rs2
-rw-r--r--src/test/pretty/fn-types.rs1
-rw-r--r--src/test/run-fail/unwind-box-fn.rs24
-rw-r--r--src/test/run-fail/unwind-closure.rs21
-rw-r--r--src/test/run-fail/unwind-lambda.rs2
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-1.rs25
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-2.rs25
-rw-r--r--src/test/run-pass/block-arg-call-as.rs6
-rw-r--r--src/test/run-pass/block-arg-used-as-lambda.rs24
-rw-r--r--src/test/run-pass/borrowck-move-by-capture-ok.rs2
-rw-r--r--src/test/run-pass/call-closure-from-overloaded-op.rs2
-rw-r--r--src/test/run-pass/cap-clause-move.rs10
-rw-r--r--src/test/run-pass/close-over-big-then-small-data.rs25
-rw-r--r--src/test/run-pass/cycle-collection2.rs28
-rw-r--r--src/test/run-pass/cycle-collection4.rs20
-rw-r--r--src/test/run-pass/cycle-collection5.rs22
-rw-r--r--src/test/run-pass/do-no-args.rs4
-rw-r--r--src/test/run-pass/do1.rs2
-rw-r--r--src/test/run-pass/do2.rs2
-rw-r--r--src/test/run-pass/do3.rs2
-rw-r--r--src/test/run-pass/expr-block-fn.rs2
-rw-r--r--src/test/run-pass/expr-block-generic-box1.rs2
-rw-r--r--src/test/run-pass/expr-block-generic-box2.rs2
-rw-r--r--src/test/run-pass/expr-block-generic-unique1.rs2
-rw-r--r--src/test/run-pass/expr-block-generic-unique2.rs2
-rw-r--r--src/test/run-pass/expr-block-generic.rs2
-rw-r--r--src/test/run-pass/expr-if-generic-box1.rs2
-rw-r--r--src/test/run-pass/expr-if-generic-box2.rs2
-rw-r--r--src/test/run-pass/expr-if-generic.rs2
-rw-r--r--src/test/run-pass/expr-match-generic-box1.rs2
-rw-r--r--src/test/run-pass/expr-match-generic-box2.rs2
-rw-r--r--src/test/run-pass/expr-match-generic-unique1.rs2
-rw-r--r--src/test/run-pass/expr-match-generic-unique2.rs2
-rw-r--r--src/test/run-pass/expr-match-generic.rs2
-rw-r--r--src/test/run-pass/fixed-point-bind-box.rs30
-rw-r--r--src/test/run-pass/fixed-point-bind-unique.rs30
-rw-r--r--src/test/run-pass/fn-assign-managed-to-bare-1.rs20
-rw-r--r--src/test/run-pass/fn-bare-coerce-to-shared.rs17
-rw-r--r--src/test/run-pass/fn-coerce-field.rs4
-rw-r--r--src/test/run-pass/fn-type-infer.rs2
-rw-r--r--src/test/run-pass/fun-call-variants.rs2
-rw-r--r--src/test/run-pass/hashmap-memory.rs2
-rw-r--r--src/test/run-pass/infer-with-expected.rs25
-rw-r--r--src/test/run-pass/issue-1516.rs2
-rw-r--r--src/test/run-pass/issue-2185.rs16
-rw-r--r--src/test/run-pass/issue-2633.rs8
-rw-r--r--src/test/run-pass/issue-3052.rs2
-rw-r--r--src/test/run-pass/issue-3429.rs2
-rw-r--r--src/test/run-pass/issue-4929.rs12
-rw-r--r--src/test/run-pass/issue-5783.rs19
-rw-r--r--src/test/run-pass/issue4516_ty_param.rs25
-rw-r--r--src/test/run-pass/lambda-infer-unresolved.rs4
-rw-r--r--src/test/run-pass/lambda-no-leak.rs17
-rw-r--r--src/test/run-pass/last-use-in-cap-clause.rs4
-rw-r--r--src/test/run-pass/last-use-is-capture.rs2
-rw-r--r--src/test/run-pass/monomorphize-trait-in-fn-at.rs30
-rw-r--r--src/test/run-pass/move-nullary-fn.rs4
-rw-r--r--src/test/run-pass/nested-enum-same-names.rs16
-rw-r--r--src/test/run-pass/newlambdas-ret-infer.rs2
-rw-r--r--src/test/run-pass/newlambdas-ret-infer2.rs2
-rw-r--r--src/test/run-pass/newlambdas.rs7
-rw-r--r--src/test/run-pass/propagate-expected-type-through-block.rs12
-rw-r--r--src/test/run-pass/reflect-visit-data.rs4
-rw-r--r--src/test/run-pass/regions-fn-subtyping.rs8
-rw-r--r--src/test/run-pass/rl-human-test.rs24
-rw-r--r--src/test/run-pass/unused-move-capture.rs2
147 files changed, 2854 insertions, 2929 deletions
diff --git a/doc/tutorial.md b/doc/tutorial.md
index dd552f45f4e..a8d384226a3 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -1469,34 +1469,6 @@ cannot be stored in data structures or returned from
 functions. Despite these limitations, stack closures are used
 pervasively in Rust code.
 
-## Managed closures
-
-When you need to store a closure in a data structure, a stack closure
-will not do, since the compiler will refuse to let you store it. For
-this purpose, Rust provides a type of closure that has an arbitrary
-lifetime, written `@fn` (boxed closure, analogous to the `@` pointer
-type described earlier). This type of closure *is* first-class.
-
-A managed closure does not directly access its environment, but merely
-copies out the values that it closes over into a private data
-structure. This means that it can not assign to these variables, and
-cannot observe updates to them.
-
-This code creates a closure that adds a given string to its argument,
-returns it from a function, and then calls it:
-
-~~~~
-fn mk_appender(suffix: ~str) -> @fn(~str) -> ~str {
-    // The compiler knows that we intend this closure to be of type @fn
-    return |s| s + suffix;
-}
-
-fn main() {
-    let shout = mk_appender(~"!");
-    println(shout(~"hey ho, let's go"));
-}
-~~~~
-
 ## Owned closures
 
 Owned closures, written `~fn` in analogy to the `~` pointer type,
diff --git a/src/libextra/c_vec.rs b/src/libextra/c_vec.rs
index 30bce3a8170..bd3ce20742e 100644
--- a/src/libextra/c_vec.rs
+++ b/src/libextra/c_vec.rs
@@ -36,37 +36,39 @@
  * still held if needed.
  */
 
-
-use std::option;
 use std::ptr;
+use std::routine::Runnable;
+use std::util;
 
 /**
  * The type representing a foreign chunk of memory
- *
  */
 pub struct CVec<T> {
     priv base: *mut T,
     priv len: uint,
-    priv rsrc: @DtorRes
+    priv rsrc: @DtorRes,
 }
 
 struct DtorRes {
-  dtor: Option<@fn()>,
+    dtor: Option<~Runnable>,
 }
 
 #[unsafe_destructor]
 impl Drop for DtorRes {
     fn drop(&mut self) {
-        match self.dtor {
-            option::None => (),
-            option::Some(f) => f()
+        let dtor = util::replace(&mut self.dtor, None);
+        match dtor {
+            None => (),
+            Some(f) => f.run()
         }
     }
 }
 
-fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
-    DtorRes {
-        dtor: dtor
+impl DtorRes {
+    fn new(dtor: Option<~Runnable>) -> DtorRes {
+        DtorRes {
+            dtor: dtor,
+        }
     }
 }
 
@@ -83,10 +85,10 @@ fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
  * * len - The number of elements in the buffer
  */
 pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
-    return CVec{
+    return CVec {
         base: base,
         len: len,
-        rsrc: @DtorRes(option::None)
+        rsrc: @DtorRes::new(None)
     };
 }
 
@@ -101,12 +103,12 @@ pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
  * * dtor - A function to run when the value is destructed, useful
  *          for freeing the buffer, etc.
  */
-pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
-  -> CVec<T> {
+pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: ~Runnable)
+                                 -> CVec<T> {
     return CVec{
         base: base,
         len: len,
-        rsrc: @DtorRes(option::Some(dtor))
+        rsrc: @DtorRes::new(Some(dtor))
     };
 }
 
@@ -153,6 +155,20 @@ mod tests {
 
     use std::libc::*;
     use std::libc;
+    use std::routine::Runnable;
+
+    struct LibcFree {
+        mem: *c_void,
+    }
+
+    impl Runnable for LibcFree {
+        #[fixed_stack_segment]
+        fn run(~self) {
+            unsafe {
+                libc::free(self.mem)
+            }
+        }
+    }
 
     fn malloc(n: size_t) -> CVec<u8> {
         #[fixed_stack_segment];
@@ -163,12 +179,11 @@ mod tests {
 
             assert!(mem as int != 0);
 
-            return c_vec_with_dtor(mem as *mut u8, n as uint, || f(mem));
-        }
-
-        fn f(mem: *c_void) {
-            #[fixed_stack_segment]; #[inline(never)];
-            unsafe { libc::free(mem) }
+            return c_vec_with_dtor(mem as *mut u8,
+                                   n as uint,
+                                   ~LibcFree {
+                                    mem: mem,
+                                   } as ~Runnable);
         }
     }
 
diff --git a/src/libextra/rl.rs b/src/libextra/rl.rs
index 9476bcb8926..7662a159ba4 100644
--- a/src/libextra/rl.rs
+++ b/src/libextra/rl.rs
@@ -30,7 +30,7 @@ pub mod rustrt {
 
 macro_rules! locked {
     ($expr:expr) => {
-        unsafe {
+        {
             // FIXME #9105: can't use a static mutex in pure Rust yet.
             rustrt::rust_take_linenoise_lock();
             let x = $expr;
@@ -43,20 +43,27 @@ macro_rules! locked {
 /// Add a line to history
 pub fn add_history(line: &str) -> bool {
     do line.with_c_str |buf| {
-        (locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int
+        unsafe {
+            (locked!(rustrt::linenoiseHistoryAdd(buf))) == 1 as c_int
+        }
     }
 }
 
 /// Set the maximum amount of lines stored
 pub fn set_history_max_len(len: int) -> bool {
-    (locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1 as c_int
+    unsafe {
+        (locked!(rustrt::linenoiseHistorySetMaxLen(len as c_int))) == 1
+            as c_int
+    }
 }
 
 /// Save line history to a file
 pub fn save_history(file: &str) -> bool {
     do file.with_c_str |buf| {
         // 0 on success, -1 on failure
-        (locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int
+        unsafe {
+            (locked!(rustrt::linenoiseHistorySave(buf))) == 0 as c_int
+        }
     }
 }
 
@@ -64,14 +71,18 @@ pub fn save_history(file: &str) -> bool {
 pub fn load_history(file: &str) -> bool {
     do file.with_c_str |buf| {
         // 0 on success, -1 on failure
-        (locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int
+        unsafe {
+            (locked!(rustrt::linenoiseHistoryLoad(buf))) == 0 as c_int
+        }
     }
 }
 
 /// Print out a prompt and then wait for input and return it
 pub fn read(prompt: &str) -> Option<~str> {
     do prompt.with_c_str |buf| {
-        let line = locked!(rustrt::linenoise(buf));
+        let line = unsafe {
+            locked!(rustrt::linenoise(buf))
+        };
 
         if line.is_null() { None }
         else {
@@ -88,9 +99,13 @@ pub fn read(prompt: &str) -> Option<~str> {
     }
 }
 
-pub type CompletionCb = @fn(~str, @fn(~str));
+/// The callback used to perform completions.
+pub trait CompletionCb {
+    /// Performs a completion.
+    fn complete(&self, line: ~str, suggestion: &fn(~str));
+}
 
-local_data_key!(complete_key: CompletionCb)
+local_data_key!(complete_key: @CompletionCb)
 
 /// Bind to the main completion callback in the current task.
 ///
@@ -98,25 +113,22 @@ local_data_key!(complete_key: CompletionCb)
 /// other than the closure that it receives as its second
 /// argument. Calling such a function will deadlock on the mutex used
 /// to ensure that the calls are thread-safe.
-pub fn complete(cb: CompletionCb) {
+pub unsafe fn complete(cb: @CompletionCb) {
     local_data::set(complete_key, cb);
 
-    extern fn callback(c_line: *c_char, completions: *()) {
+    extern fn callback(line: *c_char, completions: *()) {
         do local_data::get(complete_key) |opt_cb| {
             // only fetch completions if a completion handler has been
             // registered in the current task.
             match opt_cb {
-                None => {},
+                None => {}
                 Some(cb) => {
-                    let line = unsafe { str::raw::from_c_str(c_line) };
-                    do (*cb)(line) |suggestion| {
-                        do suggestion.with_c_str |buf| {
-                            // This isn't locked, because `callback` gets
-                            // called inside `rustrt::linenoise`, which
-                            // *is* already inside the mutex, so
-                            // re-locking would be a deadlock.
-                            unsafe {
-                                rustrt::linenoiseAddCompletion(completions, buf);
+                    unsafe {
+                        do cb.complete(str::raw::from_c_str(line))
+                                |suggestion| {
+                            do suggestion.with_c_str |buf| {
+                                rustrt::linenoiseAddCompletion(completions,
+                                                               buf);
                             }
                         }
                     }
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index cc80da1506a..7400973c28a 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -807,11 +807,6 @@ pub fn filter_tests(
     }
 }
 
-struct TestFuture {
-    test: TestDesc,
-    wait: @fn() -> TestResult,
-}
-
 pub fn run_test(force_ignore: bool,
                 test: TestDescAndFn,
                 monitor_ch: SharedChan<MonitorMsg>) {
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index bd0462119bd..c9a5ca2c61c 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -113,8 +113,8 @@ pub fn build_configuration(sess: Session) ->
 }
 
 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
-fn parse_cfgspecs(cfgspecs: ~[~str],
-                  demitter: diagnostic::Emitter) -> ast::CrateConfig {
+fn parse_cfgspecs(cfgspecs: ~[~str], demitter: @diagnostic::Emitter)
+                  -> ast::CrateConfig {
     do cfgspecs.move_iter().map |s| {
         let sess = parse::new_parse_sess(Some(demitter));
         parse::parse_meta_from_source_str(@"cfgspec", s.to_managed(), ~[], sess)
@@ -439,15 +439,70 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
     phase_6_link_output(sess, &trans, outputs);
 }
 
-pub fn pretty_print_input(sess: Session, cfg: ast::CrateConfig, input: &input,
-                          ppm: PpMode) {
+struct IdentifiedAnnotation {
+    contents: (),
+}
 
-    fn ann_paren_for_expr(node: pprust::ann_node) {
+impl pprust::pp_ann for IdentifiedAnnotation {
+    fn pre(&self, node: pprust::ann_node) {
         match node {
-          pprust::node_expr(s, _) => pprust::popen(s),
-          _ => ()
+            pprust::node_expr(s, _) => pprust::popen(s),
+            _ => ()
+        }
+    }
+    fn post(&self, node: pprust::ann_node) {
+        match node {
+            pprust::node_item(s, item) => {
+                pp::space(s.s);
+                pprust::synth_comment(s, item.id.to_str());
+            }
+            pprust::node_block(s, ref blk) => {
+                pp::space(s.s);
+                pprust::synth_comment(s, ~"block " + blk.id.to_str());
+            }
+            pprust::node_expr(s, expr) => {
+                pp::space(s.s);
+                pprust::synth_comment(s, expr.id.to_str());
+                pprust::pclose(s);
+            }
+            pprust::node_pat(s, pat) => {
+                pp::space(s.s);
+                pprust::synth_comment(s, ~"pat " + pat.id.to_str());
+            }
         }
     }
+}
+
+struct TypedAnnotation {
+    analysis: CrateAnalysis,
+}
+
+impl pprust::pp_ann for TypedAnnotation {
+    fn pre(&self, node: pprust::ann_node) {
+        match node {
+            pprust::node_expr(s, _) => pprust::popen(s),
+            _ => ()
+        }
+    }
+    fn post(&self, node: pprust::ann_node) {
+        let tcx = self.analysis.ty_cx;
+        match node {
+            pprust::node_expr(s, expr) => {
+                pp::space(s.s);
+                pp::word(s.s, "as");
+                pp::space(s.s);
+                pp::word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
+                pprust::pclose(s);
+            }
+            _ => ()
+        }
+    }
+}
+
+pub fn pretty_print_input(sess: Session,
+                          cfg: ast::CrateConfig,
+                          input: &input,
+                          ppm: PpMode) {
     fn ann_typed_post(tcx: ty::ctxt, node: pprust::ann_node) {
         match node {
           pprust::node_expr(s, expr) => {
@@ -460,28 +515,6 @@ pub fn pretty_print_input(sess: Session, cfg: ast::CrateConfig, input: &input,
           _ => ()
         }
     }
-    fn ann_identified_post(node: pprust::ann_node) {
-        match node {
-          pprust::node_item(s, item) => {
-            pp::space(s.s);
-            pprust::synth_comment(s, item.id.to_str());
-          }
-          pprust::node_block(s, ref blk) => {
-            pp::space(s.s);
-            pprust::synth_comment(
-                s, ~"block " + blk.id.to_str());
-          }
-          pprust::node_expr(s, expr) => {
-            pp::space(s.s);
-            pprust::synth_comment(s, expr.id.to_str());
-            pprust::pclose(s);
-          }
-          pprust::node_pat(s, pat) => {
-            pp::space(s.s);
-            pprust::synth_comment(s, ~"pat " + pat.id.to_str());
-          }
-        }
-    }
 
     let crate = phase_1_parse_input(sess, cfg.clone(), input);
 
@@ -494,28 +527,30 @@ pub fn pretty_print_input(sess: Session, cfg: ast::CrateConfig, input: &input,
 
     let annotation = match ppm {
         PpmIdentified | PpmExpandedIdentified => {
-            pprust::pp_ann {
-                pre: ann_paren_for_expr,
-                post: ann_identified_post
-            }
+            @IdentifiedAnnotation {
+                contents: (),
+            } as @pprust::pp_ann
         }
         PpmTyped => {
             let analysis = phase_3_run_analysis_passes(sess, crate);
-            pprust::pp_ann {
-                pre: ann_paren_for_expr,
-                post: |a| ann_typed_post(analysis.ty_cx, a)
-            }
+            @TypedAnnotation {
+                analysis: analysis
+            } as @pprust::pp_ann
         }
-        _ => pprust::no_ann()
+        _ => @pprust::no_ann::new() as @pprust::pp_ann,
     };
 
     let src = sess.codemap.get_filemap(source_name(input)).src;
     do io::with_str_reader(src) |rdr| {
-        pprust::print_crate(sess.codemap, token::get_ident_interner(),
-                            sess.span_diagnostic, crate,
+        pprust::print_crate(sess.codemap,
+                            token::get_ident_interner(),
+                            sess.span_diagnostic,
+                            crate,
                             source_name(input),
-                            rdr, io::stdout(),
-                            annotation, is_expanded);
+                            rdr,
+                            io::stdout(),
+                            annotation,
+                            is_expanded);
     }
 }
 
@@ -554,8 +589,8 @@ static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'stat
     ("mips",   abi::Mips)];
 
 pub fn build_target_config(sopts: @session::options,
-                           demitter: diagnostic::Emitter)
-                        -> @session::config {
+                           demitter: @diagnostic::Emitter)
+                           -> @session::config {
     let os = match get_os(sopts.target_triple) {
       Some(os) => os,
       None => early_error(demitter, ~"unknown operating system")
@@ -603,8 +638,8 @@ pub fn host_triple() -> ~str {
 
 pub fn build_session_options(binary: @str,
                              matches: &getopts::Matches,
-                             demitter: diagnostic::Emitter)
-                          -> @session::options {
+                             demitter: @diagnostic::Emitter)
+                             -> @session::options {
     let crate_type = if matches.opt_present("lib") {
         session::lib_crate
     } else if matches.opt_present("bin") {
@@ -777,8 +812,8 @@ pub fn build_session_options(binary: @str,
     return sopts;
 }
 
-pub fn build_session(sopts: @session::options,
-                     demitter: diagnostic::Emitter) -> Session {
+pub fn build_session(sopts: @session::options, demitter: @diagnostic::Emitter)
+                     -> Session {
     let codemap = @codemap::CodeMap::new();
     let diagnostic_handler =
         diagnostic::mk_handler(Some(demitter));
@@ -789,9 +824,9 @@ pub fn build_session(sopts: @session::options,
 
 pub fn build_session_(sopts: @session::options,
                       cm: @codemap::CodeMap,
-                      demitter: diagnostic::Emitter,
+                      demitter: @diagnostic::Emitter,
                       span_diagnostic_handler: @mut diagnostic::span_handler)
-                   -> Session {
+                      -> Session {
     let target_cfg = build_target_config(sopts, demitter);
     let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
                                                     cm);
@@ -1000,8 +1035,8 @@ pub fn build_output_filenames(input: &input,
     }
 }
 
-pub fn early_error(emitter: diagnostic::Emitter, msg: ~str) -> ! {
-    emitter(None, msg, diagnostic::fatal);
+pub fn early_error(emitter: @diagnostic::Emitter, msg: ~str) -> ! {
+    emitter.emit(None, msg, diagnostic::fatal);
     fail!();
 }
 
@@ -1030,8 +1065,12 @@ mod test {
               Err(f) => fail!("test_switch_implies_cfg_test: %s", f.to_err_msg())
             };
         let sessopts = build_session_options(
-            @"rustc", matches, diagnostic::emit);
-        let sess = build_session(sessopts, diagnostic::emit);
+            @"rustc",
+            matches,
+            @diagnostic::DefaultEmitter as @diagnostic::Emitter);
+        let sess = build_session(sessopts,
+                                 @diagnostic::DefaultEmitter as
+                                    @diagnostic::Emitter);
         let cfg = build_configuration(sess);
         assert!((attr::contains_name(cfg, "test")));
     }
@@ -1048,8 +1087,12 @@ mod test {
               }
             };
         let sessopts = build_session_options(
-            @"rustc", matches, diagnostic::emit);
-        let sess = build_session(sessopts, diagnostic::emit);
+            @"rustc",
+            matches,
+            @diagnostic::DefaultEmitter as @diagnostic::Emitter);
+        let sess = build_session(sessopts,
+                                 @diagnostic::DefaultEmitter as
+                                    @diagnostic::Emitter);
         let cfg = build_configuration(sess);
         let mut test_items = cfg.iter().filter(|m| "test" == m.name());
         assert!(test_items.next().is_some());
diff --git a/src/librustc/front/assign_node_ids.rs b/src/librustc/front/assign_node_ids.rs
index 446db5c35e9..fc1b034de97 100644
--- a/src/librustc/front/assign_node_ids.rs
+++ b/src/librustc/front/assign_node_ids.rs
@@ -11,9 +11,22 @@
 use driver::session::Session;
 
 use syntax::ast;
-use syntax::ast_util;
+use syntax::fold::ast_fold;
+
+struct NodeIdAssigner {
+    sess: Session,
+}
+
+impl ast_fold for NodeIdAssigner {
+    fn new_id(&self, old_id: ast::NodeId) -> ast::NodeId {
+        assert_eq!(old_id, ast::DUMMY_NODE_ID);
+        self.sess.next_node_id()
+    }
+}
 
 pub fn assign_node_ids(sess: Session, crate: @ast::Crate) -> @ast::Crate {
-    let fold = ast_util::node_id_assigner(|| sess.next_node_id());
+    let fold = NodeIdAssigner {
+        sess: sess,
+    };
     @fold.fold_crate(crate)
 }
diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs
index 2c0068729a7..efaebcca011 100644
--- a/src/librustc/front/config.rs
+++ b/src/librustc/front/config.rs
@@ -9,13 +9,11 @@
 // except according to those terms.
 
 
-use std::option;
+use syntax::fold::ast_fold;
 use syntax::{ast, fold, attr};
 
-type in_cfg_pred = @fn(attrs: &[ast::Attribute]) -> bool;
-
-struct Context {
-    in_cfg: in_cfg_pred
+struct Context<'self> {
+    in_cfg: &'self fn(attrs: &[ast::Attribute]) -> bool,
 }
 
 // Support conditional compilation by transforming the AST, stripping out
@@ -26,43 +24,55 @@ pub fn strip_unconfigured_items(crate: @ast::Crate) -> @ast::Crate {
     }
 }
 
-pub fn strip_items(crate: &ast::Crate, in_cfg: in_cfg_pred)
-    -> @ast::Crate {
-
-    let ctxt = @Context { in_cfg: in_cfg };
+impl<'self> fold::ast_fold for Context<'self> {
+    fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
+        fold_mod(self, module)
+    }
+    fn fold_block(&self, block: &ast::Block) -> ast::Block {
+        fold_block(self, block)
+    }
+    fn fold_foreign_mod(&self, foreign_module: &ast::foreign_mod)
+                        -> ast::foreign_mod {
+        fold_foreign_mod(self, foreign_module)
+    }
+    fn fold_item_underscore(&self, item: &ast::item_) -> ast::item_ {
+        fold_item_underscore(self, item)
+    }
+}
 
-    let precursor = @fold::AstFoldFns {
-          fold_mod: |a,b| fold_mod(ctxt, a, b),
-          fold_block: |a,b| fold_block(ctxt, a, b),
-          fold_foreign_mod: |a,b| fold_foreign_mod(ctxt, a, b),
-          fold_item_underscore: |a,b| fold_item_underscore(ctxt, a, b),
-          .. *fold::default_ast_fold()
+pub fn strip_items(crate: &ast::Crate,
+                   in_cfg: &fn(attrs: &[ast::Attribute]) -> bool)
+                   -> @ast::Crate {
+    let ctxt = Context {
+        in_cfg: in_cfg,
     };
-
-    let fold = fold::make_fold(precursor);
-    @fold.fold_crate(crate)
+    @ctxt.fold_crate(crate)
 }
 
-fn filter_item(cx: @Context, item: @ast::item) ->
-   Option<@ast::item> {
-    if item_in_cfg(cx, item) { option::Some(item) } else { option::None }
+fn filter_item(cx: &Context, item: @ast::item) -> Option<@ast::item> {
+    if item_in_cfg(cx, item) {
+        Some(item)
+    } else {
+        None
+    }
 }
 
-fn filter_view_item<'r>(cx: @Context, view_item: &'r ast::view_item)-> Option<&'r ast::view_item> {
+fn filter_view_item<'r>(cx: &Context, view_item: &'r ast::view_item)
+                        -> Option<&'r ast::view_item> {
     if view_item_in_cfg(cx, view_item) {
-        option::Some(view_item)
+        Some(view_item)
     } else {
-        option::None
+        None
     }
 }
 
-fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod {
-    let filtered_items = do  m.items.iter().filter_map |a| {
-        filter_item(cx, *a).and_then(|x| fld.fold_item(x))
+fn fold_mod(cx: &Context, m: &ast::_mod) -> ast::_mod {
+    let filtered_items = do m.items.iter().filter_map |a| {
+        filter_item(cx, *a).and_then(|x| cx.fold_item(x))
     }.collect();
     let filtered_view_items = do m.view_items.iter().filter_map |a| {
         do filter_view_item(cx, a).map_move |x| {
-            fld.fold_view_item(x)
+            cx.fold_view_item(x)
         }
     }.collect();
     ast::_mod {
@@ -71,22 +81,23 @@ fn fold_mod(cx: @Context, m: &ast::_mod, fld: @fold::ast_fold) -> ast::_mod {
     }
 }
 
-fn filter_foreign_item(cx: @Context, item: @ast::foreign_item) ->
-   Option<@ast::foreign_item> {
+fn filter_foreign_item(cx: &Context, item: @ast::foreign_item)
+                       -> Option<@ast::foreign_item> {
     if foreign_item_in_cfg(cx, item) {
-        option::Some(item)
-    } else { option::None }
+        Some(item)
+    } else {
+        None
+    }
 }
 
-fn fold_foreign_mod(
-    cx: @Context,
-    nm: &ast::foreign_mod,
-    fld: @fold::ast_fold
-) -> ast::foreign_mod {
-    let filtered_items = nm.items.iter().filter_map(|a| filter_foreign_item(cx, *a)).collect();
+fn fold_foreign_mod(cx: &Context, nm: &ast::foreign_mod) -> ast::foreign_mod {
+    let filtered_items = nm.items
+                           .iter()
+                           .filter_map(|a| filter_foreign_item(cx, *a))
+                           .collect();
     let filtered_view_items = do nm.view_items.iter().filter_map |a| {
         do filter_view_item(cx, a).map_move |x| {
-            fld.fold_view_item(x)
+            cx.fold_view_item(x)
         }
     }.collect();
     ast::foreign_mod {
@@ -97,8 +108,7 @@ fn fold_foreign_mod(
     }
 }
 
-fn fold_item_underscore(cx: @Context, item: &ast::item_,
-                        fld: @fold::ast_fold) -> ast::item_ {
+fn fold_item_underscore(cx: &Context, item: &ast::item_) -> ast::item_ {
     let item = match *item {
         ast::item_impl(ref a, ref b, ref c, ref methods) => {
             let methods = methods.iter().filter(|m| method_in_cfg(cx, **m))
@@ -106,71 +116,70 @@ fn fold_item_underscore(cx: @Context, item: &ast::item_,
             ast::item_impl((*a).clone(), (*b).clone(), (*c).clone(), methods)
         }
         ast::item_trait(ref a, ref b, ref methods) => {
-            let methods = methods.iter().filter(|m| trait_method_in_cfg(cx, *m) )
-                .map(|x| (*x).clone()).collect();
+            let methods = methods.iter()
+                                 .filter(|m| trait_method_in_cfg(cx, *m) )
+                                 .map(|x| (*x).clone())
+                                 .collect();
             ast::item_trait((*a).clone(), (*b).clone(), methods)
         }
         ref item => (*item).clone(),
     };
 
-    fold::noop_fold_item_underscore(&item, fld)
+    fold::noop_fold_item_underscore(&item, cx)
 }
 
-fn filter_stmt(cx: @Context, stmt: @ast::Stmt) ->
-   Option<@ast::Stmt> {
+fn filter_stmt(cx: &Context, stmt: @ast::Stmt) -> Option<@ast::Stmt> {
     match stmt.node {
       ast::StmtDecl(decl, _) => {
         match decl.node {
           ast::DeclItem(item) => {
             if item_in_cfg(cx, item) {
-                option::Some(stmt)
-            } else { option::None }
+                Some(stmt)
+            } else {
+                None
+            }
           }
-          _ => option::Some(stmt)
+          _ => Some(stmt)
         }
       }
-      _ => option::Some(stmt)
+      _ => Some(stmt),
     }
 }
 
-fn fold_block(
-    cx: @Context,
-    b: &ast::Block,
-    fld: @fold::ast_fold
-) -> ast::Block {
+fn fold_block(cx: &Context, b: &ast::Block) -> ast::Block {
     let resulting_stmts = do b.stmts.iter().filter_map |a| {
-        filter_stmt(cx, *a).and_then(|stmt| fld.fold_stmt(stmt))
+        filter_stmt(cx, *a).and_then(|stmt| cx.fold_stmt(stmt))
     }.collect();
     let filtered_view_items = do b.view_items.iter().filter_map |a| {
-        filter_view_item(cx, a).map(|x| fld.fold_view_item(*x))
+        filter_view_item(cx, a).map(|x| cx.fold_view_item(*x))
     }.collect();
     ast::Block {
         view_items: filtered_view_items,
         stmts: resulting_stmts,
-        expr: b.expr.map(|x| fld.fold_expr(*x)),
+        expr: b.expr.map(|x| cx.fold_expr(*x)),
         id: b.id,
         rules: b.rules,
         span: b.span,
     }
 }
 
-fn item_in_cfg(cx: @Context, item: @ast::item) -> bool {
+fn item_in_cfg(cx: &Context, item: @ast::item) -> bool {
     return (cx.in_cfg)(item.attrs);
 }
 
-fn foreign_item_in_cfg(cx: @Context, item: @ast::foreign_item) -> bool {
+fn foreign_item_in_cfg(cx: &Context, item: @ast::foreign_item) -> bool {
     return (cx.in_cfg)(item.attrs);
 }
 
-fn view_item_in_cfg(cx: @Context, item: &ast::view_item) -> bool {
+fn view_item_in_cfg(cx: &Context, item: &ast::view_item) -> bool {
     return (cx.in_cfg)(item.attrs);
 }
 
-fn method_in_cfg(cx: @Context, meth: @ast::method) -> bool {
+fn method_in_cfg(cx: &Context, meth: @ast::method) -> bool {
     return (cx.in_cfg)(meth.attrs);
 }
 
-fn trait_method_in_cfg(cx: @Context, meth: &ast::trait_method) -> bool {
+fn trait_method_in_cfg(cx: &Context, meth: &ast::trait_method) -> bool {
     match *meth {
         ast::required(ref meth) => (cx.in_cfg)(meth.attrs),
         ast::provided(@ref meth) => (cx.in_cfg)(meth.attrs)
@@ -182,3 +191,4 @@ fn trait_method_in_cfg(cx: @Context, meth: &ast::trait_method) -> bool {
 fn in_cfg(cfg: &[@ast::MetaItem], attrs: &[ast::Attribute]) -> bool {
     attr::test_cfg(cfg, attrs.iter().map(|x| *x))
 }
+
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index 79e554090f3..ab407806bcc 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -16,6 +16,7 @@ use syntax::ast;
 use syntax::attr;
 use syntax::codemap::dummy_sp;
 use syntax::codemap;
+use syntax::fold::ast_fold;
 use syntax::fold;
 use syntax::opt_vec;
 
@@ -38,91 +39,103 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool {
     attr::contains_name(attrs, "no_implicit_prelude")
 }
 
-fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
-    fn spanned<T>(x: T) -> codemap::Spanned<T> {
-        codemap::Spanned { node: x, span: dummy_sp() }
+fn spanned<T>(x: T) -> codemap::Spanned<T> {
+    codemap::Spanned {
+        node: x,
+        span: dummy_sp(),
     }
+}
 
-    let precursor = @fold::AstFoldFns {
-        fold_crate: |crate, fld| {
-            let n1 = ast::DUMMY_NODE_ID;
-            let vi1 = ast::view_item {
-                node: ast::view_item_extern_mod(
-                        sess.ident_of("std"), None, ~[], n1),
-                attrs: ~[
-                    attr::mk_attr(
-                        attr::mk_name_value_item_str(@"vers", STD_VERSION.to_managed()))
-                ],
-                vis: ast::private,
-                span: dummy_sp()
-            };
-
-            let vis = vec::append(~[vi1], crate.module.view_items);
-            let mut new_module = ast::_mod {
-                view_items: vis,
-                ..crate.module.clone()
-            };
-
-            if !no_prelude(crate.attrs) {
-                // only add `use std::prelude::*;` if there wasn't a
-                // `#[no_implicit_prelude];` at the crate level.
-                new_module = fld.fold_mod(&new_module);
-            }
-
-            // FIXME #2543: Bad copy.
-            ast::Crate {
-                module: new_module,
-                ..(*crate).clone()
-            }
-        },
-        fold_item: |item, fld| {
-            if !no_prelude(item.attrs) {
-                // only recur if there wasn't `#[no_implicit_prelude];`
-                // on this item, i.e. this means that the prelude is not
-                // implicitly imported though the whole subtree
-                fold::noop_fold_item(item, fld)
-            } else {
-                Some(item)
-            }
-        },
-        fold_mod: |module, fld| {
-            let n2 = ast::DUMMY_NODE_ID;
-
-            let prelude_path = ast::Path {
-                span: dummy_sp(),
-                global: false,
-                segments: ~[
-                    ast::PathSegment {
-                        identifier: sess.ident_of("std"),
-                        lifetime: None,
-                        types: opt_vec::Empty,
-                    },
-                    ast::PathSegment {
-                        identifier: sess.ident_of("prelude"),
-                        lifetime: None,
-                        types: opt_vec::Empty,
-                    },
-                ],
-            };
-
-            let vp = @spanned(ast::view_path_glob(prelude_path, n2));
-            let vi2 = ast::view_item { node: ast::view_item_use(~[vp]),
-                                        attrs: ~[],
-                                        vis: ast::private,
-                                        span: dummy_sp() };
-
-            let vis = vec::append(~[vi2], module.view_items);
-
-            // FIXME #2543: Bad copy.
-            let new_module = ast::_mod {
-                view_items: vis,
-                ..(*module).clone()
-            };
-            fold::noop_fold_mod(&new_module, fld)
-        },
-        ..*fold::default_ast_fold()
-    };
+struct StandardLibraryInjector {
+    sess: Session,
+}
 
-    let fold = fold::make_fold(precursor);
+impl fold::ast_fold for StandardLibraryInjector {
+    fn fold_crate(&self, crate: &ast::Crate) -> ast::Crate {
+        let version = STD_VERSION.to_managed();
+        let vi1 = ast::view_item {
+            node: ast::view_item_extern_mod(self.sess.ident_of("std"),
+                                            None,
+                                            ~[],
+                                            ast::DUMMY_NODE_ID),
+            attrs: ~[
+                attr::mk_attr(attr::mk_name_value_item_str(@"vers", version))
+            ],
+            vis: ast::private,
+            span: dummy_sp()
+        };
+
+        let vis = vec::append(~[vi1], crate.module.view_items);
+        let mut new_module = ast::_mod {
+            view_items: vis,
+            ..crate.module.clone()
+        };
+
+        if !no_prelude(crate.attrs) {
+            // only add `use std::prelude::*;` if there wasn't a
+            // `#[no_implicit_prelude];` at the crate level.
+            new_module = self.fold_mod(&new_module);
+        }
+
+        // FIXME #2543: Bad copy.
+        ast::Crate {
+            module: new_module,
+            ..(*crate).clone()
+        }
+    }
+
+    fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
+        if !no_prelude(item.attrs) {
+            // only recur if there wasn't `#[no_implicit_prelude];`
+            // on this item, i.e. this means that the prelude is not
+            // implicitly imported though the whole subtree
+            fold::noop_fold_item(item, self)
+        } else {
+            Some(item)
+        }
+    }
+
+    fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
+        let prelude_path = ast::Path {
+            span: dummy_sp(),
+            global: false,
+            segments: ~[
+                ast::PathSegment {
+                    identifier: self.sess.ident_of("std"),
+                    lifetime: None,
+                    types: opt_vec::Empty,
+                },
+                ast::PathSegment {
+                    identifier: self.sess.ident_of("prelude"),
+                    lifetime: None,
+                    types: opt_vec::Empty,
+                },
+            ],
+        };
+
+        let vp = @spanned(ast::view_path_glob(prelude_path,
+                                              ast::DUMMY_NODE_ID));
+        let vi2 = ast::view_item {
+            node: ast::view_item_use(~[vp]),
+            attrs: ~[],
+            vis: ast::private,
+            span: dummy_sp(),
+        };
+
+        let vis = vec::append(~[vi2], module.view_items);
+
+        // FIXME #2543: Bad copy.
+        let new_module = ast::_mod {
+            view_items: vis,
+            ..(*module).clone()
+        };
+        fold::noop_fold_mod(&new_module, self)
+    }
+}
+
+fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate {
+    let fold = StandardLibraryInjector {
+        sess: sess,
+    };
     @fold.fold_crate(crate)
 }
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index f0d7f6c892b..18998015e95 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -21,13 +21,12 @@ use syntax::attr;
 use syntax::codemap::{dummy_sp, Span, ExpnInfo, NameAndSpan};
 use syntax::codemap;
 use syntax::ext::base::ExtCtxt;
+use syntax::fold::ast_fold;
 use syntax::fold;
 use syntax::opt_vec;
 use syntax::print::pprust;
 use syntax::{ast, ast_util};
 
-type node_id_gen = @fn() -> ast::NodeId;
-
 struct Test {
     span: Span,
     path: ~[ast::Ident],
@@ -61,9 +60,89 @@ pub fn modify_for_testing(sess: session::Session,
     }
 }
 
-fn generate_test_harness(sess: session::Session,
-                         crate: @ast::Crate)
-                      -> @ast::Crate {
+struct TestHarnessGenerator {
+    cx: @mut TestCtxt,
+}
+
+impl fold::ast_fold for TestHarnessGenerator {
+    fn fold_crate(&self, c: &ast::Crate) -> ast::Crate {
+        let folded = fold::noop_fold_crate(c, self);
+
+        // Add a special __test module to the crate that will contain code
+        // generated for the test harness
+        ast::Crate {
+            module: add_test_module(self.cx, &folded.module),
+            .. folded
+        }
+    }
+
+    fn fold_item(&self, i: @ast::item) -> Option<@ast::item> {
+        self.cx.path.push(i.ident);
+        debug!("current path: %s",
+               ast_util::path_name_i(self.cx.path.clone()));
+
+        if is_test_fn(self.cx, i) || is_bench_fn(i) {
+            match i.node {
+                ast::item_fn(_, purity, _, _, _)
+                    if purity == ast::unsafe_fn => {
+                    let sess = self.cx.sess;
+                    sess.span_fatal(i.span,
+                                    "unsafe functions cannot be used for \
+                                     tests");
+                }
+                _ => {
+                    debug!("this is a test function");
+                    let test = Test {
+                        span: i.span,
+                        path: self.cx.path.clone(),
+                        bench: is_bench_fn(i),
+                        ignore: is_ignored(self.cx, i),
+                        should_fail: should_fail(i)
+                    };
+                    self.cx.testfns.push(test);
+                    // debug!("have %u test/bench functions",
+                    //        cx.testfns.len());
+                }
+            }
+        }
+
+        let res = fold::noop_fold_item(i, self);
+        self.cx.path.pop();
+        return res;
+    }
+
+    fn fold_mod(&self, m: &ast::_mod) -> ast::_mod {
+        // Remove any #[main] from the AST so it doesn't clash with
+        // the one we're going to add. Only if compiling an executable.
+
+        fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item {
+            if !*cx.sess.building_library {
+                @ast::item {
+                    attrs: do item.attrs.iter().filter_map |attr| {
+                        if "main" != attr.name() {
+                            Some(*attr)
+                        } else {
+                            None
+                        }
+                    }.collect(),
+                    .. (*item).clone()
+                }
+            } else {
+                item
+            }
+        }
+
+        let mod_nomain = ast::_mod {
+            view_items: m.view_items.clone(),
+            items: m.items.iter().map(|i| nomain(self.cx, *i)).collect(),
+        };
+
+        fold::noop_fold_mod(&mod_nomain, self)
+    }
+}
+
+fn generate_test_harness(sess: session::Session, crate: @ast::Crate)
+                         -> @ast::Crate {
     let cx: @mut TestCtxt = @mut TestCtxt {
         sess: sess,
         crate: crate,
@@ -81,12 +160,9 @@ fn generate_test_harness(sess: session::Session,
         }
     });
 
-    let precursor = @fold::AstFoldFns {
-        fold_crate: |a,b| fold_crate(cx, a, b),
-        fold_item: |a,b| fold_item(cx, a, b),
-        fold_mod: |a,b| fold_mod(cx, a, b),.. *fold::default_ast_fold()};
-
-    let fold = fold::make_fold(precursor);
+    let fold = TestHarnessGenerator {
+        cx: cx
+    };
     let res = @fold.fold_crate(&*crate);
     ext_cx.bt_pop();
     return res;
@@ -101,85 +177,6 @@ fn strip_test_functions(crate: &ast::Crate) -> @ast::Crate {
     }
 }
 
-fn fold_mod(cx: @mut TestCtxt,
-            m: &ast::_mod,
-            fld: @fold::ast_fold)
-         -> ast::_mod {
-    // Remove any #[main] from the AST so it doesn't clash with
-    // the one we're going to add. Only if compiling an executable.
-
-    fn nomain(cx: @mut TestCtxt, item: @ast::item) -> @ast::item {
-        if !*cx.sess.building_library {
-            @ast::item {
-                attrs: do item.attrs.iter().filter_map |attr| {
-                    if "main" != attr.name() {
-                        Some(*attr)
-                    } else {
-                        None
-                    }
-                }.collect(),
-                .. (*item).clone()
-            }
-        } else {
-            item
-        }
-    }
-
-    let mod_nomain = ast::_mod {
-        view_items: m.view_items.clone(),
-        items: m.items.iter().map(|i| nomain(cx, *i)).collect(),
-    };
-
-    fold::noop_fold_mod(&mod_nomain, fld)
-}
-
-fn fold_crate(cx: @mut TestCtxt, c: &ast::Crate, fld: @fold::ast_fold)
-              -> ast::Crate {
-    let folded = fold::noop_fold_crate(c, fld);
-
-    // Add a special __test module to the crate that will contain code
-    // generated for the test harness
-    ast::Crate {
-        module: add_test_module(cx, &folded.module),
-        .. folded
-    }
-}
-
-
-fn fold_item(cx: @mut TestCtxt, i: @ast::item, fld: @fold::ast_fold)
-          -> Option<@ast::item> {
-    cx.path.push(i.ident);
-    debug!("current path: %s",
-           ast_util::path_name_i(cx.path.clone()));
-
-    if is_test_fn(cx, i) || is_bench_fn(i) {
-        match i.node {
-          ast::item_fn(_, purity, _, _, _) if purity == ast::unsafe_fn => {
-            let sess = cx.sess;
-            sess.span_fatal(
-                i.span,
-                "unsafe functions cannot be used for tests");
-          }
-          _ => {
-            debug!("this is a test function");
-            let test = Test {
-                span: i.span,
-                path: cx.path.clone(),
-                bench: is_bench_fn(i),
-                ignore: is_ignored(cx, i),
-                should_fail: should_fail(i)
-            };
-            cx.testfns.push(test);
-            // debug!("have %u test/bench functions", cx.testfns.len());
-          }
-        }
-    }
-
-    let res = fold::noop_fold_item(i, fld);
-    cx.path.pop();
-    return res;
-}
-
 fn is_test_fn(cx: @mut TestCtxt, i: @ast::item) -> bool {
     let has_test_attr = attr::contains_name(i.attrs, "test");
 
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 6e4b6180fd2..b94a43e07a1 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -95,8 +95,7 @@ pub fn parse_ident(st: &mut PState, last: char) -> ast::Ident {
     return parse_ident_(st, |a| is_last(last, a) );
 }
 
-fn parse_ident_(st: &mut PState, is_last: @fn(char) -> bool) ->
-   ast::Ident {
+fn parse_ident_(st: &mut PState, is_last: &fn(char) -> bool) -> ast::Ident {
     let rslt = scan(st, is_last, str::from_utf8);
     return st.tcx.sess.ident_of(rslt);
 }
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index e81da60ed17..417a6dae7be 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -26,7 +26,7 @@ use syntax::print::pprust::*;
 pub struct ctxt {
     diag: @mut span_handler,
     // Def -> str Callback:
-    ds: @fn(DefId) -> ~str,
+    ds: extern "Rust" fn(DefId) -> ~str,
     // The type context.
     tcx: ty::ctxt,
     abbrevs: abbrev_ctxt
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index bcc333afeec..683fbba09cc 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -24,6 +24,7 @@ use middle;
 use util::ppaux::ty_to_str;
 
 use std::at_vec;
+use std::libc;
 use extra::ebml::reader;
 use extra::ebml;
 use extra::serialize;
@@ -287,26 +288,24 @@ fn encode_ast(ebml_w: &mut writer::Encoder, item: ast::inlined_item) {
     ebml_w.end_tag();
 }
 
-// Produces a simplified copy of the AST which does not include things
-// that we do not need to or do not want to export.  For example, we
-// do not include any nested items: if these nested items are to be
-// inlined, their AST will be exported separately (this only makes
-// sense because, in Rust, nested items are independent except for
-// their visibility).
-//
-// As it happens, trans relies on the fact that we do not export
-// nested items, as otherwise it would get confused when translating
-// inlined items.
-fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
-    fn drop_nested_items(blk: &ast::Block, fld: @fold::ast_fold) -> ast::Block {
+struct NestedItemsDropper {
+    contents: (),
+}
+
+impl fold::ast_fold for NestedItemsDropper {
+    fn fold_block(&self, blk: &ast::Block) -> ast::Block {
         let stmts_sans_items = do blk.stmts.iter().filter_map |stmt| {
             match stmt.node {
-              ast::StmtExpr(_, _) | ast::StmtSemi(_, _) |
-              ast::StmtDecl(@codemap::Spanned { node: ast::DeclLocal(_), span: _}, _)
-                => Some(*stmt),
-              ast::StmtDecl(@codemap::Spanned { node: ast::DeclItem(_), span: _}, _)
-                => None,
-              ast::StmtMac(*) => fail!("unexpanded macro in astencode")
+                ast::StmtExpr(_, _) | ast::StmtSemi(_, _) |
+                ast::StmtDecl(@codemap::Spanned {
+                    node: ast::DeclLocal(_),
+                    span: _
+                }, _) => Some(*stmt),
+                ast::StmtDecl(@codemap::Spanned {
+                    node: ast::DeclItem(_),
+                    span: _
+                }, _) => None,
+                ast::StmtMac(*) => fail!("unexpanded macro in astencode")
             }
         }.collect();
         let blk_sans_items = ast::Block {
@@ -318,13 +317,24 @@ fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
             rules: blk.rules,
             span: blk.span,
         };
-        fold::noop_fold_block(&blk_sans_items, fld)
+        fold::noop_fold_block(&blk_sans_items, self)
     }
+}
 
-    let fld = fold::make_fold(@fold::AstFoldFns {
-        fold_block: drop_nested_items,
-        .. *fold::default_ast_fold()
-    });
+// Produces a simplified copy of the AST which does not include things
+// that we do not need to or do not want to export.  For example, we
+// do not include any nested items: if these nested items are to be
+// inlined, their AST will be exported separately (this only makes
+// sense because, in Rust, nested items are independent except for
+// their visibility).
+//
+// As it happens, trans relies on the fact that we do not export
+// nested items, as otherwise it would get confused when translating
+// inlined items.
+fn simplify_ast(ii: &ast::inlined_item) -> ast::inlined_item {
+    let fld = NestedItemsDropper {
+        contents: (),
+    };
 
     match *ii {
         //hack: we're not dropping items
@@ -341,14 +351,24 @@ fn decode_ast(par_doc: ebml::Doc) -> ast::inlined_item {
     Decodable::decode(&mut d)
 }
 
+struct AstRenumberer {
+    xcx: @ExtendedDecodeContext,
+}
+
+impl fold::ast_fold for AstRenumberer {
+    fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
+        self.xcx.tr_id(id)
+    }
+    fn new_span(&self, span: Span) -> Span {
+        self.xcx.tr_span(span)
+    }
+}
+
 fn renumber_ast(xcx: @ExtendedDecodeContext, ii: ast::inlined_item)
     -> ast::inlined_item {
-    let fld = fold::make_fold(@fold::AstFoldFns{
-        new_id: |a| xcx.tr_id(a),
-        new_span: |a| xcx.tr_span(a),
-        .. *fold::default_ast_fold()
-    });
-
+    let fld = AstRenumberer {
+        xcx: xcx,
+    };
     match ii {
         ast::ii_item(i) => ast::ii_item(fld.fold_item(i).unwrap()),
         ast::ii_method(d, is_provided, m) =>
@@ -830,6 +850,26 @@ impl write_tag_and_id for writer::Encoder {
     }
 }
 
+struct SideTableEncodingIdVisitor {
+    ecx_ptr: *libc::c_void,
+    new_ebml_w: writer::Encoder,
+    maps: Maps,
+}
+
+impl ast_util::IdVisitingOperation for SideTableEncodingIdVisitor {
+    fn visit_id(&self, id: ast::NodeId) {
+        // Note: this will cause a copy of ebml_w, which is bad as
+        // it is mutable. But I believe it's harmless since we generate
+        // balanced EBML.
+        let mut new_ebml_w = self.new_ebml_w.clone();
+        // See above
+        let ecx: &e::EncodeContext = unsafe {
+            cast::transmute(self.ecx_ptr)
+        };
+        encode_side_tables_for_id(ecx, self.maps, &mut new_ebml_w, id)
+    }
+}
+
 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
                              maps: Maps,
                              ebml_w: &mut writer::Encoder,
@@ -837,22 +877,16 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
     ebml_w.start_tag(c::tag_table as uint);
     let new_ebml_w = (*ebml_w).clone();
 
-    // Because the ast visitor uses @fn, I can't pass in
-    // ecx directly, but /I/ know that it'll be fine since
-    // the lifetime is tied to the CrateContext that
-    // lives this entire section.
-    let ecx_ptr : *() = unsafe { cast::transmute(ecx) };
-    ast_util::visit_ids_for_inlined_item(
-        ii,
-        |id: ast::NodeId| {
-            // Note: this will cause a copy of ebml_w, which is bad as
-            // it is mutable. But I believe it's harmless since we generate
-            // balanced EBML.
-            let mut new_ebml_w = new_ebml_w.clone();
-            // See above
-            let ecx : &e::EncodeContext = unsafe { cast::transmute(ecx_ptr) };
-            encode_side_tables_for_id(ecx, maps, &mut new_ebml_w, id)
-        });
+    // Because the ast visitor uses @IdVisitingOperation, I can't pass in
+    // ecx directly, but /I/ know that it'll be fine since the lifetime is
+    // tied to the CrateContext that lives throughout this entire section.
+    ast_util::visit_ids_for_inlined_item(ii, @SideTableEncodingIdVisitor {
+        ecx_ptr: unsafe {
+            cast::transmute(ecx)
+        },
+        new_ebml_w: new_ebml_w,
+        maps: maps,
+    } as @ast_util::IdVisitingOperation);
     ebml_w.end_tag();
 }
 
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 992d4ea2119..1af39f02d82 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -87,6 +87,42 @@ struct LoopScope<'self> {
     break_bits: ~[uint]
 }
 
+impl<O:DataFlowOperator> pprust::pp_ann for DataFlowContext<O> {
+    fn pre(&self, node: pprust::ann_node) {
+        let (ps, id) = match node {
+            pprust::node_expr(ps, expr) => (ps, expr.id),
+            pprust::node_block(ps, blk) => (ps, blk.id),
+            pprust::node_item(ps, _) => (ps, 0),
+            pprust::node_pat(ps, pat) => (ps, pat.id)
+        };
+
+        if self.nodeid_to_bitset.contains_key(&id) {
+            let (start, end) = self.compute_id_range_frozen(id);
+            let on_entry = self.on_entry.slice(start, end);
+            let entry_str = bits_to_str(on_entry);
+
+            let gens = self.gens.slice(start, end);
+            let gens_str = if gens.iter().any(|&u| u != 0) {
+                fmt!(" gen: %s", bits_to_str(gens))
+            } else {
+                ~""
+            };
+
+            let kills = self.kills.slice(start, end);
+            let kills_str = if kills.iter().any(|&u| u != 0) {
+                fmt!(" kill: %s", bits_to_str(kills))
+            } else {
+                ~""
+            };
+
+            let comment_str = fmt!("id %d: %s%s%s",
+                                   id, entry_str, gens_str, kills_str);
+            pprust::synth_comment(ps, comment_str);
+            pp::space(ps.s);
+        }
+    }
+}
+
 impl<O:DataFlowOperator> DataFlowContext<O> {
     pub fn new(tcx: ty::ctxt,
                method_map: typeck::method_map,
@@ -319,46 +355,9 @@ impl<O:DataFlowOperator+Clone+'static> DataFlowContext<O> {
     }
 
     fn pretty_print_to(@self, wr: @io::Writer, blk: &ast::Block) {
-        let pre: @fn(pprust::ann_node) = |node| {
-            let (ps, id) = match node {
-                pprust::node_expr(ps, expr) => (ps, expr.id),
-                pprust::node_block(ps, blk) => (ps, blk.id),
-                pprust::node_item(ps, _) => (ps, 0),
-                pprust::node_pat(ps, pat) => (ps, pat.id)
-            };
-
-            if self.nodeid_to_bitset.contains_key(&id) {
-                let (start, end) = self.compute_id_range_frozen(id);
-                let on_entry = self.on_entry.slice(start, end);
-                let entry_str = bits_to_str(on_entry);
-
-                let gens = self.gens.slice(start, end);
-                let gens_str = if gens.iter().any(|&u| u != 0) {
-                    fmt!(" gen: %s", bits_to_str(gens))
-                } else {
-                    ~""
-                };
-
-                let kills = self.kills.slice(start, end);
-                let kills_str = if kills.iter().any(|&u| u != 0) {
-                    fmt!(" kill: %s", bits_to_str(kills))
-                } else {
-                    ~""
-                };
-
-                let comment_str = fmt!("id %d: %s%s%s",
-                                       id, entry_str, gens_str, kills_str);
-                pprust::synth_comment(ps, comment_str);
-                pp::space(ps.s);
-            }
-        };
-
-        let post: @fn(pprust::ann_node) = |_| {
-        };
-
-        let ps = pprust::rust_printer_annotated(
-            wr, self.tcx.sess.intr(),
-            pprust::pp_ann {pre:pre, post:post});
+        let ps = pprust::rust_printer_annotated(wr,
+                                                self.tcx.sess.intr(),
+                                                self as @pprust::pp_ann);
         pprust::cbox(ps, pprust::indent_unit);
         pprust::ibox(ps, 0u);
         pprust::print_block(ps, blk);
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 6ca8086efc2..1b3224a2217 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -218,14 +218,25 @@ fn with_appropriate_checker(cx: Context, id: NodeId,
 
     let fty = ty::node_id_to_type(cx.tcx, id);
     match ty::get(fty).sty {
-        ty::ty_closure(ty::ClosureTy {sigil: OwnedSigil, bounds: bounds, _}) => {
+        ty::ty_closure(ty::ClosureTy {
+            sigil: OwnedSigil,
+            bounds: bounds,
+            _
+        }) => {
             b(|cx, fv| check_for_uniq(cx, fv, bounds))
         }
-        ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, bounds: bounds, _}) => {
-            b(|cx, fv| check_for_box(cx, fv, bounds))
+        ty::ty_closure(ty::ClosureTy {
+            sigil: ManagedSigil,
+            _
+        }) => {
+            // can't happen
         }
-        ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, bounds: bounds,
-                                      region: region, _}) => {
+        ty::ty_closure(ty::ClosureTy {
+            sigil: BorrowedSigil,
+            bounds: bounds,
+            region: region,
+            _
+        }) => {
             b(|cx, fv| check_for_block(cx, fv, bounds, region))
         }
         ty::ty_bare_fn(_) => {
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index da181ff2eb6..c29a5159e81 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -1228,17 +1228,27 @@ fn lint_unused_mut() -> @mut OuterLint {
     @mut UnusedMutLintVisitor{ stopping_on_items: false } as @mut OuterLint
 }
 
-fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
-    ast_util::id_visitor(|id| {
-        match cx.tcx.sess.lints.pop(&id) {
-            None => {},
+struct LintReportingIdVisitor {
+    cx: @mut Context,
+}
+
+impl ast_util::IdVisitingOperation for LintReportingIdVisitor {
+    fn visit_id(&self, id: ast::NodeId) {
+        match self.cx.tcx.sess.lints.pop(&id) {
+            None => {}
             Some(l) => {
                 for (lint, span, msg) in l.move_iter() {
-                    cx.span_lint(lint, span, msg)
+                    self.cx.span_lint(lint, span, msg)
                 }
             }
         }
-    }, false)
+    }
+}
+
+fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
+    ast_util::id_visitor(@LintReportingIdVisitor {
+        cx: cx,
+    } as @ast_util::IdVisitingOperation, false)
 }
 
 struct UnnecessaryAllocationLintVisitor { stopping_on_items: bool }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 0e3c10ef214..9cc95b873d2 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -187,8 +187,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_ptr(gc_ptr(m)))
         }
 
-        ty::ty_estr(ty::vstore_box) |
-        ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
+        ty::ty_estr(ty::vstore_box) => {
             Some(deref_ptr(gc_ptr(ast::MutImmutable)))
         }
 
@@ -515,7 +514,8 @@ impl mem_categorization_ctxt {
                           (ast::BorrowedSigil, ast::Once) => true,
                           // Heap closures always capture by copy/move, and can
                           // move out iff they are once.
-                          (ast::OwnedSigil, _) | (ast::ManagedSigil, _) => false,
+                          (ast::OwnedSigil, _) |
+                          (ast::ManagedSigil, _) => false,
 
                       };
                       if var_is_refd {
diff --git a/src/librustc/middle/stack_check.rs b/src/librustc/middle/stack_check.rs
index 7ab6cfcdf7b..5388e64348c 100644
--- a/src/librustc/middle/stack_check.rs
+++ b/src/librustc/middle/stack_check.rs
@@ -116,8 +116,7 @@ fn stack_check_fn<'a>(v: StackCheckVisitor,
         visit::fk_anon(*) | visit::fk_fn_block => {
             match ty::get(ty::node_id_to_type(in_cx.tcx, id)).sty {
                 ty::ty_bare_fn(*) |
-                ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) |
-                ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
+                ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
                     false
                 }
                 _ => {
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index c9a113aeb96..0de01bced1f 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -533,7 +533,7 @@ fn enter_default<'r>(bcx: @mut Block,
                      m: &[Match<'r>],
                      col: uint,
                      val: ValueRef,
-                     chk: Option<mk_fail>)
+                     chk: FailureHandler)
                       -> ~[Match<'r>] {
     debug!("enter_default(bcx=%s, m=%s, col=%u, val=%s)",
            bcx.to_str(),
@@ -567,7 +567,7 @@ fn enter_default<'r>(bcx: @mut Block,
     // we don't need any default cases. If the check *isn't* nonexhaustive
     // (because chk is Some), then we need the defaults anyways.
     let is_exhaustive = match matches.last_opt() {
-        Some(m) if m.data.arm.guard.is_some() && chk.is_none() => true,
+        Some(m) if m.data.arm.guard.is_some() && chk.is_infallible() => true,
         _ => false
     };
 
@@ -1185,7 +1185,62 @@ fn any_tuple_struct_pat(bcx: @mut Block, m: &[Match], col: uint) -> bool {
     }
 }
 
-type mk_fail = @fn() -> BasicBlockRef;
+trait CustomFailureHandler {
+    fn handle_fail(&self) -> BasicBlockRef;
+}
+
+struct DynamicFailureHandler {
+    bcx: @mut Block,
+    sp: Span,
+    msg: @str,
+    finished: @mut Option<BasicBlockRef>,
+}
+
+impl CustomFailureHandler for DynamicFailureHandler {
+    fn handle_fail(&self) -> BasicBlockRef {
+        match *self.finished {
+            Some(bb) => return bb,
+            _ => (),
+        }
+
+        let fail_cx = sub_block(self.bcx, "case_fallthrough");
+        controlflow::trans_fail(fail_cx, Some(self.sp), self.msg);
+        *self.finished = Some(fail_cx.llbb);
+        fail_cx.llbb
+    }
+}
+
+/// What to do when the pattern match fails.
+enum FailureHandler {
+    Infallible,
+    JumpToBasicBlock(BasicBlockRef),
+    CustomFailureHandlerClass(@CustomFailureHandler),
+}
+
+impl FailureHandler {
+    fn is_infallible(&self) -> bool {
+        match *self {
+            Infallible => true,
+            _ => false,
+        }
+    }
+
+    fn is_fallible(&self) -> bool {
+        !self.is_infallible()
+    }
+
+    fn handle_fail(&self) -> BasicBlockRef {
+        match *self {
+            Infallible => {
+                fail!("attempted to fail in infallible failure handler!")
+            }
+            JumpToBasicBlock(basic_block) => basic_block,
+            CustomFailureHandlerClass(custom_failure_handler) => {
+                custom_failure_handler.handle_fail()
+            }
+        }
+    }
+}
 
 fn pick_col(m: &[Match]) -> uint {
     fn score(p: &ast::Pat) -> uint {
@@ -1347,7 +1402,7 @@ fn compile_guard(bcx: @mut Block,
                      data: &ArmData,
                      m: &[Match],
                      vals: &[ValueRef],
-                     chk: Option<mk_fail>)
+                     chk: FailureHandler)
                   -> @mut Block {
     debug!("compile_guard(bcx=%s, guard_expr=%s, m=%s, vals=%s)",
            bcx.to_str(),
@@ -1400,9 +1455,9 @@ fn compile_guard(bcx: @mut Block,
 }
 
 fn compile_submatch(bcx: @mut Block,
-                        m: &[Match],
-                        vals: &[ValueRef],
-                        chk: Option<mk_fail>) {
+                    m: &[Match],
+                    vals: &[ValueRef],
+                    chk: FailureHandler) {
     debug!("compile_submatch(bcx=%s, m=%s, vals=%s)",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -1412,11 +1467,11 @@ fn compile_submatch(bcx: @mut Block,
     /*
       For an empty match, a fall-through case must exist
      */
-    assert!((m.len() > 0u || chk.is_some()));
+    assert!((m.len() > 0u || chk.is_fallible()));
     let _icx = push_ctxt("match::compile_submatch");
     let mut bcx = bcx;
     if m.len() == 0u {
-        Br(bcx, chk.unwrap()());
+        Br(bcx, chk.handle_fail());
         return;
     }
     if m[0].pats.len() == 0u {
@@ -1454,7 +1509,7 @@ fn compile_submatch(bcx: @mut Block,
 fn compile_submatch_continue(mut bcx: @mut Block,
                              m: &[Match],
                              vals: &[ValueRef],
-                             chk: Option<mk_fail>,
+                             chk: FailureHandler,
                              col: uint,
                              val: ValueRef) {
     let tcx = bcx.tcx();
@@ -1617,7 +1672,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
     };
 
     let defaults = enter_default(else_cx, dm, m, col, val, chk);
-    let exhaustive = chk.is_none() && defaults.len() == 0u;
+    let exhaustive = chk.is_infallible() && defaults.len() == 0u;
     let len = opts.len();
 
     // Compile subtrees for each option
@@ -1721,7 +1776,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
 
                   // If none of these subcases match, move on to the
                   // next condition.
-                  branch_chk = Some::<mk_fail>(|| bcx.llbb);
+                  branch_chk = JumpToBasicBlock(bcx.llbb);
                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
               }
               _ => ()
@@ -1860,11 +1915,15 @@ fn trans_match_inner(scope_cx: @mut Block,
         if ty::type_is_empty(tcx, t) {
             // Special case for empty types
             let fail_cx = @mut None;
-            let f: mk_fail = || mk_fail(scope_cx, discr_expr.span,
-                            @"scrutinizing value that can't exist", fail_cx);
-            Some(f)
+            let fail_handler = @DynamicFailureHandler {
+                bcx: scope_cx,
+                sp: discr_expr.span,
+                msg: @"scrutinizing value that can't exist",
+                finished: fail_cx,
+            } as @CustomFailureHandler;
+            CustomFailureHandlerClass(fail_handler)
         } else {
-            None
+            Infallible
         }
     };
     let lldiscr = discr_datum.to_zeroable_ref_llval(bcx);
@@ -1892,15 +1951,6 @@ fn trans_match_inner(scope_cx: @mut Block,
 
     bcx = controlflow::join_blocks(scope_cx, arm_cxs);
     return bcx;
-
-    fn mk_fail(bcx: @mut Block, sp: Span, msg: @str,
-               finished: @mut Option<BasicBlockRef>) -> BasicBlockRef {
-        match *finished { Some(bb) => return bb, _ => () }
-        let fail_cx = sub_block(bcx, "case_fallthrough");
-        controlflow::trans_fail(fail_cx, Some(sp), msg);
-        *finished = Some(fail_cx.llbb);
-        return fail_cx.llbb;
-    }
 }
 
 enum IrrefutablePatternBindingMode {
@@ -1913,7 +1963,7 @@ enum IrrefutablePatternBindingMode {
 pub fn store_local(bcx: @mut Block,
                    pat: @ast::Pat,
                    opt_init_expr: Option<@ast::Expr>)
-                               -> @mut Block {
+                   -> @mut Block {
     /*!
      * Generates code for a local variable declaration like
      * `let <pat>;` or `let <pat> = <opt_init_expr>`.
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 441cc1bfae2..67aee43bc46 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1320,7 +1320,7 @@ pub fn trans_block_cleanups_(bcx: @mut Block,
                 // Some types don't need to be cleaned up during
                 // landing pads because they can be freed en mass later
                 if cleanup_type == normal_exit_and_unwind || !is_lpad {
-                    bcx = cfn(bcx);
+                    bcx = cfn.clean(bcx);
                 }
             }
         }
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 605032dc20c..b5b181e22a6 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -172,7 +172,7 @@ pub fn allocate_cbox(bcx: @mut Block, sigil: ast::Sigil, cdata_ty: ty::t)
     // Allocate and initialize the box:
     match sigil {
         ast::ManagedSigil => {
-            malloc_raw(bcx, cdata_ty, heap_managed)
+            tcx.sess.bug("trying to trans allocation of @fn")
         }
         ast::OwnedSigil => {
             malloc_raw(bcx, cdata_ty, heap_for_unique_closure(bcx, cdata_ty))
@@ -197,7 +197,8 @@ pub struct ClosureResult {
 // Otherwise, it is stack allocated and copies pointers to the upvars.
 pub fn store_environment(bcx: @mut Block,
                          bound_values: ~[EnvValue],
-                         sigil: ast::Sigil) -> ClosureResult {
+                         sigil: ast::Sigil)
+                         -> ClosureResult {
     let _icx = push_ctxt("closure::store_environment");
     let ccx = bcx.ccx();
     let tcx = ccx.tcx;
@@ -444,27 +445,6 @@ pub fn make_closure_glue(
     }
 }
 
-pub fn make_opaque_cbox_take_glue(
-    bcx: @mut Block,
-    sigil: ast::Sigil,
-    cboxptr: ValueRef)     // ptr to ptr to the opaque closure
-    -> @mut Block {
-    // Easy cases:
-    let _icx = push_ctxt("closure::make_opaque_cbox_take_glue");
-    match sigil {
-        ast::BorrowedSigil => {
-            return bcx;
-        }
-        ast::ManagedSigil => {
-            glue::incr_refcnt_of_boxed(bcx, Load(bcx, cboxptr));
-            return bcx;
-        }
-        ast::OwnedSigil => {
-            fail!("unique closures are not copyable")
-        }
-    }
-}
-
 pub fn make_opaque_cbox_drop_glue(
     bcx: @mut Block,
     sigil: ast::Sigil,
@@ -474,9 +454,7 @@ pub fn make_opaque_cbox_drop_glue(
     match sigil {
         ast::BorrowedSigil => bcx,
         ast::ManagedSigil => {
-            glue::decr_refcnt_maybe_free(
-                bcx, Load(bcx, cboxptr), Some(cboxptr),
-                ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
+            bcx.tcx().sess.bug("trying to trans drop glue of @fn")
         }
         ast::OwnedSigil => {
             glue::free_ty(
@@ -516,12 +494,8 @@ pub fn make_opaque_cbox_free_glue(
                                     abi::tydesc_field_drop_glue, None);
 
         // Free the ty descr (if necc) and the box itself
-        match sigil {
-            ast::ManagedSigil => glue::trans_free(bcx, cbox),
-            ast::OwnedSigil => glue::trans_exchange_free(bcx, cbox),
-            ast::BorrowedSigil => {
-                bcx.sess().bug("impossible")
-            }
-        }
+        glue::trans_exchange_free(bcx, cbox);
+
+        bcx
     }
 }
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index b659a93f5f0..377144b38e7 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -294,9 +294,85 @@ pub enum cleantype {
     normal_exit_and_unwind
 }
 
+// Cleanup functions
+
+/// A cleanup function: a built-in destructor.
+pub trait CleanupFunction {
+    fn clean(&self, block: @mut Block) -> @mut Block;
+}
+
+/// A cleanup function that calls the "drop glue" (destructor function) on
+/// a typed value.
+pub struct TypeDroppingCleanupFunction {
+    val: ValueRef,
+    t: ty::t,
+}
+
+impl CleanupFunction for TypeDroppingCleanupFunction {
+    fn clean(&self, block: @mut Block) -> @mut Block {
+        glue::drop_ty(block, self.val, self.t)
+    }
+}
+
+/// A cleanup function that calls the "drop glue" (destructor function) on
+/// an immediate typed value.
+pub struct ImmediateTypeDroppingCleanupFunction {
+    val: ValueRef,
+    t: ty::t,
+}
+
+impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
+    fn clean(&self, block: @mut Block) -> @mut Block {
+        glue::drop_ty_immediate(block, self.val, self.t)
+    }
+}
+
+/// A cleanup function that releases a write guard, returning a value to
+/// mutable status.
+pub struct WriteGuardReleasingCleanupFunction {
+    root_key: root_map_key,
+    frozen_val_ref: ValueRef,
+    bits_val_ref: ValueRef,
+    filename_val: ValueRef,
+    line_val: ValueRef,
+}
+
+impl CleanupFunction for WriteGuardReleasingCleanupFunction {
+    fn clean(&self, bcx: @mut Block) -> @mut Block {
+        write_guard::return_to_mut(bcx,
+                                   self.root_key,
+                                   self.frozen_val_ref,
+                                   self.bits_val_ref,
+                                   self.filename_val,
+                                   self.line_val)
+    }
+}
+
+/// A cleanup function that frees some memory in the garbage-collected heap.
+pub struct GCHeapFreeingCleanupFunction {
+    ptr: ValueRef,
+}
+
+impl CleanupFunction for GCHeapFreeingCleanupFunction {
+    fn clean(&self, bcx: @mut Block) -> @mut Block {
+        glue::trans_free(bcx, self.ptr)
+    }
+}
+
+/// A cleanup function that frees some memory in the exchange heap.
+pub struct ExchangeHeapFreeingCleanupFunction {
+    ptr: ValueRef,
+}
+
+impl CleanupFunction for ExchangeHeapFreeingCleanupFunction {
+    fn clean(&self, bcx: @mut Block) -> @mut Block {
+        glue::trans_exchange_free(bcx, self.ptr)
+    }
+}
+
 pub enum cleanup {
-    clean(@fn(@mut Block) -> @mut Block, cleantype),
-    clean_temp(ValueRef, @fn(@mut Block) -> @mut Block, cleantype),
+    clean(@CleanupFunction, cleantype),
+    clean_temp(ValueRef, @CleanupFunction, cleantype),
 }
 
 // Can't use deriving(Clone) because of the managed closure.
@@ -337,13 +413,19 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
 }
 
 pub fn add_clean(bcx: @mut Block, val: ValueRef, t: ty::t) {
-    if !ty::type_needs_drop(bcx.tcx(), t) { return; }
+    if !ty::type_needs_drop(bcx.tcx(), t) {
+        return
+    }
 
     debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
 
     let cleanup_type = cleanup_type(bcx.tcx(), t);
     do in_scope_cx(bcx, None) |scope_info| {
-        scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
+        scope_info.cleanups.push(clean(@TypeDroppingCleanupFunction {
+            val: val,
+            t: t,
+        } as @CleanupFunction,
+        cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
@@ -355,9 +437,12 @@ pub fn add_clean_temp_immediate(cx: @mut Block, val: ValueRef, ty: ty::t) {
            ty.repr(cx.tcx()));
     let cleanup_type = cleanup_type(cx.tcx(), ty);
     do in_scope_cx(cx, None) |scope_info| {
-        scope_info.cleanups.push(
-            clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
-                       cleanup_type));
+        scope_info.cleanups.push(clean_temp(val,
+            @ImmediateTypeDroppingCleanupFunction {
+                val: val,
+                t: ty,
+            } as @CleanupFunction,
+            cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
@@ -381,7 +466,12 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @mut Block, scope_id: Option<ast::NodeI
            t.repr(bcx.tcx()));
     let cleanup_type = cleanup_type(bcx.tcx(), t);
     do in_scope_cx(bcx, scope_id) |scope_info| {
-        scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
+        scope_info.cleanups.push(clean_temp(val,
+            @TypeDroppingCleanupFunction {
+                val: val,
+                t: t,
+            } as @CleanupFunction,
+            cleanup_type));
         grow_scope_clean(scope_info);
     }
 }
@@ -405,29 +495,36 @@ pub fn add_clean_return_to_mut(bcx: @mut Block,
            bcx.val_to_str(frozen_val_ref),
            bcx.val_to_str(bits_val_ref));
     do in_scope_cx(bcx, Some(scope_id)) |scope_info| {
-        scope_info.cleanups.push(
-            clean_temp(
+        scope_info.cleanups.push(clean_temp(
                 frozen_val_ref,
-                |bcx| write_guard::return_to_mut(bcx, root_key, frozen_val_ref, bits_val_ref,
-                                                 filename_val, line_val),
+                @WriteGuardReleasingCleanupFunction {
+                    root_key: root_key,
+                    frozen_val_ref: frozen_val_ref,
+                    bits_val_ref: bits_val_ref,
+                    filename_val: filename_val,
+                    line_val: line_val,
+                } as @CleanupFunction,
                 normal_exit_only));
         grow_scope_clean(scope_info);
     }
 }
 pub fn add_clean_free(cx: @mut Block, ptr: ValueRef, heap: heap) {
     let free_fn = match heap {
-      heap_managed | heap_managed_unique => {
-        let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_free(a, ptr);
-        f
-      }
-      heap_exchange | heap_exchange_closure => {
-        let f: @fn(@mut Block) -> @mut Block = |a| glue::trans_exchange_free(a, ptr);
-        f
-      }
+        heap_managed | heap_managed_unique => {
+            @GCHeapFreeingCleanupFunction {
+                ptr: ptr,
+            } as @CleanupFunction
+        }
+        heap_exchange | heap_exchange_closure => {
+            @ExchangeHeapFreeingCleanupFunction {
+                ptr: ptr,
+            } as @CleanupFunction
+        }
     };
     do in_scope_cx(cx, None) |scope_info| {
-        scope_info.cleanups.push(clean_temp(ptr, free_fn,
-                                      normal_exit_and_unwind));
+        scope_info.cleanups.push(clean_temp(ptr,
+                                            free_fn,
+                                            normal_exit_and_unwind));
         grow_scope_clean(scope_info);
     }
 }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 272ce49a377..91f6169b419 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -1086,6 +1086,36 @@ fn pointer_type_metadata(cx: &mut CrateContext,
     return ptr_metadata;
 }
 
+trait MemberDescriptionFactory {
+    fn create_member_descriptions(&self, cx: &mut CrateContext)
+                                  -> ~[MemberDescription];
+}
+
+struct StructMemberDescriptionFactory {
+    fields: ~[ty::field],
+    span: Span,
+}
+
+impl MemberDescriptionFactory for StructMemberDescriptionFactory {
+    fn create_member_descriptions(&self, cx: &mut CrateContext)
+                                  -> ~[MemberDescription] {
+        do self.fields.map |field| {
+            let name = if field.ident.name == special_idents::unnamed_field.name {
+                @""
+            } else {
+                token::ident_to_str(&field.ident)
+            };
+
+            MemberDescription {
+                name: name,
+                llvm_type: type_of::type_of(cx, field.mt.ty),
+                type_metadata: type_metadata(cx, field.mt.ty, self.span),
+                offset: ComputedMemberOffset,
+            }
+        }
+    }
+}
+
 fn prepare_struct_metadata(cx: &mut CrateContext,
                            struct_type: ty::t,
                            def_id: ast::DefId,
@@ -1114,22 +1144,10 @@ fn prepare_struct_metadata(cx: &mut CrateContext,
         metadata_stub: struct_metadata_stub,
         llvm_type: struct_llvm_type,
         file_metadata: file_metadata,
-        member_description_factory: |cx| {
-            do fields.map |field| {
-                let name = if field.ident.name == special_idents::unnamed_field.name {
-                    @""
-                } else {
-                    token::ident_to_str(&field.ident)
-                };
-
-                MemberDescription {
-                    name: name,
-                    llvm_type: type_of::type_of(cx, field.mt.ty),
-                    type_metadata: type_metadata(cx, field.mt.ty, span),
-                    offset: ComputedMemberOffset,
-                }
-            }
-        }
+        member_description_factory: @StructMemberDescriptionFactory {
+            fields: fields,
+            span: span,
+        } as @MemberDescriptionFactory,
     }
 }
 
@@ -1139,7 +1157,7 @@ enum RecursiveTypeDescription {
         metadata_stub: DICompositeType,
         llvm_type: Type,
         file_metadata: DIFile,
-        member_description_factory: @fn(cx: &mut CrateContext) -> ~[MemberDescription],
+        member_description_factory: @MemberDescriptionFactory,
     },
     FinalMetadata(DICompositeType)
 }
@@ -1167,7 +1185,8 @@ impl RecursiveTypeDescription {
                 debug_context(cx).created_types.insert(cache_id, metadata_stub);
 
                 // ... then create the member descriptions ...
-                let member_descriptions = member_description_factory(cx);
+                let member_descriptions = member_description_factory.
+                    create_member_descriptions(cx);
 
                 // ... and attach them to the stub to complete it.
                 set_members_of_composite_type(cx,
@@ -1182,6 +1201,25 @@ impl RecursiveTypeDescription {
     }
 }
 
+struct TupleMemberDescriptionFactory {
+    component_types: ~[ty::t],
+    span: Span,
+}
+
+impl MemberDescriptionFactory for TupleMemberDescriptionFactory {
+    fn create_member_descriptions(&self, cx: &mut CrateContext)
+                                  -> ~[MemberDescription] {
+        do self.component_types.map |&component_type| {
+            MemberDescription {
+                name: @"",
+                llvm_type: type_of::type_of(cx, component_type),
+                type_metadata: type_metadata(cx, component_type, self.span),
+                offset: ComputedMemberOffset,
+            }
+        }
+    }
+}
+
 fn prepare_tuple_metadata(cx: &mut CrateContext,
                           tuple_type: ty::t,
                           component_types: &[ty::t],
@@ -1192,8 +1230,6 @@ fn prepare_tuple_metadata(cx: &mut CrateContext,
 
     let loc = span_start(cx, span);
     let file_metadata = file_metadata(cx, loc.file.name);
-    // Needs to be copied for closure below :(
-    let component_types = component_types.to_owned();
 
     UnfinishedMetadata {
         cache_id: cache_id_for_type(tuple_type),
@@ -1205,17 +1241,147 @@ fn prepare_tuple_metadata(cx: &mut CrateContext,
                                           span),
         llvm_type: tuple_llvm_type,
         file_metadata: file_metadata,
-        member_description_factory: |cx| {
-            do component_types.map |&component_type| {
+        member_description_factory: @TupleMemberDescriptionFactory {
+            component_types: component_types.to_owned(),
+            span: span,
+        } as @MemberDescriptionFactory
+    }
+}
+
+struct GeneralMemberDescriptionFactory {
+    type_rep: @adt::Repr,
+    variants: @~[@ty::VariantInfo],
+    discriminant_type_metadata: ValueRef,
+    containing_scope: DIScope,
+    file_metadata: DIFile,
+    span: Span,
+}
+
+impl MemberDescriptionFactory for GeneralMemberDescriptionFactory {
+    fn create_member_descriptions(&self, cx: &mut CrateContext)
+                                  -> ~[MemberDescription] {
+        // Capture type_rep, so we don't have to copy the struct_defs array
+        let struct_defs = match *self.type_rep {
+            adt::General(ref struct_defs) => struct_defs,
+            _ => cx.sess.bug("unreachable")
+        };
+
+        do struct_defs
+            .iter()
+            .enumerate()
+            .map |(i, struct_def)| {
+                let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
+                    describe_variant(cx,
+                                     struct_def,
+                                     self.variants[i],
+                                     Some(self.discriminant_type_metadata),
+                                     self.containing_scope,
+                                     self.file_metadata,
+                                     self.span);
+
+                let member_descriptions =
+                    member_desc_factory.create_member_descriptions(cx);
+
+                set_members_of_composite_type(cx,
+                                              variant_type_metadata,
+                                              variant_llvm_type,
+                                              member_descriptions,
+                                              self.file_metadata,
+                                              codemap::dummy_sp());
                 MemberDescription {
                     name: @"",
-                    llvm_type: type_of::type_of(cx, component_type),
-                    type_metadata: type_metadata(cx, component_type, span),
-                    offset: ComputedMemberOffset,
+                    llvm_type: variant_llvm_type,
+                    type_metadata: variant_type_metadata,
+                    offset: FixedMemberOffset { bytes: 0 },
                 }
+        }.collect()
+    }
+}
+
+struct EnumVariantMemberDescriptionFactory {
+    args: ~[(@str, ty::t)],
+    discriminant_type_metadata: Option<DIType>,
+    span: Span,
+}
+
+impl MemberDescriptionFactory for EnumVariantMemberDescriptionFactory {
+    fn create_member_descriptions(&self, cx: &mut CrateContext)
+                                  -> ~[MemberDescription] {
+        do self.args.iter().enumerate().map |(i, &(name, ty))| {
+            MemberDescription {
+                name: name,
+                llvm_type: type_of::type_of(cx, ty),
+                type_metadata: match self.discriminant_type_metadata {
+                    Some(metadata) if i == 0 => metadata,
+                    _ => type_metadata(cx, ty, self.span)
+                },
+                offset: ComputedMemberOffset,
+            }
+        }.collect()
+    }
+}
+
+fn describe_variant(cx: &mut CrateContext,
+                    struct_def: &adt::Struct,
+                    variant_info: &ty::VariantInfo,
+                    discriminant_type_metadata: Option<DIType>,
+                    containing_scope: DIScope,
+                    file_metadata: DIFile,
+                    span: Span)
+                 -> (DICompositeType, Type, @MemberDescriptionFactory) {
+    let variant_name = token::ident_to_str(&variant_info.name);
+    let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
+                                          struct_def.packed);
+    // Could some consistency checks here: size, align, field count, discr type
+
+    // Find the source code location of the variant's definition
+    let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
+        match cx.tcx.items.find(&variant_info.id.node) {
+            Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
+            ref node => {
+                cx.sess.span_warn(span,
+                    fmt!("debuginfo::enum_metadata()::adt_struct_metadata() - Unexpected node \
+                          type: %?. This is a bug.", node));
+                codemap::dummy_sp()
             }
         }
+    } else {
+        // For definitions from other crates we have no location information available.
+        codemap::dummy_sp()
+    };
+
+    let metadata_stub = create_struct_stub(cx,
+                                           variant_llvm_type,
+                                           variant_name,
+                                           containing_scope,
+                                           file_metadata,
+                                           variant_definition_span);
+
+    // Get the argument names from the enum variant info
+    let mut arg_names = match variant_info.arg_names {
+        Some(ref names) => do names.map |ident| { token::ident_to_str(ident) },
+        None => do variant_info.args.map |_| { @"" }
+    };
+
+    // If this is not a univariant enum, there is also the (unnamed) discriminant field
+    if discriminant_type_metadata.is_some() {
+        arg_names.insert(0, @"");
     }
+
+    // Build an array of (field name, field type) pairs to be captured in the factory closure.
+    let args: ~[(@str, ty::t)] = arg_names.iter()
+        .zip(struct_def.fields.iter())
+        .map(|(&s, &t)| (s, t))
+        .collect();
+
+    let member_description_factory =
+        @EnumVariantMemberDescriptionFactory {
+            args: args,
+            discriminant_type_metadata: discriminant_type_metadata,
+            span: span,
+        } as @MemberDescriptionFactory;
+
+    (metadata_stub, variant_llvm_type, member_description_factory)
 }
 
 fn prepare_enum_metadata(cx: &mut CrateContext,
@@ -1336,42 +1502,14 @@ fn prepare_enum_metadata(cx: &mut CrateContext,
                 metadata_stub: enum_metadata,
                 llvm_type: enum_llvm_type,
                 file_metadata: file_metadata,
-                member_description_factory: |cx| {
-                    // Capture type_rep, so we don't have to copy the struct_defs array
-                    let struct_defs = match *type_rep {
-                        adt::General(ref struct_defs) => struct_defs,
-                        _ => cx.sess.bug("unreachable")
-                    };
-
-                    do struct_defs
-                        .iter()
-                        .enumerate()
-                        .map |(i, struct_def)| {
-                            let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
-                                describe_variant(cx,
-                                                 struct_def,
-                                                 variants[i],
-                                                 Some(discriminant_type_metadata),
-                                                 containing_scope,
-                                                 file_metadata,
-                                                 span);
-
-                            let member_descriptions = member_desc_factory(cx);
-
-                            set_members_of_composite_type(cx,
-                                                          variant_type_metadata,
-                                                          variant_llvm_type,
-                                                          member_descriptions,
-                                                          file_metadata,
-                                                          codemap::dummy_sp());
-                            MemberDescription {
-                                name: @"",
-                                llvm_type: variant_llvm_type,
-                                type_metadata: variant_type_metadata,
-                                offset: FixedMemberOffset { bytes: 0 },
-                            }
-                    }.collect()
-                }
+                member_description_factory: @GeneralMemberDescriptionFactory {
+                    type_rep: type_rep,
+                    variants: variants,
+                    discriminant_type_metadata: discriminant_type_metadata,
+                    containing_scope: containing_scope,
+                    file_metadata: file_metadata,
+                    span: span,
+                } as @MemberDescriptionFactory,
             }
         }
         adt::NullablePointer { nonnull: ref struct_def, nndiscr, _ } => {
@@ -1393,76 +1531,6 @@ fn prepare_enum_metadata(cx: &mut CrateContext,
             }
         }
     };
-
-    fn describe_variant(cx: &mut CrateContext,
-                        struct_def: &adt::Struct,
-                        variant_info: &ty::VariantInfo,
-                        discriminant_type_metadata: Option<DIType>,
-                        containing_scope: DIScope,
-                        file_metadata: DIFile,
-                        span: Span)
-                     -> (DICompositeType, Type, @fn(&mut CrateContext) -> ~[MemberDescription]) {
-        let variant_name = token::ident_to_str(&variant_info.name);
-        let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
-                                              struct_def.packed);
-        // Could some consistency checks here: size, align, field count, discr type
-
-        // Find the source code location of the variant's definition
-        let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
-            match cx.tcx.items.find(&variant_info.id.node) {
-                Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
-                ref node => {
-                    cx.sess.span_warn(span,
-                        fmt!("debuginfo::enum_metadata()::adt_struct_metadata() - Unexpected node \
-                              type: %?. This is a bug.", node));
-                    codemap::dummy_sp()
-                }
-            }
-        } else {
-            // For definitions from other crates we have no location information available.
-            codemap::dummy_sp()
-        };
-
-        let metadata_stub = create_struct_stub(cx,
-                                               variant_llvm_type,
-                                               variant_name,
-                                               containing_scope,
-                                               file_metadata,
-                                               variant_definition_span);
-
-        // Get the argument names from the enum variant info
-        let mut arg_names = match variant_info.arg_names {
-            Some(ref names) => do names.map |ident| { token::ident_to_str(ident) },
-            None => do variant_info.args.map |_| { @"" }
-        };
-
-        // If this is not a univariant enum, there is also the (unnamed) discriminant field
-        if discriminant_type_metadata.is_some() {
-            arg_names.insert(0, @"");
-        }
-
-        // Build an array of (field name, field type) pairs to be captured in the factory closure.
-        let args: ~[(@str, ty::t)] = arg_names.iter()
-            .zip(struct_def.fields.iter())
-            .map(|(&s, &t)| (s, t))
-            .collect();
-
-        let member_description_factory: @fn(cx: &mut CrateContext) -> ~[MemberDescription] = |cx| {
-            do args.iter().enumerate().map |(i, &(name, ty))| {
-                MemberDescription {
-                    name: name,
-                    llvm_type: type_of::type_of(cx, ty),
-                    type_metadata: match discriminant_type_metadata {
-                        Some(metadata) if i == 0 => metadata,
-                        _ => type_metadata(cx, ty, span)
-                    },
-                    offset: ComputedMemberOffset,
-                }
-            }.collect()
-        };
-
-        (metadata_stub, variant_llvm_type, member_description_factory)
-    }
 }
 
 enum MemberOffset {
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 1958d3c9adb..a760801d73a 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -581,11 +581,7 @@ pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
       | ty::ty_estr(ty::vstore_slice(_)) => {
         bcx
       }
-      ty::ty_closure(ty::ClosureTy { sigil: ast::BorrowedSigil, _ }) |
-      ty::ty_closure(ty::ClosureTy { sigil: ast::ManagedSigil, _ }) => {
-        closure::make_closure_glue(bcx, v, t, take_ty)
-      }
-      ty::ty_closure(ty::ClosureTy { sigil: ast::OwnedSigil, _ }) => bcx,
+      ty::ty_closure(_) => bcx,
       ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
         let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]));
         incr_refcnt_of_boxed(bcx, llbox);
@@ -606,9 +602,7 @@ pub fn make_take_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
                                 None);
           bcx
       }
-      ty::ty_opaque_closure_ptr(ck) => {
-        closure::make_opaque_cbox_take_glue(bcx, ck, v)
-      }
+      ty::ty_opaque_closure_ptr(_) => bcx,
       ty::ty_struct(did, _) => {
         let tcx = bcx.tcx();
         let bcx = iter_structural_ty(bcx, v, t, take_ty);
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 9abee133290..bcf4de08073 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2308,12 +2308,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             ast::Many => TC_NONE
         };
         // Prevent noncopyable types captured in the environment from being copied.
-        let ct = if cty.sigil == ast::ManagedSigil {
-            TC_NONE
-        } else {
-            TC_NONCOPY_TRAIT
-        };
-        st + rt + ot + ct
+        st + rt + ot + TC_NONCOPY_TRAIT
     }
 
     fn trait_contents(store: TraitStore, mutbl: ast::Mutability,
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 36405136e63..024010e40df 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -400,6 +400,11 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope + Clone + 'static>(
                                             bf.abis, &bf.lifetimes, &bf.decl))
       }
       ast::ty_closure(ref f) => {
+        if f.sigil == ast::ManagedSigil {
+            tcx.sess.span_err(ast_ty.span,
+                              "managed closures are not supported");
+        }
+
           let bounds = conv_builtin_bounds(this.tcx(), &f.bounds, match f.sigil {
               // Use corresponding trait store to figure out default bounds
               // if none were specified.
diff --git a/src/librustc/rustc.rs b/src/librustc/rustc.rs
index a90ab11535e..f1f7a7bf2d6 100644
--- a/src/librustc/rustc.rs
+++ b/src/librustc/rustc.rs
@@ -33,6 +33,7 @@ use driver::driver::{compile_input};
 use driver::session;
 use middle::lint;
 
+use std::comm;
 use std::io;
 use std::num;
 use std::os;
@@ -43,6 +44,7 @@ use std::vec;
 use extra::getopts::groups;
 use extra::getopts;
 use syntax::codemap;
+use syntax::diagnostic::Emitter;
 use syntax::diagnostic;
 
 pub mod middle {
@@ -191,7 +193,7 @@ pub fn describe_debug_flags() {
     }
 }
 
-pub fn run_compiler(args: &[~str], demitter: diagnostic::Emitter) {
+pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
     // Don't display log spew by default. Can override with RUST_LOG.
     ::std::logging::console_off();
 
@@ -291,6 +293,23 @@ pub enum monitor_msg {
     done,
 }
 
+struct RustcEmitter {
+    ch_capture: comm::SharedChan<monitor_msg>
+}
+
+impl diagnostic::Emitter for RustcEmitter {
+    fn emit(&self,
+            cmsp: Option<(@codemap::CodeMap, codemap::Span)>,
+            msg: &str,
+            lvl: diagnostic::level) {
+        if lvl == diagnostic::fatal {
+            self.ch_capture.send(fatal)
+        }
+
+        diagnostic::DefaultEmitter.emit(cmsp, msg, lvl)
+    }
+}
+
 /*
 This is a sanity check that any failure of the compiler is performed
 through the diagnostic module and reported properly - we shouldn't be calling
@@ -303,7 +322,7 @@ diagnostic emitter which records when we hit a fatal error. If the task
 fails without recording a fatal error then we've encountered a compiler
 bug and need to present an error.
 */
-pub fn monitor(f: ~fn(diagnostic::Emitter)) {
+pub fn monitor(f: ~fn(@diagnostic::Emitter)) {
     use std::comm::*;
 
     // XXX: This is a hack for newsched since it doesn't support split stacks.
@@ -324,18 +343,11 @@ pub fn monitor(f: ~fn(diagnostic::Emitter)) {
 
     match do task_builder.try {
         let ch = ch_capture.clone();
-        let ch_capture = ch.clone();
         // The 'diagnostics emitter'. Every error, warning, etc. should
         // go through this function.
-        let demitter: @fn(Option<(@codemap::CodeMap, codemap::Span)>,
-                          &str,
-                          diagnostic::level) =
-                          |cmsp, msg, lvl| {
-            if lvl == diagnostic::fatal {
-                ch_capture.send(fatal);
-            }
-            diagnostic::emit(cmsp, msg, lvl);
-        };
+        let demitter = @RustcEmitter {
+            ch_capture: ch.clone(),
+        } as @diagnostic::Emitter;
 
         struct finally {
             ch: SharedChan<monitor_msg>,
@@ -357,7 +369,7 @@ pub fn monitor(f: ~fn(diagnostic::Emitter)) {
         result::Err(_) => {
             // Task failed without emitting a fatal diagnostic
             if p.recv() == done {
-                diagnostic::emit(
+                diagnostic::DefaultEmitter.emit(
                     None,
                     diagnostic::ice_msg("unexpected failure"),
                     diagnostic::error);
@@ -370,7 +382,9 @@ pub fn monitor(f: ~fn(diagnostic::Emitter)) {
                      to github.com/mozilla/rust/issues"
                 ];
                 for note in xs.iter() {
-                    diagnostic::emit(None, *note, diagnostic::note)
+                    diagnostic::DefaultEmitter.emit(None,
+                                                    *note,
+                                                    diagnostic::note)
                 }
             }
             // Fail so the process returns a failure code
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 46620319a82..8337354724a 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -60,12 +60,12 @@ pub fn field_exprs(fields: ~[ast::Field]) -> ~[@ast::Expr] {
     fields.map(|f| f.expr)
 }
 
-struct LoopQueryVisitor {
-    p: @fn(&ast::Expr_) -> bool
+struct LoopQueryVisitor<'self> {
+    p: &'self fn(&ast::Expr_) -> bool
 }
 
-impl Visitor<@mut bool> for LoopQueryVisitor {
-    fn visit_expr(&mut self, e:@ast::Expr, flag:@mut bool) {
+impl<'self> Visitor<@mut bool> for LoopQueryVisitor<'self> {
+    fn visit_expr(&mut self, e: @ast::Expr, flag: @mut bool) {
         *flag |= (self.p)(&e.node);
         match e.node {
           // Skip inner loops, since a break in the inner loop isn't a
@@ -78,19 +78,21 @@ impl Visitor<@mut bool> for LoopQueryVisitor {
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn loop_query(b: &ast::Block, p: @fn(&ast::Expr_) -> bool) -> bool {
+pub fn loop_query(b: &ast::Block, p: &fn(&ast::Expr_) -> bool) -> bool {
     let rs = @mut false;
-    let mut v = LoopQueryVisitor { p: p };
+    let mut v = LoopQueryVisitor {
+        p: p,
+    };
     visit::walk_block(&mut v, b, rs);
     return *rs;
 }
 
-struct BlockQueryVisitor {
-    p: @fn(@ast::Expr) -> bool
+struct BlockQueryVisitor<'self> {
+    p: &'self fn(@ast::Expr) -> bool
 }
 
-impl Visitor<@mut bool> for BlockQueryVisitor {
-    fn visit_expr(&mut self, e:@ast::Expr, flag:@mut bool) {
+impl<'self> Visitor<@mut bool> for BlockQueryVisitor<'self> {
+    fn visit_expr(&mut self, e: @ast::Expr, flag: @mut bool) {
         *flag |= (self.p)(e);
         visit::walk_expr(self, e, flag)
     }
@@ -98,9 +100,11 @@ impl Visitor<@mut bool> for BlockQueryVisitor {
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn block_query(b: &ast::Block, p: @fn(@ast::Expr) -> bool) -> bool {
+pub fn block_query(b: &ast::Block, p: &fn(@ast::Expr) -> bool) -> bool {
     let rs = @mut false;
-    let mut v = BlockQueryVisitor { p: p };
+    let mut v = BlockQueryVisitor {
+        p: p,
+    };
     visit::walk_block(&mut v, b, rs);
     return *rs;
 }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 9fb5e8c04c1..8a7bb1f9346 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -11,9 +11,10 @@
 use rustc;
 use rustc::{driver, middle};
 
-use syntax;
-use syntax::parse;
 use syntax::ast;
+use syntax::diagnostic;
+use syntax::parse;
+use syntax;
 
 use std::os;
 use std::local_data;
@@ -48,9 +49,11 @@ fn get_ast_and_resolve(cpath: &Path, libs: ~[Path]) -> DocContext {
     let span_diagnostic_handler =
         syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
 
-    let sess = driver::driver::build_session_(sessopts, parsesess.cm,
-                                                  syntax::diagnostic::emit,
-                                                  span_diagnostic_handler);
+    let sess = driver::driver::build_session_(sessopts,
+                                              parsesess.cm,
+                                              @diagnostic::DefaultEmitter as
+                                                @diagnostic::Emitter,
+                                              span_diagnostic_handler);
 
     let mut cfg = build_configuration(sess);
     cfg.push(@dummy_spanned(ast::MetaWord(@"stage2")));
diff --git a/src/librusti/rusti.rs b/src/librusti/rusti.rs
index 368596b3f44..462c0a29236 100644
--- a/src/librusti/rusti.rs
+++ b/src/librusti/rusti.rs
@@ -72,12 +72,14 @@ extern mod syntax;
 
 use std::{libc, io, os, task};
 use std::cell::Cell;
+use extra::rl::CompletionCb;
 use extra::rl;
 
 use rustc::driver::{driver, session};
 use rustc::back::link::jit;
-use syntax::{ast, diagnostic};
+use syntax::{ast, codemap, diagnostic};
 use syntax::ast_util::*;
+use syntax::diagnostic::Emitter;
 use syntax::parse::token;
 use syntax::print::pprust;
 
@@ -107,6 +109,28 @@ enum CmdAction {
     action_run_line(~str),
 }
 
+struct EncodableWarningEmitter;
+
+impl diagnostic::Emitter for EncodableWarningEmitter {
+    fn emit(&self,
+            cm: Option<(@codemap::CodeMap, codemap::Span)>,
+            msg: &str,
+            lvl: diagnostic::level) {
+        diagnostic::DefaultEmitter.emit(cm, msg, lvl);
+        if msg.contains("failed to find an implementation of trait") &&
+           msg.contains("extra::serialize::Encodable") {
+            diagnostic::DefaultEmitter.emit(cm,
+                                            "Currrently rusti serializes \
+                                             bound locals between different \
+                                             lines of input. This means that \
+                                             all values of local variables \
+                                             need to be encodable, and this \
+                                             type isn't encodable",
+                                            diagnostic::note);
+        }
+    }
+}
+
 /// Run an input string in a Repl, returning the new Repl.
 fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
        input: ~str) -> (~Program, Option<~jit::Engine>)
@@ -124,18 +148,9 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
     // extra helpful information if the error crops up. Otherwise people are
     // bound to be very confused when they find out code is running that they
     // never typed in...
-    let sess = driver::build_session(options, |cm, msg, lvl| {
-        diagnostic::emit(cm, msg, lvl);
-        if msg.contains("failed to find an implementation of trait") &&
-           msg.contains("extra::serialize::Encodable") {
-            diagnostic::emit(cm,
-                             "Currrently rusti serializes bound locals between \
-                              different lines of input. This means that all \
-                              values of local variables need to be encodable, \
-                              and this type isn't encodable",
-                             diagnostic::note);
-        }
-    });
+    let sess = driver::build_session(options,
+                                     @EncodableWarningEmitter as
+                                        @diagnostic::Emitter);
     let intr = token::get_ident_interner();
 
     //
@@ -243,7 +258,9 @@ fn run(mut program: ~Program, binary: ~str, lib_search_paths: ~[~str],
     let input = driver::str_input(code.to_managed());
     let cfg = driver::build_configuration(sess);
     let outputs = driver::build_output_filenames(&input, &None, &None, [], sess);
-    let sess = driver::build_session(options, diagnostic::emit);
+    let sess = driver::build_session(options,
+                                     @diagnostic::DefaultEmitter as
+                                        @diagnostic::Emitter);
 
     let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
     let expanded_crate = driver::phase_2_configure_and_expand(sess, cfg, crate);
@@ -305,7 +322,9 @@ fn compile_crate(src_filename: ~str, binary: ~str) -> Option<bool> {
             .. (*session::basic_options()).clone()
         };
         let input = driver::file_input(src_path.clone());
-        let sess = driver::build_session(options, diagnostic::emit);
+        let sess = driver::build_session(options,
+                                         @diagnostic::DefaultEmitter as
+                                            @diagnostic::Emitter);
         *sess.building_library = true;
         let cfg = driver::build_configuration(sess);
         let outputs = driver::build_output_filenames(
@@ -502,6 +521,19 @@ pub fn main() {
     main_args(args);
 }
 
+struct Completer;
+
+impl CompletionCb for Completer {
+    fn complete(&self, line: ~str, suggest: &fn(~str)) {
+        if line.starts_with(":") {
+            suggest(~":clear");
+            suggest(~":exit");
+            suggest(~":help");
+            suggest(~":load");
+        }
+    }
+}
+
 pub fn main_args(args: &[~str]) {
     #[fixed_stack_segment]; #[inline(never)];
 
@@ -525,13 +557,8 @@ pub fn main_args(args: &[~str]) {
         println("unstable. If you encounter problems, please use the");
         println("compiler instead. Type :help for help.");
 
-        do rl::complete |line, suggest| {
-            if line.starts_with(":") {
-                suggest(~":clear");
-                suggest(~":exit");
-                suggest(~":help");
-                suggest(~":load");
-            }
+        unsafe {
+            rl::complete(@Completer as @CompletionCb)
         }
     }
 
diff --git a/src/librusti/utils.rs b/src/librusti/utils.rs
index 400399253a5..904594fdfb8 100644
--- a/src/librusti/utils.rs
+++ b/src/librusti/utils.rs
@@ -15,11 +15,11 @@ use syntax::print::pprust;
 use syntax::parse::token;
 use syntax::visit;
 
-struct EachBindingVisitor {
-    f: @fn(&ast::Path, ast::NodeId)
+struct EachBindingVisitor<'self> {
+    f: &'self fn(&ast::Path, ast::NodeId)
 }
 
-impl visit::Visitor<()> for EachBindingVisitor {
+impl<'self> visit::Visitor<()> for EachBindingVisitor<'self> {
     fn visit_pat(&mut self, pat:@ast::Pat, _:()) {
                 match pat.node {
                     ast::PatIdent(_, ref path, _) => {
@@ -32,7 +32,7 @@ impl visit::Visitor<()> for EachBindingVisitor {
     }
 }
 
-pub fn each_binding(l: @ast::Local, f: @fn(&ast::Path, ast::NodeId)) {
+pub fn each_binding(l: @ast::Local, f: &fn(&ast::Path, ast::NodeId)) {
     use syntax::visit::Visitor;
 
     let mut vt = EachBindingVisitor{ f: f };
diff --git a/src/librustpkg/rustpkg.rs b/src/librustpkg/rustpkg.rs
index 077d1cf02f8..25d0802b9ad 100644
--- a/src/librustpkg/rustpkg.rs
+++ b/src/librustpkg/rustpkg.rs
@@ -110,7 +110,9 @@ impl<'self> PkgScript<'self> {
             .. (*session::basic_options()).clone()
         };
         let input = driver::file_input(script.clone());
-        let sess = driver::build_session(options, diagnostic::emit);
+        let sess = driver::build_session(options,
+                                         @diagnostic::DefaultEmitter as
+                                            @diagnostic::Emitter);
         let cfg = driver::build_configuration(sess);
         let crate = driver::phase_1_parse_input(sess, cfg.clone(), &input);
         let crate = driver::phase_2_configure_and_expand(sess, cfg.clone(), crate);
diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs
index f3992c3fe57..79f137de853 100644
--- a/src/librustpkg/tests.rs
+++ b/src/librustpkg/tests.rs
@@ -1567,8 +1567,11 @@ fn test_linker_build() {
     let matches = getopts([], optgroups());
     let options = build_session_options(@"rustpkg",
                                         matches.get_ref(),
-                                        diagnostic::emit);
-    let sess = build_session(options, diagnostic::emit);
+                                        @diagnostic::DefaultEmitter as
+                                            @diagnostic::Emitter);
+    let sess = build_session(options,
+                             @diagnostic::DefaultEmitter as
+                                @diagnostic::Emitter);
     command_line_test([test_sysroot().to_str(),
                        ~"install",
                        ~"--linker",
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index 906bed2f234..5d5e895a5ad 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -16,8 +16,11 @@ use extra::getopts::groups::getopts;
 use syntax::ast_util::*;
 use syntax::codemap::{dummy_sp, Spanned};
 use syntax::ext::base::ExtCtxt;
-use syntax::{ast, attr, codemap, diagnostic, fold};
+use syntax::{ast, attr, codemap, diagnostic, fold, visit};
 use syntax::attr::AttrMetaMethods;
+use syntax::fold::ast_fold;
+use syntax::visit::Visitor;
+use rustc::back::link::output_type_exe;
 use rustc::back::link;
 use rustc::driver::session::{lib_crate, bin_crate};
 use context::{in_target, StopBefore, Link, Assemble, BuildContext};
@@ -26,6 +29,7 @@ use package_source::PkgSrc;
 use workspace::pkg_parent_workspaces;
 use path_util::{installed_library_in_workspace, U_RWX, rust_path, system_library, target_build_dir};
 use messages::error;
+use conditions::nonexistent_package::cond;
 
 pub use target::{OutputType, Main, Lib, Bench, Test, JustOne, lib_name_of, lib_crate_filename};
 use workcache_support::{digest_file_with_date, digest_only_date};
@@ -70,9 +74,8 @@ struct ReadyCtx {
     fns: ~[ListenerFn]
 }
 
-fn fold_mod(_ctx: @mut ReadyCtx,
-            m: &ast::_mod,
-            fold: @fold::ast_fold) -> ast::_mod {
+fn fold_mod(_ctx: @mut ReadyCtx, m: &ast::_mod, fold: &CrateSetup)
+            -> ast::_mod {
     fn strip_main(item: @ast::item) -> @ast::item {
         @ast::item {
             attrs: do item.attrs.iter().filter_map |attr| {
@@ -94,9 +97,8 @@ fn fold_mod(_ctx: @mut ReadyCtx,
     }, fold)
 }
 
-fn fold_item(ctx: @mut ReadyCtx,
-             item: @ast::item,
-             fold: @fold::ast_fold) -> Option<@ast::item> {
+fn fold_item(ctx: @mut ReadyCtx, item: @ast::item, fold: &CrateSetup)
+             -> Option<@ast::item> {
     ctx.path.push(item.ident);
 
     let mut cmds = ~[];
@@ -134,6 +136,19 @@ fn fold_item(ctx: @mut ReadyCtx,
     res
 }
 
+struct CrateSetup {
+    ctx: @mut ReadyCtx,
+}
+
+impl fold::ast_fold for CrateSetup {
+    fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
+        fold_item(self.ctx, item, self)
+    }
+    fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
+        fold_mod(self.ctx, module, self)
+    }
+}
+
 /// Generate/filter main function, add the list of commands, etc.
 pub fn ready_crate(sess: session::Session,
                    crate: @ast::Crate) -> @ast::Crate {
@@ -144,15 +159,9 @@ pub fn ready_crate(sess: session::Session,
         path: ~[],
         fns: ~[]
     };
-    let precursor = @fold::AstFoldFns {
-        // fold_crate: fold::wrap(|a, b| fold_crate(ctx, a, b)),
-        fold_item: |a, b| fold_item(ctx, a, b),
-        fold_mod: |a, b| fold_mod(ctx, a, b),
-        .. *fold::default_ast_fold()
+    let fold = CrateSetup {
+        ctx: ctx,
     };
-
-    let fold = fold::make_fold(precursor);
-
     @fold.fold_crate(crate)
 }
 
@@ -225,7 +234,10 @@ pub fn compile_input(context: &BuildContext,
         maybe_sysroot: Some(sysroot_to_use),
         addl_lib_search_paths: @mut (~[]),
         output_type: output_type,
-        .. (*driver::build_session_options(binary, &matches, diagnostic::emit)).clone()
+        .. (*driver::build_session_options(binary,
+                                           &matches,
+                                           @diagnostic::DefaultEmitter as
+                                            @diagnostic::Emitter)).clone()
     };
 
     let addl_lib_search_paths = @mut options.addl_lib_search_paths;
@@ -240,7 +252,9 @@ pub fn compile_input(context: &BuildContext,
         }
     }
 
-    let sess = driver::build_session(options, diagnostic::emit);
+    let sess = driver::build_session(options,
+                                     @diagnostic::DefaultEmitter as
+                                        @diagnostic::Emitter);
 
     // Infer dependencies that rustpkg needs to build, by scanning for
     // `extern mod` directives.
@@ -383,31 +397,28 @@ pub fn compile_crate(ctxt: &BuildContext,
     compile_input(ctxt, exec, pkg_id, crate, workspace, flags, cfgs, opt, what)
 }
 
+struct ViewItemVisitor<'self> {
+    context: &'self BuildContext,
+    parent: &'self PkgId,
+    sess: session::Session,
+    exec: &'self mut workcache::Exec,
+    c: &'self ast::Crate,
+    save: &'self fn(Path),
+}
 
-/// Collect all `extern mod` directives in `c`, then
-/// try to install their targets, failing if any target
-/// can't be found.
-pub fn find_and_install_dependencies(context: &BuildContext,
-                                     parent: &PkgId,
-                                     sess: session::Session,
-                                     exec: &mut workcache::Exec,
-                                     c: &ast::Crate,
-                                     save: @fn(Path)
-                                     ) {
-    use conditions::nonexistent_package::cond;
-
-    do c.each_view_item() |vi: &ast::view_item| {
+impl<'self> Visitor<()> for ViewItemVisitor<'self> {
+    fn visit_view_item(&mut self, vi: &ast::view_item, env: ()) {
         debug!("A view item!");
         match vi.node {
             // ignore metadata, I guess
             ast::view_item_extern_mod(lib_ident, path_opt, _, _) => {
                 let lib_name = match path_opt {
                     Some(p) => p,
-                    None => sess.str_of(lib_ident)
+                    None => self.sess.str_of(lib_ident)
                 };
                 debug!("Finding and installing... %s", lib_name);
                 // Check standard Rust library path first
-                match system_library(&context.sysroot(), lib_name) {
+                match system_library(&self.context.sysroot(), lib_name) {
                     Some(ref installed_path) => {
                         debug!("It exists: %s", installed_path.to_str());
                         // Say that [path for c] has a discovered dependency on
@@ -416,8 +427,9 @@ pub fn find_and_install_dependencies(context: &BuildContext,
                         // I'm not sure what the right thing is.
                         // Now we know that this crate has a discovered dependency on
                         // installed_path
-                        exec.discover_input("binary", installed_path.to_str(),
-                                                      digest_only_date(installed_path));
+                        self.exec.discover_input("binary",
+                                                 installed_path.to_str(),
+                                                 digest_only_date(installed_path));
                     }
                     None => {
                         // FIXME #8711: need to parse version out of path_opt
@@ -425,35 +437,44 @@ pub fn find_and_install_dependencies(context: &BuildContext,
                                lib_name.to_str());
                         // Try to install it
                         let pkg_id = PkgId::new(lib_name);
-                        let workspaces = pkg_parent_workspaces(&context.context, &pkg_id);
+                        let workspaces = pkg_parent_workspaces(&self.context.context,
+                                                               &pkg_id);
                         let dep_workspace = if workspaces.is_empty() {
                             error(fmt!("Couldn't find package %s, which is needed by %s, \
                                             in any of the workspaces in the RUST_PATH (%?)",
-                                            lib_name, parent.to_str(), rust_path()));
+                                            lib_name,
+                                            self.parent.to_str(),
+                                            rust_path()));
                             cond.raise((pkg_id.clone(), ~"Dependency not found"))
                         }
                         else {
                             workspaces[0]
                         };
                         let (outputs_disc, inputs_disc) =
-                            context.install(PkgSrc::new(dep_workspace.clone(),
-                                false, pkg_id), &JustOne(Path(lib_crate_filename)));
+                            self.context.install(PkgSrc::new(dep_workspace.clone(),
+                                                             false,
+                                                             pkg_id),
+                                                 &JustOne(Path(
+                                                    lib_crate_filename)));
                         debug!("Installed %s, returned %? dependencies and \
                                %? transitive dependencies",
                                lib_name, outputs_disc.len(), inputs_disc.len());
                         for dep in outputs_disc.iter() {
                             debug!("Discovering a binary input: %s", dep.to_str());
-                            exec.discover_input("binary", dep.to_str(),
-                                                digest_only_date(dep));
+                            self.exec.discover_input("binary",
+                                                     dep.to_str(),
+                                                     digest_only_date(dep));
                         }
                         for &(ref what, ref dep) in inputs_disc.iter() {
                             if *what == ~"file" {
-                                exec.discover_input(*what, *dep,
-                                                    digest_file_with_date(&Path(*dep)));
+                                self.exec.discover_input(*what,
+                                                         *dep,
+                                                         digest_file_with_date(&Path(*dep)));
                             }
                             else if *what == ~"binary" {
-                                exec.discover_input(*what, *dep,
-                                                    digest_only_date(&Path(*dep)));
+                                self.exec.discover_input(*what,
+                                                         *dep,
+                                                         digest_only_date(&Path(*dep)));
                             }
                             else {
                                 fail!("Bad kind: %s", *what);
@@ -468,14 +489,36 @@ pub fn find_and_install_dependencies(context: &BuildContext,
                         let install_dir = installed_library.pop();
                         debug!("Installed %s into %s [%?]", lib_name, install_dir.to_str(),
                                datestamp(&installed_library));
-                        save(install_dir);
+                        (self.save)(install_dir);
                     }
                 }}
             // Ignore `use`s
             _ => ()
         }
-        true
+
+        visit::walk_view_item(self, vi, env)
+    }
+}
+
+/// Collect all `extern mod` directives in `c`, then
+/// try to install their targets, failing if any target
+/// can't be found.
+pub fn find_and_install_dependencies(context: &BuildContext,
+                                     parent: &PkgId,
+                                     sess: session::Session,
+                                     exec: &mut workcache::Exec,
+                                     c: &ast::Crate,
+                                     save: &fn(Path)) {
+    debug!("In find_and_install_dependencies...");
+    let mut visitor = ViewItemVisitor {
+        context: context,
+        parent: parent,
+        sess: sess,
+        exec: exec,
+        c: c,
+        save: save,
     };
+    visit::walk_crate(&mut visitor, c, ())
 }
 
 pub fn mk_string_lit(s: @str) -> ast::lit {
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
index 890a53690d9..ab8af22e116 100644
--- a/src/libstd/io.rs
+++ b/src/libstd/io.rs
@@ -1846,31 +1846,38 @@ pub mod fsync {
     pub struct Arg<t> {
         val: t,
         opt_level: Option<Level>,
-        fsync_fn: @fn(f: &t, Level) -> int,
+        fsync_fn: extern "Rust" fn(f: &t, Level) -> int,
     }
 
     // fsync file after executing blk
     // FIXME (#2004) find better way to create resources within lifetime of
     // outer res
-    pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
+    pub fn FILE_res_sync(file: &FILERes,
+                         opt_level: Option<Level>,
                          blk: &fn(v: Res<*libc::FILE>)) {
         blk(Res::new(Arg {
-            val: file.f, opt_level: opt_level,
-            fsync_fn: |file, l| fsync_fd(fileno(*file), l)
+            val: file.f,
+            opt_level: opt_level,
+            fsync_fn: fsync_FILE,
         }));
 
         fn fileno(stream: *libc::FILE) -> libc::c_int {
             #[fixed_stack_segment]; #[inline(never)];
             unsafe { libc::fileno(stream) }
         }
+
+        fn fsync_FILE(stream: &*libc::FILE, level: Level) -> int {
+            fsync_fd(fileno(*stream), level)
+        }
     }
 
     // fsync fd after executing blk
     pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
                        blk: &fn(v: Res<fd_t>)) {
         blk(Res::new(Arg {
-            val: fd.fd, opt_level: opt_level,
-            fsync_fn: |fd, l| fsync_fd(*fd, l)
+            val: fd.fd,
+            opt_level: opt_level,
+            fsync_fn: fsync_fd_helper,
         }));
     }
 
@@ -1880,6 +1887,10 @@ pub mod fsync {
         os::fsync_fd(fd, level) as int
     }
 
+    fn fsync_fd_helper(fd_ptr: &libc::c_int, level: Level) -> int {
+        fsync_fd(*fd_ptr, level)
+    }
+
     // Type of objects that may want to fsync
     pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
 
@@ -1887,10 +1898,15 @@ pub mod fsync {
     pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
                     blk: &fn(v: Res<@FSyncable>)) {
         blk(Res::new(Arg {
-            val: o, opt_level: opt_level,
-            fsync_fn: |o, l| (*o).fsync(l)
+            val: o,
+            opt_level: opt_level,
+            fsync_fn: obj_fsync_fn,
         }));
     }
+
+    fn obj_fsync_fn(o: &@FSyncable, level: Level) -> int {
+        (*o).fsync(level)
+    }
 }
 
 #[cfg(test)]
diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs
index 91e3719e3d0..833a9f5ed82 100644
--- a/src/libstd/reflect.rs
+++ b/src/libstd/reflect.rs
@@ -485,9 +485,11 @@ impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
     }
 
     fn visit_closure_ptr(&mut self, ck: uint) -> bool {
-        self.align_to::<@fn()>();
-        if ! self.inner.visit_closure_ptr(ck) { return false; }
-        self.bump_past::<@fn()>();
+        self.align_to::<~fn()>();
+        if ! self.inner.visit_closure_ptr(ck) {
+            return false
+        }
+        self.bump_past::<~fn()>();
         true
     }
 }
diff --git a/src/test/run-pass/fn-assign-managed-to-bare-2.rs b/src/libstd/routine.rs
index f8daacfa233..e8a91b49c8e 100644
--- a/src/test/run-pass/fn-assign-managed-to-bare-2.rs
+++ b/src/libstd/routine.rs
@@ -8,21 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn add(n: int) -> @fn(int) -> int {
-    let result: @fn(int) -> int = |m| m + n;
-    result
-}
-
-pub fn main()
-{
-    assert_eq!(add(3)(4), 7);
+/*!
+ * Routines are like closures except that they own their arguments and can
+ * only run once.
+ */
 
-    let add1 : @fn(int)->int = add(1);
-    assert_eq!(add1(6), 7);
+/// A routine that takes no arguments and returns nothing.
+pub trait Runnable {
+    /// The entry point for the routine.
+    fn run(~self);
+}
 
-    let add2 : &(@fn(int)->int) = &add(2);
-    assert_eq!((*add2)(5), 7);
+/// A convenience routine that does nothing.
+pub struct NoOpRunnable;
 
-    let add3 : &fn(int)->int = add(3);
-    assert_eq!(add3(4), 7);
+impl Runnable for NoOpRunnable {
+    fn run(~self) {}
 }
+
diff --git a/src/libstd/std.rs b/src/libstd/std.rs
index f7b55e977e0..5c1bac7418e 100644
--- a/src/libstd/std.rs
+++ b/src/libstd/std.rs
@@ -189,7 +189,7 @@ pub mod reflect;
 pub mod condition;
 pub mod logging;
 pub mod util;
-
+pub mod routine;
 
 /* Unsupported interfaces */
 
diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs
index f2cfd114349..4d53dd7d7bf 100644
--- a/src/libstd/unstable/extfmt.rs
+++ b/src/libstd/unstable/extfmt.rs
@@ -158,11 +158,14 @@ pub mod ct {
 
     // A fragment of the output sequence
     #[deriving(Eq)]
-    pub enum Piece { PieceString(~str), PieceConv(Conv), }
+    pub enum Piece {
+        PieceString(~str),
+        PieceConv(Conv),
+    }
 
-    pub type ErrorFn = @fn(&str) -> !;
+    pub type ErrorFn<'self> = &'self fn(&str) -> !;
 
-    pub fn parse_fmt_string(s: &str, err: ErrorFn) -> ~[Piece] {
+    pub fn parse_fmt_string<'a>(s: &str, err: ErrorFn<'a>) -> ~[Piece] {
         fn push_slice(ps: &mut ~[Piece], s: &str, from: uint, to: uint) {
             if to > from {
                 ps.push(PieceString(s.slice(from, to).to_owned()));
@@ -185,7 +188,10 @@ pub mod ct {
                     i += 1;
                 } else {
                     push_slice(&mut pieces, s, h, i - 1);
-                    let Parsed {val, next} = parse_conversion(s, i, lim, err);
+                    let Parsed {
+                        val,
+                        next
+                    } = parse_conversion(s, i, lim, |s| err(s));
                     pieces.push(val);
                     i = next;
                 }
@@ -224,8 +230,8 @@ pub mod ct {
         }
     }
 
-    pub fn parse_conversion(s: &str, i: uint, lim: uint, err: ErrorFn) ->
-        Parsed<Piece> {
+    pub fn parse_conversion<'a>(s: &str, i: uint, lim: uint, err: ErrorFn<'a>)
+                                -> Parsed<Piece> {
         let param = parse_parameter(s, i, lim);
         // avoid copying ~[Flag] by destructuring
         let Parsed {val: flags_val, next: flags_next} = parse_flags(s,
@@ -308,8 +314,8 @@ pub mod ct {
         }
     }
 
-    pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) ->
-        Parsed<Ty> {
+    pub fn parse_type<'a>(s: &str, i: uint, lim: uint, err: ErrorFn<'a>)
+                          -> Parsed<Ty> {
         if i >= lim { err("missing type in conversion"); }
 
         // FIXME (#2249): Do we really want two signed types here?
diff --git a/src/libstd/unstable/finally.rs b/src/libstd/unstable/finally.rs
index 6833ca6d7cf..ba5986aa4ab 100644
--- a/src/libstd/unstable/finally.rs
+++ b/src/libstd/unstable/finally.rs
@@ -55,7 +55,6 @@ impl<'self,T> Finally<T> for &'self fn() -> T {
 }
 
 finally_fn!(~fn() -> T)
-finally_fn!(@fn() -> T)
 finally_fn!(extern "Rust" fn() -> T)
 
 struct Finallyalizer<'self> {
@@ -119,14 +118,3 @@ fn test_owned() {
     spawn_with_finalizer(owned);
 }
 
-#[test]
-fn test_managed() {
-    let i = @mut 10;
-    let managed: @fn() -> int = || {
-        let r = *i;
-        *i += 10;
-        r
-    };
-    assert_eq!(do managed.finally {}, 10);
-    assert_eq!(*i, 20);
-}
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index f0f86911f50..ac88fc835d5 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -12,7 +12,6 @@ use ast::*;
 use ast;
 use ast_util;
 use codemap::{Span, dummy_sp};
-use fold;
 use opt_vec;
 use parse::token;
 use visit::Visitor;
@@ -371,21 +370,6 @@ pub fn empty_generics() -> Generics {
               ty_params: opt_vec::Empty}
 }
 
-///////////////////////////////////////////////////////////////////////////
-// Assigning node ids
-
-fn node_id_assigner(next_id: @fn() -> ast::NodeId) -> @fold::ast_fold {
-    let precursor = @fold::AstFoldFns {
-        new_id: |old_id| {
-            assert_eq!(old_id, ast::DUMMY_NODE_ID);
-            next_id()
-        },
-        ..*fold::default_ast_fold()
-    };
-
-    fold::make_fold(precursor)
-}
-
 // ______________________________________________________________________
 // Enumerating the IDs which appear in an AST
 
@@ -413,18 +397,22 @@ impl id_range {
     }
 }
 
-pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool)
+pub fn id_visitor(operation: @IdVisitingOperation, pass_through_items: bool)
                   -> @mut Visitor<()> {
     let visitor = @mut IdVisitor {
-        visit_callback: vfn,
+        operation: operation,
         pass_through_items: pass_through_items,
         visited_outermost: false,
     };
     visitor as @mut Visitor<()>
 }
 
+pub trait IdVisitingOperation {
+    fn visit_id(&self, node_id: NodeId);
+}
+
 pub struct IdVisitor {
-    visit_callback: @fn(NodeId),
+    operation: @IdVisitingOperation,
     pass_through_items: bool,
     visited_outermost: bool,
 }
@@ -432,10 +420,10 @@ pub struct IdVisitor {
 impl IdVisitor {
     fn visit_generics_helper(&self, generics: &Generics) {
         for type_parameter in generics.ty_params.iter() {
-            (self.visit_callback)(type_parameter.id)
+            self.operation.visit_id(type_parameter.id)
         }
         for lifetime in generics.lifetimes.iter() {
-            (self.visit_callback)(lifetime.id)
+            self.operation.visit_id(lifetime.id)
         }
     }
 }
@@ -446,26 +434,26 @@ impl Visitor<()> for IdVisitor {
                  _: Span,
                  node_id: NodeId,
                  env: ()) {
-        (self.visit_callback)(node_id);
+        self.operation.visit_id(node_id);
         visit::walk_mod(self, module, env)
     }
 
     fn visit_view_item(&mut self, view_item: &view_item, env: ()) {
         match view_item.node {
             view_item_extern_mod(_, _, _, node_id) => {
-                (self.visit_callback)(node_id)
+                self.operation.visit_id(node_id)
             }
             view_item_use(ref view_paths) => {
                 for view_path in view_paths.iter() {
                     match view_path.node {
                         view_path_simple(_, _, node_id) |
                         view_path_glob(_, node_id) => {
-                            (self.visit_callback)(node_id)
+                            self.operation.visit_id(node_id)
                         }
                         view_path_list(_, ref paths, node_id) => {
-                            (self.visit_callback)(node_id);
+                            self.operation.visit_id(node_id);
                             for path in paths.iter() {
-                                (self.visit_callback)(path.node.id)
+                                self.operation.visit_id(path.node.id)
                             }
                         }
                     }
@@ -476,7 +464,7 @@ impl Visitor<()> for IdVisitor {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: @foreign_item, env: ()) {
-        (self.visit_callback)(foreign_item.id);
+        self.operation.visit_id(foreign_item.id);
         visit::walk_foreign_item(self, foreign_item, env)
     }
 
@@ -489,11 +477,11 @@ impl Visitor<()> for IdVisitor {
             }
         }
 
-        (self.visit_callback)(item.id);
+        self.operation.visit_id(item.id);
         match item.node {
             item_enum(ref enum_definition, _) => {
                 for variant in enum_definition.variants.iter() {
-                    (self.visit_callback)(variant.node.id)
+                    self.operation.visit_id(variant.node.id)
                 }
             }
             _ => {}
@@ -505,22 +493,22 @@ impl Visitor<()> for IdVisitor {
     }
 
     fn visit_local(&mut self, local: @Local, env: ()) {
-        (self.visit_callback)(local.id);
+        self.operation.visit_id(local.id);
         visit::walk_local(self, local, env)
     }
 
     fn visit_block(&mut self, block: &Block, env: ()) {
-        (self.visit_callback)(block.id);
+        self.operation.visit_id(block.id);
         visit::walk_block(self, block, env)
     }
 
     fn visit_stmt(&mut self, statement: @Stmt, env: ()) {
-        (self.visit_callback)(ast_util::stmt_id(statement));
+        self.operation.visit_id(ast_util::stmt_id(statement));
         visit::walk_stmt(self, statement, env)
     }
 
     fn visit_pat(&mut self, pattern: @Pat, env: ()) {
-        (self.visit_callback)(pattern.id);
+        self.operation.visit_id(pattern.id);
         visit::walk_pat(self, pattern, env)
     }
 
@@ -529,17 +517,17 @@ impl Visitor<()> for IdVisitor {
         {
             let optional_callee_id = expression.get_callee_id();
             for callee_id in optional_callee_id.iter() {
-                (self.visit_callback)(*callee_id)
+                self.operation.visit_id(*callee_id)
             }
         }
-        (self.visit_callback)(expression.id);
+        self.operation.visit_id(expression.id);
         visit::walk_expr(self, expression, env)
     }
 
     fn visit_ty(&mut self, typ: &Ty, env: ()) {
-        (self.visit_callback)(typ.id);
+        self.operation.visit_id(typ.id);
         match typ.node {
-            ty_path(_, _, id) => (self.visit_callback)(id),
+            ty_path(_, _, id) => self.operation.visit_id(id),
             _ => {}
         }
         visit::walk_ty(self, typ, env)
@@ -565,21 +553,21 @@ impl Visitor<()> for IdVisitor {
             }
         }
 
-        (self.visit_callback)(node_id);
+        self.operation.visit_id(node_id);
 
         match *function_kind {
             visit::fk_item_fn(_, generics, _, _) => {
                 self.visit_generics_helper(generics)
             }
             visit::fk_method(_, generics, method) => {
-                (self.visit_callback)(method.self_id);
+                self.operation.visit_id(method.self_id);
                 self.visit_generics_helper(generics)
             }
             visit::fk_anon(_) | visit::fk_fn_block => {}
         }
 
         for argument in function_declaration.inputs.iter() {
-            (self.visit_callback)(argument.id)
+            self.operation.visit_id(argument.id)
         }
 
         visit::walk_fn(self,
@@ -599,25 +587,36 @@ impl Visitor<()> for IdVisitor {
     }
 
     fn visit_struct_field(&mut self, struct_field: @struct_field, env: ()) {
-        (self.visit_callback)(struct_field.node.id);
+        self.operation.visit_id(struct_field.node.id);
         visit::walk_struct_field(self, struct_field, env)
     }
 }
 
-pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) {
+pub fn visit_ids_for_inlined_item(item: &inlined_item,
+                                  operation: @IdVisitingOperation) {
     let mut id_visitor = IdVisitor {
-        visit_callback: vfn,
+        operation: operation,
         pass_through_items: true,
         visited_outermost: false,
     };
     item.accept((), &mut id_visitor);
 }
 
-pub fn compute_id_range(visit_ids_fn: &fn(@fn(NodeId))) -> id_range {
-    let result = @mut id_range::max();
-    do visit_ids_fn |id| {
-        result.add(id);
+struct IdRangeComputingVisitor {
+    result: @mut id_range,
+}
+
+impl IdVisitingOperation for IdRangeComputingVisitor {
+    fn visit_id(&self, id: NodeId) {
+        self.result.add(id)
     }
+}
+
+pub fn compute_id_range(visit_ids_fn: &fn(@IdVisitingOperation)) -> id_range {
+    let result = @mut id_range::max();
+    visit_ids_fn(@IdRangeComputingVisitor {
+        result: result,
+    } as @IdVisitingOperation);
     *result
 }
 
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 5e9714ca5b2..aa06e1bee41 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -15,9 +15,12 @@ use std::io;
 use std::local_data;
 use extra::term;
 
-pub type Emitter = @fn(cmsp: Option<(@codemap::CodeMap, Span)>,
-                       msg: &str,
-                       lvl: level);
+pub trait Emitter {
+    fn emit(&self,
+            cmsp: Option<(@codemap::CodeMap, Span)>,
+            msg: &str,
+            lvl: level);
+}
 
 // a handler deals with errors; certain errors
 // (fatal, bug, unimpl) may cause immediate exit,
@@ -55,7 +58,7 @@ pub trait span_handler {
 
 struct HandlerT {
     err_count: uint,
-    emit: Emitter,
+    emit: @Emitter,
 }
 
 struct CodemapT {
@@ -91,11 +94,11 @@ impl span_handler for CodemapT {
 
 impl handler for HandlerT {
     fn fatal(@mut self, msg: &str) -> ! {
-        (self.emit)(None, msg, fatal);
+        self.emit.emit(None, msg, fatal);
         fail!();
     }
     fn err(@mut self, msg: &str) {
-        (self.emit)(None, msg, error);
+        self.emit.emit(None, msg, error);
         self.bump_err_count();
     }
     fn bump_err_count(@mut self) {
@@ -120,10 +123,10 @@ impl handler for HandlerT {
         self.fatal(s);
     }
     fn warn(@mut self, msg: &str) {
-        (self.emit)(None, msg, warning);
+        self.emit.emit(None, msg, warning);
     }
     fn note(@mut self, msg: &str) {
-        (self.emit)(None, msg, note);
+        self.emit.emit(None, msg, note);
     }
     fn bug(@mut self, msg: &str) -> ! {
         self.fatal(ice_msg(msg));
@@ -135,7 +138,7 @@ impl handler for HandlerT {
             cmsp: Option<(@codemap::CodeMap, Span)>,
             msg: &str,
             lvl: level) {
-        (self.emit)(cmsp, msg, lvl);
+        self.emit.emit(cmsp, msg, lvl);
     }
 }
 
@@ -145,19 +148,22 @@ pub fn ice_msg(msg: &str) -> ~str {
 
 pub fn mk_span_handler(handler: @mut handler, cm: @codemap::CodeMap)
                     -> @mut span_handler {
-    @mut CodemapT { handler: handler, cm: cm } as @mut span_handler
+    @mut CodemapT {
+        handler: handler,
+        cm: cm,
+    } as @mut span_handler
 }
 
-pub fn mk_handler(emitter: Option<Emitter>) -> @mut handler {
-    let emit: Emitter = match emitter {
+pub fn mk_handler(emitter: Option<@Emitter>) -> @mut handler {
+    let emit: @Emitter = match emitter {
         Some(e) => e,
-        None => {
-            let emit: Emitter = |cmsp, msg, t| emit(cmsp, msg, t);
-            emit
-        }
+        None => @DefaultEmitter as @Emitter
     };
 
-    @mut HandlerT { err_count: 0, emit: emit } as @mut handler
+    @mut HandlerT {
+        err_count: 0,
+        emit: emit,
+    } as @mut handler
 }
 
 #[deriving(Eq)]
@@ -230,31 +236,30 @@ fn print_diagnostic(topic: &str, lvl: level, msg: &str) {
     print_maybe_styled(fmt!("%s\n", msg), term::attr::Bold);
 }
 
-pub fn collect(messages: @mut ~[~str])
-            -> @fn(Option<(@codemap::CodeMap, Span)>, &str, level) {
-    let f: @fn(Option<(@codemap::CodeMap, Span)>, &str, level) =
-        |_o, msg: &str, _l| { messages.push(msg.to_str()); };
-    f
-}
+pub struct DefaultEmitter;
 
-pub fn emit(cmsp: Option<(@codemap::CodeMap, Span)>, msg: &str, lvl: level) {
-    match cmsp {
-      Some((cm, sp)) => {
-        let sp = cm.adjust_span(sp);
-        let ss = cm.span_to_str(sp);
-        let lines = cm.span_to_lines(sp);
-        print_diagnostic(ss, lvl, msg);
-        highlight_lines(cm, sp, lvl, lines);
-        print_macro_backtrace(cm, sp);
-      }
-      None => {
-        print_diagnostic("", lvl, msg);
-      }
+impl Emitter for DefaultEmitter {
+    fn emit(&self,
+            cmsp: Option<(@codemap::CodeMap, Span)>,
+            msg: &str,
+            lvl: level) {
+        match cmsp {
+            Some((cm, sp)) => {
+                let sp = cm.adjust_span(sp);
+                let ss = cm.span_to_str(sp);
+                let lines = cm.span_to_lines(sp);
+                print_diagnostic(ss, lvl, msg);
+                highlight_lines(cm, sp, lvl, lines);
+                print_macro_backtrace(cm, sp);
+            }
+            None => print_diagnostic("", lvl, msg),
+        }
     }
 }
 
 fn highlight_lines(cm: @codemap::CodeMap,
-                   sp: Span, lvl: level,
+                   sp: Span,
+                   lvl: level,
                    lines: @codemap::FileLines) {
     let fm = lines.file;
 
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 2bcfafc3bb4..48eb9a350f1 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -33,62 +33,120 @@ pub struct MacroDef {
     ext: SyntaxExtension
 }
 
-// No context arg for an Item Decorator macro, simply because
-// adding it would require adding a ctxt field to all items.
-// we could do this if it turns out to be useful.
-
-pub type ItemDecoratorFun = @fn(@ExtCtxt,
-                             Span,
-                             @ast::MetaItem,
-                             ~[@ast::item])
-                          -> ~[@ast::item];
-
-pub type SyntaxExpanderTTFun = @fn(@ExtCtxt,
-                                   Span,
-                                   &[ast::token_tree],
-                                   ast::SyntaxContext)
-                                -> MacResult;
-
-pub type SyntaxExpanderTTItemFun = @fn(@ExtCtxt,
-                                       Span,
-                                       ast::Ident,
-                                       ~[ast::token_tree],
-                                       ast::SyntaxContext)
-                                    -> MacResult;
-
-// oog... in order to make the presentation of builtin_normal_tt_no_ctxt
-// and builtin_ident_tt_no_ctxt palatable, we need one-off types for
-// functions that don't consume a ctxt:
-
-pub type SyntaxExpanderTTFunNoCtxt = @fn(@ExtCtxt,
-                                   Span,
-                                   &[ast::token_tree])
-                                -> MacResult;
-
-pub type SyntaxExpanderTTItemFunNoCtxt = @fn(@ExtCtxt,
-                                       Span,
-                                       ast::Ident,
-                                       ~[ast::token_tree])
-                                    -> MacResult;
+pub type ItemDecorator = extern "Rust" fn(@ExtCtxt,
+                                          Span,
+                                          @ast::MetaItem,
+                                          ~[@ast::item])
+                                          -> ~[@ast::item];
+
+pub struct SyntaxExpanderTT {
+    expander: SyntaxExpanderTTExpander,
+    span: Option<Span>
+}
+
+pub trait SyntaxExpanderTTTrait {
+    fn expand(&self,
+              ecx: @ExtCtxt,
+              span: Span,
+              token_tree: &[ast::token_tree],
+              context: ast::SyntaxContext)
+              -> MacResult;
+}
+
+pub type SyntaxExpanderTTFunNoCtxt =
+    extern "Rust" fn(ecx: @ExtCtxt,
+                     span: codemap::Span,
+                     token_tree: &[ast::token_tree])
+                     -> MacResult;
+
+enum SyntaxExpanderTTExpander {
+    SyntaxExpanderTTExpanderWithoutContext(SyntaxExpanderTTFunNoCtxt),
+}
+
+impl SyntaxExpanderTTTrait for SyntaxExpanderTT {
+    fn expand(&self,
+              ecx: @ExtCtxt,
+              span: Span,
+              token_tree: &[ast::token_tree],
+              _: ast::SyntaxContext)
+              -> MacResult {
+        match self.expander {
+            SyntaxExpanderTTExpanderWithoutContext(f) => {
+                f(ecx, span, token_tree)
+            }
+        }
+    }
+}
 
+enum SyntaxExpanderTTItemExpander {
+    SyntaxExpanderTTItemExpanderWithContext(SyntaxExpanderTTItemFun),
+    SyntaxExpanderTTItemExpanderWithoutContext(SyntaxExpanderTTItemFunNoCtxt),
+}
 
+pub struct SyntaxExpanderTTItem {
+    expander: SyntaxExpanderTTItemExpander,
+    span: Option<Span>
+}
+
+pub trait SyntaxExpanderTTItemTrait {
+    fn expand(&self,
+              cx: @ExtCtxt,
+              sp: Span,
+              ident: ast::Ident,
+              token_tree: ~[ast::token_tree],
+              context: ast::SyntaxContext)
+              -> MacResult;
+}
+
+impl SyntaxExpanderTTItemTrait for SyntaxExpanderTTItem {
+    fn expand(&self,
+              cx: @ExtCtxt,
+              sp: Span,
+              ident: ast::Ident,
+              token_tree: ~[ast::token_tree],
+              context: ast::SyntaxContext)
+              -> MacResult {
+        match self.expander {
+            SyntaxExpanderTTItemExpanderWithContext(fun) => {
+                fun(cx, sp, ident, token_tree, context)
+            }
+            SyntaxExpanderTTItemExpanderWithoutContext(fun) => {
+                fun(cx, sp, ident, token_tree)
+            }
+        }
+    }
+}
+
+pub type SyntaxExpanderTTItemFun = extern "Rust" fn(@ExtCtxt,
+                                                    Span,
+                                                    ast::Ident,
+                                                    ~[ast::token_tree],
+                                                    ast::SyntaxContext)
+                                                    -> MacResult;
+
+pub type SyntaxExpanderTTItemFunNoCtxt =
+    extern "Rust" fn(@ExtCtxt, Span, ast::Ident, ~[ast::token_tree])
+                     -> MacResult;
+
+pub trait AnyMacro {
+    fn make_expr(&self) -> @ast::Expr;
+    fn make_item(&self) -> Option<@ast::item>;
+    fn make_stmt(&self) -> @ast::Stmt;
+}
 
 pub enum MacResult {
     MRExpr(@ast::Expr),
     MRItem(@ast::item),
-    MRAny(@fn() -> @ast::Expr,
-          @fn() -> Option<@ast::item>,
-          @fn() -> @ast::Stmt),
-    MRDef(MacroDef)
+    MRAny(@AnyMacro),
+    MRDef(MacroDef),
 }
 
 pub enum SyntaxExtension {
-
     // #[auto_encode] and such
-    ItemDecorator(ItemDecoratorFun),
+    ItemDecorator(ItemDecorator),
 
     // Token-tree expanders
-    NormalTT(SyntaxExpanderTTFun, Option<Span>),
+    NormalTT(@SyntaxExpanderTTTrait, Option<Span>),
 
     // An IdentTT is a macro that has an
     // identifier in between the name of the
@@ -98,7 +156,7 @@ pub enum SyntaxExtension {
 
     // perhaps macro_rules! will lose its odd special identifier argument,
     // and this can go away also
-    IdentTT(SyntaxExpanderTTItemFun, Option<Span>),
+    IdentTT(@SyntaxExpanderTTItemTrait, Option<Span>),
 }
 
 
@@ -133,16 +191,22 @@ type RenameList = ~[(ast::Ident,Name)];
 // AST nodes into full ASTs
 pub fn syntax_expander_table() -> SyntaxEnv {
     // utility function to simplify creating NormalTT syntax extensions
-    // that ignore their contexts
-    fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt) -> @Transformer {
-        let wrapped_expander : SyntaxExpanderTTFun = |a,b,c,_d|{f(a,b,c)};
-        @SE(NormalTT(wrapped_expander, None))
+    fn builtin_normal_tt_no_ctxt(f: SyntaxExpanderTTFunNoCtxt)
+                                 -> @Transformer {
+        @SE(NormalTT(@SyntaxExpanderTT{
+            expander: SyntaxExpanderTTExpanderWithoutContext(f),
+            span: None,
+        } as @SyntaxExpanderTTTrait,
+        None))
     }
     // utility function to simplify creating IdentTT syntax extensions
     // that ignore their contexts
     fn builtin_item_tt_no_ctxt(f: SyntaxExpanderTTItemFunNoCtxt) -> @Transformer {
-        let wrapped_expander : SyntaxExpanderTTItemFun = |a,b,c,d,_e|{f(a,b,c,d)};
-        @SE(IdentTT(wrapped_expander, None))
+        @SE(IdentTT(@SyntaxExpanderTTItem {
+            expander: SyntaxExpanderTTItemExpanderWithoutContext(f),
+            span: None,
+        } as @SyntaxExpanderTTItemTrait,
+        None))
     }
     let mut syntax_expanders = HashMap::new();
     // NB identifier starts with space, and can't conflict with legal idents
@@ -152,11 +216,18 @@ pub fn syntax_expander_table() -> SyntaxEnv {
                                 pending_renames : @mut ~[]
                             }));
     syntax_expanders.insert(intern(&"macro_rules"),
-                            @SE(IdentTT(ext::tt::macro_rules::add_new_extension, None)));
+                            @SE(IdentTT(@SyntaxExpanderTTItem {
+                                expander: SyntaxExpanderTTItemExpanderWithContext(
+                                    ext::tt::macro_rules::add_new_extension),
+                                span: None,
+                            } as @SyntaxExpanderTTItemTrait,
+                            None)));
     syntax_expanders.insert(intern(&"fmt"),
-                            builtin_normal_tt_no_ctxt(ext::fmt::expand_syntax_ext));
+                            builtin_normal_tt_no_ctxt(
+                                ext::fmt::expand_syntax_ext));
     syntax_expanders.insert(intern(&"format_args"),
-                            builtin_normal_tt_no_ctxt(ext::format::expand_args));
+                            builtin_normal_tt_no_ctxt(
+                                ext::format::expand_args));
     syntax_expanders.insert(
         intern(&"auto_encode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_encode)));
@@ -164,67 +235,77 @@ pub fn syntax_expander_table() -> SyntaxEnv {
         intern(&"auto_decode"),
         @SE(ItemDecorator(ext::auto_encode::expand_auto_decode)));
     syntax_expanders.insert(intern(&"env"),
-                            builtin_normal_tt_no_ctxt(ext::env::expand_env));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::env::expand_env));
     syntax_expanders.insert(intern(&"option_env"),
-                            builtin_normal_tt_no_ctxt(ext::env::expand_option_env));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::env::expand_option_env));
     syntax_expanders.insert(intern("bytes"),
-                            builtin_normal_tt_no_ctxt(ext::bytes::expand_syntax_ext));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::bytes::expand_syntax_ext));
     syntax_expanders.insert(intern("concat_idents"),
                             builtin_normal_tt_no_ctxt(
-                                ext::concat_idents::expand_syntax_ext));
+                                    ext::concat_idents::expand_syntax_ext));
     syntax_expanders.insert(intern(&"log_syntax"),
                             builtin_normal_tt_no_ctxt(
-                                ext::log_syntax::expand_syntax_ext));
+                                    ext::log_syntax::expand_syntax_ext));
     syntax_expanders.insert(intern(&"deriving"),
                             @SE(ItemDecorator(
                                 ext::deriving::expand_meta_deriving)));
 
     // Quasi-quoting expanders
     syntax_expanders.insert(intern(&"quote_tokens"),
-                            builtin_normal_tt_no_ctxt(
-                                ext::quote::expand_quote_tokens));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_tokens));
     syntax_expanders.insert(intern(&"quote_expr"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_expr));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_expr));
     syntax_expanders.insert(intern(&"quote_ty"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_ty));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_ty));
     syntax_expanders.insert(intern(&"quote_item"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_item));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_item));
     syntax_expanders.insert(intern(&"quote_pat"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_pat));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_pat));
     syntax_expanders.insert(intern(&"quote_stmt"),
-                            builtin_normal_tt_no_ctxt(ext::quote::expand_quote_stmt));
+                       builtin_normal_tt_no_ctxt(
+                            ext::quote::expand_quote_stmt));
 
     syntax_expanders.insert(intern(&"line"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_line));
+                                    ext::source_util::expand_line));
     syntax_expanders.insert(intern(&"col"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_col));
+                                    ext::source_util::expand_col));
     syntax_expanders.insert(intern(&"file"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_file));
+                                    ext::source_util::expand_file));
     syntax_expanders.insert(intern(&"stringify"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_stringify));
+                                    ext::source_util::expand_stringify));
     syntax_expanders.insert(intern(&"include"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_include));
+                                    ext::source_util::expand_include));
     syntax_expanders.insert(intern(&"include_str"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_include_str));
+                                    ext::source_util::expand_include_str));
     syntax_expanders.insert(intern(&"include_bin"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_include_bin));
+                                    ext::source_util::expand_include_bin));
     syntax_expanders.insert(intern(&"module_path"),
                             builtin_normal_tt_no_ctxt(
-                                ext::source_util::expand_mod));
+                                    ext::source_util::expand_mod));
     syntax_expanders.insert(intern(&"asm"),
-                            builtin_normal_tt_no_ctxt(ext::asm::expand_asm));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::asm::expand_asm));
     syntax_expanders.insert(intern(&"cfg"),
-                            builtin_normal_tt_no_ctxt(ext::cfg::expand_cfg));
-    syntax_expanders.insert(
-        intern(&"trace_macros"),
-        builtin_normal_tt_no_ctxt(ext::trace_macros::expand_trace_macros));
+                            builtin_normal_tt_no_ctxt(
+                                    ext::cfg::expand_cfg));
+    syntax_expanders.insert(intern(&"trace_macros"),
+                            builtin_normal_tt_no_ctxt(
+                                    ext::trace_macros::expand_trace_macros));
     MapChain::new(~syntax_expanders)
 }
 
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 889c2a5976e..ba2342d7827 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -15,6 +15,7 @@ use ast_util;
 use codemap::{Span, respan, dummy_sp};
 use ext::base::ExtCtxt;
 use ext::quote::rt::*;
+use fold;
 use opt_vec;
 use opt_vec::OptVec;
 
@@ -862,3 +863,32 @@ impl AstBuilder for @ExtCtxt {
                                 ast::view_path_glob(self.path(sp, path), ast::DUMMY_NODE_ID))])
     }
 }
+
+struct Duplicator {
+    cx: @ExtCtxt,
+}
+
+impl fold::ast_fold for Duplicator {
+    fn new_id(&self, _: NodeId) -> NodeId {
+        ast::DUMMY_NODE_ID
+    }
+}
+
+pub trait Duplicate {
+    //
+    // Duplication functions
+    //
+    // These functions just duplicate AST nodes.
+    //
+
+    fn duplicate(&self, cx: @ExtCtxt) -> Self;
+}
+
+impl Duplicate for @ast::Expr {
+    fn duplicate(&self, cx: @ExtCtxt) -> @ast::Expr {
+        let folder = @Duplicator {
+            cx: cx,
+        } as @fold::ast_fold;
+        folder.fold_expr(*self)
+    }
+}
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 82d452bc734..004a889fb4d 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -10,7 +10,7 @@
 
 use ast::{Block, Crate, DeclLocal, Expr_, ExprMac, SyntaxContext};
 use ast::{Local, Ident, mac_invoc_tt};
-use ast::{item_mac, Mrk, Stmt_, StmtDecl, StmtMac, StmtExpr, StmtSemi};
+use ast::{item_mac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi};
 use ast::{token_tree};
 use ast;
 use ast_util::{mtwt_outer_mark, new_rename, new_mark};
@@ -21,6 +21,7 @@ use codemap;
 use codemap::{Span, Spanned, ExpnInfo, NameAndSpan};
 use ext::base::*;
 use fold::*;
+use opt_vec;
 use parse;
 use parse::{parse_item_from_source_str};
 use parse::token;
@@ -32,12 +33,10 @@ use std::vec;
 
 pub fn expand_expr(extsbox: @mut SyntaxEnv,
                    cx: @ExtCtxt,
-                   e: &Expr_,
-                   span: Span,
-                   fld: @ast_fold,
-                   orig: @fn(&Expr_, Span, @ast_fold) -> (Expr_, Span))
-                -> (Expr_, Span) {
-    match *e {
+                   e: @ast::Expr,
+                   fld: &MacroExpander)
+                   -> @ast::Expr {
+    match e.node {
         // expr_mac should really be expr_ext or something; it's the
         // entry-point for all syntax extensions.
         ExprMac(ref mac) => {
@@ -66,7 +65,7 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                         }
                         Some(@SE(NormalTT(expandfun, exp_span))) => {
                             cx.bt_push(ExpnInfo {
-                                call_site: span,
+                                call_site: e.span,
                                 callee: NameAndSpan {
                                     name: extnamestr,
                                     span: exp_span,
@@ -84,10 +83,12 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                             let mac_span = original_span(cx);
 
                             let expanded =
-                                match expandfun(cx, mac_span.call_site,
-                                                marked_before, marked_ctxt) {
+                                match expandfun.expand(cx,
+                                                       mac_span.call_site,
+                                                       marked_before,
+                                                       marked_ctxt) {
                                     MRExpr(e) => e,
-                                    MRAny(expr_maker,_,_) => expr_maker(),
+                                    MRAny(any_macro) => any_macro.make_expr(),
                                     _ => {
                                         cx.span_fatal(
                                             pth.span,
@@ -101,12 +102,19 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                             // mark after:
                             let marked_after = mark_expr(expanded,fm);
 
-                            //keep going, outside-in
+                            // Keep going, outside-in.
+                            //
+                            // XXX(pcwalton): Is it necessary to clone the
+                            // node here?
                             let fully_expanded =
                                 fld.fold_expr(marked_after).node.clone();
                             cx.bt_pop();
 
-                            (fully_expanded, span)
+                            @ast::Expr {
+                                id: ast::DUMMY_NODE_ID,
+                                node: fully_expanded,
+                                span: e.span,
+                            }
                         }
                         _ => {
                             cx.span_fatal(
@@ -125,8 +133,48 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
         ast::ExprForLoop(src_pat, src_expr, ref src_loop_block, opt_ident) => {
             // Expand any interior macros etc.
             // NB: we don't fold pats yet. Curious.
-            let src_expr = fld.fold_expr(src_expr);
-            let src_loop_block = fld.fold_block(src_loop_block);
+            let src_expr = fld.fold_expr(src_expr).clone();
+            let src_loop_block = fld.fold_block(src_loop_block).clone();
+
+            let span = e.span;
+
+            pub fn mk_expr(_: @ExtCtxt, span: Span, node: Expr_)
+                           -> @ast::Expr {
+                @ast::Expr {
+                    id: ast::DUMMY_NODE_ID,
+                    node: node,
+                    span: span,
+                }
+            }
+
+            fn mk_block(_: @ExtCtxt,
+                        stmts: &[@ast::Stmt],
+                        expr: Option<@ast::Expr>,
+                        span: Span)
+                        -> ast::Block {
+                ast::Block {
+                    view_items: ~[],
+                    stmts: stmts.to_owned(),
+                    expr: expr,
+                    id: ast::DUMMY_NODE_ID,
+                    rules: ast::DefaultBlock,
+                    span: span,
+                }
+            }
+
+            fn mk_simple_path(ident: ast::Ident, span: Span) -> ast::Path {
+                ast::Path {
+                    span: span,
+                    global: false,
+                    segments: ~[
+                        ast::PathSegment {
+                            identifier: ident,
+                            lifetime: None,
+                            types: opt_vec::Empty,
+                        }
+                    ],
+                }
+            }
 
             // to:
             //
@@ -182,10 +230,14 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
                                  ~[iter_decl_stmt],
                                  Some(loop_expr));
 
-            (ast::ExprBlock(block), span)
+            @ast::Expr {
+                id: ast::DUMMY_NODE_ID,
+                node: ast::ExprBlock(block),
+                span: span,
+            }
         }
 
-        _ => orig(e, span, fld)
+        _ => noop_fold_expr(e, fld)
     }
 }
 
@@ -201,12 +253,10 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv,
 pub fn expand_mod_items(extsbox: @mut SyntaxEnv,
                         cx: @ExtCtxt,
                         module_: &ast::_mod,
-                        fld: @ast_fold,
-                        orig: @fn(&ast::_mod, @ast_fold) -> ast::_mod)
-                     -> ast::_mod {
-
+                        fld: &MacroExpander)
+                        -> ast::_mod {
     // Fold the contents first:
-    let module_ = orig(module_, fld);
+    let module_ = noop_fold_mod(module_, fld);
 
     // For each item, look through the attributes.  If any of them are
     // decorated with "item decorators", then use that function to transform
@@ -233,7 +283,10 @@ pub fn expand_mod_items(extsbox: @mut SyntaxEnv,
         }
     };
 
-    ast::_mod { items: new_items, ..module_ }
+    ast::_mod {
+        items: new_items,
+        ..module_
+    }
 }
 
 // eval $e with a new exts frame:
@@ -256,19 +309,20 @@ static special_block_name : &'static str = " block";
 pub fn expand_item(extsbox: @mut SyntaxEnv,
                    cx: @ExtCtxt,
                    it: @ast::item,
-                   fld: @ast_fold,
-                   orig: @fn(@ast::item, @ast_fold) -> Option<@ast::item>)
-                -> Option<@ast::item> {
+                   fld: &MacroExpander)
+                   -> Option<@ast::item> {
     match it.node {
         ast::item_mac(*) => expand_item_mac(extsbox, cx, it, fld),
         ast::item_mod(_) | ast::item_foreign_mod(_) => {
             cx.mod_push(it.ident);
             let macro_escape = contains_macro_escape(it.attrs);
-            let result = with_exts_frame!(extsbox,macro_escape,orig(it,fld));
+            let result = with_exts_frame!(extsbox,
+                                          macro_escape,
+                                          noop_fold_item(it, fld));
             cx.mod_pop();
             result
         },
-        _ => orig(it,fld)
+        _ => noop_fold_item(it, fld)
     }
 }
 
@@ -280,11 +334,15 @@ pub fn contains_macro_escape(attrs: &[ast::Attribute]) -> bool {
 // Support for item-position macro invocations, exactly the same
 // logic as for expression-position macro invocations.
 pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
-                       cx: @ExtCtxt, it: @ast::item,
-                       fld: @ast_fold)
-                    -> Option<@ast::item> {
+                       cx: @ExtCtxt,
+                       it: @ast::item,
+                       fld: &MacroExpander)
+                       -> Option<@ast::item> {
     let (pth, tts, ctxt) = match it.node {
-        item_mac(codemap::Spanned { node: mac_invoc_tt(ref pth, ref tts, ctxt), _}) => {
+        item_mac(codemap::Spanned {
+            node: mac_invoc_tt(ref pth, ref tts, ctxt),
+            _
+        }) => {
             (pth, (*tts).clone(), ctxt)
         }
         _ => cx.span_bug(it.span, "invalid item macro invocation")
@@ -314,7 +372,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
             // mark before expansion:
             let marked_before = mark_tts(tts,fm);
             let marked_ctxt = new_mark(fm,ctxt);
-            expander(cx, it.span, marked_before, marked_ctxt)
+            expander.expand(cx, it.span, marked_before, marked_ctxt)
         }
         Some(@SE(IdentTT(expander, span))) => {
             if it.ident.name == parse::token::special_idents::invalid.name {
@@ -332,7 +390,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
             // mark before expansion:
             let marked_tts = mark_tts(tts,fm);
             let marked_ctxt = new_mark(fm,ctxt);
-            expander(cx, it.span, it.ident, marked_tts, marked_ctxt)
+            expander.expand(cx, it.span, it.ident, marked_tts, marked_ctxt)
         }
         _ => cx.span_fatal(
             it.span, fmt!("%s! is not legal in item position", extnamestr))
@@ -346,10 +404,10 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv,
         MRExpr(_) => {
             cx.span_fatal(pth.span, fmt!("expr macro in item position: %s", extnamestr))
         }
-        MRAny(_, item_maker, _) => {
-            item_maker()
-                .and_then(|i| mark_item(i,fm))
-                .and_then(|i| fld.fold_item(i))
+        MRAny(any_macro) => {
+            any_macro.make_item()
+                     .and_then(|i| mark_item(i,fm))
+                     .and_then(|i| fld.fold_item(i))
         }
         MRDef(ref mdef) => {
             // yikes... no idea how to apply the mark to this. I'm afraid
@@ -382,15 +440,12 @@ fn insert_macro(exts: SyntaxEnv, name: ast::Name, transformer: @Transformer) {
 // expand a stmt
 pub fn expand_stmt(extsbox: @mut SyntaxEnv,
                    cx: @ExtCtxt,
-                   s: &Stmt_,
-                   sp: Span,
-                   fld: @ast_fold,
-                   orig: @fn(&Stmt_, Span, @ast_fold)
-                             -> (Option<Stmt_>, Span))
-                -> (Option<Stmt_>, Span) {
+                   s: &Stmt,
+                   fld: &MacroExpander)
+                   -> Option<@Stmt> {
     // why the copying here and not in expand_expr?
     // looks like classic changed-in-only-one-place
-    let (pth, tts, semi, ctxt) = match *s {
+    let (pth, tts, semi, ctxt) = match s.node {
         StmtMac(ref mac, semi) => {
             match mac.node {
                 mac_invoc_tt(ref pth, ref tts, ctxt) => {
@@ -398,24 +453,26 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
                 }
             }
         }
-        _ => return expand_non_macro_stmt(*extsbox,s,sp,fld,orig)
+        _ => return expand_non_macro_stmt(*extsbox, s, fld)
     };
     if (pth.segments.len() > 1u) {
-        cx.span_fatal(
-            pth.span,
-            fmt!("expected macro name without module \
-                  separators"));
+        cx.span_fatal(pth.span,
+                      "expected macro name without module separators");
     }
     let extname = &pth.segments[0].identifier;
     let extnamestr = ident_to_str(extname);
-    let (fully_expanded, sp) = match (*extsbox).find(&extname.name) {
-        None =>
-            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", extnamestr)),
+    let fully_expanded: @ast::Stmt = match (*extsbox).find(&extname.name) {
+        None => {
+            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", extnamestr))
+        }
 
         Some(@SE(NormalTT(expandfun, exp_span))) => {
             cx.bt_push(ExpnInfo {
-                call_site: sp,
-                callee: NameAndSpan { name: extnamestr, span: exp_span }
+                call_site: s.span,
+                callee: NameAndSpan {
+                    name: extnamestr,
+                    span: exp_span,
+                }
             });
             let fm = fresh_mark();
             // mark before expansion:
@@ -426,24 +483,32 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
             // not the current mac.span.
             let mac_span = original_span(cx);
 
-            let expanded = match expandfun(cx, mac_span.call_site,
-                                           marked_tts, marked_ctxt) {
-                MRExpr(e) =>
-                    @codemap::Spanned { node: StmtExpr(e, ast::DUMMY_NODE_ID),
-                                        span: e.span},
-                MRAny(_,_,stmt_mkr) => stmt_mkr(),
+            let expanded = match expandfun.expand(cx,
+                                                  mac_span.call_site,
+                                                  marked_tts,
+                                                  marked_ctxt) {
+                MRExpr(e) => {
+                    @codemap::Spanned {
+                        node: StmtExpr(e, ast::DUMMY_NODE_ID),
+                        span: e.span,
+                    }
+                }
+                MRAny(any_macro) => any_macro.make_stmt(),
                 _ => cx.span_fatal(
                     pth.span,
                     fmt!("non-stmt macro in stmt pos: %s", extnamestr))
             };
             let marked_after = mark_stmt(expanded,fm);
 
-            //keep going, outside-in
+            // Keep going, outside-in.
             let fully_expanded = match fld.fold_stmt(marked_after) {
                 Some(stmt) => {
                     let fully_expanded = &stmt.node;
                     cx.bt_pop();
-                    (*fully_expanded).clone()
+                    @Spanned {
+                        span: stmt.span,
+                        node: (*fully_expanded).clone(),
+                    }
                 }
                 None => {
                     cx.span_fatal(pth.span,
@@ -451,7 +516,7 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
                 }
             };
 
-            (fully_expanded, sp)
+            fully_expanded
         }
 
         _ => {
@@ -460,24 +525,28 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv,
         }
     };
 
-    (match fully_expanded {
-        StmtExpr(e, stmt_id) if semi => Some(StmtSemi(e, stmt_id)),
-        _ => { Some(fully_expanded) } /* might already have a semi */
-    }, sp)
-
+    match fully_expanded.node {
+        StmtExpr(e, stmt_id) if semi => {
+            Some(@Spanned {
+                span: fully_expanded.span,
+                node: StmtSemi(e, stmt_id),
+            })
+        }
+        _ => Some(fully_expanded), /* might already have a semi */
+    }
 }
 
 // expand a non-macro stmt. this is essentially the fallthrough for
 // expand_stmt, above.
-fn expand_non_macro_stmt (exts: SyntaxEnv,
-                          s: &Stmt_,
-                          sp: Span,
-                          fld: @ast_fold,
-                          orig: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span))
-    -> (Option<Stmt_>,Span) {
+fn expand_non_macro_stmt(exts: SyntaxEnv, s: &Stmt, fld: &MacroExpander)
+                         -> Option<@Stmt> {
     // is it a let?
-    match *s {
-        StmtDecl(@Spanned{node: DeclLocal(ref local), span: stmt_span}, node_id) => {
+    match s.node {
+        StmtDecl(@Spanned {
+            node: DeclLocal(ref local),
+            span: stmt_span
+        },
+        node_id) => {
             let block_info = get_block_info(exts);
             let pending_renames = block_info.pending_renames;
 
@@ -515,19 +584,24 @@ fn expand_non_macro_stmt (exts: SyntaxEnv,
             // also, don't forget to expand the init:
             let new_init_opt = init.map(|e| fld.fold_expr(*e));
             let rewritten_local =
-                @Local{is_mutbl:is_mutbl,
-                       ty:ty,
-                       pat:rewritten_pat,
-                       init:new_init_opt,
-                       id:id,
-                       span:span};
-            (Some(StmtDecl(@Spanned{node:DeclLocal(rewritten_local),
-                                     span: stmt_span},node_id)),
-             sp)
+                @Local {
+                    is_mutbl: is_mutbl,
+                    ty: ty,
+                    pat: rewritten_pat,
+                    init: new_init_opt,
+                    id: id,
+                    span: span,
+                };
+            Some(@Spanned {
+                node: StmtDecl(@Spanned {
+                        node: DeclLocal(rewritten_local),
+                        span: stmt_span
+                    },
+                    node_id),
+                span: span
+            })
         },
-        _ => {
-            orig(s, sp, fld)
-        }
+        _ => noop_fold_stmt(s, fld),
     }
 }
 
@@ -628,18 +702,18 @@ pub fn new_path_finder(paths: @mut ~[ast::Path]) -> @mut Visitor<()> {
 
 // expand a block. pushes a new exts_frame, then calls expand_block_elts
 pub fn expand_block(extsbox: @mut SyntaxEnv,
-                    _cx: @ExtCtxt,
+                    _: @ExtCtxt,
                     blk: &Block,
-                    fld: @ast_fold,
-                    _orig: @fn(&Block, @ast_fold) -> Block)
-                 -> Block {
+                    fld: &MacroExpander)
+                    -> Block {
     // see note below about treatment of exts table
     with_exts_frame!(extsbox,false,
                      expand_block_elts(*extsbox, blk, fld))
 }
 
 // expand the elements of a block.
-pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: @ast_fold) -> Block {
+pub fn expand_block_elts(exts: SyntaxEnv, b: &Block, fld: &MacroExpander)
+                         -> Block {
     let block_info = get_block_info(exts);
     let pending_renames = block_info.pending_renames;
     let rename_fld = renames_to_fold(pending_renames);
@@ -680,9 +754,47 @@ fn get_block_info(exts : SyntaxEnv) -> BlockInfo {
     }
 }
 
+struct IdentRenamer {
+    renames: @mut ~[(ast::Ident,ast::Name)],
+}
+
+impl ast_fold for IdentRenamer {
+    fn fold_ident(&self, id: ast::Ident) -> ast::Ident {
+        let new_ctxt = self.renames.iter().fold(id.ctxt, |ctxt, &(from, to)| {
+            new_rename(from, to, ctxt)
+        });
+        ast::Ident {
+            name: id.name,
+            ctxt: new_ctxt,
+        }
+    }
+}
+
+// given a mutable list of renames, return a tree-folder that applies those
+// renames.
+pub fn renames_to_fold(renames: @mut ~[(ast::Ident,ast::Name)]) -> @ast_fold {
+    @IdentRenamer {
+        renames: renames,
+    } as @ast_fold
+}
+
+// perform a bunch of renames
+fn apply_pending_renames(folder : @ast_fold, stmt : ast::Stmt) -> @ast::Stmt {
+    match folder.fold_stmt(&stmt) {
+        Some(s) => s,
+        None => fail!(fmt!("renaming of stmt produced None"))
+    }
+}
+
+
+
 pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span {
     /* this discards information in the case of macro-defining macros */
-    return Span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
+    Span {
+        lo: sp.lo,
+        hi: sp.hi,
+        expn_info: cx.backtrace(),
+    }
 }
 
 // FIXME (#2247): this is a moderately bad kludge to inject some macros into
@@ -1025,10 +1137,28 @@ pub fn std_macros() -> @str {
 }";
 }
 
+struct Injector {
+    sm: @ast::item,
+}
+
+impl ast_fold for Injector {
+    fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
+        // Just inject the standard macros at the start of the first module
+        // in the crate: that is, at the start of the crate file itself.
+        let items = vec::append(~[ self.sm ], module.items);
+        ast::_mod {
+            items: items,
+            ..(*module).clone() // FIXME #2543: Bad copy.
+        }
+    }
+}
+
 // add a bunch of macros as though they were placed at the head of the
 // program (ick). This should run before cfg stripping.
 pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
-                         cfg: ast::CrateConfig, c: &Crate) -> @Crate {
+                         cfg: ast::CrateConfig,
+                         c: @Crate)
+                         -> @Crate {
     let sm = match parse_item_from_source_str(@"<std-macros>",
                                               std_macros(),
                                               cfg.clone(),
@@ -1038,48 +1168,80 @@ pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
         None => fail!("expected core macros to parse correctly")
     };
 
-    let injecter = @AstFoldFns {
-        fold_mod: |modd, _| {
-            // just inject the std macros at the start of the first
-            // module in the crate (i.e the crate file itself.)
-            let items = vec::append(~[sm], modd.items);
-            ast::_mod {
-                items: items,
-                // FIXME #2543: Bad copy.
-                .. (*modd).clone()
-            }
-        },
-        .. *default_ast_fold()
-    };
-    @make_fold(injecter).fold_crate(c)
+    let injector = @Injector {
+        sm: sm,
+    } as @ast_fold;
+    @injector.fold_crate(c)
+}
+
+struct NoOpFolder {
+    contents: (),
+}
+
+impl ast_fold for NoOpFolder {}
+
+struct MacroExpander {
+    extsbox: @mut SyntaxEnv,
+    cx: @ExtCtxt,
+}
+
+impl ast_fold for MacroExpander {
+    fn fold_expr(&self, expr: @ast::Expr) -> @ast::Expr {
+        expand_expr(self.extsbox,
+                    self.cx,
+                    expr,
+                    self)
+    }
+
+    fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
+        expand_mod_items(self.extsbox,
+                         self.cx,
+                         module,
+                         self)
+    }
+
+    fn fold_item(&self, item: @ast::item) -> Option<@ast::item> {
+        expand_item(self.extsbox,
+                    self.cx,
+                    item,
+                    self)
+    }
+
+    fn fold_stmt(&self, stmt: &ast::Stmt) -> Option<@ast::Stmt> {
+        expand_stmt(self.extsbox,
+                    self.cx,
+                    stmt,
+                    self)
+    }
+
+    fn fold_block(&self, block: &ast::Block) -> ast::Block {
+        expand_block(self.extsbox,
+                     self.cx,
+                     block,
+                     self)
+    }
+
+    fn new_span(&self, span: Span) -> Span {
+        new_span(self.cx, span)
+    }
 }
 
 pub fn expand_crate(parse_sess: @mut parse::ParseSess,
-                    cfg: ast::CrateConfig, c: &Crate) -> @Crate {
+                    cfg: ast::CrateConfig,
+                    c: &Crate) -> @Crate {
     // adding *another* layer of indirection here so that the block
     // visitor can swap out one exts table for another for the duration
     // of the block.  The cleaner alternative would be to thread the
     // exts table through the fold, but that would require updating
     // every method/element of AstFoldFns in fold.rs.
-    let extsbox = @mut syntax_expander_table();
-    let afp = default_ast_fold();
+    let extsbox = syntax_expander_table();
     let cx = ExtCtxt::new(parse_sess, cfg.clone());
-    let f_pre = @AstFoldFns {
-        fold_expr: |expr,span,recur|
-            expand_expr(extsbox, cx, expr, span, recur, afp.fold_expr),
-        fold_mod: |modd,recur|
-            expand_mod_items(extsbox, cx, modd, recur, afp.fold_mod),
-        fold_item: |item,recur|
-            expand_item(extsbox, cx, item, recur, afp.fold_item),
-        fold_stmt: |stmt,span,recur|
-            expand_stmt(extsbox, cx, stmt, span, recur, afp.fold_stmt),
-        fold_block: |blk,recur|
-            expand_block(extsbox, cx, blk, recur, afp.fold_block),
-        new_span: |a| new_span(cx, a),
-        .. *afp};
-    let f = make_fold(f_pre);
-
-    let ret = @f.fold_crate(c);
+    let expander = @MacroExpander {
+        extsbox: @mut extsbox,
+        cx: cx,
+    } as @ast_fold;
+
+    let ret = @expander.fold_crate(c);
     parse_sess.span_diagnostic.handler().abort_if_errors();
     return ret;
 }
@@ -1145,53 +1307,56 @@ impl CtxtFn for Repainter {
     }
 }
 
-// given a function from ctxts to ctxts, produce
-// an ast_fold that applies that function to all ctxts:
-pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @AstFoldFns {
-    let afp = default_ast_fold();
-    let fi : @fn(ast::Ident, @ast_fold) -> ast::Ident =
-        |ast::Ident{name, ctxt}, _| {
-        ast::Ident{name:name,ctxt:cf.f(ctxt)}
-    };
-    let fm : @fn(&ast::mac_, Span, @ast_fold) -> (ast::mac_,Span) =
-        |m, sp, fld| {
-        match *m {
-            mac_invoc_tt(ref path, ref tts, ctxt) =>
-            (mac_invoc_tt(fld.fold_path(path),
-                          fold_tts(*tts,fld),
-                          cf.f(ctxt)),
-            sp)
-        }
+pub struct ContextWrapper {
+    context_function: @CtxtFn,
+}
 
-    };
-    @AstFoldFns{
-        fold_ident : fi,
-        fold_mac : fm,
-        .. *afp
+impl ast_fold for ContextWrapper {
+    fn fold_ident(&self, id: ast::Ident) -> ast::Ident {
+        let ast::Ident {
+            name,
+            ctxt
+        } = id;
+        ast::Ident {
+            name: name,
+            ctxt: self.context_function.f(ctxt),
+        }
+    }
+    fn fold_mac(&self, m: &ast::mac) -> ast::mac {
+        let macro = match m.node {
+            mac_invoc_tt(ref path, ref tts, ctxt) => {
+                mac_invoc_tt(self.fold_path(path),
+                             fold_tts(*tts, self),
+                             self.context_function.f(ctxt))
+            }
+        };
+        Spanned {
+            node: macro,
+            span: m.span,
+        }
     }
 }
 
-
-
-// given a mutable list of renames, return a tree-folder that applies those
-// renames.
-// FIXME #4536: currently pub to allow testing
-pub fn renames_to_fold(renames : @mut ~[(ast::Ident,ast::Name)]) -> @AstFoldFns {
-    fun_to_ctxt_folder(@MultiRenamer{renames : renames})
+// given a function from ctxts to ctxts, produce
+// an ast_fold that applies that function to all ctxts:
+pub fn fun_to_ctxt_folder<T : 'static + CtxtFn>(cf: @T) -> @ContextWrapper {
+    @ContextWrapper {
+        context_function: cf as @CtxtFn,
+    }
 }
 
 // just a convenience:
-pub fn new_mark_folder(m : Mrk) -> @AstFoldFns {
+pub fn new_mark_folder(m: Mrk) -> @ContextWrapper {
     fun_to_ctxt_folder(@Marker{mark:m})
 }
 
-pub fn new_rename_folder(from : ast::Ident, to : ast::Name) -> @AstFoldFns {
+pub fn new_rename_folder(from: ast::Ident, to: ast::Name) -> @ContextWrapper {
     fun_to_ctxt_folder(@Renamer{from:from,to:to})
 }
 
 // apply a given mark to the given token trees. Used prior to expansion of a macro.
 fn mark_tts(tts : &[token_tree], m : Mrk) -> ~[token_tree] {
-    fold_tts(tts,new_mark_folder(m) as @ast_fold)
+    fold_tts(tts,new_mark_folder(m))
 }
 
 // apply a given mark to the given expr. Used following the expansion of a macro.
@@ -1359,7 +1524,7 @@ mod test {
         let ident_str = @"x";
         let tts = string_to_tts(ident_str);
         let fm = fresh_mark();
-        let marked_once = fold::fold_tts(tts,new_mark_folder(fm) as @fold::ast_fold);
+        let marked_once = fold::fold_tts(tts,new_mark_folder(fm));
         assert_eq!(marked_once.len(),1);
         let marked_once_ctxt =
             match marked_once[0] {
diff --git a/src/libsyntax/ext/fmt.rs b/src/libsyntax/ext/fmt.rs
index 9adb02ecc98..d48fa03c0ef 100644
--- a/src/libsyntax/ext/fmt.rs
+++ b/src/libsyntax/ext/fmt.rs
@@ -38,7 +38,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
     fn parse_fmt_err_(cx: @ExtCtxt, sp: Span, msg: &str) -> ! {
         cx.span_fatal(sp, msg);
     }
-    let parse_fmt_err: @fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s);
+    let parse_fmt_err: &fn(&str) -> ! = |s| parse_fmt_err_(cx, fmtspan, s);
     let pieces = parse_fmt_string(fmt, parse_fmt_err);
     MRExpr(pieces_to_expr(cx, sp, pieces, args))
 }
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 74de8eaa09e..3fd394b3652 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -12,9 +12,9 @@ use ast::{Ident, matcher_, matcher, match_tok, match_nonterminal, match_seq};
 use ast::{tt_delim};
 use ast;
 use codemap::{Span, Spanned, dummy_sp};
-use ext::base::{ExtCtxt, MacResult, MRAny, MRDef, MacroDef, NormalTT};
+use ext::base::{AnyMacro, ExtCtxt, MacResult, MRAny, MRDef, MacroDef};
+use ext::base::{NormalTT, SyntaxExpanderTTTrait};
 use ext::base;
-use ext::expand;
 use ext::tt::macro_parser::{error};
 use ext::tt::macro_parser::{named_match, matched_seq, matched_nonterminal};
 use ext::tt::macro_parser::{parse, parse_or_else, success, failure};
@@ -24,6 +24,112 @@ use parse::token::{get_ident_interner, special_idents, gensym_ident, ident_to_st
 use parse::token::{FAT_ARROW, SEMI, nt_matchers, nt_tt};
 use print;
 
+struct ParserAnyMacro {
+    parser: @Parser,
+}
+
+impl AnyMacro for ParserAnyMacro {
+    fn make_expr(&self) -> @ast::Expr {
+        self.parser.parse_expr()
+    }
+    fn make_item(&self) -> Option<@ast::item> {
+        self.parser.parse_item(~[])     // no attrs
+    }
+    fn make_stmt(&self) -> @ast::Stmt {
+        self.parser.parse_stmt(~[])     // no attrs
+    }
+}
+
+struct MacroRulesSyntaxExpanderTTFun {
+    name: Ident,
+    lhses: @~[@named_match],
+    rhses: @~[@named_match],
+}
+
+impl SyntaxExpanderTTTrait for MacroRulesSyntaxExpanderTTFun {
+    fn expand(&self,
+              cx: @ExtCtxt,
+              sp: Span,
+              arg: &[ast::token_tree],
+              _: ast::SyntaxContext)
+              -> MacResult {
+        generic_extension(cx, sp, self.name, arg, *self.lhses, *self.rhses)
+    }
+}
+
+// Given `lhses` and `rhses`, this is the new macro we create
+fn generic_extension(cx: @ExtCtxt,
+                     sp: Span,
+                     name: Ident,
+                     arg: &[ast::token_tree],
+                     lhses: &[@named_match],
+                     rhses: &[@named_match])
+                     -> MacResult {
+    if cx.trace_macros() {
+        printfln!("%s! { %s }",
+                  cx.str_of(name),
+                  print::pprust::tt_to_str(
+                      &ast::tt_delim(@mut arg.to_owned()),
+                      get_ident_interner()));
+    }
+
+    // Which arm's failure should we report? (the one furthest along)
+    let mut best_fail_spot = dummy_sp();
+    let mut best_fail_msg = ~"internal error: ran no matchers";
+
+    let s_d = cx.parse_sess().span_diagnostic;
+
+    for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
+        match *lhs {
+          @matched_nonterminal(nt_matchers(ref mtcs)) => {
+            // `none` is because we're not interpolating
+            let arg_rdr = new_tt_reader(
+                s_d,
+                None,
+                arg.to_owned()
+            ) as @mut reader;
+            match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
+              success(named_matches) => {
+                let rhs = match rhses[i] {
+                    // okay, what's your transcriber?
+                    @matched_nonterminal(nt_tt(@ref tt)) => {
+                        match (*tt) {
+                            // cut off delimiters; don't parse 'em
+                            tt_delim(ref tts) => {
+                                (*tts).slice(1u,(*tts).len()-1u).to_owned()
+                            }
+                            _ => cx.span_fatal(
+                                sp, "macro rhs must be delimited")
+                        }
+                    },
+                    _ => cx.span_bug(sp, "bad thing in rhs")
+                };
+                // rhs has holes ( `$id` and `$(...)` that need filled)
+                let trncbr = new_tt_reader(s_d, Some(named_matches),
+                                           rhs);
+                let p = @Parser(cx.parse_sess(),
+                                cx.cfg(),
+                                trncbr as @mut reader);
+
+                // Let the context choose how to interpret the result.
+                // Weird, but useful for X-macros.
+                return MRAny(@ParserAnyMacro {
+                    parser: p,
+                } as @AnyMacro)
+              }
+              failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
+                best_fail_spot = sp;
+                best_fail_msg = (*msg).clone();
+              },
+              error(sp, ref msg) => cx.span_fatal(sp, (*msg))
+            }
+          }
+          _ => cx.bug("non-matcher found in parsed lhses")
+        }
+    }
+    cx.span_fatal(best_fail_spot, best_fail_msg);
+}
+
 // this procedure performs the expansion of the
 // macro_rules! macro. It parses the RHS and adds
 // an extension to the current context.
@@ -31,10 +137,8 @@ pub fn add_new_extension(cx: @ExtCtxt,
                          sp: Span,
                          name: Ident,
                          arg: ~[ast::token_tree],
-                         stx_ctxt: ast::SyntaxContext)
-                      -> base::MacResult {
-    let arg = expand::mtwt_cancel_outer_mark(arg,stx_ctxt);
-    // Wrap a matcher_ in a spanned to produce a matcher.
+                         _: ast::SyntaxContext)
+                         -> base::MacResult {
     // these spans won't matter, anyways
     fn ms(m: matcher_) -> matcher {
         Spanned {
@@ -82,11 +186,13 @@ pub fn add_new_extension(cx: @ExtCtxt,
     };
 
     // Given `lhses` and `rhses`, this is the new macro we create
-    fn generic_extension(cx: @ExtCtxt, sp: Span, name: Ident,
+    fn generic_extension(cx: @ExtCtxt,
+                         sp: Span,
+                         name: Ident,
                          arg: &[ast::token_tree],
-                         lhses: &[@named_match], rhses: &[@named_match])
-    -> MacResult {
-
+                         lhses: &[@named_match],
+                         rhses: &[@named_match])
+                         -> MacResult {
         if cx.trace_macros() {
             printfln!("%s! { %s }",
                       cx.str_of(name),
@@ -135,9 +241,9 @@ pub fn add_new_extension(cx: @ExtCtxt,
 
                     // Let the context choose how to interpret the result.
                     // Weird, but useful for X-macros.
-                    return MRAny(|| p.parse_expr(),
-                                  || p.parse_item(~[/* no attrs*/]),
-                                  || p.parse_stmt(~[/* no attrs*/]));
+                    return MRAny(@ParserAnyMacro {
+                        parser: p
+                    } as @AnyMacro);
                   }
                   failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                     best_fail_spot = sp;
@@ -152,10 +258,13 @@ pub fn add_new_extension(cx: @ExtCtxt,
         cx.span_fatal(best_fail_spot, best_fail_msg);
     }
 
-    let exp: @fn(@ExtCtxt, Span, &[ast::token_tree], ctxt: ast::SyntaxContext) -> MacResult =
-        |cx, sp, arg, _ctxt| generic_extension(cx, sp, name, arg, *lhses, *rhses);
+    let exp = @MacroRulesSyntaxExpanderTTFun {
+        name: name,
+        lhses: lhses,
+        rhses: rhses,
+    } as @SyntaxExpanderTTTrait;
 
-    return MRDef(MacroDef{
+    return MRDef(MacroDef {
         name: ident_to_str(&name),
         ext: NormalTT(exp, Some(sp))
     });
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5472c61a155..a25f267c458 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -14,227 +14,434 @@ use codemap::{Span, Spanned};
 use parse::token;
 use opt_vec::OptVec;
 
-// this file defines an ast_fold trait for objects that can perform
-// a "fold" on Rust ASTs. It also contains a structure that implements
-// that trait, and a "default_fold" whose fields contain closures
-// that perform "default traversals", visiting all of the sub-elements
-// and re-assembling the result. The "fun_to_ident_folder" in the
-// test module provides a simple example of creating a very simple
-// fold that only looks at identifiers.
-
+// We may eventually want to be able to fold over type parameters, too.
 pub trait ast_fold {
-    fn fold_crate(@self, &Crate) -> Crate;
-    fn fold_view_item(@self, &view_item) -> view_item;
-    fn fold_foreign_item(@self, @foreign_item) -> @foreign_item;
-    fn fold_item(@self, @item) -> Option<@item>;
-    fn fold_struct_field(@self, @struct_field) -> @struct_field;
-    fn fold_item_underscore(@self, &item_) -> item_;
-    fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod;
-    fn fold_method(@self, @method) -> @method;
-    fn fold_block(@self, &Block) -> Block;
-    fn fold_stmt(@self, &Stmt) -> Option<@Stmt>;
-    fn fold_arm(@self, &Arm) -> Arm;
-    fn fold_pat(@self, @Pat) -> @Pat;
-    fn fold_decl(@self, @Decl) -> Option<@Decl>;
-    fn fold_expr(@self, @Expr) -> @Expr;
-    fn fold_ty(@self, &Ty) -> Ty;
-    fn fold_mod(@self, &_mod) -> _mod;
-    fn fold_foreign_mod(@self, &foreign_mod) -> foreign_mod;
-    fn fold_variant(@self, &variant) -> variant;
-    fn fold_ident(@self, Ident) -> Ident;
-    fn fold_path(@self, &Path) -> Path;
-    fn fold_local(@self, @Local) -> @Local;
-    fn fold_mac(@self, &mac) -> mac;
-    fn map_exprs(@self, @fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr];
-    fn new_id(@self, NodeId) -> NodeId;
-    fn new_span(@self, Span) -> Span;
-
-    // New style, using default methods:
-
-    fn fold_variant_arg(@self, va: &variant_arg) -> variant_arg {
-        variant_arg {
-            ty: self.fold_ty(&va.ty),
-            id: self.new_id(va.id)
-        }
-    }
-
-    fn fold_spanned<T>(@self, s: &Spanned<T>, f: &fn(&T) -> T) -> Spanned<T> {
-        Spanned {
-            node: f(&s.node),
-            span: self.new_span(s.span)
-        }
+    fn fold_crate(&self, c: &Crate) -> Crate {
+        noop_fold_crate(c, self)
     }
 
-    fn fold_view_path(@self, vp: &view_path) -> view_path {
-        self.fold_spanned(vp, |v| self.fold_view_path_(v))
+    fn fold_meta_items(&self, meta_items: &[@MetaItem]) -> ~[@MetaItem] {
+        meta_items.map(|x| fold_meta_item_(*x, self))
     }
 
-    fn fold_view_paths(@self, vps: &[@view_path]) -> ~[@view_path] {
-        vps.map(|vp| @self.fold_view_path(*vp))
+    fn fold_view_paths(&self, view_paths: &[@view_path]) -> ~[@view_path] {
+        view_paths.map(|view_path| {
+            let inner_view_path = match view_path.node {
+                view_path_simple(ref ident, ref path, node_id) => {
+                    view_path_simple(ident.clone(),
+                                     self.fold_path(path),
+                                     self.new_id(node_id))
+                }
+                view_path_glob(ref path, node_id) => {
+                    view_path_glob(self.fold_path(path), self.new_id(node_id))
+                }
+                view_path_list(ref path, ref path_list_idents, node_id) => {
+                    view_path_list(self.fold_path(path),
+                                   path_list_idents.map(|path_list_ident| {
+                                    let id = self.new_id(path_list_ident.node
+                                                                        .id);
+                                    Spanned {
+                                        node: path_list_ident_ {
+                                            name: path_list_ident.node
+                                                                 .name
+                                                                 .clone(),
+                                            id: id,
+                                        },
+                                        span: self.new_span(
+                                            path_list_ident.span)
+                                   }
+                                  }),
+                                  self.new_id(node_id))
+                }
+            };
+            @Spanned {
+                node: inner_view_path,
+                span: self.new_span(view_path.span),
+            }
+        })
     }
 
-    fn fold_view_path_(@self, vp: &view_path_) -> view_path_ {
-        match *vp {
-            view_path_simple(ident, ref path, node_id) => {
-                view_path_simple(self.fold_ident(ident),
-                                 self.fold_path(path),
-                                 self.new_id(node_id))
-            }
-            view_path_glob(ref path, node_id) => {
-                view_path_glob(self.fold_path(path),
-                               self.new_id(node_id))
+    fn fold_view_item(&self, vi: &view_item) -> view_item {
+        let inner_view_item = match vi.node {
+            view_item_extern_mod(ref ident,
+                                 string,
+                                 ref meta_items,
+                                 node_id) => {
+                view_item_extern_mod(ident.clone(),
+                                     string,
+                                     self.fold_meta_items(*meta_items),
+                                     self.new_id(node_id))
             }
-            view_path_list(ref path, ref idents, node_id) => {
-                view_path_list(self.fold_path(path),
-                               self.fold_path_list_idents(*idents),
-                               self.new_id(node_id))
+            view_item_use(ref view_paths) => {
+                view_item_use(self.fold_view_paths(*view_paths))
             }
+        };
+        view_item {
+            node: inner_view_item,
+            attrs: vi.attrs.map(|a| fold_attribute_(*a, self)),
+            vis: vi.vis,
+            span: self.new_span(vi.span),
+        }
+    }
+
+    fn fold_foreign_item(&self, ni: @foreign_item) -> @foreign_item {
+        let fold_attribute = |x| fold_attribute_(x, self);
+
+        @ast::foreign_item {
+            ident: self.fold_ident(ni.ident),
+            attrs: ni.attrs.map(|x| fold_attribute(*x)),
+            node:
+                match ni.node {
+                    foreign_item_fn(ref fdec, ref generics) => {
+                        foreign_item_fn(
+                            ast::fn_decl {
+                                inputs: fdec.inputs.map(|a| fold_arg_(a,
+                                                                      self)),
+                                output: self.fold_ty(&fdec.output),
+                                cf: fdec.cf,
+                            },
+                            fold_generics(generics, self))
+                    }
+                    foreign_item_static(ref t, m) => {
+                        foreign_item_static(self.fold_ty(t), m)
+                    }
+                },
+            id: self.new_id(ni.id),
+            span: self.new_span(ni.span),
+            vis: ni.vis,
         }
     }
 
-    fn fold_path_list_idents(@self, idents: &[path_list_ident]) -> ~[path_list_ident] {
-        idents.map(|i| self.fold_path_list_ident(i))
+    fn fold_item(&self, i: @item) -> Option<@item> {
+        noop_fold_item(i, self)
     }
 
-    fn fold_path_list_ident(@self, ident: &path_list_ident) -> path_list_ident {
-        self.fold_spanned(ident, |i| self.fold_path_list_ident_(i))
-    }
+    fn fold_struct_field(&self, sf: @struct_field) -> @struct_field {
+        let fold_attribute = |x| fold_attribute_(x, self);
 
-    fn fold_path_list_ident_(@self, ident: &path_list_ident_) -> path_list_ident_ {
-        path_list_ident_ {
-            name: self.fold_ident(ident.name),
-            id: self.new_id(ident.id)
+        @Spanned {
+            node: ast::struct_field_ {
+                kind: sf.node.kind,
+                id: self.new_id(sf.node.id),
+                ty: self.fold_ty(&sf.node.ty),
+                attrs: sf.node.attrs.map(|e| fold_attribute(*e))
+            },
+            span: self.new_span(sf.span)
         }
     }
 
-    fn fold_arg(@self, a: &arg) -> arg {
-        arg {
-            is_mutbl: a.is_mutbl,
-            ty: self.fold_ty(&a.ty),
-            pat: self.fold_pat(a.pat),
-            id: self.new_id(a.id),
+    fn fold_item_underscore(&self, i: &item_) -> item_ {
+        noop_fold_item_underscore(i, self)
+    }
+
+    fn fold_type_method(&self, m: &TypeMethod) -> TypeMethod {
+        noop_fold_type_method(m, self)
+    }
+
+    fn fold_method(&self, m: @method) -> @method {
+        @ast::method {
+            ident: self.fold_ident(m.ident),
+            attrs: m.attrs.map(|a| fold_attribute_(*a, self)),
+            generics: fold_generics(&m.generics, self),
+            explicit_self: m.explicit_self,
+            purity: m.purity,
+            decl: fold_fn_decl(&m.decl, self),
+            body: self.fold_block(&m.body),
+            id: self.new_id(m.id),
+            span: self.new_span(m.span),
+            self_id: self.new_id(m.self_id),
+            vis: m.vis,
         }
     }
 
-    fn fold_trait_ref(@self, p: &trait_ref) -> trait_ref {
-        trait_ref {
-            path: self.fold_path(&p.path),
-            ref_id: self.new_id(p.ref_id),
+    fn fold_block(&self, b: &Block) -> Block {
+        noop_fold_block(b, self)
+    }
+
+    fn fold_stmt(&self, s: &Stmt) -> Option<@Stmt> {
+        noop_fold_stmt(s, self)
+    }
+
+    fn fold_arm(&self, a: &Arm) -> Arm {
+        Arm {
+            pats: a.pats.map(|x| self.fold_pat(*x)),
+            guard: a.guard.map_move(|x| self.fold_expr(x)),
+            body: self.fold_block(&a.body),
         }
     }
 
-    fn fold_ty_param_bound(@self, tpb: &TyParamBound) -> TyParamBound {
-        match *tpb {
-            TraitTyParamBound(ref ty) => {
-                TraitTyParamBound(self.fold_trait_ref(ty))
+    fn fold_pat(&self, p: @Pat) -> @Pat {
+        let node = match p.node {
+            PatWild => PatWild,
+            PatIdent(binding_mode, ref pth, ref sub) => {
+                PatIdent(binding_mode,
+                         self.fold_path(pth),
+                         sub.map_move(|x| self.fold_pat(x)))
+            }
+            PatLit(e) => PatLit(self.fold_expr(e)),
+            PatEnum(ref pth, ref pats) => {
+                PatEnum(self.fold_path(pth),
+                        pats.map(|pats| pats.map(|x| self.fold_pat(*x))))
             }
-            RegionTyParamBound => {
-                RegionTyParamBound
+            PatStruct(ref pth, ref fields, etc) => {
+                let pth_ = self.fold_path(pth);
+                let fs = do fields.map |f| {
+                    ast::FieldPat {
+                        ident: f.ident,
+                        pat: self.fold_pat(f.pat)
+                    }
+                };
+                PatStruct(pth_, fs, etc)
             }
+            PatTup(ref elts) => PatTup(elts.map(|x| self.fold_pat(*x))),
+            PatBox(inner) => PatBox(self.fold_pat(inner)),
+            PatUniq(inner) => PatUniq(self.fold_pat(inner)),
+            PatRegion(inner) => PatRegion(self.fold_pat(inner)),
+            PatRange(e1, e2) => {
+                PatRange(self.fold_expr(e1), self.fold_expr(e2))
+            },
+            PatVec(ref before, ref slice, ref after) => {
+                PatVec(before.map(|x| self.fold_pat(*x)),
+                       slice.map_move(|x| self.fold_pat(x)),
+                       after.map(|x| self.fold_pat(*x)))
+            }
+        };
+
+        @Pat {
+            id: self.new_id(p.id),
+            span: self.new_span(p.span),
+            node: node,
         }
     }
 
-    fn fold_ty_param(@self, tp: &TyParam) -> TyParam {
-        TyParam {
-            ident: self.fold_ident(tp.ident),
-            id: self.new_id(tp.id),
-            bounds: tp.bounds.map(|x| self.fold_ty_param_bound(x))
+    fn fold_decl(&self, d: @Decl) -> Option<@Decl> {
+        let node = match d.node {
+            DeclLocal(ref l) => Some(DeclLocal(self.fold_local(*l))),
+            DeclItem(it) => {
+                match self.fold_item(it) {
+                    Some(it_folded) => Some(DeclItem(it_folded)),
+                    None => None,
+                }
+            }
+        };
+
+        node.map_move(|node| {
+            @Spanned {
+                node: node,
+                span: d.span,
+            }
+        })
+    }
+
+    fn fold_expr(&self, e: @Expr) -> @Expr {
+        noop_fold_expr(e, self)
+    }
+
+    fn fold_ty(&self, t: &Ty) -> Ty {
+        let node = match t.node {
+            ty_nil | ty_bot | ty_infer => t.node.clone(),
+            ty_box(ref mt) => ty_box(fold_mt(mt, self)),
+            ty_uniq(ref mt) => ty_uniq(fold_mt(mt, self)),
+            ty_vec(ref mt) => ty_vec(fold_mt(mt, self)),
+            ty_ptr(ref mt) => ty_ptr(fold_mt(mt, self)),
+            ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, self)),
+            ty_closure(ref f) => {
+                ty_closure(@TyClosure {
+                    sigil: f.sigil,
+                    purity: f.purity,
+                    region: f.region,
+                    onceness: f.onceness,
+                    bounds: fold_opt_bounds(&f.bounds, self),
+                    decl: fold_fn_decl(&f.decl, self),
+                    lifetimes: f.lifetimes.map(|l| fold_lifetime(l, self)),
+                })
+            }
+            ty_bare_fn(ref f) => {
+                ty_bare_fn(@TyBareFn {
+                    lifetimes: f.lifetimes.map(|l| fold_lifetime(l, self)),
+                    purity: f.purity,
+                    abis: f.abis,
+                    decl: fold_fn_decl(&f.decl, self)
+                })
+            }
+            ty_tup(ref tys) => ty_tup(tys.map(|ty| self.fold_ty(ty))),
+            ty_path(ref path, ref bounds, id) => {
+                ty_path(self.fold_path(path),
+                        fold_opt_bounds(bounds, self),
+                        self.new_id(id))
+            }
+            ty_fixed_length_vec(ref mt, e) => {
+                ty_fixed_length_vec(fold_mt(mt, self), self.fold_expr(e))
+            }
+            ty_mac(ref mac) => ty_mac(self.fold_mac(mac)),
+            ty_typeof(expr) => ty_typeof(self.fold_expr(expr)),
+        };
+        Ty {
+            id: self.new_id(t.id),
+            span: self.new_span(t.span),
+            node: node,
         }
     }
 
-    fn fold_ty_params(@self, tps: &OptVec<TyParam>) -> OptVec<TyParam> {
-        tps.map(|tp| self.fold_ty_param(tp))
+    fn fold_mod(&self, m: &_mod) -> _mod {
+        noop_fold_mod(m, self)
     }
 
-    fn fold_lifetime(@self, l: &Lifetime) -> Lifetime {
-        Lifetime {
-            id: self.new_id(l.id),
-            span: self.new_span(l.span),
-            ident: l.ident, // Folding this ident causes hygiene errors - ndm
+    fn fold_foreign_mod(&self, nm: &foreign_mod) -> foreign_mod {
+        ast::foreign_mod {
+            sort: nm.sort,
+            abis: nm.abis,
+            view_items: nm.view_items
+                          .iter()
+                          .map(|x| self.fold_view_item(x))
+                          .collect(),
+            items: nm.items
+                     .iter()
+                     .map(|x| self.fold_foreign_item(*x))
+                     .collect(),
         }
     }
 
-    fn fold_lifetimes(@self, lts: &OptVec<Lifetime>) -> OptVec<Lifetime> {
-        lts.map(|l| self.fold_lifetime(l))
+    fn fold_variant(&self, v: &variant) -> variant {
+        let kind;
+        match v.node.kind {
+            tuple_variant_kind(ref variant_args) => {
+                kind = tuple_variant_kind(variant_args.map(|x|
+                    fold_variant_arg_(x, self)))
+            }
+            struct_variant_kind(ref struct_def) => {
+                kind = struct_variant_kind(@ast::struct_def {
+                    fields: struct_def.fields.iter()
+                        .map(|f| self.fold_struct_field(*f)).collect(),
+                    ctor_id: struct_def.ctor_id.map(|c| self.new_id(*c))
+                })
+            }
+        }
+
+        let fold_attribute = |x| fold_attribute_(x, self);
+        let attrs = v.node.attrs.map(|x| fold_attribute(*x));
+
+        let de = match v.node.disr_expr {
+          Some(e) => Some(self.fold_expr(e)),
+          None => None
+        };
+        let node = ast::variant_ {
+            name: v.node.name,
+            attrs: attrs,
+            kind: kind,
+            id: self.new_id(v.node.id),
+            disr_expr: de,
+            vis: v.node.vis,
+        };
+        Spanned {
+            node: node,
+            span: self.new_span(v.span),
+        }
     }
 
+    fn fold_ident(&self, i: Ident) -> Ident {
+        i
+    }
 
-    fn fold_meta_item(@self, mi: &MetaItem) -> @MetaItem {
-        @self.fold_spanned(mi, |n| match *n {
-                MetaWord(id) => {
-                    MetaWord(id)
-                }
-                MetaList(id, ref mis) => {
-                    MetaList(id, self.fold_meta_items(*mis))
-                }
-                MetaNameValue(id, s) => {
-                    MetaNameValue(id, s)
-                }
+    fn fold_path(&self, p: &Path) -> Path {
+        ast::Path {
+            span: self.new_span(p.span),
+            global: p.global,
+            segments: p.segments.map(|segment| ast::PathSegment {
+                identifier: self.fold_ident(segment.identifier),
+                lifetime: segment.lifetime,
+                types: segment.types.map(|typ| self.fold_ty(typ)),
             })
+        }
     }
 
-    fn fold_meta_items(@self, mis: &[@MetaItem]) -> ~[@MetaItem] {
-        mis.map(|&mi| self.fold_meta_item(mi))
+    fn fold_local(&self, l: @Local) -> @Local {
+        @Local {
+            is_mutbl: l.is_mutbl,
+            ty: self.fold_ty(&l.ty),
+            pat: self.fold_pat(l.pat),
+            init: l.init.map_move(|e| self.fold_expr(e)),
+            id: self.new_id(l.id),
+            span: self.new_span(l.span),
+        }
     }
 
-    fn fold_attribute(@self, at: &Attribute) -> Attribute {
+    fn fold_mac(&self, macro: &mac) -> mac {
         Spanned {
-            span: self.new_span(at.span),
-            node: Attribute_ {
-                style: at.node.style,
-                value: self.fold_meta_item(at.node.value),
-                is_sugared_doc: at.node.is_sugared_doc
-            }
+            node: match macro.node {
+                mac_invoc_tt(ref p, ref tts, ctxt) => {
+                    mac_invoc_tt(self.fold_path(p),
+                                 fold_tts(*tts, self),
+                                 ctxt)
+                }
+            },
+            span: self.new_span(macro.span)
         }
     }
 
-    fn fold_attributes(@self, attrs: &[Attribute]) -> ~[Attribute] {
-        attrs.map(|x| self.fold_attribute(x))
+    fn map_exprs(&self, f: &fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] {
+        es.map(|x| f(*x))
+    }
+
+    fn new_id(&self, i: NodeId) -> NodeId {
+        i
+    }
+
+    fn new_span(&self, sp: Span) -> Span {
+        sp
     }
 }
 
-// We may eventually want to be able to fold over type parameters, too
-
-pub struct AstFoldFns {
-    //unlike the others, item_ is non-trivial
-    fold_crate: @fn(&Crate, @ast_fold) -> Crate,
-    fold_view_item: @fn(&view_item_, @ast_fold) -> view_item_,
-    fold_foreign_item: @fn(@foreign_item, @ast_fold) -> @foreign_item,
-    fold_item: @fn(@item, @ast_fold) -> Option<@item>,
-    fold_struct_field: @fn(@struct_field, @ast_fold) -> @struct_field,
-    fold_item_underscore: @fn(&item_, @ast_fold) -> item_,
-    fold_type_method: @fn(&TypeMethod, @ast_fold) -> TypeMethod,
-    fold_method: @fn(@method, @ast_fold) -> @method,
-    fold_block: @fn(&Block, @ast_fold) -> Block,
-    fold_stmt: @fn(&Stmt_, Span, @ast_fold) -> (Option<Stmt_>, Span),
-    fold_arm: @fn(&Arm, @ast_fold) -> Arm,
-    fold_pat: @fn(&Pat_, Span, @ast_fold) -> (Pat_, Span),
-    fold_decl: @fn(&Decl_, Span, @ast_fold) -> (Option<Decl_>, Span),
-    fold_expr: @fn(&Expr_, Span, @ast_fold) -> (Expr_, Span),
-    fold_ty: @fn(&ty_, Span, @ast_fold) -> (ty_, Span),
-    fold_mod: @fn(&_mod, @ast_fold) -> _mod,
-    fold_foreign_mod: @fn(&foreign_mod, @ast_fold) -> foreign_mod,
-    fold_variant: @fn(&variant_, Span, @ast_fold) -> (variant_, Span),
-    fold_ident: @fn(Ident, @ast_fold) -> Ident,
-    fold_path: @fn(&Path, @ast_fold) -> Path,
-    fold_local: @fn(@Local, @ast_fold) -> @Local,
-    fold_mac: @fn(&mac_, Span, @ast_fold) -> (mac_, Span),
-    map_exprs: @fn(@fn(@Expr) -> @Expr, &[@Expr]) -> ~[@Expr],
-    new_id: @fn(NodeId) -> NodeId,
-    new_span: @fn(Span) -> Span
+/* some little folds that probably aren't useful to have in ast_fold itself*/
+
+//used in noop_fold_item and noop_fold_crate and noop_fold_crate_directive
+fn fold_meta_item_<T:ast_fold>(mi: @MetaItem, fld: &T) -> @MetaItem {
+    @Spanned {
+        node:
+            match mi.node {
+                MetaWord(id) => MetaWord(id),
+                MetaList(id, ref mis) => {
+                    let fold_meta_item = |x| fold_meta_item_(x, fld);
+                    MetaList(
+                        id,
+                        mis.map(|e| fold_meta_item(*e))
+                    )
+                }
+                MetaNameValue(id, s) => MetaNameValue(id, s)
+            },
+        span: fld.new_span(mi.span) }
 }
 
-pub type ast_fold_fns = @AstFoldFns;
+//used in noop_fold_item and noop_fold_crate
+fn fold_attribute_<T:ast_fold>(at: Attribute, fld: &T) -> Attribute {
+    Spanned {
+        span: fld.new_span(at.span),
+        node: ast::Attribute_ {
+            style: at.node.style,
+            value: fold_meta_item_(at.node.value, fld),
+            is_sugared_doc: at.node.is_sugared_doc
+        }
+    }
+}
 
-/* some little folds that probably aren't useful to have in ast_fold itself*/
+//used in noop_fold_foreign_item and noop_fold_fn_decl
+fn fold_arg_<T:ast_fold>(a: &arg, fld: &T) -> arg {
+    ast::arg {
+        is_mutbl: a.is_mutbl,
+        ty: fld.fold_ty(&a.ty),
+        pat: fld.fold_pat(a.pat),
+        id: fld.new_id(a.id),
+    }
+}
 
-pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] {
+// build a new vector of tts by appling the ast_fold's fold_ident to
+// all of the identifiers in the token trees.
+pub fn fold_tts<T:ast_fold>(tts: &[token_tree], fld: &T) -> ~[token_tree] {
     do tts.map |tt| {
         match *tt {
             tt_tok(span, ref tok) =>
             tt_tok(span,maybe_fold_ident(tok,fld)),
-            tt_delim(ref tts) =>
-            tt_delim(@mut fold_tts(**tts, fld)),
+            tt_delim(ref tts) => tt_delim(@mut fold_tts(**tts, fld)),
             tt_seq(span, ref pattern, ref sep, is_optional) =>
             tt_seq(span,
                    @mut fold_tts(**pattern, fld),
@@ -247,33 +454,68 @@ pub fn fold_tts(tts : &[token_tree], fld: @ast_fold) -> ~[token_tree] {
 }
 
 // apply ident folder if it's an ident, otherwise leave it alone
-fn maybe_fold_ident(t : &token::Token, f: @ast_fold) -> token::Token {
+fn maybe_fold_ident<T:ast_fold>(t: &token::Token, fld: &T) -> token::Token {
     match *t {
-        token::IDENT(id,followed_by_colons) =>
-        token::IDENT(f.fold_ident(id),followed_by_colons),
+        token::IDENT(id, followed_by_colons) => {
+            token::IDENT(fld.fold_ident(id), followed_by_colons)
+        }
         _ => (*t).clone()
     }
 }
 
-pub fn fold_fn_decl(decl: &ast::fn_decl, fld: @ast_fold) -> ast::fn_decl {
+pub fn fold_fn_decl<T:ast_fold>(decl: &ast::fn_decl, fld: &T)
+                                -> ast::fn_decl {
     ast::fn_decl {
-        inputs: decl.inputs.map(|x| fld.fold_arg(x)),
+        inputs: decl.inputs.map(|x| fold_arg_(x, fld)), // bad copy
         output: fld.fold_ty(&decl.output),
         cf: decl.cf,
     }
 }
 
-pub fn fold_generics(generics: &Generics, fld: @ast_fold) -> Generics {
-    Generics {ty_params: fld.fold_ty_params(&generics.ty_params),
-              lifetimes: fld.fold_lifetimes(&generics.lifetimes)}
+fn fold_ty_param_bound<T:ast_fold>(tpb: &TyParamBound, fld: &T)
+                                   -> TyParamBound {
+    match *tpb {
+        TraitTyParamBound(ref ty) => TraitTyParamBound(fold_trait_ref(ty, fld)),
+        RegionTyParamBound => RegionTyParamBound
+    }
 }
 
-pub fn noop_fold_crate(c: &Crate, fld: @ast_fold) -> Crate {
-    Crate {
-        module: fld.fold_mod(&c.module),
-        attrs: fld.fold_attributes(c.attrs),
-        config: fld.fold_meta_items(c.config),
-        span: fld.new_span(c.span),
+pub fn fold_ty_param<T:ast_fold>(tp: &TyParam, fld: &T) -> TyParam {
+    TyParam {
+        ident: tp.ident,
+        id: fld.new_id(tp.id),
+        bounds: tp.bounds.map(|x| fold_ty_param_bound(x, fld)),
+    }
+}
+
+pub fn fold_ty_params<T:ast_fold>(tps: &OptVec<TyParam>, fld: &T)
+                                  -> OptVec<TyParam> {
+    tps.map(|tp| fold_ty_param(tp, fld))
+}
+
+pub fn fold_lifetime<T:ast_fold>(l: &Lifetime, fld: &T) -> Lifetime {
+    Lifetime {
+        id: fld.new_id(l.id),
+        span: fld.new_span(l.span),
+        ident: l.ident
+    }
+}
+
+pub fn fold_lifetimes<T:ast_fold>(lts: &OptVec<Lifetime>, fld: &T)
+                                  -> OptVec<Lifetime> {
+    lts.map(|l| fold_lifetime(l, fld))
+}
+
+pub fn fold_generics<T:ast_fold>(generics: &Generics, fld: &T) -> Generics {
+    Generics {ty_params: fold_ty_params(&generics.ty_params, fld),
+              lifetimes: fold_lifetimes(&generics.lifetimes, fld)}
+}
+
+fn fold_struct_def<T:ast_fold>(struct_def: @ast::struct_def, fld: &T)
+                               -> @ast::struct_def {
+    @ast::struct_def {
+        fields: struct_def.fields.map(|f| fold_struct_field(*f, fld)),
+        ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(*cid)),
     }
 }
 
@@ -291,753 +533,333 @@ fn noop_fold_view_item(vi: &view_item_, fld: @ast_fold) -> view_item_ {
     }
 }
 
-fn noop_fold_foreign_item(ni: @foreign_item, fld: @ast_fold)
-    -> @foreign_item {
-    @ast::foreign_item {
-        ident: fld.fold_ident(ni.ident),
-        attrs: fld.fold_attributes(ni.attrs),
-        node:
-            match ni.node {
-                foreign_item_fn(ref fdec, ref generics) => {
-                    foreign_item_fn(
-                        ast::fn_decl {
-                            inputs: fdec.inputs.map(|a| fld.fold_arg(a)),
-                            output: fld.fold_ty(&fdec.output),
-                            cf: fdec.cf,
-                        },
-                        fold_generics(generics, fld))
-                }
-                foreign_item_static(ref t, m) => {
-                    foreign_item_static(fld.fold_ty(t), m)
-                }
-            },
-        id: fld.new_id(ni.id),
-        span: fld.new_span(ni.span),
-        vis: ni.vis,
+fn fold_trait_ref<T:ast_fold>(p: &trait_ref, fld: &T) -> trait_ref {
+    ast::trait_ref {
+        path: fld.fold_path(&p.path),
+        ref_id: fld.new_id(p.ref_id),
     }
 }
 
-pub fn noop_fold_item(i: @item, fld: @ast_fold) -> Option<@item> {
-    Some(@ast::item { ident: fld.fold_ident(i.ident),
-                      attrs: fld.fold_attributes(i.attrs),
-                      id: fld.new_id(i.id),
-                      node: fld.fold_item_underscore(&i.node),
-                      vis: i.vis,
-                      span: fld.new_span(i.span) })
-}
-
-fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold)
-                       -> @struct_field {
+fn fold_struct_field<T:ast_fold>(f: @struct_field, fld: &T) -> @struct_field {
     @Spanned {
         node: ast::struct_field_ {
-            kind: sf.node.kind,
-            id: fld.new_id(sf.node.id),
-            ty: fld.fold_ty(&sf.node.ty),
-            attrs: fld.fold_attributes(sf.node.attrs),
+            kind: f.node.kind,
+            id: fld.new_id(f.node.id),
+            ty: fld.fold_ty(&f.node.ty),
+            attrs: f.node.attrs.map(|a| fold_attribute_(*a, fld)),
         },
-        span: sf.span
+        span: fld.new_span(f.span),
     }
 }
 
-pub fn noop_fold_type_method(m: &TypeMethod, fld: @ast_fold) -> TypeMethod {
-    TypeMethod {
-        ident: fld.fold_ident(m.ident),
-        attrs: fld.fold_attributes(m.attrs),
-        purity: m.purity,
-        decl: fold_fn_decl(&m.decl, fld),
-        generics: fold_generics(&m.generics, fld),
-        explicit_self: m.explicit_self,
-        id: fld.new_id(m.id),
-        span: fld.new_span(m.span),
+fn fold_field_<T:ast_fold>(field: Field, folder: &T) -> Field {
+    ast::Field {
+        ident: folder.fold_ident(field.ident),
+        expr: folder.fold_expr(field.expr),
+        span: folder.new_span(field.span),
     }
 }
 
-pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ {
+fn fold_mt<T:ast_fold>(mt: &mt, folder: &T) -> mt {
+    mt {
+        ty: ~folder.fold_ty(mt.ty),
+        mutbl: mt.mutbl,
+    }
+}
+
+fn fold_field<T:ast_fold>(f: TypeField, folder: &T) -> TypeField {
+    ast::TypeField {
+        ident: folder.fold_ident(f.ident),
+        mt: fold_mt(&f.mt, folder),
+        span: folder.new_span(f.span),
+    }
+}
+
+fn fold_opt_bounds<T:ast_fold>(b: &Option<OptVec<TyParamBound>>, folder: &T)
+                               -> Option<OptVec<TyParamBound>> {
+    do b.map |bounds| {
+        do bounds.map |bound| {
+            fold_ty_param_bound(bound, folder)
+        }
+    }
+}
+
+fn fold_variant_arg_<T:ast_fold>(va: &variant_arg, folder: &T)
+                                 -> variant_arg {
+    ast::variant_arg {
+        ty: folder.fold_ty(&va.ty),
+        id: folder.new_id(va.id)
+    }
+}
+
+pub fn noop_fold_block<T:ast_fold>(b: &Block, folder: &T) -> Block {
+    let view_items = b.view_items.map(|x| folder.fold_view_item(x));
+    let mut stmts = ~[];
+    for stmt in b.stmts.iter() {
+        match folder.fold_stmt(*stmt) {
+            None => {}
+            Some(stmt) => stmts.push(stmt)
+        }
+    }
+    ast::Block {
+        view_items: view_items,
+        stmts: stmts,
+        expr: b.expr.map(|x| folder.fold_expr(*x)),
+        id: folder.new_id(b.id),
+        rules: b.rules,
+        span: folder.new_span(b.span),
+    }
+}
+
+pub fn noop_fold_item_underscore<T:ast_fold>(i: &item_, folder: &T) -> item_ {
     match *i {
         item_static(ref t, m, e) => {
-            item_static(fld.fold_ty(t), m, fld.fold_expr(e))
+            item_static(folder.fold_ty(t), m, folder.fold_expr(e))
         }
         item_fn(ref decl, purity, abi, ref generics, ref body) => {
             item_fn(
-                fold_fn_decl(decl, fld),
+                fold_fn_decl(decl, folder),
                 purity,
                 abi,
-                fold_generics(generics, fld),
-                fld.fold_block(body)
+                fold_generics(generics, folder),
+                folder.fold_block(body)
             )
         }
-        item_mod(ref m) => {
-            item_mod(fld.fold_mod(m))
-        }
+        item_mod(ref m) => item_mod(folder.fold_mod(m)),
         item_foreign_mod(ref nm) => {
-            item_foreign_mod(fld.fold_foreign_mod(nm))
+            item_foreign_mod(folder.fold_foreign_mod(nm))
         }
         item_ty(ref t, ref generics) => {
-            item_ty(fld.fold_ty(t), fold_generics(generics, fld))
+            item_ty(folder.fold_ty(t),
+                    fold_generics(generics, folder))
         }
         item_enum(ref enum_definition, ref generics) => {
             item_enum(
                 ast::enum_def {
                     variants: do enum_definition.variants.map |x| {
-                        fld.fold_variant(x)
+                        folder.fold_variant(x)
                     },
                 },
-                fold_generics(generics, fld))
+                fold_generics(generics, folder))
         }
         item_struct(ref struct_def, ref generics) => {
-            let struct_def = fold_struct_def(*struct_def, fld);
-            item_struct(struct_def, fold_generics(generics, fld))
+            let struct_def = fold_struct_def(*struct_def, folder);
+            item_struct(struct_def, fold_generics(generics, folder))
         }
         item_impl(ref generics, ref ifce, ref ty, ref methods) => {
-            item_impl(
-                fold_generics(generics, fld),
-                ifce.map(|p| fld.fold_trait_ref(p)),
-                fld.fold_ty(ty),
-                methods.map(|x| fld.fold_method(*x))
+            item_impl(fold_generics(generics, folder),
+                      ifce.map(|p| fold_trait_ref(p, folder)),
+                      folder.fold_ty(ty),
+                      methods.map(|x| folder.fold_method(*x))
             )
         }
         item_trait(ref generics, ref traits, ref methods) => {
             let methods = do methods.map |method| {
                 match *method {
-                    required(ref m) => required(fld.fold_type_method(m)),
-                    provided(method) => provided(fld.fold_method(method))
+                    required(ref m) => required(folder.fold_type_method(m)),
+                    provided(method) => provided(folder.fold_method(method))
                 }
             };
-            item_trait(
-                fold_generics(generics, fld),
-                traits.map(|p| fld.fold_trait_ref(p)),
-                methods
-            )
-        }
-        item_mac(ref m) => {
-            item_mac(fld.fold_mac(m))
+            item_trait(fold_generics(generics, folder),
+                       traits.map(|p| fold_trait_ref(p, folder)),
+                       methods)
         }
+        item_mac(ref m) => item_mac(folder.fold_mac(m)),
     }
 }
 
-fn fold_struct_def(struct_def: @ast::struct_def, fld: @ast_fold)
-                -> @ast::struct_def {
-    @ast::struct_def {
-        fields: struct_def.fields.map(|f| fold_struct_field(*f, fld)),
-        ctor_id: struct_def.ctor_id.map(|cid| fld.new_id(*cid)),
-    }
-}
-
-fn fold_struct_field(f: @struct_field, fld: @ast_fold) -> @struct_field {
-    @Spanned {
-        node: ast::struct_field_ {
-            kind: f.node.kind,
-            id: fld.new_id(f.node.id),
-            ty: fld.fold_ty(&f.node.ty),
-            attrs: fld.fold_attributes(f.node.attrs),
-        },
-        span: fld.new_span(f.span),
-    }
-}
-
-fn noop_fold_method(m: @method, fld: @ast_fold) -> @method {
-    @ast::method {
+pub fn noop_fold_type_method<T:ast_fold>(m: &TypeMethod, fld: &T)
+                                         -> TypeMethod {
+    TypeMethod {
         ident: fld.fold_ident(m.ident),
-        attrs: fld.fold_attributes(m.attrs),
-        generics: fold_generics(&m.generics, fld),
-        explicit_self: m.explicit_self,
+        attrs: m.attrs.map(|a| fold_attribute_(*a, fld)),
         purity: m.purity,
         decl: fold_fn_decl(&m.decl, fld),
-        body: fld.fold_block(&m.body),
+        generics: fold_generics(&m.generics, fld),
+        explicit_self: m.explicit_self,
         id: fld.new_id(m.id),
         span: fld.new_span(m.span),
-        self_id: fld.new_id(m.self_id),
-        vis: m.vis,
-    }
-}
-
-
-pub fn noop_fold_block(b: &Block, fld: @ast_fold) -> Block {
-    let view_items = b.view_items.map(|x| fld.fold_view_item(x));
-    let mut stmts = ~[];
-    for stmt in b.stmts.iter() {
-        match fld.fold_stmt(*stmt) {
-            None => {}
-            Some(stmt) => stmts.push(stmt)
-        }
-    }
-    ast::Block {
-        view_items: view_items,
-        stmts: stmts,
-        expr: b.expr.map(|x| fld.fold_expr(*x)),
-        id: fld.new_id(b.id),
-        rules: b.rules,
-        span: b.span,
     }
 }
 
-fn noop_fold_stmt(s: &Stmt_, fld: @ast_fold) -> Option<Stmt_> {
-    match *s {
-        StmtDecl(d, nid) => {
-            match fld.fold_decl(d) {
-                Some(d) => Some(StmtDecl(d, fld.new_id(nid))),
-                None => None,
-            }
-        }
-        StmtExpr(e, nid) => {
-            Some(StmtExpr(fld.fold_expr(e), fld.new_id(nid)))
-        }
-        StmtSemi(e, nid) => {
-            Some(StmtSemi(fld.fold_expr(e), fld.new_id(nid)))
-        }
-        StmtMac(ref mac, semi) => Some(StmtMac(fld.fold_mac(mac), semi))
+pub fn noop_fold_mod<T:ast_fold>(m: &_mod, folder: &T) -> _mod {
+    ast::_mod {
+        view_items: m.view_items
+                     .iter()
+                     .map(|x| folder.fold_view_item(x)).collect(),
+        items: m.items.iter().filter_map(|x| folder.fold_item(*x)).collect(),
     }
 }
 
-fn noop_fold_arm(a: &Arm, fld: @ast_fold) -> Arm {
-    Arm {
-        pats: a.pats.map(|x| fld.fold_pat(*x)),
-        guard: a.guard.map_move(|x| fld.fold_expr(x)),
-        body: fld.fold_block(&a.body),
-    }
-}
+pub fn noop_fold_crate<T:ast_fold>(c: &Crate, folder: &T) -> Crate {
+    let fold_meta_item = |x| fold_meta_item_(x, folder);
+    let fold_attribute = |x| fold_attribute_(x, folder);
 
-pub fn noop_fold_pat(p: &Pat_, fld: @ast_fold) -> Pat_ {
-    match *p {
-        PatWild => PatWild,
-        PatIdent(binding_mode, ref pth, ref sub) => {
-            PatIdent(
-                binding_mode,
-                fld.fold_path(pth),
-                sub.map_move(|x| fld.fold_pat(x))
-            )
-        }
-        PatLit(e) => PatLit(fld.fold_expr(e)),
-        PatEnum(ref pth, ref pats) => {
-            PatEnum(
-                fld.fold_path(pth),
-                pats.map(|pats| pats.map(|x| fld.fold_pat(*x)))
-            )
-        }
-        PatStruct(ref pth, ref fields, etc) => {
-            let pth_ = fld.fold_path(pth);
-            let fs = do fields.map |f| {
-                ast::FieldPat {
-                    ident: f.ident,
-                    pat: fld.fold_pat(f.pat)
-                }
-            };
-            PatStruct(pth_, fs, etc)
-        }
-        PatTup(ref elts) => PatTup(elts.map(|x| fld.fold_pat(*x))),
-        PatBox(inner) => PatBox(fld.fold_pat(inner)),
-        PatUniq(inner) => PatUniq(fld.fold_pat(inner)),
-        PatRegion(inner) => PatRegion(fld.fold_pat(inner)),
-        PatRange(e1, e2) => {
-            PatRange(fld.fold_expr(e1), fld.fold_expr(e2))
-        },
-        PatVec(ref before, ref slice, ref after) => {
-            PatVec(
-                before.map(|x| fld.fold_pat(*x)),
-                slice.map_move(|x| fld.fold_pat(x)),
-                after.map(|x| fld.fold_pat(*x))
-            )
-        }
+    Crate {
+        module: folder.fold_mod(&c.module),
+        attrs: c.attrs.map(|x| fold_attribute(*x)),
+        config: c.config.map(|x| fold_meta_item(*x)),
+        span: folder.new_span(c.span),
     }
 }
 
-fn noop_fold_decl(d: &Decl_, fld: @ast_fold) -> Option<Decl_> {
-    match *d {
-        DeclLocal(ref l) => Some(DeclLocal(fld.fold_local(*l))),
-        DeclItem(it) => {
-            match fld.fold_item(it) {
-                Some(it_folded) => Some(DeclItem(it_folded)),
-                None => None,
-            }
-        }
-    }
-}
+pub fn noop_fold_item<T:ast_fold>(i: @ast::item, folder: &T)
+                                  -> Option<@ast::item> {
+    let fold_attribute = |x| fold_attribute_(x, folder);
 
-// lift a function in ast-thingy X fold -> ast-thingy to a function
-// in (ast-thingy X span X fold) -> (ast-thingy X span). Basically,
-// carries the span around.
-// It seems strange to me that the call to new_fold doesn't happen
-// here but instead in the impl down below.... probably just an
-// accident?
-pub fn wrap<T>(f: @fn(&T, @ast_fold) -> T)
-            -> @fn(&T, Span, @ast_fold) -> (T, Span) {
-    let result: @fn(&T, Span, @ast_fold) -> (T, Span) = |x, s, fld| {
-        (f(x, fld), s)
-    };
-    result
+    Some(@ast::item {
+        ident: folder.fold_ident(i.ident),
+        attrs: i.attrs.map(|e| fold_attribute(*e)),
+        id: folder.new_id(i.id),
+        node: folder.fold_item_underscore(&i.node),
+        vis: i.vis,
+        span: folder.new_span(i.span)
+    })
 }
 
-pub fn noop_fold_expr(e: &Expr_, fld: @ast_fold) -> Expr_ {
-    fn fold_field_(field: Field, fld: @ast_fold) -> Field {
-        ast::Field {
-            ident: fld.fold_ident(field.ident),
-            expr: fld.fold_expr(field.expr),
-            span: fld.new_span(field.span),
-        }
-    }
-    let fold_field = |x| fold_field_(x, fld);
+pub fn noop_fold_expr<T:ast_fold>(e: @ast::Expr, folder: &T) -> @ast::Expr {
+    let fold_field = |x| fold_field_(x, folder);
 
-    match *e {
+    let node = match e.node {
         ExprVstore(e, v) => {
-            ExprVstore(fld.fold_expr(e), v)
+            ExprVstore(folder.fold_expr(e), v)
         }
         ExprVec(ref exprs, mutt) => {
-            ExprVec(fld.map_exprs(|x| fld.fold_expr(x), *exprs), mutt)
+            ExprVec(folder.map_exprs(|x| folder.fold_expr(x), *exprs), mutt)
         }
         ExprRepeat(expr, count, mutt) => {
-            ExprRepeat(fld.fold_expr(expr), fld.fold_expr(count), mutt)
+            ExprRepeat(folder.fold_expr(expr), folder.fold_expr(count), mutt)
         }
-        ExprTup(ref elts) => ExprTup(elts.map(|x| fld.fold_expr(*x))),
+        ExprTup(ref elts) => ExprTup(elts.map(|x| folder.fold_expr(*x))),
         ExprCall(f, ref args, blk) => {
-            ExprCall(
-                fld.fold_expr(f),
-                fld.map_exprs(|x| fld.fold_expr(x), *args),
-                blk
-            )
+            ExprCall(folder.fold_expr(f),
+                     folder.map_exprs(|x| folder.fold_expr(x), *args),
+                     blk)
         }
         ExprMethodCall(callee_id, f, i, ref tps, ref args, blk) => {
             ExprMethodCall(
-                fld.new_id(callee_id),
-                fld.fold_expr(f),
-                fld.fold_ident(i),
-                tps.map(|x| fld.fold_ty(x)),
-                fld.map_exprs(|x| fld.fold_expr(x), *args),
+                folder.new_id(callee_id),
+                folder.fold_expr(f),
+                folder.fold_ident(i),
+                tps.map(|x| folder.fold_ty(x)),
+                folder.map_exprs(|x| folder.fold_expr(x), *args),
                 blk
             )
         }
         ExprBinary(callee_id, binop, lhs, rhs) => {
-            ExprBinary(
-                fld.new_id(callee_id),
-                binop,
-                fld.fold_expr(lhs),
-                fld.fold_expr(rhs)
-            )
+            ExprBinary(folder.new_id(callee_id),
+                       binop,
+                       folder.fold_expr(lhs),
+                       folder.fold_expr(rhs))
         }
         ExprUnary(callee_id, binop, ohs) => {
-            ExprUnary(
-                fld.new_id(callee_id),
-                binop,
-                fld.fold_expr(ohs)
-            )
+            ExprUnary(folder.new_id(callee_id), binop, folder.fold_expr(ohs))
         }
-        ExprDoBody(f) => ExprDoBody(fld.fold_expr(f)),
-        ExprLit(_) => (*e).clone(),
+        ExprDoBody(f) => ExprDoBody(folder.fold_expr(f)),
+        ExprLit(_) => e.node.clone(),
         ExprCast(expr, ref ty) => {
-            ExprCast(fld.fold_expr(expr), fld.fold_ty(ty))
+            ExprCast(folder.fold_expr(expr), folder.fold_ty(ty))
         }
-        ExprAddrOf(m, ohs) => ExprAddrOf(m, fld.fold_expr(ohs)),
+        ExprAddrOf(m, ohs) => ExprAddrOf(m, folder.fold_expr(ohs)),
         ExprIf(cond, ref tr, fl) => {
-            ExprIf(
-                fld.fold_expr(cond),
-                fld.fold_block(tr),
-                fl.map_move(|x| fld.fold_expr(x))
-            )
+            ExprIf(folder.fold_expr(cond),
+                   folder.fold_block(tr),
+                   fl.map_move(|x| folder.fold_expr(x)))
         }
         ExprWhile(cond, ref body) => {
-            ExprWhile(fld.fold_expr(cond), fld.fold_block(body))
+            ExprWhile(folder.fold_expr(cond), folder.fold_block(body))
         }
-        ExprForLoop(pat, iter, ref body, opt_ident) => {
-            ExprForLoop(fld.fold_pat(pat),
-                        fld.fold_expr(iter),
-                        fld.fold_block(body),
-                        opt_ident.map_move(|x| fld.fold_ident(x)))
+        ExprForLoop(pat, iter, ref body, ref maybe_ident) => {
+            ExprForLoop(folder.fold_pat(pat),
+                        folder.fold_expr(iter),
+                        folder.fold_block(body),
+                        maybe_ident.map_move(|i| folder.fold_ident(i)))
         }
         ExprLoop(ref body, opt_ident) => {
-            ExprLoop(
-                fld.fold_block(body),
-                opt_ident.map_move(|x| fld.fold_ident(x))
-            )
+            ExprLoop(folder.fold_block(body),
+                     opt_ident.map_move(|x| folder.fold_ident(x)))
         }
         ExprMatch(expr, ref arms) => {
-            ExprMatch(
-                fld.fold_expr(expr),
-                arms.map(|x| fld.fold_arm(x))
-            )
+            ExprMatch(folder.fold_expr(expr),
+                      arms.map(|x| folder.fold_arm(x)))
         }
         ExprFnBlock(ref decl, ref body) => {
             ExprFnBlock(
-                fold_fn_decl(decl, fld),
-                fld.fold_block(body)
+                fold_fn_decl(decl, folder),
+                folder.fold_block(body)
             )
         }
-        ExprBlock(ref blk) => ExprBlock(fld.fold_block(blk)),
+        ExprBlock(ref blk) => ExprBlock(folder.fold_block(blk)),
         ExprAssign(el, er) => {
-            ExprAssign(fld.fold_expr(el), fld.fold_expr(er))
+            ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
         }
         ExprAssignOp(callee_id, op, el, er) => {
-            ExprAssignOp(
-                fld.new_id(callee_id),
-                op,
-                fld.fold_expr(el),
-                fld.fold_expr(er)
-            )
+            ExprAssignOp(folder.new_id(callee_id),
+                         op,
+                         folder.fold_expr(el),
+                         folder.fold_expr(er))
         }
         ExprField(el, id, ref tys) => {
-            ExprField(
-                fld.fold_expr(el), fld.fold_ident(id),
-                tys.map(|x| fld.fold_ty(x))
-            )
+            ExprField(folder.fold_expr(el), folder.fold_ident(id),
+                      tys.map(|x| folder.fold_ty(x)))
         }
         ExprIndex(callee_id, el, er) => {
-            ExprIndex(
-                fld.new_id(callee_id),
-                fld.fold_expr(el),
-                fld.fold_expr(er)
-            )
+            ExprIndex(folder.new_id(callee_id),
+                      folder.fold_expr(el),
+                      folder.fold_expr(er))
         }
-        ExprPath(ref pth) => ExprPath(fld.fold_path(pth)),
+        ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
         ExprSelf => ExprSelf,
-        ExprBreak(ref opt_ident) => {
-            // FIXME #6993: add fold_name to fold.... then cut out the
-            // bogus Name->Ident->Name conversion.
-            ExprBreak(opt_ident.map_move(|x| {
-                // FIXME #9129: Assigning the new ident to a temporary to work around codegen bug
-                let newx = Ident::new(x);
-                fld.fold_ident(newx).name
-            }))
-        }
-        ExprAgain(ref opt_ident) => {
-            // FIXME #6993: add fold_name to fold....
-            ExprAgain(opt_ident.map_move(|x| {
-                // FIXME #9129: Assigning the new ident to a temporary to work around codegen bug
-                let newx = Ident::new(x);
-                fld.fold_ident(newx).name
-            }))
-        }
+        ExprLogLevel => ExprLogLevel,
+        ExprBreak(opt_ident) => ExprBreak(opt_ident),
+        ExprAgain(opt_ident) => ExprAgain(opt_ident),
         ExprRet(ref e) => {
-            ExprRet(e.map_move(|x| fld.fold_expr(x)))
+            ExprRet(e.map_move(|x| folder.fold_expr(x)))
         }
-        ExprLogLevel => ExprLogLevel,
         ExprInlineAsm(ref a) => {
             ExprInlineAsm(inline_asm {
-                inputs: a.inputs.map(|&(c, input)| (c, fld.fold_expr(input))),
-                outputs: a.outputs.map(|&(c, out)| (c, fld.fold_expr(out))),
+                inputs: a.inputs.map(|&(c, input)| (c, folder.fold_expr(input))),
+                outputs: a.outputs.map(|&(c, out)| (c, folder.fold_expr(out))),
                 .. (*a).clone()
             })
         }
-        ExprMac(ref mac) => ExprMac(fld.fold_mac(mac)),
+        ExprMac(ref mac) => ExprMac(folder.fold_mac(mac)),
         ExprStruct(ref path, ref fields, maybe_expr) => {
-            ExprStruct(
-                fld.fold_path(path),
-                fields.map(|x| fold_field(*x)),
-                maybe_expr.map_move(|x| fld.fold_expr(x))
-            )
+            ExprStruct(folder.fold_path(path),
+                       fields.map(|x| fold_field(*x)),
+                       maybe_expr.map_move(|x| folder.fold_expr(x)))
         },
-        ExprParen(ex) => ExprParen(fld.fold_expr(ex))
-    }
-}
-
-pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ {
-    fn fold_mt(mt: &mt, fld: @ast_fold) -> mt {
-        mt {
-            ty: ~fld.fold_ty(mt.ty),
-            mutbl: mt.mutbl,
-        }
-    }
-    fn fold_field(f: TypeField, fld: @ast_fold) -> TypeField {
-        ast::TypeField {
-            ident: fld.fold_ident(f.ident),
-            mt: fold_mt(&f.mt, fld),
-            span: fld.new_span(f.span),
-        }
-    }
-    fn fold_opt_bounds(b: &Option<OptVec<TyParamBound>>, fld: @ast_fold)
-                        -> Option<OptVec<TyParamBound>> {
-        do b.map |bounds| {
-            do bounds.map |bound| { fld.fold_ty_param_bound(bound) }
-        }
-    }
-    match *t {
-        ty_nil | ty_bot | ty_infer => (*t).clone(),
-        ty_box(ref mt) => ty_box(fold_mt(mt, fld)),
-        ty_uniq(ref mt) => ty_uniq(fold_mt(mt, fld)),
-        ty_vec(ref mt) => ty_vec(fold_mt(mt, fld)),
-        ty_ptr(ref mt) => ty_ptr(fold_mt(mt, fld)),
-        ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, fld)),
-        ty_closure(ref f) => {
-            ty_closure(@TyClosure {
-                sigil: f.sigil,
-                purity: f.purity,
-                region: f.region,
-                onceness: f.onceness,
-                bounds: fold_opt_bounds(&f.bounds, fld),
-                decl: fold_fn_decl(&f.decl, fld),
-                lifetimes: fld.fold_lifetimes(&f.lifetimes)
-            })
-        }
-        ty_bare_fn(ref f) => {
-            ty_bare_fn(@TyBareFn {
-                lifetimes: fld.fold_lifetimes(&f.lifetimes),
-                purity: f.purity,
-                abis: f.abis,
-                decl: fold_fn_decl(&f.decl, fld)
-            })
-        }
-        ty_tup(ref tys) => ty_tup(tys.map(|ty| fld.fold_ty(ty))),
-        ty_path(ref path, ref bounds, id) =>
-            ty_path(fld.fold_path(path), fold_opt_bounds(bounds, fld), fld.new_id(id)),
-        ty_fixed_length_vec(ref mt, e) => {
-            ty_fixed_length_vec(
-                fold_mt(mt, fld),
-                fld.fold_expr(e)
-            )
-        }
-        ty_typeof(e) => ty_typeof(fld.fold_expr(e)),
-        ty_mac(ref mac) => ty_mac(fld.fold_mac(mac))
-    }
-}
-
-// ...nor do modules
-pub fn noop_fold_mod(m: &_mod, fld: @ast_fold) -> _mod {
-    ast::_mod {
-        view_items: m.view_items.iter().map(|x| fld.fold_view_item(x)).collect(),
-        items: m.items.iter().filter_map(|x| fld.fold_item(*x)).collect(),
-    }
-}
-
-fn noop_fold_foreign_mod(nm: &foreign_mod, fld: @ast_fold) -> foreign_mod {
-    ast::foreign_mod {
-        sort: nm.sort,
-        abis: nm.abis,
-        view_items: nm.view_items.iter().map(|x| fld.fold_view_item(x)).collect(),
-        items: nm.items.iter().map(|x| fld.fold_foreign_item(*x)).collect(),
-    }
-}
-
-fn noop_fold_variant(v: &variant_, fld: @ast_fold) -> variant_ {
-    let kind = match v.kind {
-        tuple_variant_kind(ref variant_args) => {
-            tuple_variant_kind(variant_args.map(|x| fld.fold_variant_arg(x)))
-        }
-        struct_variant_kind(ref struct_def) => {
-            struct_variant_kind(@ast::struct_def {
-                fields: struct_def.fields.iter()
-                    .map(|f| fld.fold_struct_field(*f)).collect(),
-                ctor_id: struct_def.ctor_id.map(|c| fld.new_id(*c))
-            })
-        }
-    };
-
-    let attrs = fld.fold_attributes(v.attrs);
-
-    let de = match v.disr_expr {
-      Some(e) => Some(fld.fold_expr(e)),
-      None => None
+        ExprParen(ex) => ExprParen(folder.fold_expr(ex))
     };
-    ast::variant_ {
-        name: v.name,
-        attrs: attrs,
-        kind: kind,
-        id: fld.new_id(v.id),
-        disr_expr: de,
-        vis: v.vis,
-    }
-}
-
-fn noop_fold_ident(i: Ident, _fld: @ast_fold) -> Ident {
-    i
-}
 
-fn noop_fold_path(p: &Path, fld: @ast_fold) -> Path {
-    ast::Path {
-        span: fld.new_span(p.span),
-        global: p.global,
-        segments: p.segments.map(|segment| ast::PathSegment {
-            identifier: fld.fold_ident(segment.identifier),
-            lifetime: segment.lifetime,
-            types: segment.types.map(|typ| fld.fold_ty(typ)),
-        })
+    @Expr {
+        id: folder.new_id(e.id),
+        node: node,
+        span: folder.new_span(e.span),
     }
 }
 
-fn noop_fold_local(l: @Local, fld: @ast_fold) -> @Local {
-    @Local {
-        is_mutbl: l.is_mutbl,
-        ty: fld.fold_ty(&l.ty),
-        pat: fld.fold_pat(l.pat),
-        init: l.init.map_move(|e| fld.fold_expr(e)),
-        id: fld.new_id(l.id),
-        span: fld.new_span(l.span),
-    }
-}
-
-// the default macro traversal. visit the path
-// using fold_path, and the tts using fold_tts,
-// and the span using new_span
-fn noop_fold_mac(m: &mac_, fld: @ast_fold) -> mac_ {
-    match *m {
-        mac_invoc_tt(ref p,ref tts,ctxt) =>
-        mac_invoc_tt(fld.fold_path(p),
-                     fold_tts(*tts,fld),
-                     ctxt)
-    }
-}
-
-
-/* temporarily eta-expand because of a compiler bug with using `fn<T>` as a
-   value */
-fn noop_map_exprs(f: @fn(@Expr) -> @Expr, es: &[@Expr]) -> ~[@Expr] {
-    es.map(|x| f(*x))
-}
-
-fn noop_id(i: NodeId) -> NodeId { return i; }
-
-fn noop_span(sp: Span) -> Span { return sp; }
-
-pub fn default_ast_fold() -> ast_fold_fns {
-    @AstFoldFns {
-        fold_crate: noop_fold_crate,
-        fold_view_item: noop_fold_view_item,
-        fold_foreign_item: noop_fold_foreign_item,
-        fold_item: noop_fold_item,
-        fold_struct_field: noop_fold_struct_field,
-        fold_item_underscore: noop_fold_item_underscore,
-        fold_type_method: noop_fold_type_method,
-        fold_method: noop_fold_method,
-        fold_block: noop_fold_block,
-        fold_stmt: |x, s, fld| (noop_fold_stmt(x, fld), s),
-        fold_arm: noop_fold_arm,
-        fold_pat: wrap(noop_fold_pat),
-        fold_decl: |x, s, fld| (noop_fold_decl(x, fld), s),
-        fold_expr: wrap(noop_fold_expr),
-        fold_ty: wrap(noop_fold_ty),
-        fold_mod: noop_fold_mod,
-        fold_foreign_mod: noop_fold_foreign_mod,
-        fold_variant: wrap(noop_fold_variant),
-        fold_ident: noop_fold_ident,
-        fold_path: noop_fold_path,
-        fold_local: noop_fold_local,
-        fold_mac: wrap(noop_fold_mac),
-        map_exprs: noop_map_exprs,
-        new_id: noop_id,
-        new_span: noop_span,
-    }
-}
-
-impl ast_fold for AstFoldFns {
-    /* naturally, a macro to write these would be nice */
-    fn fold_crate(@self, c: &Crate) -> Crate {
-        (self.fold_crate)(c, self as @ast_fold)
-    }
-    fn fold_view_item(@self, x: &view_item) -> view_item {
-        ast::view_item {
-            node: (self.fold_view_item)(&x.node, self as @ast_fold),
-            attrs: self.fold_attributes(x.attrs),
-            vis: x.vis,
-            span: (self.new_span)(x.span),
-        }
-    }
-    fn fold_foreign_item(@self, x: @foreign_item) -> @foreign_item {
-        (self.fold_foreign_item)(x, self as @ast_fold)
-    }
-    fn fold_item(@self, i: @item) -> Option<@item> {
-        (self.fold_item)(i, self as @ast_fold)
-    }
-    fn fold_struct_field(@self, sf: @struct_field) -> @struct_field {
-        @Spanned {
-            node: ast::struct_field_ {
-                kind: sf.node.kind,
-                id: (self.new_id)(sf.node.id),
-                ty: self.fold_ty(&sf.node.ty),
-                attrs: self.fold_attributes(sf.node.attrs),
-            },
-            span: (self.new_span)(sf.span),
-        }
-    }
-    fn fold_item_underscore(@self, i: &item_) -> item_ {
-        (self.fold_item_underscore)(i, self as @ast_fold)
-    }
-    fn fold_type_method(@self, m: &TypeMethod) -> TypeMethod {
-        (self.fold_type_method)(m, self as @ast_fold)
-    }
-    fn fold_method(@self, x: @method) -> @method {
-        (self.fold_method)(x, self as @ast_fold)
-    }
-    fn fold_block(@self, x: &Block) -> Block {
-        (self.fold_block)(x, self as @ast_fold)
-    }
-    fn fold_stmt(@self, x: &Stmt) -> Option<@Stmt> {
-        let (n_opt, s) = (self.fold_stmt)(&x.node, x.span, self as @ast_fold);
-        match n_opt {
-            Some(n) => Some(@Spanned { node: n, span: (self.new_span)(s) }),
-            None => None,
-        }
-    }
-    fn fold_arm(@self, x: &Arm) -> Arm {
-        (self.fold_arm)(x, self as @ast_fold)
-    }
-    fn fold_pat(@self, x: @Pat) -> @Pat {
-        let (n, s) =  (self.fold_pat)(&x.node, x.span, self as @ast_fold);
-        @Pat {
-            id: (self.new_id)(x.id),
-            node: n,
-            span: (self.new_span)(s),
-        }
-    }
-    fn fold_decl(@self, x: @Decl) -> Option<@Decl> {
-        let (n_opt, s) = (self.fold_decl)(&x.node, x.span, self as @ast_fold);
-        match n_opt {
-            Some(n) => Some(@Spanned { node: n, span: (self.new_span)(s) }),
-            None => None,
+pub fn noop_fold_stmt<T:ast_fold>(s: &Stmt, folder: &T) -> Option<@Stmt> {
+    let node = match s.node {
+        StmtDecl(d, nid) => {
+            match folder.fold_decl(d) {
+                Some(d) => Some(StmtDecl(d, folder.new_id(nid))),
+                None => None,
+            }
         }
-    }
-    fn fold_expr(@self, x: @Expr) -> @Expr {
-        let (n, s) = (self.fold_expr)(&x.node, x.span, self as @ast_fold);
-        @Expr {
-            id: (self.new_id)(x.id),
-            node: n,
-            span: (self.new_span)(s),
+        StmtExpr(e, nid) => {
+            Some(StmtExpr(folder.fold_expr(e), folder.new_id(nid)))
         }
-    }
-    fn fold_ty(@self, x: &Ty) -> Ty {
-        let (n, s) = (self.fold_ty)(&x.node, x.span, self as @ast_fold);
-        Ty {
-            id: (self.new_id)(x.id),
-            node: n,
-            span: (self.new_span)(s),
+        StmtSemi(e, nid) => {
+            Some(StmtSemi(folder.fold_expr(e), folder.new_id(nid)))
         }
-    }
-    fn fold_mod(@self, x: &_mod) -> _mod {
-        (self.fold_mod)(x, self as @ast_fold)
-    }
-    fn fold_foreign_mod(@self, x: &foreign_mod) -> foreign_mod {
-        (self.fold_foreign_mod)(x, self as @ast_fold)
-    }
-    fn fold_variant(@self, x: &variant) -> variant {
-        let (n, s) = (self.fold_variant)(&x.node, x.span, self as @ast_fold);
-        Spanned { node: n, span: (self.new_span)(s) }
-    }
-    fn fold_ident(@self, x: Ident) -> Ident {
-        (self.fold_ident)(x, self as @ast_fold)
-    }
-    fn fold_path(@self, x: &Path) -> Path {
-        (self.fold_path)(x, self as @ast_fold)
-    }
-    fn fold_local(@self, x: @Local) -> @Local {
-        (self.fold_local)(x, self as @ast_fold)
-    }
-    fn fold_mac(@self, x: &mac) -> mac {
-        let (n, s) = (self.fold_mac)(&x.node, x.span, self as @ast_fold);
-        Spanned { node: n, span: (self.new_span)(s) }
-    }
-    fn map_exprs(@self,
-                 f: @fn(@Expr) -> @Expr,
-                 e: &[@Expr])
-              -> ~[@Expr] {
-        (self.map_exprs)(f, e)
-    }
-    fn new_id(@self, node_id: ast::NodeId) -> NodeId {
-        (self.new_id)(node_id)
-    }
-    fn new_span(@self, span: Span) -> Span {
-        (self.new_span)(span)
-    }
-}
+        StmtMac(ref mac, semi) => Some(StmtMac(folder.fold_mac(mac), semi))
+    };
 
-// brson agrees with me that this function's existence is probably
-// not a good or useful thing.
-pub fn make_fold(afp: ast_fold_fns) -> @ast_fold {
-    afp as @ast_fold
+    node.map_move(|node| @Spanned {
+        node: node,
+        span: folder.new_span(s.span),
+    })
 }
 
 #[cfg(test)]
@@ -1048,27 +870,18 @@ mod test {
     use print::pprust;
     use super::*;
 
-    // taken from expand
-    // given a function from idents to idents, produce
-    // an ast_fold that applies that function:
-    pub fn fun_to_ident_folder(f: @fn(ast::Ident)->ast::Ident) -> @ast_fold{
-        let afp = default_ast_fold();
-        let f_pre = @AstFoldFns{
-            fold_ident : |id, _| f(id),
-            .. *afp
-        };
-        make_fold(f_pre)
-    }
-
     // this version doesn't care about getting comments or docstrings in.
     fn fake_print_crate(s: @pprust::ps, crate: &ast::Crate) {
         pprust::print_mod(s, &crate.module, crate.attrs);
     }
 
     // change every identifier to "zz"
-    pub fn to_zz() -> @fn(ast::Ident)->ast::Ident {
-        let zz_id = token::str_to_ident("zz");
-        |_id| {zz_id}
+    struct ToZzIdentFolder;
+
+    impl ast_fold for ToZzIdentFolder {
+        fn fold_ident(&self, _: ast::Ident) -> ast::Ident {
+            token::str_to_ident("zz")
+        }
     }
 
     // maybe add to expand.rs...
@@ -1088,7 +901,7 @@ mod test {
 
     // make sure idents get transformed everywhere
     #[test] fn ident_transformation () {
-        let zz_fold = fun_to_ident_folder(to_zz());
+        let zz_fold = ToZzIdentFolder;
         let ast = string_to_crate(@"#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}");
         assert_pred!(matches_codepattern,
                      "matches_codepattern",
@@ -1099,7 +912,7 @@ mod test {
 
     // even inside macro defs....
     #[test] fn ident_transformation_in_defs () {
-        let zz_fold = fun_to_ident_folder(to_zz());
+        let zz_fold = ToZzIdentFolder;
         let ast = string_to_crate(@"macro_rules! a {(b $c:expr $(d $e:token)f+
 => (g $(d $d $e)+))} ");
         assert_pred!(matches_codepattern,
@@ -1108,15 +921,5 @@ mod test {
                                     token::get_ident_interner()),
                      ~"zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))");
     }
-
-    // and in cast expressions... this appears to be an existing bug.
-    #[test] fn ident_transformation_in_types () {
-        let zz_fold = fun_to_ident_folder(to_zz());
-        let ast = string_to_crate(@"fn a() {let z = 13 as int;}");
-        assert_pred!(matches_codepattern,
-                     "matches_codepattern",
-                     pprust::to_str(&zz_fold.fold_crate(ast),fake_print_crate,
-                                    token::get_ident_interner()),
-                     ~"fn zz(){let zz=13 as zz;}");
-    }
 }
+
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 9645dab4e8b..91ef55c78f6 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -45,7 +45,7 @@ pub struct ParseSess {
     included_mod_stack: ~[Path],
 }
 
-pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess {
+pub fn new_parse_sess(demitter: Option<@Emitter>) -> @mut ParseSess {
     let cm = @CodeMap::new();
     @mut ParseSess {
         cm: cm,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b5868cbc63d..867e4fe416b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -37,16 +37,26 @@ pub enum ann_node<'self> {
     node_expr(@ps, &'self ast::Expr),
     node_pat(@ps, &'self ast::Pat),
 }
-pub struct pp_ann {
-    pre: @fn(ann_node),
-    post: @fn(ann_node)
+
+pub trait pp_ann {
+    fn pre(&self, _node: ann_node) {}
+    fn post(&self, _node: ann_node) {}
+}
+
+pub struct no_ann {
+    contents: (),
 }
 
-pub fn no_ann() -> pp_ann {
-    fn ignore(_node: ann_node) { }
-    return pp_ann {pre: ignore, post: ignore};
+impl no_ann {
+    pub fn new() -> no_ann {
+        no_ann {
+            contents: (),
+        }
+    }
 }
 
+impl pp_ann for no_ann {}
+
 pub struct CurrentCommentAndLiteral {
     cur_cmnt: uint,
     cur_lit: uint,
@@ -60,7 +70,7 @@ pub struct ps {
     literals: Option<~[comments::lit]>,
     cur_cmnt_and_lit: @mut CurrentCommentAndLiteral,
     boxes: @mut ~[pp::breaks],
-    ann: pp_ann
+    ann: @pp_ann
 }
 
 pub fn ibox(s: @ps, u: uint) {
@@ -74,12 +84,13 @@ pub fn end(s: @ps) {
 }
 
 pub fn rust_printer(writer: @io::Writer, intr: @ident_interner) -> @ps {
-    return rust_printer_annotated(writer, intr, no_ann());
+    return rust_printer_annotated(writer, intr, @no_ann::new() as @pp_ann);
 }
 
 pub fn rust_printer_annotated(writer: @io::Writer,
                               intr: @ident_interner,
-                              ann: pp_ann) -> @ps {
+                              ann: @pp_ann)
+                              -> @ps {
     return @ps {
         s: pp::mk_printer(writer, default_columns),
         cm: None::<@CodeMap>,
@@ -109,7 +120,7 @@ pub fn print_crate(cm: @CodeMap,
                    filename: @str,
                    input: @io::Reader,
                    out: @io::Writer,
-                   ann: pp_ann,
+                   ann: @pp_ann,
                    is_expanded: bool) {
     let (cmnts, lits) = comments::gather_comments_and_literals(
         span_diagnostic,
@@ -484,7 +495,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
     let ann_node = node_item(s, item);
-    (s.ann.pre)(ann_node);
+    s.ann.pre(ann_node);
     match item.node {
       ast::item_static(ref ty, m, expr) => {
         head(s, visibility_qualified(item.vis, "static"));
@@ -635,7 +646,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
         end(s);
       }
     }
-    (s.ann.post)(ann_node);
+    s.ann.post(ann_node);
 }
 
 fn print_trait_ref(s: @ps, t: &ast::trait_ref) {
@@ -958,7 +969,7 @@ pub fn print_possibly_embedded_block_(s: @ps,
     }
     maybe_print_comment(s, blk.span.lo);
     let ann_node = node_block(s, blk);
-    (s.ann.pre)(ann_node);
+    s.ann.pre(ann_node);
     match embedded {
       block_block_fn => end(s),
       block_normal => bopen(s)
@@ -979,7 +990,7 @@ pub fn print_possibly_embedded_block_(s: @ps,
       _ => ()
     }
     bclose_maybe_open(s, blk.span, indented, close_box);
-    (s.ann.post)(ann_node);
+    s.ann.post(ann_node);
 }
 
 pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
@@ -1121,7 +1132,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
     maybe_print_comment(s, expr.span.lo);
     ibox(s, indent_unit);
     let ann_node = node_expr(s, expr);
-    (s.ann.pre)(ann_node);
+    s.ann.pre(ann_node);
     match expr.node {
         ast::ExprVstore(e, v) => {
             print_expr_vstore(s, v);
@@ -1456,7 +1467,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
           pclose(s);
       }
     }
-    (s.ann.post)(ann_node);
+    s.ann.post(ann_node);
     end(s);
 }
 
@@ -1578,7 +1589,7 @@ pub fn print_bounded_path(s: @ps, path: &ast::Path,
 pub fn print_pat(s: @ps, pat: &ast::Pat) {
     maybe_print_comment(s, pat.span.lo);
     let ann_node = node_pat(s, pat);
-    (s.ann.pre)(ann_node);
+    s.ann.pre(ann_node);
     /* Pat isn't normalized, but the beauty of it
      is that it doesn't matter */
     match pat.node {
@@ -1678,7 +1689,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
         word(s.s, "]");
       }
     }
-    (s.ann.post)(ann_node);
+    s.ann.post(ann_node);
 }
 
 pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_interner) -> ~str {
@@ -2254,17 +2265,6 @@ pub fn print_fn_header_info(s: @ps,
     print_opt_sigil(s, opt_sigil);
 }
 
-pub fn opt_sigil_to_str(opt_p: Option<ast::Sigil>) -> &'static str {
-    match opt_p {
-      None => "fn",
-      Some(p) => match p {
-          ast::BorrowedSigil => "fn&",
-          ast::OwnedSigil => "fn~",
-          ast::ManagedSigil => "fn@"
-      }
-    }
-}
-
 pub fn purity_to_str(p: ast::purity) -> &'static str {
     match p {
       ast::impure_fn => "impure",
diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs
index c9809438d94..350bd09826f 100644
--- a/src/test/auxiliary/cci_nested_lib.rs
+++ b/src/test/auxiliary/cci_nested_lib.rs
@@ -14,7 +14,7 @@ pub struct Entry<A,B> {
 }
 
 pub struct alist<A,B> {
-    eq_fn: @fn(A,A) -> bool,
+    eq_fn: extern "Rust" fn(A,A) -> bool,
     data: @mut ~[Entry<A,B>]
 }
 
diff --git a/src/test/auxiliary/issue4516_ty_param_lib.rs b/src/test/auxiliary/issue4516_ty_param_lib.rs
deleted file mode 100644
index cd90c9b06c4..00000000000
--- a/src/test/auxiliary/issue4516_ty_param_lib.rs
+++ /dev/null
@@ -1,14 +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 to_closure<A:'static + Clone>(x: A) -> @fn() -> A {
-    let result: @fn() -> A = || x.clone();
-    result
-}
diff --git a/src/test/bench/task-perf-alloc-unwind.rs b/src/test/bench/task-perf-alloc-unwind.rs
index f383f7a101f..991c102e9f0 100644
--- a/src/test/bench/task-perf-alloc-unwind.rs
+++ b/src/test/bench/task-perf-alloc-unwind.rs
@@ -46,7 +46,6 @@ type nillist = List<()>;
 struct State {
     box: @nillist,
     unique: ~nillist,
-    fn_box: @fn() -> @nillist,
     tuple: (@nillist, ~nillist),
     vec: ~[@nillist],
     res: r
@@ -79,19 +78,15 @@ fn recurse_or_fail(depth: int, st: Option<State>) {
             State {
                 box: @Nil,
                 unique: ~Nil,
-                fn_box: || @Nil::<()>,
                 tuple: (@Nil, ~Nil),
                 vec: ~[@Nil],
                 res: r(@Nil)
             }
           }
           Some(st) => {
-            let fn_box = st.fn_box;
-
             State {
                 box: @Cons((), st.box),
                 unique: ~Cons((), @*st.unique),
-                fn_box: || @Cons((), fn_box()),
                 tuple: (@Cons((), st.tuple.first()),
                         ~Cons((), @*st.tuple.second())),
                 vec: st.vec + &[@Cons((), *st.vec.last())],
diff --git a/src/test/compile-fail/borrowck-addr-of-upvar.rs b/src/test/compile-fail/borrowck-addr-of-upvar.rs
deleted file mode 100644
index 83baedc7892..00000000000
--- a/src/test/compile-fail/borrowck-addr-of-upvar.rs
+++ /dev/null
@@ -1,27 +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 foo(x: @int) -> @fn() -> &'static int {
-    let result: @fn() -> &'static int = || &*x;  //~ ERROR cannot root
-    result
-}
-
-fn bar(x: @int) -> @fn() -> &int {
-    let result: @fn() -> &int = || &*x; //~ ERROR cannot root
-    result
-}
-
-fn zed(x: @int) -> @fn() -> int {
-    let result: @fn() -> int = || *&*x;
-    result
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/borrowck-move-by-capture.rs b/src/test/compile-fail/borrowck-move-by-capture.rs
index ecb18993d93..5994b9e85d5 100644
--- a/src/test/compile-fail/borrowck-move-by-capture.rs
+++ b/src/test/compile-fail/borrowck-move-by-capture.rs
@@ -1,13 +1,13 @@
 pub fn main() {
     let foo = ~3;
     let _pfoo = &foo;
-    let _f: @fn() -> int = || *foo + 5;
+    let _f: ~fn() -> int = || *foo + 5;
     //~^ ERROR cannot move `foo`
 
     // FIXME(#2202) - Due to the way that borrowck treats closures,
     // you get two error reports here.
     let bar = ~3;
     let _g = || { //~ ERROR capture of moved value
-        let _h: @fn() -> int = || *bar; //~ ERROR capture of moved value
+        let _h: ~fn() -> int = || *bar; //~ ERROR capture of moved value
     };
 }
diff --git a/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs b/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
index b38cb895488..525f8f4a932 100644
--- a/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
+++ b/src/test/compile-fail/closure-bounds-cant-promote-superkind-in-struct.rs
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 struct X {
-    field: @fn:Send(),
+    field: ~fn:Send(),
 }
 
-fn foo(blk: @fn:()) -> X {
+fn foo(blk: ~fn:()) -> X {
     return X { field: blk }; //~ ERROR expected bounds `Send` but found no bounds
 }
 
diff --git a/src/test/compile-fail/dead-code-ret.rs b/src/test/compile-fail/dead-code-ret.rs
index 2e4ae7f8544..b6976b2c355 100644
--- a/src/test/compile-fail/dead-code-ret.rs
+++ b/src/test/compile-fail/dead-code-ret.rs
@@ -1,3 +1,8 @@
+// xfail-test
+
+// xfail'd because the lint pass doesn't know to ignore standard library
+// stuff.
+
 // -*- rust -*-
 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
diff --git a/src/test/compile-fail/do2.rs b/src/test/compile-fail/do2.rs
index 4466c07518f..1bffdaa682c 100644
--- a/src/test/compile-fail/do2.rs
+++ b/src/test/compile-fail/do2.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f(f: @fn(int) -> bool) -> bool { f(10i) }
+fn f(f: &fn(int) -> bool) -> bool { f(10i) }
 
 fn main() {
     assert!(do f() |i| { i == 10i } == 10i);
diff --git a/src/test/compile-fail/fn-variance-2.rs b/src/test/compile-fail/fn-variance-2.rs
deleted file mode 100644
index ab559190034..00000000000
--- a/src/test/compile-fail/fn-variance-2.rs
+++ /dev/null
@@ -1,30 +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 reproduce<T>(t: T) -> @fn() -> T {
-    let result: @fn() -> T = || t;
-    result
-}
-
-fn main() {
-    // type of x is the variable X,
-    // with the lower bound @mut int
-    let x = @mut 3;
-
-    // type of r is @fn() -> X
-    let r = reproduce(x);
-
-    // Requires that X be a subtype of
-    // @mut int.
-    let f: @mut int = r();
-
-    // Bad.
-    let h: @int = r(); //~ ERROR (values differ in mutability)
-}
diff --git a/src/test/compile-fail/fn-variance-3.rs b/src/test/compile-fail/fn-variance-3.rs
deleted file mode 100644
index e42c6b658e4..00000000000
--- a/src/test/compile-fail/fn-variance-3.rs
+++ /dev/null
@@ -1,32 +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 mk_identity<T>() -> @fn(T) -> T {
-    let result: @fn(t: T) -> T = |t| t;
-    result
-}
-
-fn main() {
-    // type of r is @fn(X) -> X
-    // for some fresh X
-    let r = mk_identity();
-
-    // @mut int <: X
-    r(@mut 3);
-
-    // @int <: X
-    //
-    // Here the type check fails because @const is gone and there is no
-    // supertype.
-    r(@3);  //~ ERROR mismatched types
-
-    // Here the type check succeeds.
-    *r(@mut 3) = 4;
-}
diff --git a/src/test/compile-fail/issue-1451.rs b/src/test/compile-fail/issue-1451.rs
index a295e8eb7ed..0d8acaa4464 100644
--- a/src/test/compile-fail/issue-1451.rs
+++ b/src/test/compile-fail/issue-1451.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 // xfail-test
-struct T { f: @fn() };
-struct S { f: @fn() };
+struct T { f: extern "Rust" fn() };
+struct S { f: extern "Rust" fn() };
 
 fn fooS(t: S) {
 }
@@ -22,11 +22,11 @@ fn bar() {
 }
 
 fn main() {
-    let x: @fn() = bar;
+    let x: extern "Rust" fn() = bar;
     fooS(S {f: x});
     fooS(S {f: bar});
 
-    let x: @fn() = bar;
+    let x: extern "Rust" fn() = bar;
     fooT(T {f: x});
     fooT(T {f: bar});
 }
diff --git a/src/test/compile-fail/issue-1896-1.rs b/src/test/compile-fail/issue-1896-1.rs
deleted file mode 100644
index 4750f68d59b..00000000000
--- a/src/test/compile-fail/issue-1896-1.rs
+++ /dev/null
@@ -1,26 +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.
-
-// Test that we require managed closures to be rooted when borrowed.
-
-struct boxedFn<'self> { theFn: &'self fn() -> uint }
-
-fn createClosure (closedUint: uint) -> boxedFn {
-    let theFn: @fn() -> uint = || closedUint;
-    boxedFn {theFn: theFn} //~ ERROR cannot root
-}
-
-fn main () {
-    let aFn: boxedFn = createClosure(10);
-
-    let myInt: uint = (aFn.theFn)();
-
-    assert_eq!(myInt, 10);
-}
diff --git a/src/test/compile-fail/issue-2074.rs b/src/test/compile-fail/issue-2074.rs
index 40c2772f234..7815fca16c6 100644
--- a/src/test/compile-fail/issue-2074.rs
+++ b/src/test/compile-fail/issue-2074.rs
@@ -10,11 +10,11 @@
 
 // xfail-test
 fn main() {
-    let one: @fn() -> uint = || {
+    let one: &fn() -> uint = || {
         enum r { a };
         a as uint
     };
-    let two = @fn() -> uint = || {
+    let two = &fn() -> uint = || {
         enum r { a };
         a as uint
     };
diff --git a/src/test/compile-fail/issue-897-2.rs b/src/test/compile-fail/issue-897-2.rs
index eb60e34df8f..c39c258c701 100644
--- a/src/test/compile-fail/issue-897-2.rs
+++ b/src/test/compile-fail/issue-897-2.rs
@@ -1,3 +1,7 @@
+// xfail-test
+// xfail'd because the lint pass doesn't know to ignore standard library
+// stuff.
+
 // 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.
diff --git a/src/test/compile-fail/issue-897.rs b/src/test/compile-fail/issue-897.rs
index 103156175a3..8df73aef610 100644
--- a/src/test/compile-fail/issue-897.rs
+++ b/src/test/compile-fail/issue-897.rs
@@ -1,3 +1,5 @@
+// xfail-test
+
 // 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.
diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs
deleted file mode 100644
index 2dfdb2629f7..00000000000
--- a/src/test/compile-fail/kindck-owned.rs
+++ /dev/null
@@ -1,28 +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 copy1<T:Clone>(t: T) -> @fn() -> T {
-    let result: @fn() -> T = || t.clone();  //~ ERROR does not fulfill `'static`
-    result
-}
-
-fn copy2<T:Clone + 'static>(t: T) -> @fn() -> T {
-    let result: @fn() -> T = || t.clone();
-    result
-}
-
-fn main() {
-    let x = &3;
-    copy2(&x); //~ ERROR does not fulfill `'static`
-
-    copy2(@3);
-    copy2(@&x); //~ ERROR value may contain borrowed pointers
-    //~^ ERROR does not fulfill `'static`
-}
diff --git a/src/test/compile-fail/lambda-mutate-nested.rs b/src/test/compile-fail/lambda-mutate-nested.rs
deleted file mode 100644
index bfd1e12f3a6..00000000000
--- a/src/test/compile-fail/lambda-mutate-nested.rs
+++ /dev/null
@@ -1,25 +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.
-
-// Make sure that nesting a block within a @fn doesn't let us
-// mutate upvars from a @fn.
-fn f2(x: &fn()) { x(); }
-
-fn main() {
-    let i = 0;
-    let ctr: @fn() -> int = || { f2(|| i = i + 1 ); i };
-    //~^ ERROR cannot assign
-    error!(ctr());
-    error!(ctr());
-    error!(ctr());
-    error!(ctr());
-    error!(ctr());
-    error!(i);
-}
diff --git a/src/test/compile-fail/lambda-mutate.rs b/src/test/compile-fail/lambda-mutate.rs
deleted file mode 100644
index a848d8698a3..00000000000
--- a/src/test/compile-fail/lambda-mutate.rs
+++ /dev/null
@@ -1,22 +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.
-
-// Make sure we can't write to upvars from @fns
-fn main() {
-    let i = 0;
-    let ctr: @fn() -> int = || { i = i + 1; i };
-    //~^ ERROR cannot assign
-    error!(ctr());
-    error!(ctr());
-    error!(ctr());
-    error!(ctr());
-    error!(ctr());
-    error!(i);
-}
diff --git a/src/test/compile-fail/liveness-init-in-called-fn-expr.rs b/src/test/compile-fail/liveness-init-in-called-fn-expr.rs
index 1fddea80966..7054cb0d901 100644
--- a/src/test/compile-fail/liveness-init-in-called-fn-expr.rs
+++ b/src/test/compile-fail/liveness-init-in-called-fn-expr.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let j: @fn() -> int = || {
+    let j: &fn() -> int = || {
         let i: int;
         i //~ ERROR use of possibly uninitialized variable: `i`
     };
diff --git a/src/test/compile-fail/liveness-init-in-fn-expr.rs b/src/test/compile-fail/liveness-init-in-fn-expr.rs
index b7a715d2958..b6c7895235b 100644
--- a/src/test/compile-fail/liveness-init-in-fn-expr.rs
+++ b/src/test/compile-fail/liveness-init-in-fn-expr.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let f: @fn() -> int = || {
+    let f: &fn() -> int = || {
         let i: int;
         i //~ ERROR use of possibly uninitialized variable: `i`
     };
diff --git a/src/test/compile-fail/regions-fn-subtyping.rs b/src/test/compile-fail/regions-fn-subtyping.rs
index face9c74214..5928d31a668 100644
--- a/src/test/compile-fail/regions-fn-subtyping.rs
+++ b/src/test/compile-fail/regions-fn-subtyping.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn of<T>() -> @fn(T) { fail!(); }
-fn subtype<T>(x: @fn(T)) { fail!(); }
+fn of<T>() -> &fn(T) { fail!(); }
+fn subtype<T>(x: &fn(T)) { fail!(); }
 
 fn test_fn<'x,'y,'z,T>(_x: &'x T, _y: &'y T, _z: &'z T) {
     // Here, x, y, and z are free.  Other letters
@@ -40,18 +40,6 @@ fn test_fn<'x,'y,'z,T>(_x: &'x T, _y: &'y T, _z: &'z T) {
 
     subtype::<&fn<'x,'y>(&'x T, &'y T)>(
         of::<&fn<'a,'b>(&'a T, &'b T)>()); //~ ERROR mismatched types
-
-    subtype::<&fn<'x,'a>(&'x T) -> @fn(&'a T)>(
-        of::<&fn<'x,'a>(&'x T) -> @fn(&'a T)>());
-
-    subtype::<&fn<'a>(&'a T) -> @fn(&'a T)>(
-        of::<&fn<'a,'b>(&'a T) -> @fn(&'b T)>()); //~ ERROR mismatched types
-
-    subtype::<&fn<'a>(&'a T) -> @fn(&'a T)>(
-        of::<&fn<'x,'b>(&'x T) -> @fn(&'b T)>()); //~ ERROR mismatched types
-
-    subtype::<&fn<'a,'b>(&'a T) -> @fn(&'b T)>(
-        of::<&fn<'a>(&'a T) -> @fn(&'a T)>());
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/regions-fns.rs b/src/test/compile-fail/regions-fns.rs
index 4f6cbdfdd65..715261d816a 100644
--- a/src/test/compile-fail/regions-fns.rs
+++ b/src/test/compile-fail/regions-fns.rs
@@ -12,7 +12,7 @@
 // we reported errors in this case:
 
 fn not_ok<'b>(a: &uint, b: &'b uint) {
-    let mut g: @fn(x: &uint) = |x: &'b uint| {};
+    let mut g: &fn(x: &uint) = |x: &'b uint| {};
     //~^ ERROR mismatched types
     g(a);
 }
diff --git a/src/test/compile-fail/regions-infer-at-fn-not-param.rs b/src/test/compile-fail/regions-infer-at-fn-not-param.rs
index 488d1f3940d..3ddae976ce3 100644
--- a/src/test/compile-fail/regions-infer-at-fn-not-param.rs
+++ b/src/test/compile-fail/regions-infer-at-fn-not-param.rs
@@ -13,11 +13,11 @@ struct parameterized1<'self> {
 }
 
 struct not_parameterized1 {
-    g: @fn()
+    g: &'static fn()
 }
 
 struct not_parameterized2 {
-    g: @fn()
+    g: &'static fn()
 }
 
 fn take1(p: parameterized1) -> parameterized1 { p }
diff --git a/src/test/compile-fail/regions-infer-contravariance-due-to-ret.rs b/src/test/compile-fail/regions-infer-contravariance-due-to-ret.rs
index 15f40a91735..3fcc5184b4a 100644
--- a/src/test/compile-fail/regions-infer-contravariance-due-to-ret.rs
+++ b/src/test/compile-fail/regions-infer-contravariance-due-to-ret.rs
@@ -14,7 +14,7 @@
 // the normal case.
 
 struct contravariant<'self> {
-    f: @fn() -> &'self int
+    f: &'static fn() -> &'self int
 }
 
 fn to_same_lifetime<'r>(bi: contravariant<'r>) {
diff --git a/src/test/compile-fail/regions-infer-covariance-due-to-arg.rs b/src/test/compile-fail/regions-infer-covariance-due-to-arg.rs
index c33ca2dab2e..4b26e6b6021 100644
--- a/src/test/compile-fail/regions-infer-covariance-due-to-arg.rs
+++ b/src/test/compile-fail/regions-infer-covariance-due-to-arg.rs
@@ -13,7 +13,7 @@
 // You can upcast to a *larger region* but not a smaller one.
 
 struct covariant<'self> {
-    f: @fn(x: &'self int) -> int
+    f: &'static fn(x: &'self int) -> int
 }
 
 fn to_same_lifetime<'r>(bi: covariant<'r>) {
diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
index 92447c1ef8d..6e322b170e8 100644
--- a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
+++ b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 struct invariant<'self> {
-    f: @fn(x: @mut &'self int)
+    f: &'static fn(x: @mut &'self int)
 }
 
 fn to_same_lifetime<'r>(bi: invariant<'r>) {
diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
index 61adba3aec1..380e9b27ff9 100644
--- a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
+++ b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 struct invariant<'self> {
-    f: @fn() -> @mut &'self int
+    f: &'static fn() -> @mut &'self int
 }
 
 fn to_same_lifetime<'r>(bi: invariant<'r>) {
diff --git a/src/test/compile-fail/regions-infer-not-param.rs b/src/test/compile-fail/regions-infer-not-param.rs
index fa853b82d9e..47c1f7a5757 100644
--- a/src/test/compile-fail/regions-infer-not-param.rs
+++ b/src/test/compile-fail/regions-infer-not-param.rs
@@ -14,12 +14,12 @@ struct direct<'self> {
 
 struct indirect1 {
     // Here the lifetime parameter of direct is bound by the fn()
-    g: @fn(direct)
+    g: &'static fn(direct)
 }
 
 struct indirect2<'self> {
     // But here it is set to 'self
-    g: @fn(direct<'self>)
+    g: &'static fn(direct<'self>)
 }
 
 fn take_direct(p: direct) -> direct { p } //~ ERROR mismatched types
diff --git a/src/test/compile-fail/sendfn-is-not-a-lambda.rs b/src/test/compile-fail/sendfn-is-not-a-lambda.rs
deleted file mode 100644
index 609439d7b8e..00000000000
--- a/src/test/compile-fail/sendfn-is-not-a-lambda.rs
+++ /dev/null
@@ -1,18 +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 test(f: @fn(uint) -> uint) -> uint {
-    return f(22u);
-}
-
-fn main() {
-    let f: ~fn(x: uint) -> uint = |x| 4u;
-    info!(test(f)); //~ ERROR expected @ closure, found ~ closure
-}
diff --git a/src/test/debug-info/lexical-scope-in-managed-closure.rs b/src/test/debug-info/lexical-scope-in-managed-closure.rs
deleted file mode 100644
index 96da78a9192..00000000000
--- a/src/test/debug-info/lexical-scope-in-managed-closure.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2013 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.
-
-// compile-flags:-Z extra-debug-info
-// debugger:rbreak zzz
-// debugger:run
-
-// debugger:finish
-// debugger:print x
-// check:$1 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$2 = false
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$3 = 1000
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$4 = 2.5
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$5 = true
-// debugger:continue
-
-// debugger:finish
-// debugger:print x
-// check:$6 = false
-// debugger:continue
-
-fn main() {
-
-    let x = false;
-
-    zzz();
-    sentinel();
-
-    let managed_closure: @fn(int) = |x| {
-        zzz();
-        sentinel();
-
-        let x = 2.5;
-
-        zzz();
-        sentinel();
-
-        let x = true;
-
-        zzz();
-        sentinel();
-    };
-
-    zzz();
-    sentinel();
-
-    managed_closure(1000);
-
-    zzz();
-    sentinel();
-}
-
-fn zzz() {()}
-fn sentinel() {()}
diff --git a/src/test/debug-info/var-captured-in-managed-closure.rs b/src/test/debug-info/var-captured-in-managed-closure.rs
deleted file mode 100644
index b20f40378d3..00000000000
--- a/src/test/debug-info/var-captured-in-managed-closure.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2013 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.
-
-// compile-flags:-Z extra-debug-info
-// debugger:rbreak zzz
-// debugger:run
-// debugger:finish
-
-// debugger:print constant
-// check:$1 = 1
-// debugger:print a_struct
-// check:$2 = {a = -2, b = 3.5, c = 4}
-// debugger:print *owned
-// check:$3 = 5
-// debugger:print managed->val
-// check:$4 = 6
-
-#[allow(unused_variable)];
-
-struct Struct {
-    a: int,
-    b: float,
-    c: uint
-}
-
-fn main() {
-    let constant = 1;
-
-    let a_struct = Struct {
-        a: -2,
-        b: 3.5,
-        c: 4
-    };
-
-    let owned = ~5;
-    let managed = @6;
-
-    let closure: @fn() = || {
-        zzz();
-        do_something(&constant, &a_struct.a, owned, managed);
-    };
-
-    closure();
-}
-
-fn do_something(_: &int, _:&int, _:&int, _:&int) {
-}
-
-fn zzz() {()}
diff --git a/src/test/pretty/block-arg-disambig.rs b/src/test/pretty/block-arg-disambig.rs
deleted file mode 100644
index c0f173a1a0d..00000000000
--- a/src/test/pretty/block-arg-disambig.rs
+++ /dev/null
@@ -1,12 +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 blk1(_b: &fn()) -> @fn() { return || { }; }
-fn test1() { (do blk1 { info!("hi"); })(); }
diff --git a/src/test/pretty/do1.rs b/src/test/pretty/do1.rs
index 6f9aa28f11a..751aedb39a3 100644
--- a/src/test/pretty/do1.rs
+++ b/src/test/pretty/do1.rs
@@ -10,6 +10,6 @@
 
 // pp-exact
 
-fn f(f: @fn(int)) { f(10) }
+fn f(f: &fn(int)) { f(10) }
 
 fn main() { do f |i| { assert!(i == 10) } }
diff --git a/src/test/pretty/fn-types.rs b/src/test/pretty/fn-types.rs
index 0545e9ed166..b000c9f9137 100644
--- a/src/test/pretty/fn-types.rs
+++ b/src/test/pretty/fn-types.rs
@@ -12,6 +12,5 @@
 
 fn from_foreign_fn(_x: extern "Rust" fn()) { }
 fn from_stack_closure(_x: &fn()) { }
-fn from_box_closure(_x: @fn()) { }
 fn from_unique_closure(_x: ~fn()) { }
 fn main() { }
diff --git a/src/test/run-fail/unwind-box-fn.rs b/src/test/run-fail/unwind-box-fn.rs
deleted file mode 100644
index a94f904c492..00000000000
--- a/src/test/run-fail/unwind-box-fn.rs
+++ /dev/null
@@ -1,24 +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.
-
-// error-pattern:fail
-
-fn failfn() {
-    fail!();
-}
-
-fn main() {
-    let y = ~0;
-    let x: @@fn() = @|| {
-        error!(y.clone());
-    };
-    failfn();
-    error!(x);
-}
diff --git a/src/test/run-fail/unwind-closure.rs b/src/test/run-fail/unwind-closure.rs
deleted file mode 100644
index 5ea71c94e14..00000000000
--- a/src/test/run-fail/unwind-closure.rs
+++ /dev/null
@@ -1,21 +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.
-
-// error-pattern:fail
-
-fn f(_a: @int) {
-    fail!();
-}
-
-fn main() {
-    let b = @0;
-    let g: @fn() = || f(b);
-    g();
-}
diff --git a/src/test/run-fail/unwind-lambda.rs b/src/test/run-fail/unwind-lambda.rs
index 74d6ab00802..65d9fce5ff5 100644
--- a/src/test/run-fail/unwind-lambda.rs
+++ b/src/test/run-fail/unwind-lambda.rs
@@ -14,7 +14,7 @@ fn main() {
     let cheese = ~"roquefort";
     let carrots = @~"crunchy";
 
-    let result: @fn(@~str, &fn(~str)) = (|tasties, macerate| {
+    let result: &'static fn(@~str, &fn(~str)) = (|tasties, macerate| {
         macerate((*tasties).clone());
     });
     result(carrots, |food| {
diff --git a/src/test/run-pass/alignment-gep-tup-like-1.rs b/src/test/run-pass/alignment-gep-tup-like-1.rs
index a821e4647c1..4352c139b62 100644
--- a/src/test/run-pass/alignment-gep-tup-like-1.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-1.rs
@@ -12,13 +12,30 @@ struct pair<A,B> {
     a: A, b: B
 }
 
-fn f<A:Clone + 'static>(a: A, b: u16) -> @fn() -> (A, u16) {
-    let result: @fn() -> (A, u16) = || (a.clone(), b);
-    result
+trait Invokable<A> {
+    fn f(&self) -> (A, u16);
+}
+
+struct Invoker<A> {
+    a: A,
+    b: u16,
+}
+
+impl<A:Clone> Invokable<A> for Invoker<A> {
+    fn f(&self) -> (A, u16) {
+        (self.a.clone(), self.b)
+    }
+}
+
+fn f<A:Clone + 'static>(a: A, b: u16) -> @Invokable<A> {
+    @Invoker {
+        a: a,
+        b: b,
+    } as @Invokable<A>
 }
 
 pub fn main() {
-    let (a, b) = f(22_u64, 44u16)();
+    let (a, b) = f(22_u64, 44u16).f();
     info!("a=%? b=%?", a, b);
     assert_eq!(a, 22u64);
     assert_eq!(b, 44u16);
diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs
index e924c31bad6..9bf95968a9a 100644
--- a/src/test/run-pass/alignment-gep-tup-like-2.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-2.rs
@@ -23,13 +23,30 @@ fn make_cycle<A:'static>(a: A) {
     g.rec = Some(g);
 }
 
+struct Invoker<A,B> {
+    a: A,
+    b: B,
+}
+
+trait Invokable<A,B> {
+    fn f(&self) -> (A, B);
+}
+
+impl<A:Clone,B:Clone> Invokable<A,B> for Invoker<A,B> {
+    fn f(&self) -> (A, B) {
+        (self.a.clone(), self.b.clone())
+    }
+}
+
 fn f<A:Send + Clone + 'static,
      B:Send + Clone + 'static>(
      a: A,
      b: B)
-     -> @fn() -> (A, B) {
-    let result: @fn() -> (A, B) = || (a.clone(), b.clone());
-    result
+     -> @Invokable<A,B> {
+    @Invoker {
+        a: a,
+        b: b,
+    } as @Invokable<A,B>
 }
 
 pub fn main() {
@@ -37,7 +54,7 @@ pub fn main() {
     let y = 44_u64;
     let z = f(~x, y);
     make_cycle(z);
-    let (a, b) = z();
+    let (a, b) = z.f();
     info!("a=%u b=%u", *a as uint, b as uint);
     assert_eq!(*a, x);
     assert_eq!(b, y);
diff --git a/src/test/run-pass/block-arg-call-as.rs b/src/test/run-pass/block-arg-call-as.rs
index d68b0be632e..6a59278982a 100644
--- a/src/test/run-pass/block-arg-call-as.rs
+++ b/src/test/run-pass/block-arg-call-as.rs
@@ -14,10 +14,6 @@ fn asSendfn( f : ~fn()->uint ) -> uint {
    return f();
 }
 
-fn asLambda( f : @fn()->uint ) -> uint {
-   return f();
-}
-
 fn asBlock( f : &fn()->uint ) -> uint {
    return f();
 }
@@ -25,8 +21,6 @@ fn asBlock( f : &fn()->uint ) -> uint {
 pub fn main() {
    let x = asSendfn(|| 22u);
    assert_eq!(x, 22u);
-   let x = asLambda(|| 22u);
-   assert_eq!(x, 22u);
    let x = asBlock(|| 22u);
    assert_eq!(x, 22u);
 }
diff --git a/src/test/run-pass/block-arg-used-as-lambda.rs b/src/test/run-pass/block-arg-used-as-lambda.rs
deleted file mode 100644
index 34fa7e36d97..00000000000
--- a/src/test/run-pass/block-arg-used-as-lambda.rs
+++ /dev/null
@@ -1,24 +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_lambda(f: @fn(uint) -> uint) -> @fn(uint) -> uint {
-    return f;
-}
-
-pub fn main() {
-    let x: @fn(uint) -> uint = to_lambda(|x| x * 2u );
-    let y = to_lambda(x);
-
-    let x_r = x(22u);
-    let y_r = y(x_r);
-
-    assert_eq!(x_r, 44u);
-    assert_eq!(y_r, 88u);
-}
diff --git a/src/test/run-pass/borrowck-move-by-capture-ok.rs b/src/test/run-pass/borrowck-move-by-capture-ok.rs
index 095e2ba6fea..f6328c8c658 100644
--- a/src/test/run-pass/borrowck-move-by-capture-ok.rs
+++ b/src/test/run-pass/borrowck-move-by-capture-ok.rs
@@ -1,5 +1,5 @@
 pub fn main() {
     let bar = ~3;
-    let h: @fn() -> int = || *bar;
+    let h: ~fn() -> int = || *bar;
     assert_eq!(h(), 3);
 }
diff --git a/src/test/run-pass/call-closure-from-overloaded-op.rs b/src/test/run-pass/call-closure-from-overloaded-op.rs
index cc8d8e96195..16728dffd19 100644
--- a/src/test/run-pass/call-closure-from-overloaded-op.rs
+++ b/src/test/run-pass/call-closure-from-overloaded-op.rs
@@ -11,7 +11,7 @@
 fn foo() -> int { 22 }
 
 pub fn main() {
-    let mut x: ~[@fn() -> int] = ~[];
+    let mut x: ~[extern "Rust" fn() -> int] = ~[];
     x.push(foo);
     assert_eq!((x[0])(), 22);
 }
diff --git a/src/test/run-pass/cap-clause-move.rs b/src/test/run-pass/cap-clause-move.rs
index aadd6a72494..64be8dab6e7 100644
--- a/src/test/run-pass/cap-clause-move.rs
+++ b/src/test/run-pass/cap-clause-move.rs
@@ -11,16 +11,6 @@
 use std::ptr;
 
 pub fn main() {
-    let x = ~1;
-    let y = ptr::to_unsafe_ptr(&(*x)) as uint;
-    let lam_move: @fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
-    assert_eq!(lam_move(), y);
-
-    let x = ~2;
-    let y = ptr::to_unsafe_ptr(&(*x)) as uint;
-    let lam_move: @fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
-    assert_eq!(lam_move(), y);
-
     let x = ~3;
     let y = ptr::to_unsafe_ptr(&(*x)) as uint;
     let snd_move: ~fn() -> uint = || ptr::to_unsafe_ptr(&(*x)) as uint;
diff --git a/src/test/run-pass/close-over-big-then-small-data.rs b/src/test/run-pass/close-over-big-then-small-data.rs
index 01c6442fa00..8b7967ac150 100644
--- a/src/test/run-pass/close-over-big-then-small-data.rs
+++ b/src/test/run-pass/close-over-big-then-small-data.rs
@@ -16,13 +16,30 @@ struct Pair<A,B> {
     a: A, b: B
 }
 
-fn f<A:Clone + 'static>(a: A, b: u16) -> @fn() -> (A, u16) {
-    let result: @fn() -> (A, u16) = || (a.clone(), b);
-    result
+struct Invoker<A> {
+    a: A,
+    b: u16,
+}
+
+trait Invokable<A> {
+    fn f(&self) -> (A, u16);
+}
+
+impl<A:Clone> Invokable<A> for Invoker<A> {
+    fn f(&self) -> (A, u16) {
+        (self.a.clone(), self.b)
+    }
+}
+
+fn f<A:Clone + 'static>(a: A, b: u16) -> @Invokable<A> {
+    @Invoker {
+        a: a,
+        b: b,
+    } as @Invokable<A>
 }
 
 pub fn main() {
-    let (a, b) = f(22_u64, 44u16)();
+    let (a, b) = f(22_u64, 44u16).f();
     info!("a=%? b=%?", a, b);
     assert_eq!(a, 22u64);
     assert_eq!(b, 44u16);
diff --git a/src/test/run-pass/cycle-collection2.rs b/src/test/run-pass/cycle-collection2.rs
index cd148417f4c..46c0c52e0c7 100644
--- a/src/test/run-pass/cycle-collection2.rs
+++ b/src/test/run-pass/cycle-collection2.rs
@@ -8,13 +8,33 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct foo { z: @fn() }
+struct foo {
+    z: Option<@Invokable>,
+}
+
+struct Thing {
+    w: @mut foo,
+}
+
+trait Invokable {
+    fn f(&self);
+}
+
+impl Invokable for Thing {
+    fn f(&self) {
+        nop_foo(self.w);
+    }
+}
 
 fn nop() { }
 fn nop_foo(_x : @mut foo) { }
 
 pub fn main() {
-    let w = @mut foo{ z: || nop() };
-    let x: @fn() = || nop_foo(w);
-    w.z = x;
+    let w = @mut foo {
+        z: None,
+    };
+    let x = @Thing {
+        w: w,
+    } as @Invokable;
+    w.z = Some(x);
 }
diff --git a/src/test/run-pass/cycle-collection4.rs b/src/test/run-pass/cycle-collection4.rs
deleted file mode 100644
index 8b613093944..00000000000
--- a/src/test/run-pass/cycle-collection4.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.
-
-struct foo { z : @fn() }
-
-fn nop() { }
-fn nop_foo(_y: ~[int], _x : @mut foo) { }
-
-pub fn main() {
-    let w = @mut foo{ z: || nop() };
-    let x : @fn() = || nop_foo(~[], w);
-    w.z = x;
-}
diff --git a/src/test/run-pass/cycle-collection5.rs b/src/test/run-pass/cycle-collection5.rs
deleted file mode 100644
index f724a86555c..00000000000
--- a/src/test/run-pass/cycle-collection5.rs
+++ /dev/null
@@ -1,22 +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 foo { z: @fn() }
-
-fn nop() { }
-fn nop_foo(_y: @int, _x: @mut foo) { }
-
-fn o() -> @int { @10 }
-
-pub fn main() {
-    let w = @mut foo { z: || nop() };
-    let x : @fn() = || nop_foo(o(), w);
-    w.z = x;
-}
diff --git a/src/test/run-pass/do-no-args.rs b/src/test/run-pass/do-no-args.rs
index 6aef1f5f9e5..1f725ffb357 100644
--- a/src/test/run-pass/do-no-args.rs
+++ b/src/test/run-pass/do-no-args.rs
@@ -10,9 +10,9 @@
 
 // Testing that we can drop the || in do exprs
 
-fn f(_f: @fn() -> bool) -> bool { true }
+fn f(_f: &fn() -> bool) -> bool { true }
 
-fn d(_f: @fn()) { }
+fn d(_f: &fn()) { }
 
 pub fn main() {
     do d { }
diff --git a/src/test/run-pass/do1.rs b/src/test/run-pass/do1.rs
index 735621a19fe..0444b269cb3 100644
--- a/src/test/run-pass/do1.rs
+++ b/src/test/run-pass/do1.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f(f: @fn(int)) { f(10) }
+fn f(f: &fn(int)) { f(10) }
 
 pub fn main() {
     do f() |i| { assert!(i == 10) }
diff --git a/src/test/run-pass/do2.rs b/src/test/run-pass/do2.rs
index 684a2c108eb..9feededc980 100644
--- a/src/test/run-pass/do2.rs
+++ b/src/test/run-pass/do2.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f(f: @fn(int) -> int) -> int { f(10) }
+fn f(f: &fn(int) -> int) -> int { f(10) }
 
 pub fn main() {
     assert_eq!(do f() |i| { i }, 10);
diff --git a/src/test/run-pass/do3.rs b/src/test/run-pass/do3.rs
index b0d49fd2bdd..eeb983b4557 100644
--- a/src/test/run-pass/do3.rs
+++ b/src/test/run-pass/do3.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f(f: @fn(int) -> int) -> int { f(10) }
+fn f(f: &fn(int) -> int) -> int { f(10) }
 
 pub fn main() {
     assert_eq!(do f |i| { i }, 10);
diff --git a/src/test/run-pass/expr-block-fn.rs b/src/test/run-pass/expr-block-fn.rs
index dbb1ac1f649..63e5c7688d3 100644
--- a/src/test/run-pass/expr-block-fn.rs
+++ b/src/test/run-pass/expr-block-fn.rs
@@ -11,7 +11,7 @@
 
 
 fn test_fn() {
-    type t = @fn() -> int;
+    type t = &'static fn() -> int;
     fn ten() -> int { return 10; }
     let rs: t = { ten };
     assert!((rs() == 10));
diff --git a/src/test/run-pass/expr-block-generic-box1.rs b/src/test/run-pass/expr-block-generic-box1.rs
index 2c902181810..12b387b7eae 100644
--- a/src/test/run-pass/expr-block-generic-box1.rs
+++ b/src/test/run-pass/expr-block-generic-box1.rs
@@ -12,7 +12,7 @@
 
 
 // -*- rust -*-
-type compare<T> = @fn(@T, @T) -> bool;
+type compare<T> = &'static fn(@T, @T) -> bool;
 
 fn test_generic<T>(expected: @T, eq: compare<T>) {
     let actual: @T = { expected };
diff --git a/src/test/run-pass/expr-block-generic-box2.rs b/src/test/run-pass/expr-block-generic-box2.rs
index 7d849bbff01..cfa59d68635 100644
--- a/src/test/run-pass/expr-block-generic-box2.rs
+++ b/src/test/run-pass/expr-block-generic-box2.rs
@@ -11,7 +11,7 @@
 
 // xfail-fast
 
-type compare<T> = @fn(T, T) -> bool;
+type compare<'self, T> = &'self fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
     let actual: T = { expected.clone() };
diff --git a/src/test/run-pass/expr-block-generic-unique1.rs b/src/test/run-pass/expr-block-generic-unique1.rs
index 0249820410c..3f9c101761f 100644
--- a/src/test/run-pass/expr-block-generic-unique1.rs
+++ b/src/test/run-pass/expr-block-generic-unique1.rs
@@ -11,7 +11,7 @@
 
 
 // -*- rust -*-
-type compare<T> = @fn(~T, ~T) -> bool;
+type compare<'self, T> = &'self fn(~T, ~T) -> bool;
 
 fn test_generic<T:Clone>(expected: ~T, eq: compare<T>) {
     let actual: ~T = { expected.clone() };
diff --git a/src/test/run-pass/expr-block-generic-unique2.rs b/src/test/run-pass/expr-block-generic-unique2.rs
index 389a42ae7af..3484a4f7f5a 100644
--- a/src/test/run-pass/expr-block-generic-unique2.rs
+++ b/src/test/run-pass/expr-block-generic-unique2.rs
@@ -11,7 +11,7 @@
 // xfail-fast
 // -*- rust -*-
 
-type compare<T> = @fn(T, T) -> bool;
+type compare<'self, T> = &'self fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
     let actual: T = { expected.clone() };
diff --git a/src/test/run-pass/expr-block-generic.rs b/src/test/run-pass/expr-block-generic.rs
index 7091fceb771..2f379602c6b 100644
--- a/src/test/run-pass/expr-block-generic.rs
+++ b/src/test/run-pass/expr-block-generic.rs
@@ -13,7 +13,7 @@
 // xfail-fast
 
 // Tests for standalone blocks as expressions with dynamic type sizes
-type compare<T> = @fn(T, T) -> bool;
+type compare<'self, T> = &'self fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
     let actual: T = { expected.clone() };
diff --git a/src/test/run-pass/expr-if-generic-box1.rs b/src/test/run-pass/expr-if-generic-box1.rs
index def991adea8..8bf6e658408 100644
--- a/src/test/run-pass/expr-if-generic-box1.rs
+++ b/src/test/run-pass/expr-if-generic-box1.rs
@@ -12,7 +12,7 @@
 
 
 // -*- rust -*-
-type compare<T> = @fn(@T, @T) -> bool;
+type compare<T> = &'static fn(@T, @T) -> bool;
 
 fn test_generic<T>(expected: @T, not_expected: @T, eq: compare<T>) {
     let actual: @T = if true { expected } else { not_expected };
diff --git a/src/test/run-pass/expr-if-generic-box2.rs b/src/test/run-pass/expr-if-generic-box2.rs
index a2d28a2be04..2c4707a87d5 100644
--- a/src/test/run-pass/expr-if-generic-box2.rs
+++ b/src/test/run-pass/expr-if-generic-box2.rs
@@ -11,7 +11,7 @@
 // xfail-fast
 // -*- rust -*-
 
-type compare<T> = @fn(T, T) -> bool;
+type compare<T> = &'static fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, not_expected: T, eq: compare<T>) {
     let actual: T = if true { expected.clone() } else { not_expected };
diff --git a/src/test/run-pass/expr-if-generic.rs b/src/test/run-pass/expr-if-generic.rs
index f5b2a1a7986..1bbf3a537db 100644
--- a/src/test/run-pass/expr-if-generic.rs
+++ b/src/test/run-pass/expr-if-generic.rs
@@ -12,7 +12,7 @@
 // -*- rust -*-
 
 // Tests for if as expressions with dynamic type sizes
-type compare<T> = @fn(T, T) -> bool;
+type compare<T> = &'static fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, not_expected: T, eq: compare<T>) {
     let actual: T = if true { expected.clone() } else { not_expected };
diff --git a/src/test/run-pass/expr-match-generic-box1.rs b/src/test/run-pass/expr-match-generic-box1.rs
index 4ea2d0fba9b..064e3343620 100644
--- a/src/test/run-pass/expr-match-generic-box1.rs
+++ b/src/test/run-pass/expr-match-generic-box1.rs
@@ -12,7 +12,7 @@
 
 
 // -*- rust -*-
-type compare<T> = @fn(@T, @T) -> bool;
+type compare<T> = &'static fn(@T, @T) -> bool;
 
 fn test_generic<T>(expected: @T, eq: compare<T>) {
     let actual: @T = match true { true => { expected }, _ => fail!() };
diff --git a/src/test/run-pass/expr-match-generic-box2.rs b/src/test/run-pass/expr-match-generic-box2.rs
index a2ccf5c0fb9..bca06ebdbb5 100644
--- a/src/test/run-pass/expr-match-generic-box2.rs
+++ b/src/test/run-pass/expr-match-generic-box2.rs
@@ -11,7 +11,7 @@
 // xfail-fast
 // -*- rust -*-
 
-type compare<T> = @fn(T, T) -> bool;
+type compare<T> = &'static fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
     let actual: T = match true { true => { expected.clone() }, _ => fail!("wat") };
diff --git a/src/test/run-pass/expr-match-generic-unique1.rs b/src/test/run-pass/expr-match-generic-unique1.rs
index 0f564e6a780..7371f8fd89b 100644
--- a/src/test/run-pass/expr-match-generic-unique1.rs
+++ b/src/test/run-pass/expr-match-generic-unique1.rs
@@ -11,7 +11,7 @@
 
 
 // -*- rust -*-
-type compare<T> = @fn(~T, ~T) -> bool;
+type compare<T> = &'static fn(~T, ~T) -> bool;
 
 fn test_generic<T:Clone>(expected: ~T, eq: compare<T>) {
     let actual: ~T = match true {
diff --git a/src/test/run-pass/expr-match-generic-unique2.rs b/src/test/run-pass/expr-match-generic-unique2.rs
index ae88d48bc44..d07d40e6757 100644
--- a/src/test/run-pass/expr-match-generic-unique2.rs
+++ b/src/test/run-pass/expr-match-generic-unique2.rs
@@ -11,7 +11,7 @@
 // xfail-fast
 // -*- rust -*-
 
-type compare<T> = @fn(T, T) -> bool;
+type compare<'self, T> = &'self fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
     let actual: T = match true {
diff --git a/src/test/run-pass/expr-match-generic.rs b/src/test/run-pass/expr-match-generic.rs
index 59f1ff14f59..b43085d346f 100644
--- a/src/test/run-pass/expr-match-generic.rs
+++ b/src/test/run-pass/expr-match-generic.rs
@@ -11,7 +11,7 @@
 // xfail-fast
 // -*- rust -*-
 
-type compare<T> = @fn(T, T) -> bool;
+type compare<T> = extern "Rust" fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
   let actual: T = match true { true => { expected.clone() }, _ => fail!("wat") };
diff --git a/src/test/run-pass/fixed-point-bind-box.rs b/src/test/run-pass/fixed-point-bind-box.rs
deleted file mode 100644
index 4c28151224c..00000000000
--- a/src/test/run-pass/fixed-point-bind-box.rs
+++ /dev/null
@@ -1,30 +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.
-
-// xfail-fast
-
-fn fix_help<A, B>(f: extern fn(@fn(A) -> B, A) -> B, x: A) -> B {
-    return f( |a| fix_help(f, a), x);
-}
-
-fn fix<A, B>(f: extern fn(@fn(A) -> B, A) -> B) -> @fn(A) -> B {
-    return |a| fix_help(f, a);
-}
-
-fn fact_(f: @fn(v: int) -> int, n: int) -> int {
-    // fun fact 0 = 1
-    return if n == 0 { 1 } else { n * f(n - 1) };
-}
-
-pub fn main() {
-    let fact = fix(fact_);
-    assert_eq!(fact(5), 120);
-    assert_eq!(fact(2), 2);
-}
diff --git a/src/test/run-pass/fixed-point-bind-unique.rs b/src/test/run-pass/fixed-point-bind-unique.rs
deleted file mode 100644
index c7b64fde3fd..00000000000
--- a/src/test/run-pass/fixed-point-bind-unique.rs
+++ /dev/null
@@ -1,30 +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.
-
-// xfail-fast
-
-fn fix_help<A:'static,B:Send>(f: extern fn(@fn(A) -> B, A) -> B, x: A) -> B {
-    return f(|a| fix_help(f, a), x);
-}
-
-fn fix<A:'static,B:Send>(f: extern fn(@fn(A) -> B, A) -> B) -> @fn(A) -> B {
-    return |a| fix_help(f, a);
-}
-
-fn fact_(f: @fn(v: int) -> int, n: int) -> int {
-    // fun fact 0 = 1
-    return if n == 0 { 1 } else { n * f(n - 1) };
-}
-
-pub fn main() {
-    let fact = fix(fact_);
-    assert_eq!(fact(5), 120);
-    assert_eq!(fact(2), 2);
-}
diff --git a/src/test/run-pass/fn-assign-managed-to-bare-1.rs b/src/test/run-pass/fn-assign-managed-to-bare-1.rs
deleted file mode 100644
index dece77595bc..00000000000
--- a/src/test/run-pass/fn-assign-managed-to-bare-1.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 add(n: int) -> @fn(int) -> int {
-    let result: @fn(int) -> int = |m| m + n;
-    result
-}
-
-pub fn main() {
-      assert_eq!(add(3)(4), 7);
-      let add3 : &fn(int)->int = add(3);
-      assert_eq!(add3(4), 7);
-}
diff --git a/src/test/run-pass/fn-bare-coerce-to-shared.rs b/src/test/run-pass/fn-bare-coerce-to-shared.rs
deleted file mode 100644
index 853b44ed76c..00000000000
--- a/src/test/run-pass/fn-bare-coerce-to-shared.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 bare() {}
-
-fn likes_shared(f: @fn()) { f() }
-
-pub fn main() {
-    likes_shared(bare);
-}
diff --git a/src/test/run-pass/fn-coerce-field.rs b/src/test/run-pass/fn-coerce-field.rs
index 22aab1aa661..ae2e353f913 100644
--- a/src/test/run-pass/fn-coerce-field.rs
+++ b/src/test/run-pass/fn-coerce-field.rs
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-struct r {
-    field: @fn()
+struct r<'self> {
+    field: &'self fn()
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/fn-type-infer.rs b/src/test/run-pass/fn-type-infer.rs
index bb9254589f7..09e7ababa6c 100644
--- a/src/test/run-pass/fn-type-infer.rs
+++ b/src/test/run-pass/fn-type-infer.rs
@@ -11,7 +11,7 @@
 #[allow(unused_variable)];
 
 pub fn main() {
-    // We should be able to type infer inside of @fns.
+    // We should be able to type infer inside of &fns.
     let _f = || {
         let i = 10;
     };
diff --git a/src/test/run-pass/fun-call-variants.rs b/src/test/run-pass/fun-call-variants.rs
index 52e6a4649a8..5011998f929 100644
--- a/src/test/run-pass/fun-call-variants.rs
+++ b/src/test/run-pass/fun-call-variants.rs
@@ -9,7 +9,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn ho(f: @fn(int) -> int) -> int { let n: int = f(3); return n; }
+fn ho(f: &fn(int) -> int) -> int { let n: int = f(3); return n; }
 
 fn direct(x: int) -> int { return x + 1; }
 
diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs
index 7cd26dd84c4..15286a85c01 100644
--- a/src/test/run-pass/hashmap-memory.rs
+++ b/src/test/run-pass/hashmap-memory.rs
@@ -24,7 +24,7 @@ mod map_reduce {
     use std::str;
     use std::task;
 
-    pub type putter = @fn(~str, ~str);
+    pub type putter<'self> = &'self fn(~str, ~str);
 
     pub type mapper = extern fn(~str, putter);
 
diff --git a/src/test/run-pass/infer-with-expected.rs b/src/test/run-pass/infer-with-expected.rs
deleted file mode 100644
index 6f2fd54bc9c..00000000000
--- a/src/test/run-pass/infer-with-expected.rs
+++ /dev/null
@@ -1,25 +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.
-
-// Tests the passing down of expected types through boxing and
-// wrapping in a record or tuple. (The a.x would complain about 'this
-// type must be known in this context' if the passing down doesn't
-// happen.)
-
-fn eat_tup(_r: ~@(int, @fn(Pair) -> int)) {}
-fn eat_rec(_r: ~Rec) {}
-
-struct Rec<'self> { a: int, b: &'self fn(Pair) -> int }
-struct Pair { x: int, y: int }
-
-pub fn main() {
-    eat_tup(~@(10, |a| a.x ));
-    eat_rec(~Rec{a: 10, b: |a| a.x });
-}
diff --git a/src/test/run-pass/issue-1516.rs b/src/test/run-pass/issue-1516.rs
index 2767ac6d69f..4b73d83595e 100644
--- a/src/test/run-pass/issue-1516.rs
+++ b/src/test/run-pass/issue-1516.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 pub fn main() {
-    let early_error: @fn(&str) -> !  = |_msg| { fail!() };
+    let early_error: &'static fn(&str) -> !  = |_msg| { fail!() };
 }
diff --git a/src/test/run-pass/issue-2185.rs b/src/test/run-pass/issue-2185.rs
index c84386c722d..a1ea1b90809 100644
--- a/src/test/run-pass/issue-2185.rs
+++ b/src/test/run-pass/issue-2185.rs
@@ -18,11 +18,11 @@
 //
 // Running /usr/local/bin/rustc:
 // issue-2185.rs:24:0: 26:1 error: conflicting implementations for a trait
-// issue-2185.rs:24 impl iterable<uint> for @fn(&fn(uint)) {
+// issue-2185.rs:24 impl iterable<uint> for &'static fn(&fn(uint)) {
 // issue-2185.rs:25     fn iter(&self, blk: &fn(v: uint)) { self( |i| blk(i) ) }
 // issue-2185.rs:26 }
 // issue-2185.rs:20:0: 22:1 note: note conflicting implementation here
-// issue-2185.rs:20 impl<A> iterable<A> for @fn(&fn(A)) {
+// issue-2185.rs:20 impl<A> iterable<A> for &'static fn(&fn(A)) {
 // issue-2185.rs:21     fn iter(&self, blk: &fn(A)) { self(blk); }
 // issue-2185.rs:22 }
 //
@@ -42,15 +42,17 @@ trait iterable<A> {
     fn iter(&self, blk: &fn(A));
 }
 
-impl<A> iterable<A> for @fn(&fn(A)) {
+impl<A> iterable<A> for &'static fn(&fn(A)) {
     fn iter(&self, blk: &fn(A)) { self(blk); }
 }
 
-impl iterable<uint> for @fn(&fn(uint)) {
+impl iterable<uint> for &'static fn(&fn(uint)) {
     fn iter(&self, blk: &fn(v: uint)) { self( |i| blk(i) ) }
 }
 
-fn filter<A,IA:iterable<A>>(self: IA, prd: @fn(A) -> bool, blk: &fn(A)) {
+fn filter<A,IA:iterable<A>>(self: IA,
+                            prd: &'static fn(A) -> bool,
+                            blk: &fn(A)) {
     do self.iter |a| {
         if prd(a) { blk(a) }
     }
@@ -73,8 +75,8 @@ fn range(lo: uint, hi: uint, it: &fn(uint)) {
 }
 
 pub fn main() {
-    let range: @fn(&fn(uint)) = |a| range(0u, 1000u, a);
-    let filt: @fn(&fn(v: uint)) = |a| filter(
+    let range: &'static fn(&fn(uint)) = |a| range(0u, 1000u, a);
+    let filt: &'static fn(&fn(v: uint)) = |a| filter(
         range,
         |&&n: uint| n % 3u != 0u && n % 5u != 0u,
         a);
diff --git a/src/test/run-pass/issue-2633.rs b/src/test/run-pass/issue-2633.rs
index e7da1286137..bde18d77b9a 100644
--- a/src/test/run-pass/issue-2633.rs
+++ b/src/test/run-pass/issue-2633.rs
@@ -9,12 +9,16 @@
 // except according to those terms.
 
 struct cat {
-    meow: @fn(),
+    meow: extern "Rust" fn(),
+}
+
+fn meow() {
+    error!("meow")
 }
 
 fn cat() -> cat {
     cat {
-        meow: || error!("meow")
+        meow: meow,
     }
 }
 
diff --git a/src/test/run-pass/issue-3052.rs b/src/test/run-pass/issue-3052.rs
index 852c6d995c6..cb1ffc38908 100644
--- a/src/test/run-pass/issue-3052.rs
+++ b/src/test/run-pass/issue-3052.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-type Connection = @fn(~[u8]);
+type Connection = &'static fn(~[u8]);
 
 fn f() -> Option<Connection> {
     let mock_connection: Connection = |_| {};
diff --git a/src/test/run-pass/issue-3429.rs b/src/test/run-pass/issue-3429.rs
index abea01cefd3..fc493485b79 100644
--- a/src/test/run-pass/issue-3429.rs
+++ b/src/test/run-pass/issue-3429.rs
@@ -10,6 +10,6 @@
 
 pub fn main() {
   let x = 1;
-  let y: @fn() -> int = || x;
+  let y: &fn() -> int = || x;
   let _z = y();
 }
diff --git a/src/test/run-pass/issue-4929.rs b/src/test/run-pass/issue-4929.rs
deleted file mode 100644
index 5803c3da6cc..00000000000
--- a/src/test/run-pass/issue-4929.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2013 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 make_adder(x: int) -> @fn(int) -> int { |y| x + y }
-pub fn main() { }
diff --git a/src/test/run-pass/issue-5783.rs b/src/test/run-pass/issue-5783.rs
deleted file mode 100644
index 7f988dc6489..00000000000
--- a/src/test/run-pass/issue-5783.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2013 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.
-
-// Issue #5783
-// Nondeterministic behavior when referencing a closure more than once
-
-fn main() {
-    let a: &fn(int) -> @fn(int) -> int = |x:int| |y:int| -> int x + y;
-    let b = a(2);
-    assert!(a(2)(3) == 5);
-    assert!(b(6) == 8);
-}
diff --git a/src/test/run-pass/issue4516_ty_param.rs b/src/test/run-pass/issue4516_ty_param.rs
deleted file mode 100644
index 35df47df036..00000000000
--- a/src/test/run-pass/issue4516_ty_param.rs
+++ /dev/null
@@ -1,25 +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.
-
-// xfail-fast - check-fast doesn't understand aux-build
-// aux-build:issue4516_ty_param_lib.rs
-
-// Trigger a bug concerning inlining of generic functions.
-// The def-ids in type parameters were not being correctly
-// resolved and hence when we checked the type of the closure
-// variable (see the library mod) to determine if the value
-// should be moved into the closure, trans failed to find
-// the relevant kind bounds.
-
-extern mod issue4516_ty_param_lib;
-use issue4516_ty_param_lib::to_closure;
-pub fn main() {
-    to_closure(22)();
-}
diff --git a/src/test/run-pass/lambda-infer-unresolved.rs b/src/test/run-pass/lambda-infer-unresolved.rs
index 9eecc788a69..d55150e448e 100644
--- a/src/test/run-pass/lambda-infer-unresolved.rs
+++ b/src/test/run-pass/lambda-infer-unresolved.rs
@@ -9,13 +9,13 @@
 // except according to those terms.
 
 // This should typecheck even though the type of e is not fully
-// resolved when we finish typechecking the @fn.
+// resolved when we finish typechecking the &fn.
 
 
 struct Refs { refs: ~[int], n: int }
 
 pub fn main() {
     let e = @mut Refs{refs: ~[], n: 0};
-    let _f: @fn() = || error!(e.n);
+    let _f: &fn() = || error!(e.n);
     e.refs.push(1);
 }
diff --git a/src/test/run-pass/lambda-no-leak.rs b/src/test/run-pass/lambda-no-leak.rs
deleted file mode 100644
index e19503240f0..00000000000
--- a/src/test/run-pass/lambda-no-leak.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.
-
-// Make sure we don't leak @fns in silly ways.
-fn force(f: @fn()) { f() }
-pub fn main() {
-    let x = 7;
-    let _f: @fn() = || error!(x);
-    force(|| error!(x));
-}
diff --git a/src/test/run-pass/last-use-in-cap-clause.rs b/src/test/run-pass/last-use-in-cap-clause.rs
index 75c3008af8e..d014a3cf1a1 100644
--- a/src/test/run-pass/last-use-in-cap-clause.rs
+++ b/src/test/run-pass/last-use-in-cap-clause.rs
@@ -12,10 +12,10 @@
 
 struct A { a: ~int }
 
-fn foo() -> @fn() -> int {
+fn foo() -> &'static fn() -> int {
     let k = ~22;
     let _u = A {a: k.clone()};
-    let result: @fn() -> int = || 22;
+    let result: &'static fn() -> int = || 22;
     result
 }
 
diff --git a/src/test/run-pass/last-use-is-capture.rs b/src/test/run-pass/last-use-is-capture.rs
index 2c62b6894d0..079d2374a29 100644
--- a/src/test/run-pass/last-use-is-capture.rs
+++ b/src/test/run-pass/last-use-is-capture.rs
@@ -13,7 +13,7 @@
 struct A { a: ~int }
 
 pub fn main() {
-    fn invoke(f: @fn()) { f(); }
+    fn invoke(f: &fn()) { f(); }
     let k = ~22;
     let _u = A {a: k.clone()};
     invoke(|| error!(k.clone()) )
diff --git a/src/test/run-pass/monomorphize-trait-in-fn-at.rs b/src/test/run-pass/monomorphize-trait-in-fn-at.rs
deleted file mode 100644
index 8e36b1138bd..00000000000
--- a/src/test/run-pass/monomorphize-trait-in-fn-at.rs
+++ /dev/null
@@ -1,30 +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.
-
-// test that invoking functions which require
-// dictionaries from inside an @fn works
-// (at one point, it didn't)
-
-fn mk_nil<C:ty_ops>(cx: C) -> uint {
-    cx.mk()
-}
-
-trait ty_ops {
-    fn mk(&self) -> uint;
-}
-
-impl ty_ops for () {
-    fn mk(&self) -> uint { 22u }
-}
-
-pub fn main() {
-    let fn_env: @fn() -> uint = || mk_nil(());
-    assert_eq!(fn_env(), 22u);
-}
diff --git a/src/test/run-pass/move-nullary-fn.rs b/src/test/run-pass/move-nullary-fn.rs
index 464d915b2c4..87281c2fd22 100644
--- a/src/test/run-pass/move-nullary-fn.rs
+++ b/src/test/run-pass/move-nullary-fn.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 // Issue #922
-fn f2(_thing: @fn()) { }
+fn f2(_thing: &fn()) { }
 
-fn f(thing: @fn()) {
+fn f(thing: &fn()) {
     f2(thing);
 }
 
diff --git a/src/test/run-pass/nested-enum-same-names.rs b/src/test/run-pass/nested-enum-same-names.rs
index 7d9b744ab0f..919b4b59dca 100644
--- a/src/test/run-pass/nested-enum-same-names.rs
+++ b/src/test/run-pass/nested-enum-same-names.rs
@@ -30,20 +30,4 @@ impl Foo {
     }
 }
 
-/*
-#2074 duplicate symbols with enum in boxed closure
-*/
-
-fn foo() {
-    let one: @fn() -> uint = || {
-        enum r { a }
-        a as uint
-    };
-    let two: @fn() -> uint = || {
-        enum r { a }
-        a as uint
-    };
-    one(); two();
-}
-
 fn main() {}
diff --git a/src/test/run-pass/newlambdas-ret-infer.rs b/src/test/run-pass/newlambdas-ret-infer.rs
index 10ac45922aa..6d6757890ad 100644
--- a/src/test/run-pass/newlambdas-ret-infer.rs
+++ b/src/test/run-pass/newlambdas-ret-infer.rs
@@ -11,8 +11,6 @@
 // Test that the lambda kind is inferred correctly as a return
 // expression
 
-fn shared() -> @fn() { return || (); }
-
 fn unique() -> ~fn() { return || (); }
 
 pub fn main() {
diff --git a/src/test/run-pass/newlambdas-ret-infer2.rs b/src/test/run-pass/newlambdas-ret-infer2.rs
index 4dfe3575eb5..17ff8ce94d9 100644
--- a/src/test/run-pass/newlambdas-ret-infer2.rs
+++ b/src/test/run-pass/newlambdas-ret-infer2.rs
@@ -11,8 +11,6 @@
 // Test that the lambda kind is inferred correctly as a return
 // expression
 
-fn shared() -> @fn() { || () }
-
 fn unique() -> ~fn() { || () }
 
 pub fn main() {
diff --git a/src/test/run-pass/newlambdas.rs b/src/test/run-pass/newlambdas.rs
index 9c2a223174c..d9d0daa7138 100644
--- a/src/test/run-pass/newlambdas.rs
+++ b/src/test/run-pass/newlambdas.rs
@@ -14,16 +14,9 @@ fn f(i: int, f: &fn(int) -> int) -> int { f(i) }
 
 fn g(_g: &fn()) { }
 
-fn ff() -> @fn(int) -> int {
-    return |x| x + 1;
-}
-
 pub fn main() {
     assert_eq!(f(10, |a| a), 10);
     g(||());
     assert_eq!(do f(10) |a| { a }, 10);
     do g() { }
-    let _x: @fn() -> int = || 10;
-    let _y: @fn(int) -> int = |a| a;
-    assert_eq!(ff()(10), 11);
 }
diff --git a/src/test/run-pass/propagate-expected-type-through-block.rs b/src/test/run-pass/propagate-expected-type-through-block.rs
deleted file mode 100644
index f8f824cd596..00000000000
--- a/src/test/run-pass/propagate-expected-type-through-block.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// Test that expected type propagates through `{}` expressions.  If it
-// did not, then the type of `x` would not be known and a compilation
-// error would result.
-
-pub fn main() {
-    let y = ~3;
-    let foo: @fn(&int) -> int = {
-        let y = y.clone();
-        |x| *x + *y
-    };
-    assert_eq!(foo(@22), 25);
-}
diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs
index 2d9f4a2ff6f..cf6f12a06e5 100644
--- a/src/test/run-pass/reflect-visit-data.rs
+++ b/src/test/run-pass/reflect-visit-data.rs
@@ -460,9 +460,9 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
     }
 
     fn visit_closure_ptr(&mut self, ck: uint) -> bool {
-        self.align_to::<@fn()>();
+        self.align_to::<(uint,uint)>();
         if ! self.inner.visit_closure_ptr(ck) { return false; }
-        self.bump_past::<@fn()>();
+        self.bump_past::<(uint,uint)>();
         true
     }
 }
diff --git a/src/test/run-pass/regions-fn-subtyping.rs b/src/test/run-pass/regions-fn-subtyping.rs
index a6b43df1f88..06c8aca4741 100644
--- a/src/test/run-pass/regions-fn-subtyping.rs
+++ b/src/test/run-pass/regions-fn-subtyping.rs
@@ -14,21 +14,21 @@
 #[allow(unused_variable)];
 
 // Should pass region checking.
-fn ok(f: @fn(x: &uint)) {
+fn ok(f: &fn(x: &uint)) {
     // Here, g is a function that can accept a uint pointer with
     // lifetime r, and f is a function that can accept a uint pointer
     // with any lifetime.  The assignment g = f should be OK (i.e.,
     // f's type should be a subtype of g's type), because f can be
     // used in any context that expects g's type.  But this currently
     // fails.
-    let mut g: @fn<'r>(y: &'r uint) = |x| { };
+    let mut g: &fn<'r>(y: &'r uint) = |x| { };
     g = f;
 }
 
 // This version is the same as above, except that here, g's type is
 // inferred.
-fn ok_inferred(f: @fn(x: &uint)) {
-    let mut g: @fn<'r>(x: &'r uint) = |_| {};
+fn ok_inferred(f: &fn(x: &uint)) {
+    let mut g: &fn<'r>(x: &'r uint) = |_| {};
     g = f;
 }
 
diff --git a/src/test/run-pass/rl-human-test.rs b/src/test/run-pass/rl-human-test.rs
index 558e0b6820d..6a87a6502d2 100644
--- a/src/test/run-pass/rl-human-test.rs
+++ b/src/test/run-pass/rl-human-test.rs
@@ -22,6 +22,20 @@ use extra::rl;
 
 static HISTORY_FILE: &'static str = "rl-human-test-history.txt";
 
+struct TestCompleter;
+
+impl rl::CompletionCb for TestCompleter {
+    fn complete(&self, line: ~str, suggest: &fn(~str)) {
+        if line.is_empty() {
+            suggest(~"empty")
+        } else {
+            for c in line.rev_iter().take(3) {
+                suggest(format!("{0}{1}{1}{1}", line, c))
+            }
+        }
+    }
+}
+
 fn main() {
     // don't run this in robot mode, but still typecheck it.
     if !cfg!(robot_mode) {
@@ -42,14 +56,8 @@ The bool return values of each step are printed.",
 
         println!("restricting history length: {}", rl::set_history_max_len(3));
 
-        do rl::complete |line, suggest| {
-            if line.is_empty() {
-                suggest(~"empty")
-            } else {
-                for c in line.rev_iter().take(3) {
-                    suggest(format!("{0}{1}{1}{1}", line, c))
-                }
-            }
+        unsafe {
+            rl::complete(@TestCompleter as @rl::CompletionCb);
         }
 
         println!("adding 'one': {}", rl::add_history("one"));
diff --git a/src/test/run-pass/unused-move-capture.rs b/src/test/run-pass/unused-move-capture.rs
index dd70b7daa70..662121a0993 100644
--- a/src/test/run-pass/unused-move-capture.rs
+++ b/src/test/run-pass/unused-move-capture.rs
@@ -10,6 +10,6 @@
 
 pub fn main() {
     let _x = ~1;
-    let lam_move: @fn() = || {};
+    let lam_move: &fn() = || {};
     lam_move();
 }