From 1195708f64f34f6c402f98f5b551e2567be731c9 Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <japaricious@gmail.com>
Date: Mon, 8 Dec 2014 20:26:43 -0500
Subject: [PATCH] librustc: use unboxed closures

---
 src/librustc/lint/context.rs                  | 12 ++-
 src/librustc/metadata/csearch.rs              | 62 ++++++++------
 src/librustc/metadata/cstore.rs               | 10 ++-
 src/librustc/metadata/decoder.rs              | 73 +++++++++-------
 src/librustc/metadata/encoder.rs              | 10 ++-
 src/librustc/metadata/filesearch.rs           |  4 +-
 src/librustc/metadata/tydecode.rs             | 21 +++--
 src/librustc/metadata/tyencode.rs             | 14 ++--
 src/librustc/middle/astencode.rs              | 28 ++++---
 src/librustc/middle/check_const.rs            | 12 ++-
 src/librustc/middle/check_loop.rs             |  4 +-
 src/librustc/middle/check_match.rs            |  4 +-
 src/librustc/middle/check_static.rs           |  4 +-
 src/librustc/middle/dataflow.rs               | 24 +++---
 src/librustc/middle/def.rs                    |  4 +-
 src/librustc/middle/graph.rs                  | 46 +++++-----
 src/librustc/middle/infer/coercion.rs         | 21 +++--
 .../middle/infer/higher_ranked/mod.rs         |  8 +-
 src/librustc/middle/infer/mod.rs              | 84 ++++++++++++-------
 .../middle/infer/region_inference/mod.rs      | 24 +++---
 src/librustc/middle/infer/skolemize.rs        | 11 +--
 src/librustc/middle/liveness.rs               | 44 +++++-----
 src/librustc/middle/mem_categorization.rs     |  5 +-
 src/librustc/middle/pat_util.rs               |  6 +-
 src/librustc/middle/region.rs                 |  4 +-
 src/librustc/middle/resolve.rs                | 44 ++++++----
 src/librustc/middle/resolve_lifetime.rs       | 18 ++--
 src/librustc/middle/stability.rs              |  4 +-
 src/librustc/middle/subst.rs                  | 15 ++--
 src/librustc/middle/traits/mod.rs             | 13 ++-
 src/librustc/middle/traits/util.rs            |  9 +-
 src/librustc/middle/ty.rs                     | 82 +++++++++++-------
 src/librustc/middle/ty_fold.rs                | 21 +++--
 src/librustc/util/common.rs                   | 46 ++++++----
 src/librustc_borrowck/borrowck/check_loans.rs | 24 +++---
 src/librustc_borrowck/borrowck/move_data.rs   | 42 +++++-----
 src/librustc_borrowck/graphviz.rs             | 18 ++--
 37 files changed, 517 insertions(+), 358 deletions(-)

diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 153a00e5617..9f9e266c6c7 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -464,9 +464,11 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
-    fn with_lint_attrs(&mut self,
-                       attrs: &[ast::Attribute],
-                       f: |&mut Context|) {
+    fn with_lint_attrs<F>(&mut self,
+                          attrs: &[ast::Attribute],
+                          f: F) where
+        F: FnOnce(&mut Context),
+    {
         // Parse all of the lint attributes, and then add them all to the
         // current dictionary of lint information. Along the way, keep a history
         // of what we changed so we can roll everything back after invoking the
@@ -528,7 +530,9 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
         }
     }
 
-    fn visit_ids(&mut self, f: |&mut ast_util::IdVisitor<Context>|) {
+    fn visit_ids<F>(&mut self, f: F) where
+        F: FnOnce(&mut ast_util::IdVisitor<Context>)
+    {
         let mut v = ast_util::IdVisitor {
             operation: self,
             pass_through_items: false,
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 7ce9893afc8..4cbb1babf9a 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -47,20 +47,22 @@ pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> String {
 }
 
 /// Iterates over all the language items in the given crate.
-pub fn each_lang_item(cstore: &cstore::CStore,
-                      cnum: ast::CrateNum,
-                      f: |ast::NodeId, uint| -> bool)
-                      -> bool {
+pub fn each_lang_item<F>(cstore: &cstore::CStore,
+                         cnum: ast::CrateNum,
+                         f: F)
+                         -> bool where
+    F: FnMut(ast::NodeId, uint) -> bool,
+{
     let crate_data = cstore.get_crate_data(cnum);
     decoder::each_lang_item(&*crate_data, f)
 }
 
 /// Iterates over each child of the given item.
-pub fn each_child_of_item(cstore: &cstore::CStore,
-                          def_id: ast::DefId,
-                          callback: |decoder::DefLike,
-                                     ast::Name,
-                                     ast::Visibility|) {
+pub fn each_child_of_item<F>(cstore: &cstore::CStore,
+                             def_id: ast::DefId,
+                             callback: F) where
+    F: FnMut(decoder::DefLike, ast::Name, ast::Visibility),
+{
     let crate_data = cstore.get_crate_data(def_id.krate);
     let get_crate_data: decoder::GetCrateDataCb = |cnum| {
         cstore.get_crate_data(cnum)
@@ -73,11 +75,11 @@ pub fn each_child_of_item(cstore: &cstore::CStore,
 }
 
 /// Iterates over each top-level crate item.
-pub fn each_top_level_item_of_crate(cstore: &cstore::CStore,
-                                    cnum: ast::CrateNum,
-                                    callback: |decoder::DefLike,
-                                               ast::Name,
-                                               ast::Visibility|) {
+pub fn each_top_level_item_of_crate<F>(cstore: &cstore::CStore,
+                                       cnum: ast::CrateNum,
+                                       callback: F) where
+    F: FnMut(decoder::DefLike, ast::Name, ast::Visibility),
+{
     let crate_data = cstore.get_crate_data(cnum);
     let get_crate_data: decoder::GetCrateDataCb = |cnum| {
         cstore.get_crate_data(cnum)
@@ -195,9 +197,11 @@ pub fn get_methods_if_impl(cstore: &cstore::CStore,
     decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.node)
 }
 
-pub fn get_item_attrs(cstore: &cstore::CStore,
-                      def_id: ast::DefId,
-                      f: |Vec<ast::Attribute>|) {
+pub fn get_item_attrs<F>(cstore: &cstore::CStore,
+                         def_id: ast::DefId,
+                         f: F) where
+    F: FnOnce(Vec<ast::Attribute>),
+{
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::get_item_attrs(&*cdata, def_id.node, f)
 }
@@ -279,23 +283,29 @@ pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
     decoder::get_native_libraries(&*cdata)
 }
 
-pub fn each_impl(cstore: &cstore::CStore,
-                 crate_num: ast::CrateNum,
-                 callback: |ast::DefId|) {
+pub fn each_impl<F>(cstore: &cstore::CStore,
+                    crate_num: ast::CrateNum,
+                    callback: F) where
+    F: FnMut(ast::DefId),
+{
     let cdata = cstore.get_crate_data(crate_num);
     decoder::each_impl(&*cdata, callback)
 }
 
-pub fn each_implementation_for_type(cstore: &cstore::CStore,
-                                    def_id: ast::DefId,
-                                    callback: |ast::DefId|) {
+pub fn each_implementation_for_type<F>(cstore: &cstore::CStore,
+                                       def_id: ast::DefId,
+                                       callback: F) where
+    F: FnMut(ast::DefId),
+{
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::each_implementation_for_type(&*cdata, def_id.node, callback)
 }
 
-pub fn each_implementation_for_trait(cstore: &cstore::CStore,
-                                     def_id: ast::DefId,
-                                     callback: |ast::DefId|) {
+pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
+                                        def_id: ast::DefId,
+                                        callback: F) where
+    F: FnMut(ast::DefId),
+{
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
 }
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index bb1c75b075c..c0642f29abc 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -113,16 +113,18 @@ impl CStore {
         self.metas.borrow_mut().insert(cnum, data);
     }
 
-    pub fn iter_crate_data(&self, i: |ast::CrateNum, &crate_metadata|) {
+    pub fn iter_crate_data<I>(&self, mut i: I) where
+        I: FnMut(ast::CrateNum, &crate_metadata),
+    {
         for (&k, v) in self.metas.borrow().iter() {
             i(k, &**v);
         }
     }
 
     /// Like `iter_crate_data`, but passes source paths (if available) as well.
-    pub fn iter_crate_data_origins(&self, i: |ast::CrateNum,
-                                              &crate_metadata,
-                                              Option<CrateSource>|) {
+    pub fn iter_crate_data_origins<I>(&self, mut i: I) where
+        I: FnMut(ast::CrateNum, &crate_metadata, Option<CrateSource>),
+    {
         for (&k, v) in self.metas.borrow().iter() {
             let origin = self.get_used_crate_source(k);
             origin.as_ref().map(|cs| { assert!(k == cs.cnum); });
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 2000c4e1abe..4e892f53186 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -60,8 +60,9 @@ pub type Cmd<'a> = &'a crate_metadata;
 // what crate that's in and give us a def_id that makes sense for the current
 // build.
 
-fn lookup_hash<'a>(d: rbml::Doc<'a>, eq_fn: |&[u8]| -> bool,
-                   hash: u64) -> Option<rbml::Doc<'a>> {
+fn lookup_hash<'a, F>(d: rbml::Doc<'a>, mut eq_fn: F, hash: u64) -> Option<rbml::Doc<'a>> where
+    F: FnMut(&[u8]) -> bool,
+{
     let index = reader::get_doc(d, tag_index);
     let table = reader::get_doc(index, tag_index_table);
     let hash_pos = table.start + (hash % 256 * 4) as uint;
@@ -448,7 +449,9 @@ pub enum DefLike {
 impl Copy for DefLike {}
 
 /// Iterates over the language items in the given crate.
-pub fn each_lang_item(cdata: Cmd, f: |ast::NodeId, uint| -> bool) -> bool {
+pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
+    F: FnMut(ast::NodeId, uint) -> bool,
+{
     let root = rbml::Doc::new(cdata.data());
     let lang_items = reader::get_doc(root, tag_lang_items);
     reader::tagged_docs(lang_items, tag_lang_items_item, |item_doc| {
@@ -464,13 +467,13 @@ pub fn each_lang_item(cdata: Cmd, f: |ast::NodeId, uint| -> bool) -> bool {
 
 pub type GetCrateDataCb<'a> = |ast::CrateNum|: 'a -> Rc<crate_metadata>;
 
-fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
-                               cdata: Cmd,
-                               item_doc: rbml::Doc,
-                               get_crate_data: GetCrateDataCb,
-                               callback: |DefLike,
-                                          ast::Name,
-                                          ast::Visibility|) {
+fn each_child_of_item_or_crate<F>(intr: Rc<IdentInterner>,
+                                  cdata: Cmd,
+                                  item_doc: rbml::Doc,
+                                  get_crate_data: GetCrateDataCb,
+                                  mut callback: F) where
+    F: FnMut(DefLike, ast::Name, ast::Visibility),
+{
     // Iterate over all children.
     let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| {
         let child_def_id = reader::with_doc_data(child_info_doc,
@@ -583,11 +586,13 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
 }
 
 /// Iterates over each child of the given item.
-pub fn each_child_of_item(intr: Rc<IdentInterner>,
-                          cdata: Cmd,
-                          id: ast::NodeId,
-                          get_crate_data: GetCrateDataCb,
-                          callback: |DefLike, ast::Name, ast::Visibility|) {
+pub fn each_child_of_item<F>(intr: Rc<IdentInterner>,
+                             cdata: Cmd,
+                             id: ast::NodeId,
+                             get_crate_data: GetCrateDataCb,
+                             callback: F) where
+    F: FnMut(DefLike, ast::Name, ast::Visibility),
+{
     // Find the item.
     let root_doc = rbml::Doc::new(cdata.data());
     let items = reader::get_doc(root_doc, tag_items);
@@ -604,12 +609,12 @@ pub fn each_child_of_item(intr: Rc<IdentInterner>,
 }
 
 /// Iterates over all the top-level crate items.
-pub fn each_top_level_item_of_crate(intr: Rc<IdentInterner>,
-                                    cdata: Cmd,
-                                    get_crate_data: GetCrateDataCb,
-                                    callback: |DefLike,
-                                               ast::Name,
-                                               ast::Visibility|) {
+pub fn each_top_level_item_of_crate<F>(intr: Rc<IdentInterner>,
+                                       cdata: Cmd,
+                                       get_crate_data: GetCrateDataCb,
+                                       callback: F) where
+    F: FnMut(DefLike, ast::Name, ast::Visibility),
+{
     let root_doc = rbml::Doc::new(cdata.data());
     let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
     let crate_items_doc = reader::get_doc(misc_info_doc,
@@ -982,9 +987,11 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
     ret
 }
 
-pub fn get_item_attrs(cdata: Cmd,
-                      orig_node_id: ast::NodeId,
-                      f: |Vec<ast::Attribute>|) {
+pub fn get_item_attrs<F>(cdata: Cmd,
+                         orig_node_id: ast::NodeId,
+                         f: F) where
+    F: FnOnce(Vec<ast::Attribute>),
+{
     // The attributes for a tuple struct are attached to the definition, not the ctor;
     // we assume that someone passing in a tuple struct ctor is actually wanting to
     // look at the definition
@@ -1224,7 +1231,9 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
     }
 }
 
-pub fn each_impl(cdata: Cmd, callback: |ast::DefId|) {
+pub fn each_impl<F>(cdata: Cmd, mut callback: F) where
+    F: FnMut(ast::DefId),
+{
     let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
     let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| {
         callback(item_def_id(impl_doc, cdata));
@@ -1232,9 +1241,11 @@ pub fn each_impl(cdata: Cmd, callback: |ast::DefId|) {
     });
 }
 
-pub fn each_implementation_for_type(cdata: Cmd,
+pub fn each_implementation_for_type<F>(cdata: Cmd,
                                     id: ast::NodeId,
-                                    callback: |ast::DefId|) {
+                                    mut callback: F) where
+    F: FnMut(ast::DefId),
+{
     let item_doc = lookup_item(id, cdata.data());
     reader::tagged_docs(item_doc,
                         tag_items_data_item_inherent_impl,
@@ -1245,9 +1256,11 @@ pub fn each_implementation_for_type(cdata: Cmd,
     });
 }
 
-pub fn each_implementation_for_trait(cdata: Cmd,
-                                     id: ast::NodeId,
-                                     callback: |ast::DefId|) {
+pub fn each_implementation_for_trait<F>(cdata: Cmd,
+                                        id: ast::NodeId,
+                                        mut callback: F) where
+    F: FnMut(ast::DefId),
+{
     let item_doc = lookup_item(id, cdata.data());
 
     let _ = reader::tagged_docs(item_doc,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 48d1284f507..9804e3c20aa 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -493,7 +493,9 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
 /// top-level items that are sub-items of the given item. Specifically:
 ///
 /// * For newtype structs, iterates through the node ID of the constructor.
-fn each_auxiliary_node_id(item: &ast::Item, callback: |NodeId| -> bool) -> bool {
+fn each_auxiliary_node_id<F>(item: &ast::Item, callback: F) -> bool where
+    F: FnOnce(NodeId) -> bool,
+{
     let mut continue_ = true;
     match item.node {
         ast::ItemStruct(ref struct_def, _) => {
@@ -1579,8 +1581,10 @@ fn encode_info_for_items(ecx: &EncodeContext,
 
 // Path and definition ID indexing
 
-fn encode_index<T: Hash>(rbml_w: &mut Encoder, index: Vec<entry<T>>,
-                         write_fn: |&mut SeekableMemWriter, &T|) {
+fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
+    F: FnMut(&mut SeekableMemWriter, &T),
+    T: Hash,
+{
     let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
     for elt in index.into_iter() {
         let h = hash::hash(&elt.val) as uint;
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 2d23a61813a..507fb751303 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -42,7 +42,9 @@ pub struct FileSearch<'a> {
 }
 
 impl<'a> FileSearch<'a> {
-    pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
+    pub fn for_each_lib_search_path<F>(&self, mut f: F) where
+        F: FnMut(&Path) -> FileMatch,
+    {
         let mut visited_dirs = HashSet::new();
         let mut found = false;
 
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 37d790df37f..7358b3bc9c9 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -89,7 +89,10 @@ fn next_byte(st: &mut PState) -> u8 {
     return b;
 }
 
-fn scan<R>(st: &mut PState, is_last: |char| -> bool, op: |&[u8]| -> R) -> R {
+fn scan<R, F, G>(st: &mut PState, mut is_last: F, op: G) -> R where
+    F: FnMut(char) -> bool,
+    G: FnOnce(&[u8]) -> R,
+{
     let start_pos = st.pos;
     debug!("scan: '{}' (start)", st.data[st.pos] as char);
     while !is_last(st.data[st.pos] as char) {
@@ -110,7 +113,9 @@ pub fn parse_name(st: &mut PState, last: char) -> ast::Name {
     parse_name_(st, |a| is_last(last, a) )
 }
 
-fn parse_name_(st: &mut PState, is_last: |char| -> bool) -> ast::Name {
+fn parse_name_<F>(st: &mut PState, is_last: F) -> ast::Name where
+    F: FnMut(char) -> bool,
+{
     scan(st, is_last, |bytes| {
         token::intern(str::from_utf8(bytes).unwrap())
     })
@@ -234,9 +239,10 @@ fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
     }
 }
 
-fn parse_vec_per_param_space<'a, 'tcx, T>(st: &mut PState<'a, 'tcx>,
-                                          f: |&mut PState<'a, 'tcx>| -> T)
-                                          -> VecPerParamSpace<T>
+fn parse_vec_per_param_space<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>,
+                                             mut f: F)
+                                             -> VecPerParamSpace<T> where
+    F: FnMut(&mut PState<'a, 'tcx>) -> T,
 {
     let mut r = VecPerParamSpace::empty();
     for &space in subst::ParamSpace::all().iter() {
@@ -350,8 +356,9 @@ fn parse_scope(st: &mut PState) -> region::CodeExtent {
     }
 }
 
-fn parse_opt<'a, 'tcx, T>(st: &mut PState<'a, 'tcx>, f: |&mut PState<'a, 'tcx>| -> T)
-                          -> Option<T> {
+fn parse_opt<'a, 'tcx, T, F>(st: &mut PState<'a, 'tcx>, f: F) -> Option<T> where
+    F: FnOnce(&mut PState<'a, 'tcx>) -> T,
+{
     match next(st) {
       'n' => None,
       's' => Some(f(st)),
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 5c7d15e1601..54376cd7b90 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -86,7 +86,9 @@ fn enc_mt<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
     enc_ty(w, cx, mt.ty);
 }
 
-fn enc_opt<T>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: |&mut SeekableMemWriter, T|) {
+fn enc_opt<T, F>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: F) where
+    F: FnOnce(&mut SeekableMemWriter, T),
+{
     match t {
         None => mywrite!(w, "n"),
         Some(v) => {
@@ -96,10 +98,12 @@ fn enc_opt<T>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: |&mut SeekableMemW
     }
 }
 
-fn enc_vec_per_param_space<'a, 'tcx, T>(w: &mut SeekableMemWriter,
-                                        cx: &ctxt<'a, 'tcx>,
-                                        v: &VecPerParamSpace<T>,
-                                        op: |&mut SeekableMemWriter, &ctxt<'a, 'tcx>, &T|) {
+fn enc_vec_per_param_space<'a, 'tcx, T, F>(w: &mut SeekableMemWriter,
+                                           cx: &ctxt<'a, 'tcx>,
+                                           v: &VecPerParamSpace<T>,
+                                           mut op: F) where
+    F: FnMut(&mut SeekableMemWriter, &ctxt<'a, 'tcx>, &T),
+{
     for &space in subst::ParamSpace::all().iter() {
         mywrite!(w, "[");
         for t in v.get_slice(space).iter() {
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 50337ec25bd..26d70502a5b 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -680,9 +680,8 @@ pub fn encode_unboxed_closure_kind(ebml_w: &mut Encoder,
 }
 
 pub trait vtable_decoder_helpers<'tcx> {
-    fn read_vec_per_param_space<T>(&mut self,
-                                   f: |&mut Self| -> T)
-                                   -> VecPerParamSpace<T>;
+    fn read_vec_per_param_space<T, F>(&mut self, f: F) -> VecPerParamSpace<T> where
+        F: FnMut(&mut Self) -> T;
     fn read_vtable_res_with_key(&mut self,
                                 tcx: &ty::ctxt<'tcx>,
                                 cdata: &cstore::crate_metadata)
@@ -699,9 +698,8 @@ pub trait vtable_decoder_helpers<'tcx> {
 }
 
 impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
-    fn read_vec_per_param_space<T>(&mut self,
-                                   f: |&mut reader::Decoder<'a>| -> T)
-                                   -> VecPerParamSpace<T>
+    fn read_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
+        F: FnMut(&mut reader::Decoder<'a>) -> T,
     {
         let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
         let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
@@ -793,9 +791,11 @@ impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
 // ___________________________________________________________________________
 //
 
-fn encode_vec_per_param_space<T>(rbml_w: &mut Encoder,
-                                 v: &subst::VecPerParamSpace<T>,
-                                 f: |&mut Encoder, &T|) {
+fn encode_vec_per_param_space<T, F>(rbml_w: &mut Encoder,
+                                    v: &subst::VecPerParamSpace<T>,
+                                    mut f: F) where
+    F: FnMut(&mut Encoder, &T),
+{
     for &space in subst::ParamSpace::all().iter() {
         rbml_w.emit_from_vec(v.get_slice(space),
                              |rbml_w, n| Ok(f(rbml_w, n))).unwrap();
@@ -1124,14 +1124,16 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
 }
 
 trait write_tag_and_id {
-    fn tag(&mut self, tag_id: c::astencode_tag, f: |&mut Self|);
+    fn tag<F>(&mut self, tag_id: c::astencode_tag, f: F) where F: FnOnce(&mut Self);
     fn id(&mut self, id: ast::NodeId);
 }
 
 impl<'a> write_tag_and_id for Encoder<'a> {
-    fn tag(&mut self,
-           tag_id: c::astencode_tag,
-           f: |&mut Encoder<'a>|) {
+    fn tag<F>(&mut self,
+              tag_id: c::astencode_tag,
+              f: F) where
+        F: FnOnce(&mut Encoder<'a>),
+    {
         self.start_tag(tag_id as uint);
         f(self);
         self.end_tag();
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index de140fd5c30..a91ea8bfef8 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -24,16 +24,22 @@ struct CheckCrateVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
-    fn with_const(&mut self, in_const: bool, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
+    fn with_const<F>(&mut self, in_const: bool, f: F) where
+        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
+    {
         let was_const = self.in_const;
         self.in_const = in_const;
         f(self);
         self.in_const = was_const;
     }
-    fn inside_const(&mut self, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
+    fn inside_const<F>(&mut self, f: F) where
+        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
+    {
         self.with_const(true, f);
     }
-    fn outside_const(&mut self, f: |&mut CheckCrateVisitor<'a, 'tcx>|) {
+    fn outside_const<F>(&mut self, f: F) where
+        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
+    {
         self.with_const(false, f);
     }
 }
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index eb073e07b02..fee2d810fcb 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -64,7 +64,9 @@ impl<'a, 'v> Visitor<'v> for CheckLoopVisitor<'a> {
 }
 
 impl<'a> CheckLoopVisitor<'a> {
-    fn with_context(&mut self, cx: Context, f: |&mut CheckLoopVisitor<'a>|) {
+    fn with_context<F>(&mut self, cx: Context, f: F) where
+        F: FnOnce(&mut CheckLoopVisitor<'a>),
+    {
         let old_cx = self.cx;
         self.cx = cx;
         f(self);
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 2c437ae046b..ea3ef2af739 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -980,7 +980,9 @@ fn check_fn(cx: &mut MatchCheckCtxt,
     }
 }
 
-fn is_refutable<A>(cx: &MatchCheckCtxt, pat: &Pat, refutable: |&Pat| -> A) -> Option<A> {
+fn is_refutable<A, F>(cx: &MatchCheckCtxt, pat: &Pat, refutable: F) -> Option<A> where
+    F: FnOnce(&Pat) -> A,
+{
     let pats = Matrix(vec!(vec!(pat)));
     match is_useful(cx, &pats, &[DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 5a53979d719..65412ff8eff 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -85,7 +85,9 @@ pub fn check_crate(tcx: &ty::ctxt) {
 }
 
 impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
-    fn with_mode(&mut self, mode: Mode, f: |&mut CheckStaticVisitor<'a, 'tcx>|) {
+    fn with_mode<F>(&mut self, mode: Mode, f: F) where
+        F: FnOnce(&mut CheckStaticVisitor<'a, 'tcx>),
+    {
         let old = self.mode;
         self.mode = mode;
         f(self);
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index db8fd999f38..9373a5704b2 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -280,10 +280,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
     }
 
 
-    pub fn each_bit_on_entry(&self,
-                             id: ast::NodeId,
-                             f: |uint| -> bool)
-                             -> bool {
+    pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, f: F) -> bool where
+        F: FnMut(uint) -> bool,
+    {
         //! Iterates through each bit that is set on entry to `id`.
         //! Only useful after `propagate()` has been called.
         if !self.has_bitset_for_nodeid(id) {
@@ -293,11 +292,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
         self.each_bit_for_node(Entry, cfgidx, f)
     }
 
-    pub fn each_bit_for_node(&self,
-                             e: EntryOrExit,
-                             cfgidx: CFGIndex,
-                             f: |uint| -> bool)
-                             -> bool {
+    pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where
+        F: FnMut(uint) -> bool,
+    {
         //! Iterates through each bit that is set on entry/exit to `cfgidx`.
         //! Only useful after `propagate()` has been called.
 
@@ -324,8 +321,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
         self.each_bit(slice, f)
     }
 
-    pub fn each_gen_bit(&self, id: ast::NodeId, f: |uint| -> bool)
-                        -> bool {
+    pub fn each_gen_bit<F>(&self, id: ast::NodeId, f: F) -> bool where
+        F: FnMut(uint) -> bool,
+    {
         //! Iterates through each bit in the gen set for `id`.
         if !self.has_bitset_for_nodeid(id) {
             return true;
@@ -345,7 +343,9 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
         self.each_bit(gens, f)
     }
 
-    fn each_bit(&self, words: &[uint], f: |uint| -> bool) -> bool {
+    fn each_bit<F>(&self, words: &[uint], mut f: F) -> bool where
+        F: FnMut(uint) -> bool,
+    {
         //! Helper for iterating over the bits in a bit set.
         //! Returns false on the first call to `f` that returns false;
         //! if all calls to `f` return true, then returns true.
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index b3e4dd25adc..ca60ac45e26 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -61,7 +61,9 @@ pub enum MethodProvenance {
 }
 
 impl MethodProvenance {
-    pub fn map(self, f: |ast::DefId| -> ast::DefId) -> MethodProvenance {
+    pub fn map<F>(self, f: F) -> MethodProvenance where
+        F: FnOnce(ast::DefId) -> ast::DefId,
+    {
         match self {
             FromTrait(did) => FromTrait(f(did)),
             FromImpl(did) => FromImpl(f(did))
diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs
index e45232a3c30..4c03ed2a480 100644
--- a/src/librustc/middle/graph.rs
+++ b/src/librustc/middle/graph.rs
@@ -221,39 +221,43 @@ impl<N,E> Graph<N,E> {
     ///////////////////////////////////////////////////////////////////////////
     // Iterating over nodes, edges
 
-    pub fn each_node<'a>(&'a self, f: |NodeIndex, &'a Node<N>| -> bool) -> bool {
+    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool where
+        F: FnMut(NodeIndex, &'a Node<N>) -> bool,
+    {
         //! Iterates over all edges defined in the graph.
         self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node))
     }
 
-    pub fn each_edge<'a>(&'a self, f: |EdgeIndex, &'a Edge<E>| -> bool) -> bool {
+    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool where
+        F: FnMut(EdgeIndex, &'a Edge<E>) -> bool,
+    {
         //! Iterates over all edges defined in the graph
         self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge))
     }
 
-    pub fn each_outgoing_edge<'a>(&'a self,
-                                  source: NodeIndex,
-                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
-                                  -> bool {
+    pub fn each_outgoing_edge<'a, F>(&'a self, source: NodeIndex, f: F) -> bool where
+        F: FnMut(EdgeIndex, &'a Edge<E>) -> bool,
+    {
         //! Iterates over all outgoing edges from the node `from`
 
         self.each_adjacent_edge(source, Outgoing, f)
     }
 
-    pub fn each_incoming_edge<'a>(&'a self,
-                                  target: NodeIndex,
-                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
-                                  -> bool {
+    pub fn each_incoming_edge<'a, F>(&'a self, target: NodeIndex, f: F) -> bool where
+        F: FnMut(EdgeIndex, &'a Edge<E>) -> bool,
+    {
         //! Iterates over all incoming edges to the node `target`
 
         self.each_adjacent_edge(target, Incoming, f)
     }
 
-    pub fn each_adjacent_edge<'a>(&'a self,
-                                  node: NodeIndex,
-                                  dir: Direction,
-                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
-                                  -> bool {
+    pub fn each_adjacent_edge<'a, F>(&'a self,
+                                     node: NodeIndex,
+                                     dir: Direction,
+                                     mut f: F)
+                                     -> bool where
+        F: FnMut(EdgeIndex, &'a Edge<E>) -> bool,
+    {
         //! Iterates over all edges adjacent to the node `node`
         //! in the direction `dir` (either `Outgoing` or `Incoming)
 
@@ -277,11 +281,9 @@ impl<N,E> Graph<N,E> {
     // variables or other bitsets. This method facilitates such a
     // computation.
 
-    pub fn iterate_until_fixed_point<'a>(&'a self,
-                                         op: |iter_index: uint,
-                                              edge_index: EdgeIndex,
-                                              edge: &'a Edge<E>|
-                                              -> bool) {
+    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F) where
+        F: FnMut(uint, EdgeIndex, &'a Edge<E>) -> bool,
+    {
         let mut iteration = 0;
         let mut changed = true;
         while changed {
@@ -294,7 +296,9 @@ impl<N,E> Graph<N,E> {
     }
 }
 
-pub fn each_edge_index(max_edge_index: EdgeIndex, f: |EdgeIndex| -> bool) {
+pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F) where
+    F: FnMut(EdgeIndex) -> bool,
+{
     let mut i = 0;
     let n = max_edge_index.get();
     while i < n {
diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs
index f04c519badc..c6422b36e38 100644
--- a/src/librustc/middle/infer/coercion.rs
+++ b/src/librustc/middle/infer/coercion.rs
@@ -194,8 +194,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         }
     }
 
-    pub fn unpack_actual_value<T>(&self, a: Ty<'tcx>, f: |&ty::sty<'tcx>| -> T)
-                                  -> T {
+    pub fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
+        F: FnOnce(&ty::sty<'tcx>) -> T,
+    {
         match resolve_type(self.get_ref().infcx, None,
                            a, try_resolve_tvar_shallow) {
             Ok(t) => {
@@ -458,13 +459,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                            || AutoUnsafe(b_mutbl, None))
     }
 
-    fn coerce_object(&self,
-                     a: Ty<'tcx>,
-                     sty_a: &ty::sty<'tcx>,
-                     b: Ty<'tcx>,
-                     b_mutbl: ast::Mutability,
-                     mk_ty: |Ty<'tcx>| -> Ty<'tcx>,
-                     mk_adjust: || -> ty::AutoRef<'tcx>) -> CoerceResult<'tcx>
+    fn coerce_object<F, G>(&self,
+                           a: Ty<'tcx>,
+                           sty_a: &ty::sty<'tcx>,
+                           b: Ty<'tcx>,
+                           b_mutbl: ast::Mutability,
+                           mk_ty: F,
+                           mk_adjust: G) -> CoerceResult<'tcx> where
+        F: FnOnce(Ty<'tcx>) -> Ty<'tcx>,
+        G: FnOnce() -> ty::AutoRef<'tcx>,
     {
         let tcx = self.get_ref().infcx.tcx;
 
diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs
index 95805ef8b94..be053afcca4 100644
--- a/src/librustc/middle/infer/higher_ranked/mod.rs
+++ b/src/librustc/middle/infer/higher_ranked/mod.rs
@@ -426,11 +426,9 @@ fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region) -> bool {
     }
 }
 
-fn fold_regions_in<'tcx, T>(tcx: &ty::ctxt<'tcx>,
-                            value: &T,
-                            fldr: |ty::Region, ty::DebruijnIndex| -> ty::Region)
-                            -> T
-    where T: HigherRankedFoldable<'tcx>
+fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>, value: &T, mut fldr: F) -> T where
+    T: HigherRankedFoldable<'tcx>,
+    F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
 {
     value.fold_contents(&mut ty_fold::RegionFolder::new(tcx, |region, current_depth| {
         // we should only be encountering "escaping" late-bound regions here,
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 3b62b96a3e9..4c3b7589d76 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -477,14 +477,17 @@ pub fn resolve_region(cx: &InferCtxt, r: ty::Region, modes: uint)
 }
 
 trait then<'tcx> {
-    fn then<T:Clone>(&self, f: || -> Result<T,ty::type_err<'tcx>>)
-        -> Result<T,ty::type_err<'tcx>>;
+    fn then<T, F>(&self, f: F) -> Result<T, ty::type_err<'tcx>> where
+        T: Clone,
+        F: FnOnce() -> Result<T, ty::type_err<'tcx>>;
 }
 
 impl<'tcx> then<'tcx> for ures<'tcx> {
-    fn then<T:Clone>(&self, f: || -> Result<T,ty::type_err<'tcx>>)
-        -> Result<T,ty::type_err<'tcx>> {
-        self.and_then(|_i| f())
+    fn then<T, F>(&self, f: F) -> Result<T, ty::type_err<'tcx>> where
+        T: Clone,
+        F: FnOnce() -> Result<T, ty::type_err<'tcx>>,
+    {
+        self.and_then(move |_| f())
     }
 }
 
@@ -502,12 +505,15 @@ impl<'tcx, T> ToUres<'tcx> for cres<'tcx, T> {
 }
 
 trait CresCompare<'tcx, T> {
-    fn compare(&self, t: T, f: || -> ty::type_err<'tcx>) -> cres<'tcx, T>;
+    fn compare<F>(&self, t: T, f: F) -> cres<'tcx, T> where
+        F: FnOnce() -> ty::type_err<'tcx>;
 }
 
 impl<'tcx, T:Clone + PartialEq> CresCompare<'tcx, T> for cres<'tcx, T> {
-    fn compare(&self, t: T, f: || -> ty::type_err<'tcx>) -> cres<'tcx, T> {
-        (*self).clone().and_then(|s| {
+    fn compare<F>(&self, t: T, f: F) -> cres<'tcx, T> where
+        F: FnOnce() -> ty::type_err<'tcx>,
+    {
+        (*self).clone().and_then(move |s| {
             if s == t {
                 (*self).clone()
             } else {
@@ -616,7 +622,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     /// Execute `f` and commit the bindings
-    pub fn commit_unconditionally<R>(&self, f: || -> R) -> R {
+    pub fn commit_unconditionally<R, F>(&self, f: F) -> R where
+        F: FnOnce() -> R,
+    {
         debug!("commit()");
         let snapshot = self.start_snapshot();
         let r = f();
@@ -625,12 +633,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     /// Execute `f` and commit the bindings if successful
-    pub fn commit_if_ok<T,E>(&self, f: || -> Result<T,E>) -> Result<T,E> {
-        self.commit_unconditionally(|| self.try(|| f()))
+    pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
+        F: FnOnce() -> Result<T, E>
+    {
+        self.commit_unconditionally(move || self.try(move || f()))
     }
 
     /// Execute `f`, unroll bindings on panic
-    pub fn try<T,E>(&self, f: || -> Result<T,E>) -> Result<T,E> {
+    pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
+        F: FnOnce() -> Result<T, E>
+    {
         debug!("try()");
         let snapshot = self.start_snapshot();
         let r = f();
@@ -647,7 +659,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     /// Execute `f` then unroll any bindings it creates
-    pub fn probe<R>(&self, f: || -> R) -> R {
+    pub fn probe<R, F>(&self, f: F) -> R where
+        F: FnOnce() -> R,
+    {
         debug!("probe()");
         let snapshot = self.start_snapshot();
         let r = f();
@@ -902,22 +916,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     // in this case. The typechecker should only ever report type errors involving mismatched
     // types using one of these four methods, and should not call span_err directly for such
     // errors.
-    pub fn type_error_message_str(&self,
-                                  sp: Span,
-                                  mk_msg: |Option<String>, String| -> String,
-                                  actual_ty: String,
-                                  err: Option<&ty::type_err<'tcx>>) {
+    pub fn type_error_message_str<M>(&self,
+                                     sp: Span,
+                                     mk_msg: M,
+                                     actual_ty: String,
+                                     err: Option<&ty::type_err<'tcx>>) where
+        M: FnOnce(Option<String>, String) -> String,
+    {
         self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
     }
 
-    pub fn type_error_message_str_with_expected(&self,
-                                                sp: Span,
-                                                mk_msg: |Option<String>,
-                                                         String|
-                                                         -> String,
-                                                expected_ty: Option<Ty<'tcx>>,
-                                                actual_ty: String,
-                                                err: Option<&ty::type_err<'tcx>>) {
+    pub fn type_error_message_str_with_expected<M>(&self,
+                                                   sp: Span,
+                                                   mk_msg: M,
+                                                   expected_ty: Option<Ty<'tcx>>,
+                                                   actual_ty: String,
+                                                   err: Option<&ty::type_err<'tcx>>) where
+        M: FnOnce(Option<String>, String) -> String,
+    {
         debug!("hi! expected_ty = {}, actual_ty = {}", expected_ty, actual_ty);
 
         let resolved_expected = expected_ty.map(|e_ty| {
@@ -942,11 +958,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn type_error_message(&self,
-                              sp: Span,
-                              mk_msg: |String| -> String,
-                              actual_ty: Ty<'tcx>,
-                              err: Option<&ty::type_err<'tcx>>) {
+    pub fn type_error_message<M>(&self,
+                                 sp: Span,
+                                 mk_msg: M,
+                                 actual_ty: Ty<'tcx>,
+                                 err: Option<&ty::type_err<'tcx>>) where
+        M: FnOnce(String) -> String,
+    {
         let actual_ty = self.resolve_type_vars_if_possible(actual_ty);
 
         // Don't report an error if actual type is ty_err.
@@ -954,7 +972,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             return;
         }
 
-        self.type_error_message_str(sp, |_e, a| { mk_msg(a) }, self.ty_to_string(actual_ty), err);
+        self.type_error_message_str(sp,
+            move |_e, a| { mk_msg(a) },
+            self.ty_to_string(actual_ty), err);
     }
 
     pub fn report_mismatched_types(&self,
diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs
index 391e37e8b9c..98f69f66b27 100644
--- a/src/librustc/middle/infer/region_inference/mod.rs
+++ b/src/librustc/middle/infer/region_inference/mod.rs
@@ -569,15 +569,15 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         }
     }
 
-    pub fn combine_vars(&self,
-                        t: CombineMapType,
-                        a: Region,
-                        b: Region,
-                        origin: SubregionOrigin<'tcx>,
-                        relate: |this: &RegionVarBindings<'a, 'tcx>,
-                                 old_r: Region,
-                                 new_r: Region|)
-                        -> Region {
+    pub fn combine_vars<F>(&self,
+                           t: CombineMapType,
+                           a: Region,
+                           b: Region,
+                           origin: SubregionOrigin<'tcx>,
+                           mut relate: F)
+                           -> Region where
+        F: FnMut(&RegionVarBindings<'a, 'tcx>, Region, Region),
+    {
         let vars = TwoRegions { a: a, b: b };
         match self.combine_map(t).borrow().get(&vars) {
             Some(&c) => {
@@ -1539,9 +1539,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         }
     }
 
-    fn iterate_until_fixed_point(&self,
-                                 tag: &str,
-                                 body: |constraint: &Constraint| -> bool) {
+    fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F) where
+        F: FnMut(&Constraint) -> bool,
+    {
         let mut iteration = 0u;
         let mut changed = true;
         while changed {
diff --git a/src/librustc/middle/infer/skolemize.rs b/src/librustc/middle/infer/skolemize.rs
index 62bf1d0126a..705b0ae730d 100644
--- a/src/librustc/middle/infer/skolemize.rs
+++ b/src/librustc/middle/infer/skolemize.rs
@@ -54,11 +54,12 @@ impl<'a, 'tcx> TypeSkolemizer<'a, 'tcx> {
         }
     }
 
-    fn skolemize(&mut self,
-                 opt_ty: Option<Ty<'tcx>>,
-                 key: ty::InferTy,
-                 skolemizer: |uint| -> ty::InferTy)
-                 -> Ty<'tcx>
+    fn skolemize<F>(&mut self,
+                    opt_ty: Option<Ty<'tcx>>,
+                    key: ty::InferTy,
+                    skolemizer: F)
+                    -> Ty<'tcx> where
+        F: FnOnce(uint) -> ty::InferTy,
     {
         match opt_ty {
             Some(ty) => { return ty.fold_with(self); }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 5edbafc4e0b..271e903bbdf 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -616,9 +616,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.ir.variable(node_id, span)
     }
 
-    fn pat_bindings(&mut self,
-                    pat: &ast::Pat,
-                    f: |&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId|) {
+    fn pat_bindings<F>(&mut self, pat: &ast::Pat, mut f: F) where
+        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
+    {
         pat_util::pat_bindings(&self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
             let ln = self.live_node(p_id, sp);
             let var = self.variable(p_id, sp);
@@ -626,9 +626,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         })
     }
 
-    fn arm_pats_bindings(&mut self,
-                         pat: Option<&ast::Pat>,
-                         f: |&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId|) {
+    fn arm_pats_bindings<F>(&mut self, pat: Option<&ast::Pat>, f: F) where
+        F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
+    {
         match pat {
             Some(pat) => {
                 self.pat_bindings(pat, f);
@@ -691,10 +691,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.assigned_on_entry(successor, var)
     }
 
-    fn indices2(&mut self,
-                ln: LiveNode,
-                succ_ln: LiveNode,
-                op: |&mut Liveness<'a, 'tcx>, uint, uint|) {
+    fn indices2<F>(&mut self, ln: LiveNode, succ_ln: LiveNode, mut op: F) where
+        F: FnMut(&mut Liveness<'a, 'tcx>, uint, uint),
+    {
         let node_base_idx = self.idx(ln, Variable(0u));
         let succ_base_idx = self.idx(succ_ln, Variable(0u));
         for var_idx in range(0u, self.ir.num_vars) {
@@ -702,10 +701,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         }
     }
 
-    fn write_vars(&self,
-                  wr: &mut io::Writer,
-                  ln: LiveNode,
-                  test: |uint| -> LiveNode) -> io::IoResult<()> {
+    fn write_vars<F>(&self,
+                     wr: &mut io::Writer,
+                     ln: LiveNode,
+                     mut test: F)
+                     -> io::IoResult<()> where
+        F: FnMut(uint) -> LiveNode,
+    {
         let node_base_idx = self.idx(ln, Variable(0));
         for var_idx in range(0u, self.ir.num_vars) {
             let idx = node_base_idx + var_idx;
@@ -1408,12 +1410,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         cond_ln
     }
 
-    fn with_loop_nodes<R>(&mut self,
-                          loop_node_id: NodeId,
-                          break_ln: LiveNode,
-                          cont_ln: LiveNode,
-                          f: |&mut Liveness<'a, 'tcx>| -> R)
-                          -> R {
+    fn with_loop_nodes<R, F>(&mut self,
+                             loop_node_id: NodeId,
+                             break_ln: LiveNode,
+                             cont_ln: LiveNode,
+                             f: F)
+                             -> R where
+        F: FnOnce(&mut Liveness<'a, 'tcx>) -> R,
+    {
         debug!("with_loop_nodes: {} {}", loop_node_id, break_ln.get());
         self.loop_scope.push(loop_node_id);
         self.break_ln.insert(loop_node_id, break_ln);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 302fbd53dd5..d96cf4495bd 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1142,12 +1142,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         })
     }
 
+    // FIXME(#19596) unbox `op`
     pub fn cat_pattern(&self,
                        cmt: cmt<'tcx>,
                        pat: &ast::Pat,
-                       op: |&MemCategorizationContext<'t,TYPER>,
-                            cmt<'tcx>,
-                            &ast::Pat|)
+                       op: |&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat|)
                        -> McResult<()> {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 8d4fbfd4cbc..8ef8e091c94 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -91,9 +91,9 @@ pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &ast::Pat) -> bool {
 
 /// Call `it` on every "binding" in a pattern, e.g., on `a` in
 /// `match foo() { Some(a) => (), None => () }`
-pub fn pat_bindings(dm: &resolve::DefMap,
-                    pat: &ast::Pat,
-                    it: |ast::BindingMode, ast::NodeId, Span, &ast::SpannedIdent|) {
+pub fn pat_bindings<I>(dm: &resolve::DefMap, pat: &ast::Pat, mut it: I) where
+    I: FnMut(ast::BindingMode, ast::NodeId, Span, &ast::SpannedIdent),
+{
     walk_pat(pat, |p| {
         match p.node {
           ast::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 370097004e9..390729df012 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -62,7 +62,9 @@ impl CodeExtent {
 
     /// Maps this scope to a potentially new one according to the
     /// NodeId transformer `f_id`.
-    pub fn map_id(&self, f_id: |ast::NodeId| -> ast::NodeId) -> CodeExtent {
+    pub fn map_id<F>(&self, f_id: F) -> CodeExtent where
+        F: FnOnce(ast::NodeId) -> ast::NodeId,
+    {
         match *self {
             CodeExtent::Misc(node_id) => CodeExtent::Misc(f_id(node_id)),
         }
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 2899f60f736..85e0c9294a6 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -1837,10 +1837,12 @@ impl<'a> Resolver<'a> {
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item(&mut self,
-                                            foreign_item: &ForeignItem,
-                                            parent: ReducedGraphParent,
-                                            f: |&mut Resolver|) {
+    fn build_reduced_graph_for_foreign_item<F>(&mut self,
+                                               foreign_item: &ForeignItem,
+                                               parent: ReducedGraphParent,
+                                               f: F) where
+        F: FnOnce(&mut Resolver),
+    {
         let name = foreign_item.ident.name;
         let is_public = foreign_item.vis == ast::Public;
         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
@@ -3970,7 +3972,9 @@ impl<'a> Resolver<'a> {
     // generate a fake "implementation scope" containing all the
     // implementations thus found, for compatibility with old resolve pass.
 
-    fn with_scope(&mut self, name: Option<Name>, f: |&mut Resolver|) {
+    fn with_scope<F>(&mut self, name: Option<Name>, f: F) where
+        F: FnOnce(&mut Resolver),
+    {
         let orig_module = self.current_module.clone();
 
         // Move down in the graph.
@@ -4373,9 +4377,9 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn with_type_parameter_rib(&mut self,
-                               type_parameters: TypeParameters,
-                               f: |&mut Resolver|) {
+    fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F) where
+        F: FnOnce(&mut Resolver),
+    {
         match type_parameters {
             HasTypeParameters(generics, space, node_id, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
@@ -4422,13 +4426,17 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn with_label_rib(&mut self, f: |&mut Resolver|) {
+    fn with_label_rib<F>(&mut self, f: F) where
+        F: FnOnce(&mut Resolver),
+    {
         self.label_ribs.push(Rib::new(NormalRibKind));
         f(self);
         self.label_ribs.pop();
     }
 
-    fn with_constant_rib(&mut self, f: |&mut Resolver|) {
+    fn with_constant_rib<F>(&mut self, f: F) where
+        F: FnOnce(&mut Resolver),
+    {
         self.value_ribs.push(Rib::new(ConstantItemRibKind));
         self.type_ribs.push(Rib::new(ConstantItemRibKind));
         f(self);
@@ -4676,7 +4684,9 @@ impl<'a> Resolver<'a> {
                               method.pe_body());
     }
 
-    fn with_current_self_type<T>(&mut self, self_type: &Ty, f: |&mut Resolver| -> T) -> T {
+    fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
+        F: FnOnce(&mut Resolver) -> T,
+    {
         // Handle nested impls (inside fn bodies)
         let previous_value = replace(&mut self.current_self_type, Some(self_type.clone()));
         let result = f(self);
@@ -4684,9 +4694,11 @@ impl<'a> Resolver<'a> {
         result
     }
 
-    fn with_optional_trait_ref<T>(&mut self, id: NodeId,
-                                  opt_trait_ref: &Option<TraitRef>,
-                                  f: |&mut Resolver| -> T) -> T {
+    fn with_optional_trait_ref<T, F>(&mut self, id: NodeId,
+                                     opt_trait_ref: &Option<TraitRef>,
+                                     f: F) -> T where
+        F: FnOnce(&mut Resolver) -> T,
+    {
         let new_val = match *opt_trait_ref {
             Some(ref trait_ref) => {
                 self.resolve_trait_reference(id, trait_ref, TraitImplementation);
@@ -5620,7 +5632,9 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn with_no_errors<T>(&mut self, f: |&mut Resolver| -> T) -> T {
+    fn with_no_errors<T, F>(&mut self, f: F) -> T where
+        F: FnOnce(&mut Resolver) -> T,
+    {
         self.emit_errors = false;
         let rs = f(self);
         self.emit_errors = true;
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 3ab94d3ca66..83332d275ce 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -247,7 +247,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
 }
 
 impl<'a> LifetimeContext<'a> {
-    fn with(&mut self, wrap_scope: ScopeChain, f: |&mut LifetimeContext|) {
+    fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
+        F: FnOnce(&mut LifetimeContext),
+    {
         let LifetimeContext {sess, ref mut named_region_map, ..} = *self;
         let mut this = LifetimeContext {
             sess: sess,
@@ -278,10 +280,12 @@ impl<'a> LifetimeContext<'a> {
     /// already in scope (for a fn item, that will be 0, but for a method it might not be). Late
     /// bound lifetimes are resolved by name and associated with a binder id (`binder_id`), so the
     /// ordering is not important there.
-    fn visit_early_late(&mut self,
-                        early_space: subst::ParamSpace,
-                        generics: &ast::Generics,
-                        walk: |&mut LifetimeContext|) {
+    fn visit_early_late<F>(&mut self,
+                           early_space: subst::ParamSpace,
+                           generics: &ast::Generics,
+                           walk: F) where
+        F: FnOnce(&mut LifetimeContext),
+    {
         let referenced_idents = early_bound_lifetime_names(generics);
 
         debug!("visit_early_late: referenced_idents={}",
@@ -290,8 +294,8 @@ impl<'a> LifetimeContext<'a> {
         let (early, late) = generics.lifetimes.clone().partition(
             |l| referenced_idents.iter().any(|&i| i == l.lifetime.name));
 
-        self.with(EarlyScope(early_space, &early, self.scope), |this| {
-            this.with(LateScope(&late, this.scope), |this| {
+        self.with(EarlyScope(early_space, &early, self.scope), move |this| {
+            this.with(LateScope(&late, this.scope), move |this| {
                 this.check_lifetime_defs(&generics.lifetimes);
                 walk(this);
             });
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 994fe2e9e27..ca8029fdfca 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -43,7 +43,9 @@ struct Annotator {
 impl Annotator {
     // Determine the stability for a node based on its attributes and inherited
     // stability. The stability is recorded in the index and used as the parent.
-    fn annotate(&mut self, id: NodeId, attrs: &Vec<Attribute>, f: |&mut Annotator|) {
+    fn annotate<F>(&mut self, id: NodeId, attrs: &Vec<Attribute>, f: F) where
+        F: FnOnce(&mut Annotator),
+    {
         match attr::find_stability(attrs.as_slice()) {
             Some(stab) => {
                 self.index.local.insert(id, stab.clone());
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 9791f8d2f59..2098aa3db53 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -167,10 +167,9 @@ impl<'tcx> Substs<'tcx> {
 }
 
 impl RegionSubsts {
-    fn map<A>(self,
-              a: A,
-              op: |VecPerParamSpace<ty::Region>, A| -> VecPerParamSpace<ty::Region>)
-              -> RegionSubsts {
+    fn map<A, F>(self, a: A, op: F) -> RegionSubsts where
+        F: FnOnce(VecPerParamSpace<ty::Region>, A) -> VecPerParamSpace<ty::Region>,
+    {
         match self {
             ErasedRegions => ErasedRegions,
             NonerasedRegions(r) => NonerasedRegions(op(r, a))
@@ -415,7 +414,9 @@ impl<T> VecPerParamSpace<T> {
         self.content.as_slice()
     }
 
-    pub fn all_vecs(&self, pred: |&[T]| -> bool) -> bool {
+    pub fn all_vecs<P>(&self, mut pred: P) -> bool where
+        P: FnMut(&[T]) -> bool,
+    {
         let spaces = [TypeSpace, SelfSpace, FnSpace];
         spaces.iter().all(|&space| { pred(self.get_slice(space)) })
     }
@@ -450,7 +451,9 @@ impl<T> VecPerParamSpace<T> {
                                        self.assoc_limit)
     }
 
-    pub fn map_move<U>(self, pred: |T| -> U) -> VecPerParamSpace<U> {
+    pub fn map_move<U, F>(self, mut pred: F) -> VecPerParamSpace<U> where
+        F: FnMut(T) -> U,
+    {
         let SeparateVecsPerParamSpace {
             types: t,
             selfs: s,
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 52d33153982..936304c5eb4 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -322,7 +322,9 @@ impl<'tcx, N> Vtable<'tcx, N> {
         }
     }
 
-    pub fn map_move_nested<M>(self, op: |N| -> M) -> Vtable<'tcx, M> {
+    pub fn map_move_nested<M, F>(self, op: F) -> Vtable<'tcx, M> where
+        F: FnMut(N) -> M,
+    {
         match self {
             VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
             VtableFnPointer(sig) => VtableFnPointer(sig),
@@ -348,8 +350,9 @@ impl<'tcx, N> VtableImplData<'tcx, N> {
         }
     }
 
-    pub fn map_move_nested<M>(self, op: |N| -> M)
-                              -> VtableImplData<'tcx, M> {
+    pub fn map_move_nested<M, F>(self, op: F) -> VtableImplData<'tcx, M> where
+        F: FnMut(N) -> M,
+    {
         let VtableImplData { impl_def_id, substs, nested } = self;
         VtableImplData {
             impl_def_id: impl_def_id,
@@ -370,7 +373,9 @@ impl<N> VtableBuiltinData<N> {
         }
     }
 
-    pub fn map_move_nested<M>(self, op: |N| -> M) -> VtableBuiltinData<M> {
+    pub fn map_move_nested<M, F>(self, op: F) -> VtableBuiltinData<M> where
+        F: FnMut(N) -> M,
+    {
         VtableBuiltinData {
             nested: self.nested.map_move(op)
         }
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 52154e0be7a..d8956246d32 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -306,10 +306,11 @@ pub fn predicate_for_builtin_bound<'tcx>(
 /// of caller obligations), search through the trait and supertraits to find one where `test(d)` is
 /// true, where `d` is the def-id of the trait/supertrait. If any is found, return `Some(p)` where
 /// `p` is the path to that trait/supertrait. Else `None`.
-pub fn search_trait_and_supertraits_from_bound<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                                     caller_bound: Rc<ty::TraitRef<'tcx>>,
-                                                     test: |ast::DefId| -> bool)
-                                                     -> Option<VtableParamData<'tcx>>
+pub fn search_trait_and_supertraits_from_bound<'tcx, F>(tcx: &ty::ctxt<'tcx>,
+                                                        caller_bound: Rc<ty::TraitRef<'tcx>>,
+                                                        mut test: F)
+                                                        -> Option<VtableParamData<'tcx>> where
+    F: FnMut(ast::DefId) -> bool,
 {
     for bound in transitive_bounds(tcx, &[caller_bound]) {
         if test(bound.def_id) {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index ffca616d76a..8e99045cffb 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2420,10 +2420,13 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t
 
 pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
 
-pub fn walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>|) {
+pub fn walk_ty<'tcx, F>(ty: Ty<'tcx>, mut f: F) where
+    F: FnMut(Ty<'tcx>),
+{
     maybe_walk_ty(ty, |ty| { f(ty); true });
 }
 
+// FIXME(#19596) unbox `f`
 pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) {
     if !f(ty) {
         return;
@@ -2464,9 +2467,11 @@ pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) {
 }
 
 // Folds types from the bottom up.
-pub fn fold_ty<'tcx>(cx: &ctxt<'tcx>, t0: Ty<'tcx>,
-                     fldop: |Ty<'tcx>| -> Ty<'tcx>)
-                     -> Ty<'tcx> {
+pub fn fold_ty<'tcx, F>(cx: &ctxt<'tcx>, t0: Ty<'tcx>,
+                        fldop: F)
+                        -> Ty<'tcx> where
+    F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
+{
     let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
     f.fold_ty(t0)
 }
@@ -2843,7 +2848,9 @@ impl TypeContents {
         *self & TC::ReachesAll
     }
 
-    pub fn union<T>(v: &[T], f: |&T| -> TypeContents) -> TypeContents {
+    pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where
+        F: FnMut(&T) -> TypeContents,
+    {
         v.iter().fold(TC::None, |tc, ty| tc | f(ty))
     }
 
@@ -3162,10 +3169,12 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
 
         // Iterates over all builtin bounds on the type parameter def, including
         // those inherited from traits with builtin-kind-supertraits.
-        fn each_inherited_builtin_bound<'tcx>(cx: &ctxt<'tcx>,
-                                              bounds: BuiltinBounds,
-                                              traits: &[Rc<TraitRef<'tcx>>],
-                                              f: |BuiltinBound|) {
+        fn each_inherited_builtin_bound<'tcx, F>(cx: &ctxt<'tcx>,
+                                                 bounds: BuiltinBounds,
+                                                 traits: &[Rc<TraitRef<'tcx>>],
+                                                 mut f: F) where
+            F: FnMut(BuiltinBound),
+        {
             for bound in bounds.iter() {
                 f(bound);
             }
@@ -3959,14 +3968,15 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
 }
 
 /// See `expr_ty_adjusted`
-pub fn adjust_ty<'tcx>(cx: &ctxt<'tcx>,
-                       span: Span,
-                       expr_id: ast::NodeId,
-                       unadjusted_ty: Ty<'tcx>,
-                       adjustment: Option<&AutoAdjustment<'tcx>>,
-                       method_type: |MethodCall| -> Option<Ty<'tcx>>)
-                       -> Ty<'tcx> {
-
+pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
+                          span: Span,
+                          expr_id: ast::NodeId,
+                          unadjusted_ty: Ty<'tcx>,
+                          adjustment: Option<&AutoAdjustment<'tcx>>,
+                          mut method_type: F)
+                          -> Ty<'tcx> where
+    F: FnMut(MethodCall) -> Option<Ty<'tcx>>,
+{
     if let ty_err = unadjusted_ty.sty {
         return unadjusted_ty;
     }
@@ -4604,11 +4614,13 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
 /// id is local, it should have been loaded into the map by the `typeck::collect` phase.  If the
 /// def-id is external, then we have to go consult the crate loading code (and cache the result for
 /// the future).
-fn lookup_locally_or_in_crate_store<V:Clone>(
-                                    descr: &str,
-                                    def_id: ast::DefId,
-                                    map: &mut DefIdMap<V>,
-                                    load_external: || -> V) -> V {
+fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
+                                          def_id: ast::DefId,
+                                          map: &mut DefIdMap<V>,
+                                          load_external: F) -> V where
+    V: Clone,
+    F: FnOnce() -> V,
+{
     match map.get(&def_id).cloned() {
         Some(v) => { return v; }
         None => { }
@@ -5164,7 +5176,9 @@ pub fn predicates<'tcx>(
 /// Iterate over attributes of a definition.
 // (This should really be an iterator, but that would require csearch and
 // decoder to use iterators instead of higher-order functions.)
-pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool {
+pub fn each_attr<F>(tcx: &ctxt, did: DefId, mut f: F) -> bool where
+    F: FnMut(&ast::Attribute) -> bool,
+{
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
         item.attrs.iter().all(|attr| f(attr))
@@ -5503,10 +5517,11 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
 // Here, the supertraits are the transitive closure of the supertrait
 // relation on the supertraits from each bounded trait's constraint
 // list.
-pub fn each_bound_trait_and_supertraits<'tcx>(tcx: &ctxt<'tcx>,
-                                              bounds: &[Rc<TraitRef<'tcx>>],
-                                              f: |Rc<TraitRef<'tcx>>| -> bool)
-                                              -> bool
+pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>,
+                                                 bounds: &[Rc<TraitRef<'tcx>>],
+                                                 mut f: F)
+                                                 -> bool where
+    F: FnMut(Rc<TraitRef<'tcx>>) -> bool,
 {
     for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
         if !f(bound_trait_ref) {
@@ -6194,7 +6209,9 @@ pub type FreevarMap = NodeMap<Vec<Freevar>>;
 
 pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
 
-pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T) -> T {
+pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
+    F: FnOnce(&[Freevar]) -> T,
+{
     match tcx.freevars.borrow().get(&fid) {
         None => f(&[]),
         Some(d) => f(d.as_slice())
@@ -6242,12 +6259,13 @@ pub fn erase_late_bound_regions<'tcx, HR>(
 }
 
 /// Replaces the late-bound-regions in `value` that are bound by `value`.
-pub fn replace_late_bound_regions<'tcx, HR>(
+pub fn replace_late_bound_regions<'tcx, HR, F>(
     tcx: &ty::ctxt<'tcx>,
     value: &HR,
-    mapf: |BoundRegion, DebruijnIndex| -> ty::Region)
-    -> (HR, FnvHashMap<ty::BoundRegion,ty::Region>)
-    where HR : HigherRankedFoldable<'tcx>
+    mut mapf: F)
+-> (HR, FnvHashMap<ty::BoundRegion, ty::Region>) where
+    HR : HigherRankedFoldable<'tcx>,
+    F: FnMut(BoundRegion, DebruijnIndex) -> ty::Region,
 {
     debug!("replace_late_bound_regions({})", value.repr(tcx));
 
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 8b54a46bfb9..63ee71dc6a5 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -743,12 +743,14 @@ impl<'tcx, T:HigherRankedFoldable<'tcx>> HigherRankedFoldable<'tcx> for Rc<T> {
 ///////////////////////////////////////////////////////////////////////////
 // Some sample folders
 
-pub struct BottomUpFolder<'a, 'tcx: 'a> {
+pub struct BottomUpFolder<'a, 'tcx: 'a, F> where F: FnMut(Ty<'tcx>) -> Ty<'tcx> {
     pub tcx: &'a ty::ctxt<'tcx>,
-    pub fldop: |Ty<'tcx>|: 'a -> Ty<'tcx>,
+    pub fldop: F,
 }
 
-impl<'a, 'tcx> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx> {
+impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
+    F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
+{
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -772,15 +774,14 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx> {
 /// (The distinction between "free" and "bound" is represented by
 /// keeping track of each `FnSig` in the lexical context of the
 /// current position of the fold.)
-pub struct RegionFolder<'a, 'tcx: 'a> {
+pub struct RegionFolder<'a, 'tcx: 'a, F> where F: FnMut(ty::Region, uint) -> ty::Region {
     tcx: &'a ty::ctxt<'tcx>,
     current_depth: uint,
-    fld_r: |ty::Region, uint|: 'a -> ty::Region,
+    fld_r: F,
 }
 
-impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
-    pub fn new(tcx: &'a ty::ctxt<'tcx>, fld_r: |ty::Region, uint|: 'a -> ty::Region)
-               -> RegionFolder<'a, 'tcx> {
+impl<'a, 'tcx, F> RegionFolder<'a, 'tcx, F> where F: FnMut(ty::Region, uint) -> ty::Region {
+    pub fn new(tcx: &'a ty::ctxt<'tcx>, fld_r: F) -> RegionFolder<'a, 'tcx, F> {
         RegionFolder {
             tcx: tcx,
             current_depth: 1,
@@ -789,7 +790,9 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
+impl<'a, 'tcx, F> TypeFolder<'tcx> for RegionFolder<'a, 'tcx, F> where
+    F: FnMut(ty::Region, uint) -> ty::Region,
+{
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.tcx }
 
     fn enter_region_binder(&mut self) {
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 30318cc129c..51e18c80d05 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -27,7 +27,9 @@ pub struct ErrorReported;
 
 impl Copy for ErrorReported {}
 
-pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
+pub fn time<T, U, F>(do_it: bool, what: &str, u: U, f: F) -> T where
+    F: FnOnce(U) -> T,
+{
     thread_local!(static DEPTH: Cell<uint> = Cell::new(0));
     if !do_it { return f(u); }
 
@@ -39,9 +41,13 @@ pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
 
     let mut u = Some(u);
     let mut rv = None;
-    let dur = Duration::span(|| {
-        rv = Some(f(u.take().unwrap()))
-    });
+    let dur = {
+        let ref mut rvp = rv;
+
+        Duration::span(move || {
+            *rvp = Some(f(u.take().unwrap()))
+        })
+    };
     let rv = rv.unwrap();
 
     println!("{}time: {}.{:03} \t{}", "  ".repeat(old),
@@ -51,7 +57,10 @@ pub fn time<T, U>(do_it: bool, what: &str, u: U, f: |U| -> T) -> T {
     rv
 }
 
-pub fn indent<R: Show>(op: || -> R) -> R {
+pub fn indent<R, F>(op: F) -> R where
+    R: Show,
+    F: FnOnce() -> R,
+{
     // Use in conjunction with the log post-processor like `src/etc/indenter`
     // to make debug output more readable.
     debug!(">>");
@@ -73,12 +82,12 @@ pub fn indenter() -> Indenter {
     Indenter { _cannot_construct_outside_of_this_module: () }
 }
 
-struct LoopQueryVisitor<'a> {
-    p: |&ast::Expr_|: 'a -> bool,
+struct LoopQueryVisitor<P> where P: FnMut(&ast::Expr_) -> bool {
+    p: P,
     flag: bool,
 }
 
-impl<'a, 'v> Visitor<'v> for LoopQueryVisitor<'a> {
+impl<'v, P> Visitor<'v> for LoopQueryVisitor<P> where P: FnMut(&ast::Expr_) -> bool {
     fn visit_expr(&mut self, e: &ast::Expr) {
         self.flag |= (self.p)(&e.node);
         match e.node {
@@ -92,7 +101,7 @@ impl<'a, 'v> Visitor<'v> for LoopQueryVisitor<'a> {
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn loop_query(b: &ast::Block, p: |&ast::Expr_| -> bool) -> bool {
+pub fn loop_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr_) -> bool {
     let mut v = LoopQueryVisitor {
         p: p,
         flag: false,
@@ -101,12 +110,12 @@ pub fn loop_query(b: &ast::Block, p: |&ast::Expr_| -> bool) -> bool {
     return v.flag;
 }
 
-struct BlockQueryVisitor<'a> {
-    p: |&ast::Expr|: 'a -> bool,
+struct BlockQueryVisitor<P> where P: FnMut(&ast::Expr) -> bool {
+    p: P,
     flag: bool,
 }
 
-impl<'a, 'v> Visitor<'v> for BlockQueryVisitor<'a> {
+impl<'v, P> Visitor<'v> for BlockQueryVisitor<P> where P: FnMut(&ast::Expr) -> bool {
     fn visit_expr(&mut self, e: &ast::Expr) {
         self.flag |= (self.p)(e);
         visit::walk_expr(self, e)
@@ -115,7 +124,7 @@ impl<'a, 'v> Visitor<'v> for BlockQueryVisitor<'a> {
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn block_query(b: &ast::Block, p: |&ast::Expr| -> bool) -> bool {
+pub fn block_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) -> bool {
     let mut v = BlockQueryVisitor {
         p: p,
         flag: false,
@@ -194,11 +203,12 @@ pub fn can_reach<S,H:Hasher<S>,T:Eq+Clone+Hash<S>>(
 /// }
 /// ```
 #[inline(always)]
-pub fn memoized<T: Clone + Hash<S> + Eq, U: Clone, S, H: Hasher<S>>(
-    cache: &RefCell<HashMap<T, U, H>>,
-    arg: T,
-    f: |T| -> U
-) -> U {
+pub fn memoized<T, U, S, H, F>(cache: &RefCell<HashMap<T, U, H>>, arg: T, f: F) -> U where
+    T: Clone + Hash<S> + Eq,
+    U: Clone,
+    H: Hasher<S>,
+    F: FnOnce(T) -> U,
+{
     let key = arg.clone();
     let result = cache.borrow().get(&key).map(|result| result.clone());
     match result {
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 4244cec7534..3bf817b42b0 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -232,8 +232,9 @@ fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind,
 impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
     pub fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.bccx.tcx }
 
-    pub fn each_issued_loan(&self, scope: region::CodeExtent, op: |&Loan<'tcx>| -> bool)
-                            -> bool {
+    pub fn each_issued_loan<F>(&self, scope: region::CodeExtent, mut op: F) -> bool where
+        F: FnMut(&Loan<'tcx>) -> bool,
+    {
         //! Iterates over each loan that has been issued
         //! on entrance to `scope`, regardless of whether it is
         //! actually *in scope* at that point.  Sometimes loans
@@ -246,10 +247,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         })
     }
 
-    pub fn each_in_scope_loan(&self,
-                              scope: region::CodeExtent,
-                              op: |&Loan<'tcx>| -> bool)
-                              -> bool {
+    pub fn each_in_scope_loan<F>(&self, scope: region::CodeExtent, mut op: F) -> bool where
+        F: FnMut(&Loan<'tcx>) -> bool,
+    {
         //! Like `each_issued_loan()`, but only considers loans that are
         //! currently in scope.
 
@@ -263,11 +263,13 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         })
     }
 
-    fn each_in_scope_loan_affecting_path(&self,
-                                         scope: region::CodeExtent,
-                                         loan_path: &LoanPath<'tcx>,
-                                         op: |&Loan<'tcx>| -> bool)
-                                         -> bool {
+    fn each_in_scope_loan_affecting_path<F>(&self,
+                                            scope: region::CodeExtent,
+                                            loan_path: &LoanPath<'tcx>,
+                                            mut op: F)
+                                            -> bool where
+        F: FnMut(&Loan<'tcx>) -> bool,
+    {
         //! Iterates through all of the in-scope loans affecting `loan_path`,
         //! calling `op`, and ceasing iteration if `false` is returned.
 
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index 681a5772849..00b1377af73 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -523,8 +523,9 @@ impl<'tcx> MoveData<'tcx> {
         }
     }
 
-    fn each_base_path(&self, index: MovePathIndex, f: |MovePathIndex| -> bool)
-                      -> bool {
+    fn each_base_path<F>(&self, index: MovePathIndex, mut f: F) -> bool where
+        F: FnMut(MovePathIndex) -> bool,
+    {
         let mut p = index;
         while p != InvalidMovePathIndex {
             if !f(p) {
@@ -535,10 +536,8 @@ impl<'tcx> MoveData<'tcx> {
         return true;
     }
 
-    fn each_extending_path(&self,
-                           index: MovePathIndex,
-                           f: |MovePathIndex| -> bool)
-                           -> bool {
+    // FIXME(#19596) unbox `f`
+    fn each_extending_path(&self, index: MovePathIndex, f: |MovePathIndex| -> bool) -> bool {
         if !f(index) {
             return false;
         }
@@ -554,10 +553,9 @@ impl<'tcx> MoveData<'tcx> {
         return true;
     }
 
-    fn each_applicable_move(&self,
-                            index0: MovePathIndex,
-                            f: |MoveIndex| -> bool)
-                            -> bool {
+    fn each_applicable_move<F>(&self, index0: MovePathIndex, mut f: F) -> bool where
+        F: FnMut(MoveIndex) -> bool,
+    {
         let mut ret = true;
         self.each_extending_path(index0, |index| {
             let mut p = self.path_first_move(index);
@@ -660,11 +658,13 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
     /// Iterates through each move of `loan_path` (or some base path of `loan_path`) that *may*
     /// have occurred on entry to `id` without an intervening assignment. In other words, any moves
     /// that would invalidate a reference to `loan_path` at location `id`.
-    pub fn each_move_of(&self,
-                        id: ast::NodeId,
-                        loan_path: &Rc<LoanPath<'tcx>>,
-                        f: |&Move, &LoanPath<'tcx>| -> bool)
-                        -> bool {
+    pub fn each_move_of<F>(&self,
+                           id: ast::NodeId,
+                           loan_path: &Rc<LoanPath<'tcx>>,
+                           mut f: F)
+                           -> bool where
+        F: FnMut(&Move, &LoanPath<'tcx>) -> bool,
+    {
         // Bad scenarios:
         //
         // 1. Move of `a.b.c`, use of `a.b.c`
@@ -715,11 +715,13 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
 
     /// Iterates through every assignment to `loan_path` that may have occurred on entry to `id`.
     /// `loan_path` must be a single variable.
-    pub fn each_assignment_of(&self,
-                              id: ast::NodeId,
-                              loan_path: &Rc<LoanPath<'tcx>>,
-                              f: |&Assignment| -> bool)
-                              -> bool {
+    pub fn each_assignment_of<F>(&self,
+                                 id: ast::NodeId,
+                                 loan_path: &Rc<LoanPath<'tcx>>,
+                                 mut f: F)
+                                 -> bool where
+        F: FnMut(&Assignment) -> bool,
+    {
         let loan_path_index = {
             match self.move_data.existing_move_path(loan_path) {
                 Some(i) => i,
diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs
index 36c74720be4..e09ec791669 100644
--- a/src/librustc_borrowck/graphviz.rs
+++ b/src/librustc_borrowck/graphviz.rs
@@ -75,11 +75,13 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
         }
     }
 
-    fn build_set<O:DataFlowOperator>(&self,
-                                     e: EntryOrExit,
-                                     cfgidx: CFGIndex,
-                                     dfcx: &DataFlowContext<'a, 'tcx, O>,
-                                     to_lp: |uint| -> Rc<LoanPath<'tcx>>) -> String {
+    fn build_set<O:DataFlowOperator, F>(&self,
+                                        e: EntryOrExit,
+                                        cfgidx: CFGIndex,
+                                        dfcx: &DataFlowContext<'a, 'tcx, O>,
+                                        mut to_lp: F) -> String where
+        F: FnMut(uint) -> Rc<LoanPath<'tcx>>,
+    {
         let mut saw_some = false;
         let mut set = "{".to_string();
         dfcx.each_bit_for_node(e, cfgidx, |index| {
@@ -98,7 +100,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
 
     fn dataflow_loans_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
         let dfcx = &self.analysis_data.loans;
-        let loan_index_to_path = |loan_index| {
+        let loan_index_to_path = |&mut: loan_index| {
             let all_loans = &self.analysis_data.all_loans;
             all_loans[loan_index].loan_path()
         };
@@ -107,7 +109,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
 
     fn dataflow_moves_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
         let dfcx = &self.analysis_data.move_data.dfcx_moves;
-        let move_index_to_path = |move_index| {
+        let move_index_to_path = |&mut: move_index| {
             let move_data = &self.analysis_data.move_data.move_data;
             let moves = move_data.moves.borrow();
             let the_move = &(*moves)[move_index];
@@ -118,7 +120,7 @@ impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
 
     fn dataflow_assigns_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
         let dfcx = &self.analysis_data.move_data.dfcx_assign;
-        let assign_index_to_path = |assign_index| {
+        let assign_index_to_path = |&mut: assign_index| {
             let move_data = &self.analysis_data.move_data.move_data;
             let assignments = move_data.var_assignments.borrow();
             let assignment = &(*assignments)[assign_index];