about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-06-29 04:22:53 -0700
committerbors <bors@rust-lang.org>2013-06-29 04:22:53 -0700
commit132cfcdd8898a12b19ba01ae64cd9cff9a4c45d9 (patch)
tree53a9a390765ba6af5988811ee3f23944cf888af8
parentc80e3bac3e676abb106f7ef8ac7da5b153c65c8e (diff)
parentd7544fe987104ad0a82b1929b819cfd7e2321bb2 (diff)
downloadrust-132cfcdd8898a12b19ba01ae64cd9cff9a4c45d9.tar.gz
rust-132cfcdd8898a12b19ba01ae64cd9cff9a4c45d9.zip
auto merge of #7363 : bblum/rust/soundness, r=nikomatsakis
The commit f9a5453 is meant to be a temporary hold-over. Whether or not there is added a way for the compiler to "implicitly borrow" stack closures in this way, there should be a codegen optimization that prevents having to traverse possibly-very-many function pointers to find the function you ultimately wanted to call. I tried to separate out the changes so this particular commit could be straight-up reverted if auto-borrowing happens in the future.

r? @nikomatsakis
-rw-r--r--src/libextra/fun_treemap.rs4
-rw-r--r--src/libextra/rope.rs4
-rw-r--r--src/libextra/sort.rs9
-rw-r--r--src/libextra/sync.rs12
-rw-r--r--src/libextra/test.rs6
-rw-r--r--src/libextra/treemap.rs12
-rw-r--r--src/libextra/workcache.rs2
-rw-r--r--src/librust/rust.rs6
-rw-r--r--src/librustc/metadata/filesearch.rs2
-rw-r--r--src/librustc/metadata/tydecode.rs40
-rw-r--r--src/librustc/middle/borrowck/move_data.rs2
-rw-r--r--src/librustc/middle/kind.rs37
-rw-r--r--src/librustc/middle/mem_categorization.rs16
-rw-r--r--src/librustc/middle/trans/base.rs2
-rw-r--r--src/librustc/middle/trans/common.rs42
-rw-r--r--src/librustc/middle/ty.rs266
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs12
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs4
-rw-r--r--src/librustc/middle/typeck/infer/region_inference.rs27
-rw-r--r--src/libstd/hashmap.rs5
-rw-r--r--src/libstd/iterator.rs2
-rw-r--r--src/libstd/local_data.rs2
-rw-r--r--src/libstd/os.rs2
-rw-r--r--src/libstd/str.rs4
-rw-r--r--src/libstd/task/spawn.rs4
-rw-r--r--src/libstd/to_bytes.rs9
-rw-r--r--src/libstd/trie.rs6
-rw-r--r--src/libstd/vec.rs8
-rw-r--r--src/libsyntax/ast.rs265
-rw-r--r--src/libsyntax/ast_util.rs21
-rw-r--r--src/libsyntax/codemap.rs53
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax/ext/deriving/iter_bytes.rs12
-rw-r--r--src/libsyntax/ext/deriving/rand.rs2
-rw-r--r--src/libsyntax/opt_vec.rs2
-rw-r--r--src/libsyntax/parse/token.rs8
-rw-r--r--src/test/compile-fail/kindck-owned.rs2
-rw-r--r--src/test/compile-fail/regions-creating-enums.rs4
-rw-r--r--src/test/compile-fail/the-case-of-the-recurring-closure-2.rs44
-rw-r--r--src/test/compile-fail/the-case-of-the-recurring-closure.rs44
40 files changed, 366 insertions, 640 deletions
diff --git a/src/libextra/fun_treemap.rs b/src/libextra/fun_treemap.rs
index eb8c27e9902..5906e809c98 100644
--- a/src/libextra/fun_treemap.rs
+++ b/src/libextra/fun_treemap.rs
@@ -66,9 +66,9 @@ pub fn traverse<K, V: Copy>(m: Treemap<K, V>, f: &fn(&K, &V)) {
         // matches to me, so I changed it. but that may be a
         // de-optimization -- tjc
         Node(@ref k, @ref v, left, right) => {
-            traverse(left, f);
+            traverse(left, |k,v| f(k,v));
             f(k, v);
-            traverse(right, f);
+            traverse(right, |k,v| f(k,v));
         }
     }
 }
diff --git a/src/libextra/rope.rs b/src/libextra/rope.rs
index fed73256c00..71393ff9fae 100644
--- a/src/libextra/rope.rs
+++ b/src/libextra/rope.rs
@@ -1078,7 +1078,7 @@ pub mod node {
 
     pub fn loop_chars(node: @Node, it: &fn(c: char) -> bool) -> bool {
         return loop_leaves(node,|leaf| {
-            leaf.content.slice(leaf.byte_offset, leaf.byte_len).iter().all(it)
+            leaf.content.slice(leaf.byte_offset, leaf.byte_len).iter().all(|c| it(c))
         });
     }
 
@@ -1101,7 +1101,7 @@ pub mod node {
         loop {
             match (*current) {
               Leaf(x) => return it(x),
-              Concat(ref x) => if loop_leaves(x.left, it) { //non tail call
+              Concat(ref x) => if loop_leaves(x.left, |l| it(l)) { //non tail call
                 current = x.right;       //tail call
               } else {
                 return false;
diff --git a/src/libextra/sort.rs b/src/libextra/sort.rs
index 5377dfadbaa..10dbe2326d7 100644
--- a/src/libextra/sort.rs
+++ b/src/libextra/sort.rs
@@ -42,7 +42,8 @@ pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
         let mid = v_len / 2 + begin;
         let a = (begin, mid);
         let b = (mid, end);
-        return merge(le, merge_sort_(v, a, le), merge_sort_(v, b, le));
+        return merge(|x,y| le(x,y), merge_sort_(v, a, |x,y| le(x,y)),
+                                    merge_sort_(v, b, |x,y| le(x,y)));
     }
 
     fn merge<T:Copy>(le: Le<T>, a: &[T], b: &[T]) -> ~[T] {
@@ -83,10 +84,10 @@ fn qsort<T>(arr: &mut [T], left: uint,
             right: uint, compare_func: Le<T>) {
     if right > left {
         let pivot = (left + right) / 2u;
-        let new_pivot = part::<T>(arr, left, right, pivot, compare_func);
+        let new_pivot = part::<T>(arr, left, right, pivot, |x,y| compare_func(x,y));
         if new_pivot != 0u {
             // Need to do this check before recursing due to overflow
-            qsort::<T>(arr, left, new_pivot - 1u, compare_func);
+            qsort::<T>(arr, left, new_pivot - 1u, |x,y| compare_func(x,y));
         }
         qsort::<T>(arr, new_pivot + 1u, right, compare_func);
     }
@@ -1202,7 +1203,7 @@ mod big_tests {
 
     struct LVal<'self> {
         val: uint,
-        key: &'self fn(@uint),
+        key: &'self fn:Copy(@uint),
     }
 
     #[unsafe_destructor]
diff --git a/src/libextra/sync.rs b/src/libextra/sync.rs
index 3908b61381b..9c6be901d98 100644
--- a/src/libextra/sync.rs
+++ b/src/libextra/sync.rs
@@ -563,7 +563,9 @@ impl RWlock {
                 (&self.order_lock).acquire();
                 do (&self.access_lock).access_waitqueue {
                     (&self.order_lock).release();
-                    task::rekillable(blk)
+                    do task::rekillable {
+                        blk()
+                    }
                 }
             }
         }
@@ -1182,12 +1184,12 @@ mod tests {
             Write => x.write(blk),
             Downgrade =>
                 do x.write_downgrade |mode| {
-                    (&mode).write(blk);
+                    do mode.write { blk() };
                 },
             DowngradeRead =>
                 do x.write_downgrade |mode| {
                     let mode = x.downgrade(mode);
-                    (&mode).read(blk);
+                    do mode.read { blk() };
                 },
         }
     }
@@ -1340,10 +1342,10 @@ mod tests {
         fn lock_cond(x: &RWlock, downgrade: bool, blk: &fn(c: &Condvar)) {
             if downgrade {
                 do x.write_downgrade |mode| {
-                    (&mode).write_cond(blk)
+                    do mode.write_cond |c| { blk(c) }
                 }
             } else {
-                x.write_cond(blk)
+                do x.write_cond |c| { blk(c) }
             }
         }
         let x = ~RWlock();
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index 209b46809ce..50ca96e6e21 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -678,7 +678,7 @@ impl BenchHarness {
 
         // Initial bench run to get ballpark figure.
         let mut n = 1_u64;
-        self.bench_n(n, f);
+        self.bench_n(n, |x| f(x));
 
         while n < 1_000_000_000 &&
             self.ns_elapsed() < 1_000_000_000 {
@@ -694,7 +694,7 @@ impl BenchHarness {
 
             n = u64::max(u64::min(n+n/2, 100*last), last+1);
             n = round_up(n);
-            self.bench_n(n, f);
+            self.bench_n(n, |x| f(x));
         }
     }
 
@@ -714,7 +714,7 @@ impl BenchHarness {
                                             magnitude * 2);
 
             let samples = do vec::from_fn(n_samples) |_| {
-                self.bench_n(n_iter as u64, f);
+                self.bench_n(n_iter as u64, |x| f(x));
                 self.ns_per_iter() as f64
             };
 
diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs
index 4622b8c7284..d546b48f817 100644
--- a/src/libextra/treemap.rs
+++ b/src/libextra/treemap.rs
@@ -511,14 +511,14 @@ impl<K: TotalOrd, V> TreeNode<K, V> {
 
 fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
                             f: &fn(&'r K, &'r V) -> bool) -> bool {
-    node.iter().advance(|x| each(&x.left, f) && f(&x.key, &x.value) &&
-                            each(&x.right, f))
+    node.iter().advance(|x| each(&x.left,  |k,v| f(k,v)) && f(&x.key, &x.value) &&
+                            each(&x.right, |k,v| f(k,v)))
 }
 
 fn each_reverse<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
                                     f: &fn(&'r K, &'r V) -> bool) -> bool {
-    node.iter().advance(|x| each_reverse(&x.right, f) && f(&x.key, &x.value) &&
-                            each_reverse(&x.left, f))
+    node.iter().advance(|x| each_reverse(&x.right, |k,v| f(k,v)) && f(&x.key, &x.value) &&
+                            each_reverse(&x.left,  |k,v| f(k,v)))
 }
 
 fn mutate_values<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
@@ -527,9 +527,9 @@ fn mutate_values<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
     match *node {
       Some(~TreeNode{key: ref key, value: ref mut value, left: ref mut left,
                      right: ref mut right, _}) => {
-        if !mutate_values(left, f) { return false }
+        if !mutate_values(left,  |k,v| f(k,v)) { return false }
         if !f(key, value) { return false }
-        if !mutate_values(right, f) { return false }
+        if !mutate_values(right, |k,v| f(k,v)) { return false }
       }
       None => return false
     }
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index 567f9eda2fb..4d4f3c3a49b 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -107,7 +107,7 @@ struct WorkKey {
 impl to_bytes::IterBytes for WorkKey {
     #[inline]
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.kind.iter_bytes(lsb0, f) && self.name.iter_bytes(lsb0, f)
+        self.kind.iter_bytes(lsb0, |b| f(b)) && self.name.iter_bytes(lsb0, |b| f(b))
     }
 }
 
diff --git a/src/librust/rust.rs b/src/librust/rust.rs
index 68427745ff5..ba5e592b605 100644
--- a/src/librust/rust.rs
+++ b/src/librust/rust.rs
@@ -57,13 +57,13 @@ impl ValidUsage {
 }
 
 enum Action<'self> {
-    Call(&'self fn(args: &[~str]) -> ValidUsage),
-    CallMain(&'static str, &'self fn()),
+    Call(&'self fn:Copy(args: &[~str]) -> ValidUsage),
+    CallMain(&'static str, &'self fn:Copy()),
 }
 
 enum UsageSource<'self> {
     UsgStr(&'self str),
-    UsgCall(&'self fn()),
+    UsgCall(&'self fn:Copy()),
 }
 
 struct Command<'self> {
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 6268932ba99..abfb5f7d4d4 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -48,7 +48,7 @@ pub fn mk_filesearch(maybe_sysroot: &Option<@Path>,
             debug!("filesearch: searching additional lib search paths [%?]",
                    self.addl_lib_search_paths.len());
             // a little weird
-            self.addl_lib_search_paths.iter().advance(f);
+            self.addl_lib_search_paths.iter().advance(|path| f(path));
 
             debug!("filesearch: searching target lib path");
             if !f(&make_target_lib_path(self.sysroot,
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 1ec5c983f62..22786581073 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -189,11 +189,11 @@ fn parse_trait_store(st: &mut PState) -> ty::TraitStore {
 fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
     let self_r = parse_opt(st, |st| parse_region(st) );
 
-    let self_ty = parse_opt(st, |st| parse_ty(st, conv) );
+    let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
 
     assert_eq!(next(st), '[');
     let mut params: ~[ty::t] = ~[];
-    while peek(st) != ']' { params.push(parse_ty(st, conv)); }
+    while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
     st.pos = st.pos + 1u;
 
     return ty::substs {
@@ -270,8 +270,8 @@ fn parse_str(st: &mut PState, term: char) -> ~str {
 }
 
 fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef {
-    let def = parse_def(st, NominalType, conv);
-    let substs = parse_substs(st, conv);
+    let def = parse_def(st, NominalType, |x,y| conv(x,y));
+    let substs = parse_substs(st, |x,y| conv(x,y));
     ty::TraitRef {def_id: def, substs: substs}
 }
 
@@ -301,18 +301,18 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       'c' => return ty::mk_char(),
       't' => {
         assert_eq!(next(st), '[');
-        let def = parse_def(st, NominalType, conv);
-        let substs = parse_substs(st, conv);
+        let def = parse_def(st, NominalType, |x,y| conv(x,y));
+        let substs = parse_substs(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
         return ty::mk_enum(st.tcx, def, substs);
       }
       'x' => {
         assert_eq!(next(st), '[');
-        let def = parse_def(st, NominalType, conv);
-        let substs = parse_substs(st, conv);
+        let def = parse_def(st, NominalType, |x,y| conv(x,y));
+        let substs = parse_substs(st, |x,y| conv(x,y));
         let store = parse_trait_store(st);
         let mt = parse_mutability(st);
-        let bounds = parse_bounds(st, conv);
+        let bounds = parse_bounds(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
         return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
       }
@@ -346,7 +346,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = ~[];
-        while peek(st) != ']' { params.push(parse_ty(st, conv)); }
+        while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); }
         st.pos = st.pos + 1u;
         return ty::mk_tup(st.tcx, params);
       }
@@ -380,15 +380,15 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         }
       }
       '"' => {
-        let _ = parse_def(st, TypeWithId, conv);
-        let inner = parse_ty(st, conv);
+        let _ = parse_def(st, TypeWithId, |x,y| conv(x,y));
+        let inner = parse_ty(st, |x,y| conv(x,y));
         inner
       }
       'B' => ty::mk_opaque_box(st.tcx),
       'a' => {
           assert_eq!(next(st), '[');
-          let did = parse_def(st, NominalType, conv);
-          let substs = parse_substs(st, conv);
+          let did = parse_def(st, NominalType, |x,y| conv(x,y));
+          let substs = parse_substs(st, |x,y| conv(x,y));
           assert_eq!(next(st), ']');
           return ty::mk_struct(st.tcx, did, substs);
       }
@@ -473,8 +473,8 @@ fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
     let purity = parse_purity(next(st));
     let onceness = parse_onceness(next(st));
     let region = parse_region(st);
-    let bounds = parse_bounds(st, conv);
-    let sig = parse_sig(st, conv);
+    let bounds = parse_bounds(st, |x,y| conv(x,y));
+    let sig = parse_sig(st, |x,y| conv(x,y));
     ty::ClosureTy {
         purity: purity,
         sigil: sigil,
@@ -500,7 +500,7 @@ fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
     assert_eq!(next(st), '[');
     let mut inputs = ~[];
     while peek(st) != ']' {
-        inputs.push(parse_ty(st, conv));
+        inputs.push(parse_ty(st, |x,y| conv(x,y)));
     }
     st.pos += 1u; // eat the ']'
     let ret_ty = parse_ty(st, conv);
@@ -544,8 +544,8 @@ pub fn parse_type_param_def_data(data: &[u8], start: uint,
 }
 
 fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef {
-    ty::TypeParameterDef {def_id: parse_def(st, NominalType, conv),
-                          bounds: @parse_bounds(st, conv)}
+    ty::TypeParameterDef {def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
+                          bounds: @parse_bounds(st, |x,y| conv(x,y))}
 }
 
 fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
@@ -571,7 +571,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
                 param_bounds.builtin_bounds.add(ty::BoundSized);
             }
             'I' => {
-                param_bounds.trait_bounds.push(@parse_trait_ref(st, conv));
+                param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
             }
             '.' => {
                 return param_bounds;
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 7396dc1bd7b..623dbbd61b2 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -411,7 +411,7 @@ impl MoveData {
 
         let mut p = self.path(index).first_child;
         while p != InvalidMovePathIndex {
-            if !self.each_extending_path(p, f) {
+            if !self.each_extending_path(p, |x| f(x)) {
                 return false;
             }
             p = self.path(p).next_sibling;
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index f0c091ac53c..d4b91ed589d 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -171,7 +171,7 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         // check that only immutable variables are implicitly copied in
         check_imm_free_var(cx, fv.def, fv.span);
 
-        check_freevar_bounds(cx, fv.span, var_t, bounds);
+        check_freevar_bounds(cx, fv.span, var_t, bounds, None);
     }
 
     fn check_for_box(cx: Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
@@ -182,13 +182,18 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         // check that only immutable variables are implicitly copied in
         check_imm_free_var(cx, fv.def, fv.span);
 
-        check_freevar_bounds(cx, fv.span, var_t, bounds);
+        check_freevar_bounds(cx, fv.span, var_t, bounds, None);
     }
 
-    fn check_for_block(cx: Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
+    fn check_for_block(cx: Context, fv: &freevar_entry,
+                       bounds: ty::BuiltinBounds, region: ty::Region) {
         let id = ast_util::def_id_of_def(fv.def).node;
         let var_t = ty::node_id_to_type(cx.tcx, id);
-        check_freevar_bounds(cx, fv.span, var_t, bounds);
+        // FIXME(#3569): Figure out whether the implicit borrow is actually
+        // mutable. Currently we assume all upvars are referenced mutably.
+        let implicit_borrowed_type = ty::mk_mut_rptr(cx.tcx, region, var_t);
+        check_freevar_bounds(cx, fv.span, implicit_borrowed_type,
+                             bounds, Some(var_t));
     }
 
     fn check_for_bare(cx: Context, fv: @freevar_entry) {
@@ -205,8 +210,9 @@ fn with_appropriate_checker(cx: Context, id: node_id,
         ty::ty_closure(ty::ClosureTy {sigil: ManagedSigil, bounds: bounds, _}) => {
             b(|cx, fv| check_for_box(cx, fv, bounds))
         }
-        ty::ty_closure(ty::ClosureTy {sigil: BorrowedSigil, bounds: bounds, _}) => {
-            b(|cx, fv| check_for_block(cx, fv, bounds))
+        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(_) => {
             b(check_for_bare)
@@ -366,14 +372,21 @@ pub fn check_typaram_bounds(cx: Context,
 }
 
 pub fn check_freevar_bounds(cx: Context, sp: span, ty: ty::t,
-                            bounds: ty::BuiltinBounds)
+                            bounds: ty::BuiltinBounds, referenced_ty: Option<ty::t>)
 {
     do check_builtin_bounds(cx, ty, bounds) |missing| {
-        cx.tcx.sess.span_err(
-            sp,
-            fmt!("cannot capture variable of type `%s`, which does not fulfill \
-                  `%s`, in a bounded closure",
-                 ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx)));
+        // Will be Some if the freevar is implicitly borrowed (stack closure).
+        // Emit a less mysterious error message in this case.
+        match referenced_ty {
+            Some(rty) => cx.tcx.sess.span_err(sp,
+                fmt!("cannot implicitly borrow variable of type `%s` in a bounded \
+                      stack closure (implicit reference does not fulfill `%s`)",
+                     ty_to_str(cx.tcx, rty), missing.user_string(cx.tcx))),
+            None => cx.tcx.sess.span_err(sp,
+                fmt!("cannot capture variable of type `%s`, which does \
+                      not fulfill `%s`, in a bounded closure",
+                     ty_to_str(cx.tcx, ty), missing.user_string(cx.tcx))),
+        }
         cx.tcx.sess.span_note(
             sp,
             fmt!("this closure's environment must satisfy `%s`",
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 07e65e8af56..ad5951b3976 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -901,7 +901,7 @@ impl mem_categorization_ctxt {
                                 pat, downcast_cmt, subpat_ty,
                                 InteriorField(PositionalField(i)));
 
-                        self.cat_pattern(subcmt, subpat, op);
+                        self.cat_pattern(subcmt, subpat, |x,y| op(x,y));
                     }
                 }
                 Some(&ast::def_fn(*)) |
@@ -912,12 +912,12 @@ impl mem_categorization_ctxt {
                             self.cat_imm_interior(
                                 pat, cmt, subpat_ty,
                                 InteriorField(PositionalField(i)));
-                        self.cat_pattern(cmt_field, subpat, op);
+                        self.cat_pattern(cmt_field, subpat, |x,y| op(x,y));
                     }
                 }
                 Some(&ast::def_static(*)) => {
                     for subpats.iter().advance |&subpat| {
-                        self.cat_pattern(cmt, subpat, op);
+                        self.cat_pattern(cmt, subpat, |x,y| op(x,y));
                     }
                 }
                 _ => {
@@ -941,7 +941,7 @@ impl mem_categorization_ctxt {
             for field_pats.iter().advance |fp| {
                 let field_ty = self.pat_ty(fp.pat); // see (*)
                 let cmt_field = self.cat_field(pat, cmt, fp.ident, field_ty);
-                self.cat_pattern(cmt_field, fp.pat, op);
+                self.cat_pattern(cmt_field, fp.pat, |x,y| op(x,y));
             }
           }
 
@@ -953,7 +953,7 @@ impl mem_categorization_ctxt {
                     self.cat_imm_interior(
                         pat, cmt, subpat_ty,
                         InteriorField(PositionalField(i)));
-                self.cat_pattern(subcmt, subpat, op);
+                self.cat_pattern(subcmt, subpat, |x,y| op(x,y));
             }
           }
 
@@ -967,15 +967,15 @@ impl mem_categorization_ctxt {
           ast::pat_vec(ref before, slice, ref after) => {
               let elt_cmt = self.cat_index(pat, cmt, 0);
               for before.iter().advance |&before_pat| {
-                  self.cat_pattern(elt_cmt, before_pat, op);
+                  self.cat_pattern(elt_cmt, before_pat, |x,y| op(x,y));
               }
               for slice.iter().advance |&slice_pat| {
                   let slice_ty = self.pat_ty(slice_pat);
                   let slice_cmt = self.cat_rvalue(pat, slice_ty);
-                  self.cat_pattern(slice_cmt, slice_pat, op);
+                  self.cat_pattern(slice_cmt, slice_pat, |x,y| op(x,y));
               }
               for after.iter().advance |&after_pat| {
-                  self.cat_pattern(elt_cmt, after_pat, op);
+                  self.cat_pattern(elt_cmt, after_pat, |x,y| op(x,y));
               }
           }
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index efa69ab5e62..d9fea121346 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -674,7 +674,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
                                     int::to_str(variant.disr_val));
                       let variant_cx =
                           iter_variant(variant_cx, repr, av, *variant,
-                                       substs.tps, f);
+                                       substs.tps, |x,y,z| f(x,y,z));
                       match adt::trans_case(cx, repr, variant.disr_val) {
                           _match::single_result(r) => {
                               AddCase(llswitch, r.val, variant_cx.llbb)
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 7624fb13903..b255f2ca78c 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -36,6 +36,8 @@ use core::cast;
 use core::hashmap::{HashMap};
 use core::libc::{c_uint, c_longlong, c_ulonglong};
 use core::to_bytes;
+use core::str;
+use core::vec::raw::to_ptr;
 use core::vec;
 use syntax::ast::ident;
 use syntax::ast_map::{path, path_elt};
@@ -860,7 +862,7 @@ pub fn is_null(val: ValueRef) -> bool {
 }
 
 // Used to identify cached monomorphized functions and vtables
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub enum mono_param_id {
     mono_precise(ty::t, Option<@~[mono_id]>),
     mono_any,
@@ -870,7 +872,7 @@ pub enum mono_param_id {
               datum::DatumMode),
 }
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub enum MonoDataClass {
     MonoBits,    // Anything not treated differently from arbitrary integer data
     MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
@@ -895,7 +897,7 @@ pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
 }
 
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct mono_id_ {
     def: ast::def_id,
     params: ~[mono_param_id],
@@ -904,40 +906,6 @@ pub struct mono_id_ {
 
 pub type mono_id = @mono_id_;
 
-impl to_bytes::IterBytes for mono_param_id {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            mono_precise(t, ref mids) => {
-                0u8.iter_bytes(lsb0, f) &&
-                ty::type_id(t).iter_bytes(lsb0, f) &&
-                mids.iter_bytes(lsb0, f)
-            }
-
-            mono_any => 1u8.iter_bytes(lsb0, f),
-
-            mono_repr(ref a, ref b, ref c, ref d) => {
-                2u8.iter_bytes(lsb0, f) &&
-                a.iter_bytes(lsb0, f) &&
-                b.iter_bytes(lsb0, f) &&
-                c.iter_bytes(lsb0, f) &&
-                d.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
-impl to_bytes::IterBytes for MonoDataClass {
-    fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for mono_id_ {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.def.iter_bytes(lsb0, f) && self.params.iter_bytes(lsb0, f)
-    }
-}
-
 pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
     return build::Select(cx, cond, b, a);
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index f1172fb1da6..b8ee1eee26e 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -52,7 +52,7 @@ use syntax;
 
 // Data types
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct field {
     ident: ast::ident,
     mt: mt
@@ -96,13 +96,13 @@ impl Method {
     }
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct mt {
     ty: t,
     mutbl: ast::mutability,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable, IterBytes)]
 pub enum vstore {
     vstore_fixed(uint),
     vstore_uniq,
@@ -133,7 +133,7 @@ pub struct field_ty {
 
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct creader_cache_key {
     cnum: int,
     pos: uint,
@@ -142,14 +142,6 @@ pub struct creader_cache_key {
 
 type creader_cache = @mut HashMap<creader_cache_key, t>;
 
-impl to_bytes::IterBytes for creader_cache_key {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.cnum.iter_bytes(lsb0, f) &&
-        self.pos.iter_bytes(lsb0, f) &&
-        self.len.iter_bytes(lsb0, f)
-    }
-}
-
 struct intern_key {
     sty: *sty,
 }
@@ -168,6 +160,8 @@ impl cmp::Eq for intern_key {
     }
 }
 
+// NB: Do not replace this with #[deriving(IterBytes)], as above. (Figured
+// this out the hard way.)
 impl to_bytes::IterBytes for intern_key {
     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
         unsafe {
@@ -372,14 +366,14 @@ pub fn type_has_regions(t: t) -> bool {
 }
 pub fn type_id(t: t) -> uint { get(t).id }
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct BareFnTy {
     purity: ast::purity,
     abis: AbiSet,
     sig: FnSig
 }
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct ClosureTy {
     purity: ast::purity,
     sigil: ast::Sigil,
@@ -396,32 +390,13 @@ pub struct ClosureTy {
  * - `lifetimes` is the list of region names bound in this fn.
  * - `inputs` is the list of arguments and their modes.
  * - `output` is the return type. */
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct FnSig {
     bound_lifetime_names: OptVec<ast::ident>,
     inputs: ~[t],
     output: t
 }
 
-impl to_bytes::IterBytes for BareFnTy {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.purity.iter_bytes(lsb0, f) &&
-        self.abis.iter_bytes(lsb0, f) &&
-        self.sig.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for ClosureTy {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.purity.iter_bytes(lsb0, f) &&
-        self.sigil.iter_bytes(lsb0, f) &&
-        self.onceness.iter_bytes(lsb0, f) &&
-        self.region.iter_bytes(lsb0, f) &&
-        self.sig.iter_bytes(lsb0, f) &&
-        self.bounds.iter_bytes(lsb0, f)
-    }
-}
-
 #[deriving(Eq, IterBytes)]
 pub struct param_ty {
     idx: uint,
@@ -526,7 +501,7 @@ type opt_region = Option<Region>;
  * - `self_ty` is the type to which `self` should be remapped, if any.  The
  *   `self` type is rather funny in that it can only appear on traits and is
  *   always substituted away to the implementing type for a trait. */
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct substs {
     self_r: opt_region,
     self_ty: Option<ty::t>,
@@ -582,7 +557,7 @@ mod primitives {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // AST structure in libsyntax/ast.rs as well.
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub enum sty {
     ty_nil,
     ty_bot,
@@ -714,62 +689,33 @@ impl CLike for BuiltinBound {
     }
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct TyVid(uint);
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct IntVid(uint);
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub struct FloatVid(uint);
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable, IterBytes)]
 pub struct RegionVid {
     id: uint
 }
 
-#[deriving(Eq)]
+#[deriving(Eq, IterBytes)]
 pub enum InferTy {
     TyVar(TyVid),
     IntVar(IntVid),
     FloatVar(FloatVid)
 }
 
-impl to_bytes::IterBytes for InferTy {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            TyVar(ref tv) => {
-                0u8.iter_bytes(lsb0, f) && tv.iter_bytes(lsb0, f)
-            }
-            IntVar(ref iv) => {
-                1u8.iter_bytes(lsb0, f) && iv.iter_bytes(lsb0, f)
-            }
-            FloatVar(ref fv) => {
-                2u8.iter_bytes(lsb0, f) && fv.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
-#[deriving(Encodable, Decodable)]
+#[deriving(Encodable, Decodable, IterBytes)]
 pub enum InferRegion {
     ReVar(RegionVid),
     ReSkolemized(uint, bound_region)
 }
 
-impl to_bytes::IterBytes for InferRegion {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ReVar(ref rv) => {
-                0u8.iter_bytes(lsb0, f) && rv.iter_bytes(lsb0, f)
-            }
-            ReSkolemized(ref v, _) => {
-                1u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 impl cmp::Eq for InferRegion {
     fn eq(&self, other: &InferRegion) -> bool {
         match ((*self), *other) {
@@ -849,30 +795,6 @@ impl ToStr for IntVarValue {
     }
 }
 
-impl to_bytes::IterBytes for TyVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for IntVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for FloatVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for RegionVid {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_uint().iter_bytes(lsb0, f)
-    }
-}
-
 pub struct TypeParameterDef {
     def_id: ast::def_id,
     bounds: @ParamBounds
@@ -1319,15 +1241,15 @@ pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
       }
       ty_enum(_, ref substs) | ty_struct(_, ref substs) |
       ty_trait(_, ref substs, _, _, _) => {
-        for (*substs).tps.iter().advance |subty| { maybe_walk_ty(*subty, f); }
+        for (*substs).tps.iter().advance |subty| { maybe_walk_ty(*subty, |x| f(x)); }
       }
-      ty_tup(ref ts) => { for ts.iter().advance |tt| { maybe_walk_ty(*tt, f); } }
+      ty_tup(ref ts) => { for ts.iter().advance |tt| { maybe_walk_ty(*tt, |x| f(x)); } }
       ty_bare_fn(ref ft) => {
-        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, f); }
+        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, |x| f(x)); }
         maybe_walk_ty(ft.sig.output, f);
       }
       ty_closure(ref ft) => {
-        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, f); }
+        for ft.sig.inputs.iter().advance |a| { maybe_walk_ty(*a, |x| f(x)); }
         maybe_walk_ty(ft.sig.output, f);
       }
     }
@@ -1409,7 +1331,7 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
 
 // Folds types from the bottom up.
 pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
-    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
+    let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), |t| fldop(t)));
     fldop(mk_t(cx, sty))
 }
 
@@ -1423,8 +1345,8 @@ pub fn walk_regions_and_ty(
         fold_regions_and_ty(
             cx, ty,
             |r| { walkr(r); r },
-            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
-            |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
+            |t| { walk_regions_and_ty(cx, t, |r| walkr(r), |t| walkt(t)); t },
+            |t| { walk_regions_and_ty(cx, t, |r| walkr(r), |t| walkt(t)); t });
     }
 }
 
@@ -1504,8 +1426,8 @@ pub fn fold_regions(
         fold_regions_and_ty(
             cx, ty,
             |r| fldr(r, in_fn),
-            |t| do_fold(cx, t, true, fldr),
-            |t| do_fold(cx, t, in_fn, fldr))
+            |t| do_fold(cx, t, true,  |r,b| fldr(r,b)),
+            |t| do_fold(cx, t, in_fn, |r,b| fldr(r,b)))
     }
     do_fold(cx, ty, false, fldr)
 }
@@ -1906,7 +1828,9 @@ impl TypeContents {
             // Currently all noncopyable existentials are 2nd-class types
             // behind owned pointers. With dynamically-sized types, remove
             // this assertion.
-            assert!(self.intersects(TC_OWNED_POINTER));
+            assert!(self.intersects(TC_OWNED_POINTER) ||
+                    // (...or stack closures without a copy bound.)
+                    self.intersects(TC_BORROWED_POINTER));
         }
         let tc = TC_MANAGED + TC_DTOR + TypeContents::sendable(cx);
         self.intersects(tc)
@@ -2272,7 +2196,14 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
             ast::Once => TC_ONCE_CLOSURE,
             ast::Many => TC_NONE
         };
-        st + rt + ot
+        // Prevent noncopyable types captured in the environment from being copied.
+        let ct = if cty.bounds.contains_elem(BoundCopy) ||
+                    cty.sigil == ast::ManagedSigil {
+            TC_NONE
+        } else {
+            TC_NONCOPY_TRAIT
+        };
+        st + rt + ot + ct
     }
 
     fn trait_contents(store: TraitStore, mutbl: ast::mutability,
@@ -2452,7 +2383,7 @@ pub fn type_structurally_contains(cx: ctxt,
         for (*enum_variants(cx, did)).iter().advance |variant| {
             for variant.args.iter().advance |aty| {
                 let sty = subst(cx, substs, *aty);
-                if type_structurally_contains(cx, sty, test) { return true; }
+                if type_structurally_contains(cx, sty, |x| test(x)) { return true; }
             }
         }
         return false;
@@ -2461,14 +2392,14 @@ pub fn type_structurally_contains(cx: ctxt,
         let r = lookup_struct_fields(cx, did);
         for r.iter().advance |field| {
             let ft = lookup_field_type(cx, did, field.id, substs);
-            if type_structurally_contains(cx, ft, test) { return true; }
+            if type_structurally_contains(cx, ft, |x| test(x)) { return true; }
         }
         return false;
       }
 
       ty_tup(ref ts) => {
         for ts.iter().advance |tt| {
-            if type_structurally_contains(cx, *tt, test) { return true; }
+            if type_structurally_contains(cx, *tt, |x| test(x)) { return true; }
         }
         return false;
       }
@@ -2744,123 +2675,6 @@ impl cmp::TotalEq for bound_region {
     }
 }
 
-impl to_bytes::IterBytes for vstore {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            vstore_fixed(ref u) => {
-                0u8.iter_bytes(lsb0, f) && u.iter_bytes(lsb0, f)
-            }
-            vstore_uniq => 1u8.iter_bytes(lsb0, f),
-            vstore_box => 2u8.iter_bytes(lsb0, f),
-
-            vstore_slice(ref r) => {
-                3u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
-impl to_bytes::IterBytes for substs {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.self_r.iter_bytes(lsb0, f) &&
-        self.self_ty.iter_bytes(lsb0, f) &&
-        self.tps.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for mt {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.ty.iter_bytes(lsb0, f) && self.mutbl.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for field {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.ident.iter_bytes(lsb0, f) && self.mt.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for FnSig {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.inputs.iter_bytes(lsb0, f) && self.output.iter_bytes(lsb0, f)
-    }
-}
-
-impl to_bytes::IterBytes for sty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ty_nil => 0u8.iter_bytes(lsb0, f),
-            ty_bool => 1u8.iter_bytes(lsb0, f),
-
-            ty_int(ref t) => 2u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
-
-            ty_uint(ref t) => 3u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
-
-            ty_float(ref t) => 4u8.iter_bytes(lsb0, f) && t.iter_bytes(lsb0, f),
-
-            ty_estr(ref v) => 5u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f),
-
-            ty_enum(ref did, ref substs) => {
-                6u8.iter_bytes(lsb0, f) &&
-                did.iter_bytes(lsb0, f) &&
-                substs.iter_bytes(lsb0, f)
-            }
-
-            ty_box(ref mt) => 7u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_evec(ref mt, ref v) => {
-                8u8.iter_bytes(lsb0, f) &&
-                mt.iter_bytes(lsb0, f) &&
-                v.iter_bytes(lsb0, f)
-            }
-
-            ty_unboxed_vec(ref mt) => 9u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_tup(ref ts) => 10u8.iter_bytes(lsb0, f) && ts.iter_bytes(lsb0, f),
-
-            ty_bare_fn(ref ft) => 12u8.iter_bytes(lsb0, f) && ft.iter_bytes(lsb0, f),
-
-            ty_self(ref did) => 13u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f),
-
-            ty_infer(ref v) => 14u8.iter_bytes(lsb0, f) && v.iter_bytes(lsb0, f),
-
-            ty_param(ref p) => 15u8.iter_bytes(lsb0, f) && p.iter_bytes(lsb0, f),
-
-            ty_type => 16u8.iter_bytes(lsb0, f),
-            ty_bot => 17u8.iter_bytes(lsb0, f),
-
-            ty_ptr(ref mt) => 18u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_uniq(ref mt) => 19u8.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f),
-
-            ty_trait(ref did, ref substs, ref v, ref mutbl, bounds) => {
-                20u8.iter_bytes(lsb0, f) &&
-                did.iter_bytes(lsb0, f) &&
-                substs.iter_bytes(lsb0, f) &&
-                v.iter_bytes(lsb0, f) &&
-                mutbl.iter_bytes(lsb0, f) &&
-                bounds.iter_bytes(lsb0, f)
-            }
-
-            ty_opaque_closure_ptr(ref ck) => 21u8.iter_bytes(lsb0, f) && ck.iter_bytes(lsb0, f),
-
-            ty_opaque_box => 22u8.iter_bytes(lsb0, f),
-
-            ty_struct(ref did, ref substs) => {
-                23u8.iter_bytes(lsb0, f) && did.iter_bytes(lsb0, f) && substs.iter_bytes(lsb0, f)
-            }
-
-            ty_rptr(ref r, ref mt) => {
-                24u8.iter_bytes(lsb0, f) && r.iter_bytes(lsb0, f) && mt.iter_bytes(lsb0, f)
-            }
-
-            ty_err => 25u8.iter_bytes(lsb0, f),
-
-            ty_closure(ref ct) => 26u8.iter_bytes(lsb0, f) && ct.iter_bytes(lsb0, f),
-        }
-    }
-}
-
 pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
     match cx.trait_refs.find(&id) {
        Some(&t) => t,
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index 160737142c8..fb79a7c3c99 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -112,7 +112,7 @@ pub fn replace_bound_regions_in_fn_sig(
             // kinds of types.  This had already caused me several
             // bugs so I decided to switch over.
             do ty::fold_regions(tcx, *ty) |r, in_fn| {
-                if !in_fn { isr = append_isr(isr, to_r, r); }
+                if !in_fn { isr = append_isr(isr, |br| to_r(br), r); }
                 r
             };
 
@@ -211,18 +211,18 @@ pub fn relate_nested_regions(
         match ty::get(ty).sty {
             ty::ty_rptr(r, ref mt) |
             ty::ty_evec(ref mt, ty::vstore_slice(r)) => {
-                relate(*the_stack, r, relate_op);
+                relate(*the_stack, r, |x,y| relate_op(x,y));
                 the_stack.push(r);
-                walk_ty(tcx, the_stack, mt.ty, relate_op);
+                walk_ty(tcx, the_stack, mt.ty, |x,y| relate_op(x,y));
                 the_stack.pop();
             }
             _ => {
                 ty::fold_regions_and_ty(
                     tcx,
                     ty,
-                    |r| { relate(*the_stack, r, relate_op); r },
-                    |t| { walk_ty(tcx, the_stack, t, relate_op); t },
-                    |t| { walk_ty(tcx, the_stack, t, relate_op); t });
+                    |r| { relate(     *the_stack, r, |x,y| relate_op(x,y)); r },
+                    |t| { walk_ty(tcx, the_stack, t, |x,y| relate_op(x,y)); t },
+                    |t| { walk_ty(tcx, the_stack, t, |x,y| relate_op(x,y)); t });
             }
         }
     }
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index 1bfe452f25e..3e2d4a71dfb 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -582,7 +582,7 @@ impl InferCtxt {
 
         debug!("commit()");
         do indent {
-            let r = self.try(f);
+            let r = self.try(|| f());
 
             self.ty_var_bindings.bindings.truncate(0);
             self.int_var_bindings.bindings.truncate(0);
@@ -836,6 +836,6 @@ pub fn fold_regions_in_sig(
     fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig
 {
     do ty::fold_sig(fn_sig) |t| {
-        ty::fold_regions(tcx, t, fldr)
+        ty::fold_regions(tcx, t, |r, in_fn| fldr(r, in_fn))
     }
 }
diff --git a/src/librustc/middle/typeck/infer/region_inference.rs b/src/librustc/middle/typeck/infer/region_inference.rs
index 0aad161a678..4380711b78e 100644
--- a/src/librustc/middle/typeck/infer/region_inference.rs
+++ b/src/librustc/middle/typeck/infer/region_inference.rs
@@ -548,43 +548,18 @@ use util::ppaux::note_and_explain_region;
 
 use core::cell::Cell;
 use core::hashmap::{HashMap, HashSet};
-use core::to_bytes;
 use core::uint;
 use core::vec;
 use syntax::codemap::span;
 use syntax::ast;
 
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 enum Constraint {
     ConstrainVarSubVar(RegionVid, RegionVid),
     ConstrainRegSubVar(Region, RegionVid),
     ConstrainVarSubReg(RegionVid, Region)
 }
 
-impl to_bytes::IterBytes for Constraint {
-   fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ConstrainVarSubVar(ref v0, ref v1) => {
-                0u8.iter_bytes(lsb0, f) &&
-                v0.iter_bytes(lsb0, f) &&
-                v1.iter_bytes(lsb0, f)
-            }
-
-            ConstrainRegSubVar(ref ra, ref va) => {
-                1u8.iter_bytes(lsb0, f) &&
-                ra.iter_bytes(lsb0, f) &&
-                va.iter_bytes(lsb0, f)
-            }
-
-            ConstrainVarSubReg(ref va, ref ra) => {
-                2u8.iter_bytes(lsb0, f) &&
-                va.iter_bytes(lsb0, f) &&
-                ra.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 #[deriving(Eq, IterBytes)]
 struct TwoRegions {
     a: Region,
diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs
index bfa0f2fa124..7f9fb6ad938 100644
--- a/src/libstd/hashmap.rs
+++ b/src/libstd/hashmap.rs
@@ -671,7 +671,7 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
     fn symmetric_difference(&self,
                             other: &HashSet<T>,
                             f: &fn(&T) -> bool) -> bool {
-        self.difference(other, f) && other.difference(self, f)
+        self.difference(other, |t| f(t)) && other.difference(self, |t| f(t))
     }
 
     /// Visit the values representing the intersection
@@ -681,7 +681,8 @@ impl<T:Hash + Eq> Set<T> for HashSet<T> {
 
     /// Visit the values representing the union
     fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
-        self.iter().advance(f) && other.iter().advance(|v| self.contains(v) || f(v))
+        self.iter().advance(|t| f(t)) &&
+            other.iter().advance(|v| self.contains(v) || f(v))
     }
 }
 
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
index 765bf3b36f2..976ca8bae7a 100644
--- a/src/libstd/iterator.rs
+++ b/src/libstd/iterator.rs
@@ -964,7 +964,7 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
                     return Some(x)
                 }
             }
-            match self.iter.next().map_consume(self.f) {
+            match self.iter.next().map_consume(|x| (self.f)(x)) {
                 None => return None,
                 next => self.subiter = next,
             }
diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs
index 33b4e3f1963..c5f2c8ae584 100644
--- a/src/libstd/local_data.rs
+++ b/src/libstd/local_data.rs
@@ -46,7 +46,7 @@ use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handl
  *
  * These two cases aside, the interface is safe.
  */
-pub type LocalDataKey<'self,T> = &'self fn(v: @T);
+pub type LocalDataKey<'self,T> = &'self fn:Copy(v: @T);
 
 /**
  * Remove a task-local data value from the table, returning the
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 400a93ee28f..1fbcda12dce 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -595,7 +595,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
     let r = list_dir(p);
     r.iter().advance(|q| {
         let path = &p.push(*q);
-        f(path) && (!path_is_dir(path) || walk_dir(path, f))
+        f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
     })
 }
 
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 2144afc0fbd..e47800d70c6 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -463,7 +463,7 @@ pub fn each_split_within<'a>(ss: &'a str,
         cont
     };
 
-    ss.iter().enumerate().advance(machine);
+    ss.iter().enumerate().advance(|x| machine(x));
 
     // Let the automaton 'run out' by supplying trailing whitespace
     let mut fake_i = ss.len();
@@ -761,7 +761,7 @@ impl<'self> StrUtil for &'self str {
             // NB: len includes the trailing null.
             assert!(len > 0);
             if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
-                to_owned(self).as_c_str(f)
+                to_owned(self).as_c_str(|s| f(s))
             } else {
                 f(buf as *libc::c_char)
             }
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index 8f06fede057..c932a9660c2 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -230,11 +230,15 @@ fn each_ancestor(list:        &mut AncestorList,
         // 'do_continue'  - Did the forward_blk succeed at this point? (i.e.,
         //                  should we recurse? or should our callers unwind?)
 
+        let forward_blk = Cell::new(forward_blk);
+
         // The map defaults to None, because if ancestors is None, we're at
         // the end of the list, which doesn't make sense to coalesce.
         return do (**ancestors).map_default((None,false)) |ancestor_arc| {
             // NB: Takes a lock! (this ancestor node)
             do access_ancestors(ancestor_arc) |nobe| {
+                // Argh, but we couldn't give it to coalesce() otherwise.
+                let forward_blk = forward_blk.take();
                 // Check monotonicity
                 assert!(last_generation > nobe.generation);
                 /*##########################################################*
diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs
index 6f0c615d007..d6e92dd679e 100644
--- a/src/libstd/to_bytes.rs
+++ b/src/libstd/to_bytes.rs
@@ -232,7 +232,8 @@ impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) {
   #[inline]
   fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
     match *self {
-      (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) }
+      (ref a, ref b) => { a.iter_bytes(lsb0, |b| f(b)) &&
+                          b.iter_bytes(lsb0, |b| f(b)) }
     }
   }
 }
@@ -242,7 +243,9 @@ impl<A:IterBytes,B:IterBytes,C:IterBytes> IterBytes for (A,B,C) {
   fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
     match *self {
       (ref a, ref b, ref c) => {
-        a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f)
+        a.iter_bytes(lsb0, |b| f(b)) &&
+        b.iter_bytes(lsb0, |b| f(b)) &&
+        c.iter_bytes(lsb0, |b| f(b))
       }
     }
   }
@@ -296,7 +299,7 @@ impl<A:IterBytes> IterBytes for Option<A> {
     #[inline]
     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
         match *self {
-          Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f),
+          Some(ref a) => 0u8.iter_bytes(lsb0, |b| f(b)) && a.iter_bytes(lsb0, |b| f(b)),
           None => 1u8.iter_bytes(lsb0, f)
         }
     }
diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs
index 8f70c75439a..b9b03ea5661 100644
--- a/src/libstd/trie.rs
+++ b/src/libstd/trie.rs
@@ -251,7 +251,7 @@ impl<T> TrieNode<T> {
     fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
         for uint::range(0, self.children.len()) |idx| {
             match self.children[idx] {
-                Internal(ref x) => if !x.each(f) { return false },
+                Internal(ref x) => if !x.each(|i,t| f(i,t)) { return false },
                 External(k, ref v) => if !f(&k, v) { return false },
                 Nothing => ()
             }
@@ -262,7 +262,7 @@ impl<T> TrieNode<T> {
     fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
         for uint::range_rev(self.children.len(), 0) |idx| {
             match self.children[idx - 1] {
-                Internal(ref x) => if !x.each_reverse(f) { return false },
+                Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false },
                 External(k, ref v) => if !f(&k, v) { return false },
                 Nothing => ()
             }
@@ -273,7 +273,7 @@ impl<T> TrieNode<T> {
     fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
         for self.children.mut_iter().advance |child| {
             match *child {
-                Internal(ref mut x) => if !x.mutate_values(f) {
+                Internal(ref mut x) => if !x.mutate_values(|i,t| f(i,t)) {
                     return false
                 },
                 External(k, ref mut v) => if !f(&k, v) { return false },
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 8555d99255d..4e7943f7cfd 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -191,7 +191,7 @@ pub fn split<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut start = 0u;
     let mut result = ~[];
     while start < ln {
-        match position_between(v, start, ln, f) {
+        match position_between(v, start, ln, |t| f(t)) {
             None => break,
             Some(i) => {
                 result.push(v.slice(start, i).to_owned());
@@ -215,7 +215,7 @@ pub fn splitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut count = n;
     let mut result = ~[];
     while start < ln && count > 0u {
-        match position_between(v, start, ln, f) {
+        match position_between(v, start, ln, |t| f(t)) {
             None => break,
             Some(i) => {
                 result.push(v.slice(start, i).to_owned());
@@ -240,7 +240,7 @@ pub fn rsplit<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut end = ln;
     let mut result = ~[];
     while end > 0 {
-        match rposition_between(v, 0, end, f) {
+        match rposition_between(v, 0, end, |t| f(t)) {
             None => break,
             Some(i) => {
                 result.push(v.slice(i + 1, end).to_owned());
@@ -265,7 +265,7 @@ pub fn rsplitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] {
     let mut count = n;
     let mut result = ~[];
     while end > 0u && count > 0u {
-        match rposition_between(v, 0u, end, f) {
+        match rposition_between(v, 0u, end, |t| f(t)) {
             None => break,
             Some(i) => {
                 result.push(v.slice(i + 1u, end).to_owned());
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 8e1c51caf7c..bc432c4c7b0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -17,17 +17,14 @@ use parse::token::{interner_get, str_to_ident};
 
 use std::hashmap::HashMap;
 use std::option::Option;
-use std::to_bytes::IterBytes;
-use std::to_bytes;
 use std::to_str::ToStr;
 use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
 
-
 // an identifier contains a Name (index into the interner
 // table) and a SyntaxContext to track renaming and
 // macro expansion per Flatt et al., "Macros
 // That Work Together"
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct ident { name: Name, ctxt: SyntaxContext }
 
 /// Construct an identifier with the given name and an empty context:
@@ -57,7 +54,7 @@ pub struct SCTable {
 pub static empty_ctxt : uint = 0;
 pub static illegal_ctxt : uint = 1;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum SyntaxContext_ {
     EmptyCtxt,
     Mark (Mrk,SyntaxContext),
@@ -86,42 +83,28 @@ impl<S:Encoder> Encodable<S> for ident {
     }
 }
 
+#[deriving(IterBytes)]
 impl<D:Decoder> Decodable<D> for ident {
     fn decode(d: &mut D) -> ident {
         str_to_ident(d.read_str())
     }
 }
 
-impl to_bytes::IterBytes for ident {
-    #[inline]
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.name.iter_bytes(lsb0, f)
-    }
-}
-
 // Functions may or may not have names.
 pub type fn_ident = Option<ident>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Lifetime {
     id: node_id,
     span: span,
     ident: ident
 }
 
-impl to_bytes::IterBytes for Lifetime {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.id.iter_bytes(lsb0, f) &&
-        self.span.iter_bytes(lsb0, f) &&
-        self.ident.iter_bytes(lsb0, f)
-    }
-}
-
 // a "Path" is essentially Rust's notion of a name;
 // for instance: core::cmp::Eq  .  It's represented
 // as a sequence of identifiers, along with a bunch
 // of supporting information.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Path {
     span: span,
     global: bool,
@@ -134,7 +117,7 @@ pub type crate_num = int;
 
 pub type node_id = int;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct def_id {
     crate: crate_num,
     node: node_id,
@@ -143,7 +126,7 @@ pub struct def_id {
 pub static local_crate: crate_num = 0;
 pub static crate_node_id: node_id = 0;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 // The AST represents all type param bounds as types.
 // typeck::collect::compute_bounds matches these against
 // the "special" built-in traits (see middle::lang_items) and
@@ -153,14 +136,14 @@ pub enum TyParamBound {
     RegionTyParamBound
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct TyParam {
     ident: ident,
     id: node_id,
     bounds: @OptVec<TyParamBound>
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Generics {
     lifetimes: OptVec<Lifetime>,
     ty_params: OptVec<TyParam>
@@ -178,7 +161,7 @@ impl Generics {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum def {
     def_fn(def_id, purity),
     def_static_method(/* method */ def_id,
@@ -216,7 +199,7 @@ pub type crate_cfg = ~[@meta_item];
 
 pub type crate = spanned<crate_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct crate_ {
     module: _mod,
     attrs: ~[attribute],
@@ -225,7 +208,7 @@ pub struct crate_ {
 
 pub type meta_item = spanned<meta_item_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum meta_item_ {
     meta_word(@str),
     meta_list(@str, ~[@meta_item]),
@@ -234,7 +217,7 @@ pub enum meta_item_ {
 
 pub type blk = spanned<blk_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct blk_ {
     view_items: ~[@view_item],
     stmts: ~[@stmt],
@@ -243,40 +226,26 @@ pub struct blk_ {
     rules: blk_check_mode,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct pat {
     id: node_id,
     node: pat_,
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct field_pat {
     ident: ident,
     pat: @pat,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum binding_mode {
     bind_by_ref(mutability),
     bind_infer
 }
 
-impl to_bytes::IterBytes for binding_mode {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-          bind_by_ref(ref m) => {
-              0u8.iter_bytes(lsb0, f) && m.iter_bytes(lsb0, f)
-          }
-
-          bind_infer => {
-              1u8.iter_bytes(lsb0, f)
-          }
-        }
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum pat_ {
     pat_wild,
     // A pat_ident may either be a new bound variable,
@@ -301,28 +270,16 @@ pub enum pat_ {
     pat_vec(~[@pat], Option<@pat>, ~[@pat])
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum mutability { m_mutbl, m_imm, m_const, }
 
-impl to_bytes::IterBytes for mutability {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum Sigil {
     BorrowedSigil,
     OwnedSigil,
     ManagedSigil
 }
 
-impl to_bytes::IterBytes for Sigil {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as uint).iter_bytes(lsb0, f)
-    }
-}
-
 impl ToStr for Sigil {
     fn to_str(&self) -> ~str {
         match *self {
@@ -333,7 +290,7 @@ impl ToStr for Sigil {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum vstore {
     // FIXME (#3469): Change uint to @expr (actually only constant exprs)
     vstore_fixed(Option<uint>),     // [1,2,3,4]
@@ -342,7 +299,7 @@ pub enum vstore {
     vstore_slice(Option<@Lifetime>) // &'foo? [1,2,3,4]
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum expr_vstore {
     expr_vstore_uniq,                  // ~[1,2,3,4]
     expr_vstore_box,                   // @[1,2,3,4]
@@ -351,7 +308,7 @@ pub enum expr_vstore {
     expr_vstore_mut_slice,             // &mut [1,2,3,4]
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum binop {
     add,
     subtract,
@@ -373,7 +330,7 @@ pub enum binop {
     gt,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum unop {
     box(mutability),
     uniq(mutability),
@@ -384,7 +341,7 @@ pub enum unop {
 
 pub type stmt = spanned<stmt_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum stmt_ {
     // could be an item or a local (let) binding:
     stmt_decl(@decl, node_id),
@@ -401,7 +358,7 @@ pub enum stmt_ {
 
 // FIXME (pending discussion of #1697, #2178...): local should really be
 // a refinement on pat.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct local_ {
     is_mutbl: bool,
     ty: @Ty,
@@ -414,7 +371,7 @@ pub type local = spanned<local_>;
 
 pub type decl = spanned<decl_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum decl_ {
     // a local (let) binding:
     decl_local(@local),
@@ -422,14 +379,14 @@ pub enum decl_ {
     decl_item(@item),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct arm {
     pats: ~[@pat],
     guard: Option<@expr>,
     body: blk,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct field_ {
     ident: ident,
     expr: @expr,
@@ -437,10 +394,10 @@ pub struct field_ {
 
 pub type field = spanned<field_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum blk_check_mode { default_blk, unsafe_blk, }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct expr {
     id: node_id,
     node: expr_,
@@ -460,14 +417,14 @@ impl expr {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum CallSugar {
     NoSugar,
     DoSugar,
     ForSugar
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum expr_ {
     expr_vstore(@expr, expr_vstore),
     expr_vec(~[@expr], mutability),
@@ -538,7 +495,7 @@ pub enum expr_ {
 // else knows what to do with them, so you'll probably get a syntax
 // error.
 //
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 #[doc="For macro invocations; parsing is delegated to the macro"]
 pub enum token_tree {
     // a single token
@@ -611,7 +568,7 @@ pub enum token_tree {
 //
 pub type matcher = spanned<matcher_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum matcher_ {
     // match one token
     match_tok(::parse::token::Token),
@@ -624,14 +581,14 @@ pub enum matcher_ {
 
 pub type mac = spanned<mac_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum mac_ {
     mac_invoc_tt(@Path,~[token_tree]),   // new macro-invocation
 }
 
 pub type lit = spanned<lit_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum lit_ {
     lit_str(@str),
     lit_int(i64, int_ty),
@@ -645,13 +602,13 @@ pub enum lit_ {
 
 // NB: If you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct mt {
     ty: @Ty,
     mutbl: mutability,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct ty_field_ {
     ident: ident,
     mt: mt,
@@ -659,7 +616,7 @@ pub struct ty_field_ {
 
 pub type ty_field = spanned<ty_field_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct ty_method {
     ident: ident,
     attrs: ~[attribute],
@@ -671,7 +628,7 @@ pub struct ty_method {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 // A trait method is either required (meaning it doesn't have an
 // implementation, just a signature) or provided (meaning it has a default
 // implementation).
@@ -680,7 +637,7 @@ pub enum trait_method {
     provided(@method),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum int_ty { ty_i, ty_char, ty_i8, ty_i16, ty_i32, ty_i64, }
 
 impl ToStr for int_ty {
@@ -689,13 +646,7 @@ impl ToStr for int_ty {
     }
 }
 
-impl to_bytes::IterBytes for int_ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum uint_ty { ty_u, ty_u8, ty_u16, ty_u32, ty_u64, }
 
 impl ToStr for uint_ty {
@@ -704,13 +655,7 @@ impl ToStr for uint_ty {
     }
 }
 
-impl to_bytes::IterBytes for uint_ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum float_ty { ty_f, ty_f32, ty_f64, }
 
 impl ToStr for float_ty {
@@ -719,14 +664,8 @@ impl ToStr for float_ty {
     }
 }
 
-impl to_bytes::IterBytes for float_ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
 // NB Eq method appears below.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct Ty {
     id: node_id,
     node: ty_,
@@ -734,7 +673,7 @@ pub struct Ty {
 }
 
 // Not represented directly in the AST, referred to by name through a ty_path.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum prim_ty {
     ty_int(int_ty),
     ty_uint(uint_ty),
@@ -743,12 +682,13 @@ pub enum prim_ty {
     ty_bool,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum Onceness {
     Once,
     Many
 }
 
+#[deriving(IterBytes)]
 impl ToStr for Onceness {
     fn to_str(&self) -> ~str {
         match *self {
@@ -758,13 +698,7 @@ impl ToStr for Onceness {
     }
 }
 
-impl to_bytes::IterBytes for Onceness {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as uint).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct TyClosure {
     sigil: Sigil,
     region: Option<@Lifetime>,
@@ -779,7 +713,7 @@ pub struct TyClosure {
     bounds: Option<OptVec<TyParamBound>>,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct TyBareFn {
     purity: purity,
     abis: AbiSet,
@@ -787,7 +721,7 @@ pub struct TyBareFn {
     decl: fn_decl
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
@@ -808,19 +742,13 @@ pub enum ty_ {
     ty_infer,
 }
 
-impl to_bytes::IterBytes for Ty {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.span.lo.iter_bytes(lsb0, f) && self.span.hi.iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum asm_dialect {
     asm_att,
     asm_intel
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct inline_asm {
     asm: @str,
     clobbers: @str,
@@ -831,7 +759,7 @@ pub struct inline_asm {
     dialect: asm_dialect
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct arg {
     is_mutbl: bool,
     ty: @Ty,
@@ -839,20 +767,21 @@ pub struct arg {
     id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct fn_decl {
     inputs: ~[arg],
     output: @Ty,
     cf: ret_style,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum purity {
     unsafe_fn, // declared with "unsafe fn"
     impure_fn, // declared with "fn"
     extern_fn, // declared with "extern fn"
 }
 
+#[deriving(IterBytes)]
 impl ToStr for purity {
     fn to_str(&self) -> ~str {
         match *self {
@@ -863,26 +792,14 @@ impl ToStr for purity {
     }
 }
 
-impl to_bytes::IterBytes for purity {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum ret_style {
     noreturn, // functions with return type _|_ that always
               // raise an error or exit (i.e. never return to the caller)
     return_val, // everything else
 }
 
-impl to_bytes::IterBytes for ret_style {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (*self as u8).iter_bytes(lsb0, f)
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum explicit_self_ {
     sty_static,                                // no self
     sty_value,                                 // `self`
@@ -891,27 +808,9 @@ pub enum explicit_self_ {
     sty_uniq(mutability)                       // `~self`
 }
 
-impl to_bytes::IterBytes for explicit_self_ {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            sty_static => 0u8.iter_bytes(lsb0, f),
-            sty_value => 1u8.iter_bytes(lsb0, f),
-            sty_region(ref lft, ref mutbl) => {
-                2u8.iter_bytes(lsb0, f) && lft.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f)
-            }
-            sty_box(ref mutbl) => {
-                3u8.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f)
-            }
-            sty_uniq(ref mutbl) => {
-                4u8.iter_bytes(lsb0, f) && mutbl.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 pub type explicit_self = spanned<explicit_self_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct method {
     ident: ident,
     attrs: ~[attribute],
@@ -926,17 +825,17 @@ pub struct method {
     vis: visibility,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct _mod {
     view_items: ~[@view_item],
     items: ~[@item],
 }
 
 // Foreign mods can be named or anonymous
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum foreign_mod_sort { named, anonymous }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct foreign_mod {
     sort: foreign_mod_sort,
     abis: AbiSet,
@@ -944,24 +843,24 @@ pub struct foreign_mod {
     items: ~[@foreign_item],
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct variant_arg {
     ty: @Ty,
     id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum variant_kind {
     tuple_variant_kind(~[variant_arg]),
     struct_variant_kind(@struct_def),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct enum_def {
     variants: ~[variant],
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct variant_ {
     name: ident,
     attrs: ~[attribute],
@@ -973,7 +872,7 @@ pub struct variant_ {
 
 pub type variant = spanned<variant_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct path_list_ident_ {
     name: ident,
     id: node_id,
@@ -983,7 +882,7 @@ pub type path_list_ident = spanned<path_list_ident_>;
 
 pub type view_path = spanned<view_path_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum view_path_ {
 
     // quux = foo::bar::baz
@@ -1000,7 +899,7 @@ pub enum view_path_ {
     view_path_list(@Path, ~[path_list_ident], node_id)
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct view_item {
     node: view_item_,
     attrs: ~[attribute],
@@ -1008,7 +907,7 @@ pub struct view_item {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum view_item_ {
     view_item_extern_mod(ident, ~[@meta_item], node_id),
     view_item_use(~[@view_path]),
@@ -1020,11 +919,11 @@ pub type attribute = spanned<attribute_>;
 // Distinguishes between attributes that decorate items and attributes that
 // are contained as statements within items. These two cases need to be
 // distinguished for pretty-printing.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum attr_style { attr_outer, attr_inner, }
 
 // doc-comments are promoted to attributes that have is_sugared_doc = true
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct attribute_ {
     style: attr_style,
     value: @meta_item,
@@ -1038,13 +937,13 @@ pub struct attribute_ {
   If this impl is an item_impl, the impl_id is redundant (it could be the
   same as the impl's node id).
  */
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct trait_ref {
     path: @Path,
     ref_id: node_id,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum visibility { public, private, inherited }
 
 impl visibility {
@@ -1056,7 +955,7 @@ impl visibility {
     }
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct struct_field_ {
     kind: struct_field_kind,
     id: node_id,
@@ -1066,13 +965,13 @@ pub struct struct_field_ {
 
 pub type struct_field = spanned<struct_field_>;
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum struct_field_kind {
     named_field(ident, visibility),
     unnamed_field   // element of a tuple-like struct
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct struct_def {
     fields: ~[@struct_field], /* fields, not including ctor */
     /* ID of the constructor. This is only used for tuple- or enum-like
@@ -1084,7 +983,7 @@ pub struct struct_def {
   FIXME (#3300): Should allow items to be anonymous. Right now
   we just use dummy names for anon items.
  */
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct item {
     ident: ident,
     attrs: ~[attribute],
@@ -1094,7 +993,7 @@ pub struct item {
     span: span,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum item_ {
     item_static(@Ty, mutability, @expr),
     item_fn(fn_decl, purity, AbiSet, Generics, blk),
@@ -1112,7 +1011,7 @@ pub enum item_ {
     item_mac(mac),
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct foreign_item {
     ident: ident,
     attrs: ~[attribute],
@@ -1122,7 +1021,7 @@ pub struct foreign_item {
     vis: visibility,
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum foreign_item_ {
     foreign_item_fn(fn_decl, purity, Generics),
     foreign_item_static(@Ty, /* is_mutbl */ bool),
@@ -1131,7 +1030,7 @@ pub enum foreign_item_ {
 // The data we save and restore about an inlined item or method.  This is not
 // part of the AST that we parse from a file, but it becomes part of the tree
 // that we trans.
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub enum inlined_item {
     ii_item(@item),
     ii_method(def_id /* impl id */, @method),
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 6761736d2f3..9439f45be21 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -19,7 +19,6 @@ use visit;
 use std::hashmap::HashMap;
 use std::int;
 use std::option;
-use std::to_bytes;
 use std::cast;
 use std::local_data;
 
@@ -194,14 +193,6 @@ pub fn is_call_expr(e: @expr) -> bool {
     match e.node { expr_call(*) => true, _ => false }
 }
 
-// This makes def_id hashable
-impl to_bytes::IterBytes for def_id {
-    #[inline]
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.crate.iter_bytes(lsb0, f) && self.node.iter_bytes(lsb0, f)
-    }
-}
-
 pub fn block_from_expr(e: @expr) -> blk {
     let blk_ = default_block(~[], option::Some::<@expr>(e), e.id);
     return spanned {node: blk_, span: e.span};
@@ -544,18 +535,18 @@ pub fn walk_pat(pat: @pat, it: &fn(@pat) -> bool) -> bool {
     match pat.node {
         pat_ident(_, _, Some(p)) => walk_pat(p, it),
         pat_struct(_, ref fields, _) => {
-            fields.iter().advance(|f| walk_pat(f.pat, it))
+            fields.iter().advance(|f| walk_pat(f.pat, |p| it(p)))
         }
         pat_enum(_, Some(ref s)) | pat_tup(ref s) => {
-            s.iter().advance(|&p| walk_pat(p, it))
+            s.iter().advance(|&p| walk_pat(p, |p| it(p)))
         }
         pat_box(s) | pat_uniq(s) | pat_region(s) => {
             walk_pat(s, it)
         }
         pat_vec(ref before, ref slice, ref after) => {
-            before.iter().advance(|&p| walk_pat(p, it)) &&
-                slice.iter().advance(|&p| walk_pat(p, it)) &&
-                after.iter().advance(|&p| walk_pat(p, it))
+            before.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
+                slice.iter().advance(|&p| walk_pat(p, |p| it(p))) &&
+                after.iter().advance(|&p| walk_pat(p, |p| it(p)))
         }
         pat_wild | pat_lit(_) | pat_range(_, _) | pat_ident(_, _, _) |
         pat_enum(_, _) => {
@@ -704,7 +695,7 @@ pub fn new_sctable_internal() -> SCTable {
 pub fn get_sctable() -> @mut SCTable {
     unsafe {
         let sctable_key = (cast::transmute::<(uint, uint),
-                           &fn(v: @@mut SCTable)>(
+                           &fn:Copy(v: @@mut SCTable)>(
                                (-4 as uint, 0u)));
         match local_data::local_data_get(sctable_key) {
             None => {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 5efc96e16b5..bcf617c56ae 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -22,7 +22,6 @@ source code snippets, etc.
 */
 
 use std::cmp;
-use std::to_bytes;
 use std::uint;
 use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -32,12 +31,12 @@ pub trait Pos {
 }
 
 /// A byte offset
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct BytePos(uint);
 /// A character offset. Because of multibyte utf8 characters, a byte offset
 /// is not equivalent to a character offset. The CodeMap will convert BytePos
 /// values to CharPos values as necessary.
-#[deriving(Eq)]
+#[deriving(Eq,IterBytes)]
 pub struct CharPos(uint);
 
 // XXX: Lots of boilerplate in these impls, but so far my attempts to fix
@@ -67,12 +66,6 @@ impl Sub<BytePos, BytePos> for BytePos {
     }
 }
 
-impl to_bytes::IterBytes for BytePos {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (**self).iter_bytes(lsb0, f)
-    }
-}
-
 impl Pos for CharPos {
     fn from_uint(n: uint) -> CharPos { CharPos(n) }
     fn to_uint(&self) -> uint { **self }
@@ -85,12 +78,6 @@ impl cmp::Ord for CharPos {
     fn gt(&self, other: &CharPos) -> bool { **self > **other }
 }
 
-impl to_bytes::IterBytes for CharPos {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        (**self).iter_bytes(lsb0, f)
-    }
-}
-
 impl Add<CharPos,CharPos> for CharPos {
     fn add(&self, rhs: &CharPos) -> CharPos {
         CharPos(**self + **rhs)
@@ -109,13 +96,14 @@ are *absolute* positions from the beginning of the codemap, not positions
 relative to FileMaps. Methods on the CodeMap can be used to relate spans back
 to the original source.
 */
+#[deriving(IterBytes)]
 pub struct span {
     lo: BytePos,
     hi: BytePos,
     expn_info: Option<@ExpnInfo>
 }
 
-#[deriving(Eq, Encodable, Decodable)]
+#[deriving(Eq, Encodable, Decodable,IterBytes)]
 pub struct spanned<T> { node: T, span: span }
 
 impl cmp::Eq for span {
@@ -138,14 +126,6 @@ impl<D:Decoder> Decodable<D> for span {
     }
 }
 
-impl to_bytes::IterBytes for span {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.lo.iter_bytes(lsb0, f) &&
-        self.hi.iter_bytes(lsb0, f) &&
-        self.expn_info.iter_bytes(lsb0, f)
-    }
-}
-
 pub fn spanned<T>(lo: BytePos, hi: BytePos, t: T) -> spanned<T> {
     respan(mk_sp(lo, hi), t)
 }
@@ -191,40 +171,21 @@ pub struct LocWithOpt {
 // used to be structural records. Better names, anyone?
 pub struct FileMapAndLine {fm: @FileMap, line: uint}
 pub struct FileMapAndBytePos {fm: @FileMap, pos: BytePos}
+#[deriving(IterBytes)]
 pub struct NameAndSpan {name: @str, span: Option<span>}
 
-impl to_bytes::IterBytes for NameAndSpan {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.name.iter_bytes(lsb0, f) && self.span.iter_bytes(lsb0, f)
-    }
-}
-
+#[deriving(IterBytes)]
 pub struct CallInfo {
     call_site: span,
     callee: NameAndSpan
 }
 
-impl to_bytes::IterBytes for CallInfo {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.call_site.iter_bytes(lsb0, f) && self.callee.iter_bytes(lsb0, f)
-    }
-}
-
 /// Extra information for tracking macro expansion of spans
+#[deriving(IterBytes)]
 pub enum ExpnInfo {
     ExpandedFrom(CallInfo)
 }
 
-impl to_bytes::IterBytes for ExpnInfo {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        match *self {
-            ExpandedFrom(ref call_info) => {
-                0u8.iter_bytes(lsb0, f) && call_info.iter_bytes(lsb0, f)
-            }
-        }
-    }
-}
-
 pub type FileName = @str;
 
 pub struct FileLines
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 282a28ff9e0..78fdb99753d 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -509,7 +509,7 @@ impl <K: Eq + Hash + IterBytes ,V: Copy> MapChain<K,V>{
                 }
             },
             ConsMapChain (~ref mut map, rest) => {
-                if satisfies_pred(map,&n,pred) {
+                if satisfies_pred(map,&n,|v|pred(v)) {
                     map.insert(key,ext);
                 } else {
                     rest.insert_into_frame(key,ext,n,pred)
diff --git a/src/libsyntax/ext/deriving/iter_bytes.rs b/src/libsyntax/ext/deriving/iter_bytes.rs
index 8403234f892..15fb6ee9ff7 100644
--- a/src/libsyntax/ext/deriving/iter_bytes.rs
+++ b/src/libsyntax/ext/deriving/iter_bytes.rs
@@ -43,15 +43,21 @@ pub fn expand_deriving_iter_bytes(cx: @ExtCtxt,
 }
 
 fn iter_bytes_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
-    let lsb0_f = match substr.nonself_args {
-        [l, f] => ~[l, f],
+    let (lsb0, f)= match substr.nonself_args {
+        [l, f] => (l, f),
         _ => cx.span_bug(span, "Incorrect number of arguments in `deriving(IterBytes)`")
     };
+    // Build the "explicitly borrowed" stack closure, "|_buf| f(_buf)".
+    let blk_arg = cx.ident_of("_buf");
+    let borrowed_f =
+        cx.lambda_expr_1(span, cx.expr_call(span, f, ~[cx.expr_ident(span, blk_arg)]),
+                         blk_arg);
+
     let iter_bytes_ident = substr.method_ident;
     let call_iterbytes = |thing_expr| {
         cx.expr_method_call(span,
                               thing_expr, iter_bytes_ident,
-                              copy lsb0_f)
+                              ~[lsb0, borrowed_f])
     };
     let mut exprs = ~[];
     let fields;
diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs
index dfbc028ddf6..19aa29a62a9 100644
--- a/src/libsyntax/ext/deriving/rand.rs
+++ b/src/libsyntax/ext/deriving/rand.rs
@@ -99,7 +99,7 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr {
                     (ident, ref summary) => {
                         cx.arm(span,
                                ~[ pat ],
-                               rand_thing(cx, span, ident, summary, rand_call))
+                               rand_thing(cx, span, ident, summary, || rand_call()))
                     }
                 }
             };
diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs
index fe050fc99f1..bf8c5ae462b 100644
--- a/src/libsyntax/opt_vec.rs
+++ b/src/libsyntax/opt_vec.rs
@@ -18,7 +18,7 @@
 
 use std::vec::VecIterator;
 
-#[deriving(Encodable, Decodable)]
+#[deriving(Encodable, Decodable,IterBytes)]
 pub enum OptVec<T> {
     Empty,
     Vec(~[T])
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 793626f0e18..94147825da4 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -22,7 +22,7 @@ use std::local_data;
 use std::rand;
 use std::rand::RngUtil;
 
-#[deriving(Encodable, Decodable, Eq)]
+#[deriving(Encodable, Decodable, Eq, IterBytes)]
 pub enum binop {
     PLUS,
     MINUS,
@@ -36,7 +36,7 @@ pub enum binop {
     SHR,
 }
 
-#[deriving(Encodable, Decodable, Eq)]
+#[deriving(Encodable, Decodable, Eq, IterBytes)]
 pub enum Token {
     /* Expression-operator symbols. */
     EQ,
@@ -97,7 +97,7 @@ pub enum Token {
     EOF,
 }
 
-#[deriving(Encodable, Decodable, Eq)]
+#[deriving(Encodable, Decodable, Eq, IterBytes)]
 /// For interpolation during macro expansion.
 pub enum nonterminal {
     nt_item(@ast::item),
@@ -484,7 +484,7 @@ pub fn get_ident_interner() -> @ident_interner {
     unsafe {
         let key =
             (cast::transmute::<(uint, uint),
-             &fn(v: @@::parse::token::ident_interner)>(
+             &fn:Copy(v: @@::parse::token::ident_interner)>(
                  (-3 as uint, 0u)));
         match local_data::local_data_get(key) {
             Some(interner) => *interner,
diff --git a/src/test/compile-fail/kindck-owned.rs b/src/test/compile-fail/kindck-owned.rs
index 3f859b7dc84..848fd95a560 100644
--- a/src/test/compile-fail/kindck-owned.rs
+++ b/src/test/compile-fail/kindck-owned.rs
@@ -29,6 +29,6 @@ fn main() {
     copy2(boxed);
     let owned: ~fn() = || {};
     copy2(owned);    //~ ERROR does not fulfill `Copy`
-    let borrowed: &fn() = || {};
+    let borrowed: &fn:Copy() = || {};
     copy2(borrowed); //~ ERROR does not fulfill `'static`
 }
diff --git a/src/test/compile-fail/regions-creating-enums.rs b/src/test/compile-fail/regions-creating-enums.rs
index 2ab0c14b49b..c2d8427d5eb 100644
--- a/src/test/compile-fail/regions-creating-enums.rs
+++ b/src/test/compile-fail/regions-creating-enums.rs
@@ -33,8 +33,8 @@ fn map_nums(x: &ast, f: &fn(uint) -> uint) -> &ast {
         return &num(f(x)); //~ ERROR borrowed value does not live long enough
       }
       add(x, y) => {
-        let m_x = map_nums(x, f);
-        let m_y = map_nums(y, f);
+        let m_x = map_nums(x, |z| f(z));
+        let m_y = map_nums(y, |z| f(z));
         return &add(m_x, m_y);  //~ ERROR borrowed value does not live long enough
       }
     }
diff --git a/src/test/compile-fail/the-case-of-the-recurring-closure-2.rs b/src/test/compile-fail/the-case-of-the-recurring-closure-2.rs
new file mode 100644
index 00000000000..bfb1e910495
--- /dev/null
+++ b/src/test/compile-fail/the-case-of-the-recurring-closure-2.rs
@@ -0,0 +1,44 @@
+// 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.
+
+// Tests correct kind-checking of the reason stack closures without the :Copy
+// bound must be noncopyable. For details see
+// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
+
+struct R<'self> {
+    // This struct is needed to create the
+    // otherwise infinite type of a fn that
+    // accepts itself as argument:
+    c: &'self fn:Copy(&R, bool)
+}
+
+fn innocent_looking_victim() {
+    let mut x = Some(~"hello");
+    do conspirator |f, writer| {
+        if writer {
+            x = None; //~ ERROR cannot implicitly borrow
+        } else {
+            match x {
+                Some(ref msg) => {
+                    (f.c)(f, true);
+                    println(fmt!("%?", msg));
+                },
+                None => fail!("oops"),
+            }
+        }
+    }
+}
+
+fn conspirator(f: &fn:Copy(&R, bool)) {
+    let r = R {c: f};
+    f(&r, false)
+}
+
+fn main() { innocent_looking_victim() }
diff --git a/src/test/compile-fail/the-case-of-the-recurring-closure.rs b/src/test/compile-fail/the-case-of-the-recurring-closure.rs
new file mode 100644
index 00000000000..f05c30c3355
--- /dev/null
+++ b/src/test/compile-fail/the-case-of-the-recurring-closure.rs
@@ -0,0 +1,44 @@
+// 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.
+
+// Tests correct kind-checking of the reason stack closures without the :Copy
+// bound must be noncopyable. For details see
+// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/
+
+struct R<'self> {
+    // This struct is needed to create the
+    // otherwise infinite type of a fn that
+    // accepts itself as argument:
+    c: &'self fn(&R, bool)
+}
+
+fn innocent_looking_victim() {
+    let mut x = Some(~"hello");
+    do conspirator |f, writer| {
+        if writer {
+            x = None;
+        } else {
+            match x {
+                Some(ref msg) => {
+                    (f.c)(f, true);
+                    println(fmt!("%?", msg));
+                },
+                None => fail!("oops"),
+            }
+        }
+    }
+}
+
+fn conspirator(f: &fn(&R, bool)) {
+    let r = R {c: f};
+    f(&r, false) //~ ERROR use of moved value
+}
+
+fn main() { innocent_looking_victim() }