about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-22 13:11:36 -0700
committerbors <bors@rust-lang.org>2014-04-22 13:11:36 -0700
commit16a5b3127a97424108180a79dcd4cd53a5646e24 (patch)
tree7ab522780bc733dbd3eb08034841e96be0ef5136
parent6c82eb5d4de012ccf38620f81d8655308d37e318 (diff)
parent70f3409875be7c2d0f9d48092eb98f11ee734378 (diff)
downloadrust-16a5b3127a97424108180a79dcd4cd53a5646e24.tar.gz
rust-16a5b3127a97424108180a79dcd4cd53a5646e24.zip
auto merge of #13670 : eddyb/rust/more-de-at, r=pcwalton
-rw-r--r--src/librustc/driver/driver.rs34
-rw-r--r--src/librustc/lib/llvm.rs51
-rw-r--r--src/librustc/metadata/creader.rs25
-rw-r--r--src/librustc/metadata/csearch.rs78
-rw-r--r--src/librustc/metadata/cstore.rs18
-rw-r--r--src/librustc/metadata/decoder.rs108
-rw-r--r--src/librustc/metadata/encoder.rs287
-rw-r--r--src/librustc/metadata/tydecode.rs5
-rw-r--r--src/librustc/metadata/tyencode.rs81
-rw-r--r--src/librustc/middle/astencode.rs92
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs130
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs26
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs47
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs49
-rw-r--r--src/librustc/middle/borrowck/gather_loans/move_error.rs10
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs26
-rw-r--r--src/librustc/middle/borrowck/mod.rs190
-rw-r--r--src/librustc/middle/borrowck/move_data.rs60
-rw-r--r--src/librustc/middle/check_const.rs26
-rw-r--r--src/librustc/middle/check_match.rs6
-rw-r--r--src/librustc/middle/const_eval.rs10
-rw-r--r--src/librustc/middle/dataflow.rs5
-rw-r--r--src/librustc/middle/dead.rs23
-rw-r--r--src/librustc/middle/effect.rs9
-rw-r--r--src/librustc/middle/freevars.rs48
-rw-r--r--src/librustc/middle/kind.rs29
-rw-r--r--src/librustc/middle/lang_items.rs4
-rw-r--r--src/librustc/middle/lint.rs30
-rw-r--r--src/librustc/middle/liveness.rs19
-rw-r--r--src/librustc/middle/mem_categorization.rs225
-rw-r--r--src/librustc/middle/moves.rs69
-rw-r--r--src/librustc/middle/pat_util.rs14
-rw-r--r--src/librustc/middle/privacy.rs10
-rw-r--r--src/librustc/middle/reachable.rs11
-rw-r--r--src/librustc/middle/resolve.rs1092
-rw-r--r--src/librustc/middle/trans/_match.rs262
-rw-r--r--src/librustc/middle/trans/adt.rs28
-rw-r--r--src/librustc/middle/trans/base.rs117
-rw-r--r--src/librustc/middle/trans/callee.rs70
-rw-r--r--src/librustc/middle/trans/closure.rs2
-rw-r--r--src/librustc/middle/trans/common.rs130
-rw-r--r--src/librustc/middle/trans/consts.rs29
-rw-r--r--src/librustc/middle/trans/context.rs31
-rw-r--r--src/librustc/middle/trans/debuginfo.rs53
-rw-r--r--src/librustc/middle/trans/expr.rs35
-rw-r--r--src/librustc/middle/trans/glue.rs34
-rw-r--r--src/librustc/middle/trans/intrinsic.rs8
-rw-r--r--src/librustc/middle/trans/meth.rs159
-rw-r--r--src/librustc/middle/trans/monomorphize.rs152
-rw-r--r--src/librustc/middle/trans/reflect.rs24
-rw-r--r--src/librustc/middle/trans/type_of.rs12
-rw-r--r--src/librustc/middle/trans/write_guard.rs2
-rw-r--r--src/librustc/middle/ty.rs437
-rw-r--r--src/librustc/middle/typeck/astconv.rs32
-rw-r--r--src/librustc/middle/typeck/check/_match.rs6
-rw-r--r--src/librustc/middle/typeck/check/method.rs92
-rw-r--r--src/librustc/middle/typeck/check/mod.rs67
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs164
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs103
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs151
-rw-r--r--src/librustc/middle/typeck/coherence.rs174
-rw-r--r--src/librustc/middle/typeck/collect.rs92
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs34
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs14
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs19
-rw-r--r--src/librustc/middle/typeck/infer/glb.rs18
-rw-r--r--src/librustc/middle/typeck/infer/lattice.rs32
-rw-r--r--src/librustc/middle/typeck/infer/lub.rs18
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs28
-rw-r--r--src/librustc/middle/typeck/infer/region_inference/mod.rs22
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs18
-rw-r--r--src/librustc/middle/typeck/mod.rs37
-rw-r--r--src/librustc/middle/typeck/variance.rs15
-rw-r--r--src/librustc/util/nodemap.rs18
-rw-r--r--src/librustc/util/ppaux.rs12
-rw-r--r--src/libsyntax/util/small_vector.rs9
76 files changed, 2622 insertions, 3085 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 7da9d6f82bc..cf0e7e161c1 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -299,7 +299,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         last_private_map: last_private_map
     } =
         time(time_passes, "resolution", (), |_|
-             middle::resolve::resolve_crate(&sess, lang_items, krate));
+             middle::resolve::resolve_crate(&sess, &lang_items, krate));
 
     // Discard MTWT tables that aren't required past resolution.
     syntax::ext::mtwt::clear_tables();
@@ -316,7 +316,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
                 sess.diagnostic(), krate)));
 
     let freevars = time(time_passes, "freevar finding", (), |_|
-                        freevars::annotate_freevars(def_map, krate));
+                        freevars::annotate_freevars(&def_map, krate));
 
     let region_map = time(time_passes, "region resolution", (), |_|
                           middle::region::resolve_crate(&sess, krate));
@@ -328,7 +328,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
                             freevars, region_map, lang_items);
 
     // passes are timed inside typeck
-    let (method_map, vtable_map) = typeck::check_crate(&ty_cx, trait_map, krate);
+    typeck::check_crate(&ty_cx, trait_map, krate);
 
     time(time_passes, "check static items", (), |_|
          middle::check_static::check_crate(&ty_cx, krate));
@@ -338,56 +338,52 @@ pub fn phase_3_run_analysis_passes(sess: Session,
          middle::const_eval::process_crate(krate, &ty_cx));
 
     time(time_passes, "const checking", (), |_|
-         middle::check_const::check_crate(krate, def_map, method_map, &ty_cx));
+         middle::check_const::check_crate(krate, &ty_cx));
 
     let maps = (external_exports, last_private_map);
     let (exported_items, public_items) =
             time(time_passes, "privacy checking", maps, |(a, b)|
-                 middle::privacy::check_crate(&ty_cx, &method_map, &exp_map2,
-                                              a, b, krate));
+                 middle::privacy::check_crate(&ty_cx, &exp_map2, a, b, krate));
 
     time(time_passes, "effect checking", (), |_|
-         middle::effect::check_crate(&ty_cx, method_map, krate));
+         middle::effect::check_crate(&ty_cx, krate));
 
     let middle::moves::MoveMaps {moves_map, moved_variables_set,
                                  capture_map} =
         time(time_passes, "compute moves", (), |_|
-             middle::moves::compute_moves(&ty_cx, method_map, krate));
+             middle::moves::compute_moves(&ty_cx, krate));
 
     time(time_passes, "match checking", (), |_|
-         middle::check_match::check_crate(&ty_cx, method_map,
-                                          &moves_map, krate));
+         middle::check_match::check_crate(&ty_cx, &moves_map, krate));
 
     time(time_passes, "liveness checking", (), |_|
-         middle::liveness::check_crate(&ty_cx, method_map,
-                                       &capture_map, krate));
+         middle::liveness::check_crate(&ty_cx, &capture_map, krate));
 
     let root_map =
         time(time_passes, "borrow checking", (), |_|
-             middle::borrowck::check_crate(&ty_cx, method_map,
-                                           &moves_map, &moved_variables_set,
+             middle::borrowck::check_crate(&ty_cx, &moves_map,
+                                           &moved_variables_set,
                                            &capture_map, krate));
 
     drop(moves_map);
     drop(moved_variables_set);
 
     time(time_passes, "kind checking", (), |_|
-         kind::check_crate(&ty_cx, method_map, krate));
+         kind::check_crate(&ty_cx, krate));
 
     let reachable_map =
         time(time_passes, "reachability checking", (), |_|
-             reachable::find_reachable(&ty_cx, method_map, &exported_items));
+             reachable::find_reachable(&ty_cx, &exported_items));
 
     time(time_passes, "death checking", (), |_| {
         middle::dead::check_crate(&ty_cx,
-                                  method_map,
                                   &exported_items,
                                   &reachable_map,
                                   krate)
     });
 
     time(time_passes, "lint checking", (), |_|
-         lint::check_crate(&ty_cx, method_map, &exported_items, krate));
+         lint::check_crate(&ty_cx, &exported_items, krate));
 
     CrateAnalysis {
         exp_map2: exp_map2,
@@ -396,8 +392,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         public_items: public_items,
         maps: astencode::Maps {
             root_map: root_map,
-            method_map: method_map,
-            vtable_map: vtable_map,
             capture_map: RefCell::new(capture_map)
         },
         reachable: reachable_map
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 9e652536f6d..ba7c5054794 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1882,37 +1882,23 @@ impl TypeNames {
 
 /* Memory-managed interface to target data. */
 
-pub struct target_data_res {
-    pub td: TargetDataRef,
+pub struct TargetData {
+    pub lltd: TargetDataRef
 }
 
-impl Drop for target_data_res {
+impl Drop for TargetData {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeTargetData(self.td);
+            llvm::LLVMDisposeTargetData(self.lltd);
         }
     }
 }
 
-pub fn target_data_res(td: TargetDataRef) -> target_data_res {
-    target_data_res {
-        td: td
-    }
-}
-
-pub struct TargetData {
-    pub lltd: TargetDataRef,
-    dtor: @target_data_res
-}
-
 pub fn mk_target_data(string_rep: &str) -> TargetData {
-    let lltd = string_rep.with_c_str(|buf| {
-        unsafe { llvm::LLVMCreateTargetData(buf) }
-    });
-
     TargetData {
-        lltd: lltd,
-        dtor: @target_data_res(lltd)
+        lltd: string_rep.with_c_str(|buf| {
+            unsafe { llvm::LLVMCreateTargetData(buf) }
+        })
     }
 }
 
@@ -1949,35 +1935,22 @@ impl Drop for ObjectFile {
 
 /* Memory-managed interface to section iterators. */
 
-pub struct section_iter_res {
-    pub si: SectionIteratorRef,
+pub struct SectionIter {
+    pub llsi: SectionIteratorRef
 }
 
-impl Drop for section_iter_res {
+impl Drop for SectionIter {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeSectionIterator(self.si);
+            llvm::LLVMDisposeSectionIterator(self.llsi);
         }
     }
 }
 
-pub fn section_iter_res(si: SectionIteratorRef) -> section_iter_res {
-    section_iter_res {
-        si: si
-    }
-}
-
-pub struct SectionIter {
-    pub llsi: SectionIteratorRef,
-    dtor: @section_iter_res
-}
-
 pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
     unsafe {
-        let llsi = llvm::LLVMGetSections(llof);
         SectionIter {
-            llsi: llsi,
-            dtor: @section_iter_res(llsi)
+            llsi: llvm::LLVMGetSections(llof)
         }
     }
 }
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 799da4150c5..efbfce1b2bb 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -23,7 +23,6 @@ use metadata::loader;
 use metadata::loader::Os;
 use metadata::loader::CratePaths;
 
-use std::cell::RefCell;
 use std::rc::Rc;
 use collections::HashMap;
 use syntax::ast;
@@ -280,7 +279,7 @@ fn resolve_crate<'a>(e: &mut Env,
                      hash: Option<&Svh>,
                      should_link: bool,
                      span: Span)
-                     -> (ast::CrateNum, @cstore::crate_metadata,
+                     -> (ast::CrateNum, Rc<cstore::crate_metadata>,
                          cstore::CrateSource) {
     match existing_match(e, crate_id, hash) {
         None => {
@@ -317,7 +316,7 @@ fn resolve_crate<'a>(e: &mut Env,
             let cnum_map = if should_link {
                 resolve_crate_deps(e, root, metadata.as_slice(), span)
             } else {
-                @RefCell::new(HashMap::new())
+                HashMap::new()
             };
 
             // Claim this crate number and cache it if we're linking to the
@@ -331,13 +330,13 @@ fn resolve_crate<'a>(e: &mut Env,
                 -1
             };
 
-            let cmeta = @cstore::crate_metadata {
+            let cmeta = Rc::new(cstore::crate_metadata {
                 name: load_ctxt.crate_id.name.to_owned(),
                 data: metadata,
                 cnum_map: cnum_map,
                 cnum: cnum,
                 span: span,
-            };
+            });
 
             let source = cstore::CrateSource {
                 dylib: dylib,
@@ -346,7 +345,7 @@ fn resolve_crate<'a>(e: &mut Env,
             };
 
             if should_link {
-                e.sess.cstore.set_crate_data(cnum, cmeta);
+                e.sess.cstore.set_crate_data(cnum, cmeta.clone());
                 e.sess.cstore.add_used_crate_source(source.clone());
             }
             (cnum, cmeta, source)
@@ -365,10 +364,7 @@ fn resolve_crate_deps(e: &mut Env,
     debug!("resolving deps of external crate");
     // The map from crate numbers in the crate we're resolving to local crate
     // numbers
-    let mut cnum_map = HashMap::new();
-    let r = decoder::get_crate_deps(cdata);
-    for dep in r.iter() {
-        let extrn_cnum = dep.cnum;
+    decoder::get_crate_deps(cdata).iter().map(|dep| {
         debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
         let (local_cnum, _, _) = resolve_crate(e, root,
                                                dep.crate_id.name.as_slice(),
@@ -376,9 +372,8 @@ fn resolve_crate_deps(e: &mut Env,
                                                Some(&dep.hash),
                                                true,
                                                span);
-        cnum_map.insert(extrn_cnum, local_cnum);
-    }
-    return @RefCell::new(cnum_map);
+        (dep.cnum, local_cnum)
+    }).collect()
 }
 
 pub struct Loader<'a> {
@@ -407,8 +402,8 @@ impl<'a> CrateLoader for Loader<'a> {
                                                info.ident, &info.crate_id,
                                                None, info.should_link,
                                                krate.span);
-        let macros = decoder::get_exported_macros(data);
-        let registrar = decoder::get_macro_registrar_fn(data).map(|id| {
+        let macros = decoder::get_exported_macros(&*data);
+        let registrar = decoder::get_macro_registrar_fn(&*data).map(|id| {
             decoder::get_symbol(data.data.as_slice(), id)
         });
         MacroCrate {
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index f02f9c61582..4ebf4a52e41 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -33,8 +33,8 @@ pub struct StaticMethodInfo {
 }
 
 pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> ~str {
-    let cdata = cstore.get_crate_data(def.krate).data();
-    return decoder::get_symbol(cdata, def.node);
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::get_symbol(cdata.data(), def.node)
 }
 
 /// Iterates over all the language items in the given crate.
@@ -43,7 +43,7 @@ pub fn each_lang_item(cstore: &cstore::CStore,
                       f: |ast::NodeId, uint| -> bool)
                       -> bool {
     let crate_data = cstore.get_crate_data(cnum);
-    decoder::each_lang_item(crate_data, f)
+    decoder::each_lang_item(&*crate_data, f)
 }
 
 /// Iterates over each child of the given item.
@@ -57,7 +57,7 @@ pub fn each_child_of_item(cstore: &cstore::CStore,
         cstore.get_crate_data(cnum)
     };
     decoder::each_child_of_item(cstore.intr.clone(),
-                                crate_data,
+                                &*crate_data,
                                 def_id.node,
                                 get_crate_data,
                                 callback)
@@ -74,7 +74,7 @@ pub fn each_top_level_item_of_crate(cstore: &cstore::CStore,
         cstore.get_crate_data(cnum)
     };
     decoder::each_top_level_item_of_crate(cstore.intr.clone(),
-                                          crate_data,
+                                          &*crate_data,
                                           get_crate_data,
                                           callback)
 }
@@ -82,7 +82,7 @@ pub fn each_top_level_item_of_crate(cstore: &cstore::CStore,
 pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    let path = decoder::get_item_path(cdata, def.node);
+    let path = decoder::get_item_path(&*cdata, def.node);
 
     // FIXME #1920: This path is not always correct if the crate is not linked
     // into the root namespace.
@@ -103,26 +103,26 @@ pub fn maybe_get_item_ast(tcx: &ty::ctxt, def: ast::DefId,
                        -> found_ast {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::maybe_get_item_ast(cdata, tcx, def.node, decode_inlined_item)
+    decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
 }
 
 pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
-                      -> Vec<@ty::VariantInfo> {
+                      -> Vec<Rc<ty::VariantInfo>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    return decoder::get_enum_variants(cstore.intr.clone(), cdata, def.node, tcx)
+    decoder::get_enum_variants(cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
 /// Returns information about the given implementation.
-pub fn get_impl(tcx: &ty::ctxt, impl_def_id: ast::DefId)
-                -> ty::Impl {
-    let cdata = tcx.sess.cstore.get_crate_data(impl_def_id.krate);
-    decoder::get_impl(tcx.sess.cstore.intr.clone(), cdata, impl_def_id.node, tcx)
+pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
+                        -> Vec<ast::DefId> {
+    let cdata = cstore.get_crate_data(impl_def_id.krate);
+    decoder::get_impl_methods(&*cdata, impl_def_id.node)
 }
 
 pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
     let cdata = tcx.sess.cstore.get_crate_data(def.krate);
-    decoder::get_method(tcx.sess.cstore.intr.clone(), cdata, def.node, tcx)
+    decoder::get_method(tcx.sess.cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
 pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
@@ -130,60 +130,60 @@ pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
                                      -> (ast::Ident, ast::ExplicitSelf_)
 {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_method_name_and_explicit_self(cstore.intr.clone(), cdata, def.node)
+    decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
 }
 
 pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
                                 def: ast::DefId) -> Vec<ast::DefId> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_method_def_ids(cdata, def.node)
+    decoder::get_trait_method_def_ids(&*cdata, def.node)
 }
 
 pub fn get_item_variances(cstore: &cstore::CStore,
                           def: ast::DefId) -> ty::ItemVariances {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_item_variances(cdata, def.node)
+    decoder::get_item_variances(&*cdata, def.node)
 }
 
 pub fn get_provided_trait_methods(tcx: &ty::ctxt,
                                   def: ast::DefId)
-                               -> Vec<@ty::Method> {
+                               -> Vec<Rc<ty::Method>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_provided_trait_methods(cstore.intr.clone(), cdata, def.node, tcx)
+    decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
-pub fn get_supertraits(tcx: &ty::ctxt, def: ast::DefId) -> Vec<@ty::TraitRef> {
+pub fn get_supertraits(tcx: &ty::ctxt, def: ast::DefId) -> Vec<Rc<ty::TraitRef>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_supertraits(cdata, def.node, tcx)
+    decoder::get_supertraits(&*cdata, def.node, tcx)
 }
 
 pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: ast::DefId)
                           -> Option<ast::Ident> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type_name_if_impl(cdata, def.node)
+    decoder::get_type_name_if_impl(&*cdata, def.node)
 }
 
 pub fn get_static_methods_if_impl(cstore: &cstore::CStore,
                                   def: ast::DefId)
                                -> Option<Vec<StaticMethodInfo> > {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_static_methods_if_impl(cstore.intr.clone(), cdata, def.node)
+    decoder::get_static_methods_if_impl(cstore.intr.clone(), &*cdata, def.node)
 }
 
 pub fn get_item_attrs(cstore: &cstore::CStore,
                       def_id: ast::DefId,
                       f: |Vec<@ast::MetaItem> |) {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_item_attrs(cdata, def_id.node, f)
+    decoder::get_item_attrs(&*cdata, def_id.node, f)
 }
 
 pub fn get_struct_fields(cstore: &cstore::CStore,
                          def: ast::DefId)
                       -> Vec<ty::field_ty> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_struct_fields(cstore.intr.clone(), cdata, def.node)
+    decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
 }
 
 pub fn get_type(tcx: &ty::ctxt,
@@ -191,13 +191,13 @@ pub fn get_type(tcx: &ty::ctxt,
              -> ty::ty_param_bounds_and_ty {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type(cdata, def.node, tcx)
+    decoder::get_type(&*cdata, def.node, tcx)
 }
 
 pub fn get_trait_def(tcx: &ty::ctxt, def: ast::DefId) -> ty::TraitDef {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_def(cdata, def.node, tcx)
+    decoder::get_trait_def(&*cdata, def.node, tcx)
 }
 
 pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
@@ -213,7 +213,7 @@ pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
         decoder::maybe_find_item(def.node, class_doc),
         || format!("get_field_type: in class {:?}, field ID {:?} not found",
                  class_id, def) );
-    let ty = decoder::item_type(def, the_field, tcx, cdata);
+    let ty = decoder::item_type(def, the_field, tcx, &*cdata);
     ty::ty_param_bounds_and_ty {
         generics: ty::Generics {type_param_defs: Rc::new(Vec::new()),
                                 region_param_defs: Rc::new(Vec::new())},
@@ -224,10 +224,10 @@ pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
 // Given a def_id for an impl, return the trait it implements,
 // if there is one.
 pub fn get_impl_trait(tcx: &ty::ctxt,
-                      def: ast::DefId) -> Option<@ty::TraitRef> {
+                      def: ast::DefId) -> Option<Rc<ty::TraitRef>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_trait(cdata, def.node, tcx)
+    decoder::get_impl_trait(&*cdata, def.node, tcx)
 }
 
 // Given a def_id for an impl, return information about its vtables
@@ -235,35 +235,35 @@ pub fn get_impl_vtables(tcx: &ty::ctxt,
                         def: ast::DefId) -> typeck::impl_res {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_vtables(cdata, def.node, tcx)
+    decoder::get_impl_vtables(&*cdata, def.node, tcx)
 }
 
 pub fn get_native_libraries(cstore: &cstore::CStore,
                             crate_num: ast::CrateNum)
                                 -> Vec<(cstore::NativeLibaryKind, ~str)> {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::get_native_libraries(cdata)
+    decoder::get_native_libraries(&*cdata)
 }
 
 pub fn each_impl(cstore: &cstore::CStore,
                  crate_num: ast::CrateNum,
                  callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::each_impl(cdata, callback)
+    decoder::each_impl(&*cdata, callback)
 }
 
 pub fn each_implementation_for_type(cstore: &cstore::CStore,
                                     def_id: ast::DefId,
                                     callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::each_implementation_for_type(cdata, def_id.node, callback)
+    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|) {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::each_implementation_for_trait(cdata, def_id.node, callback)
+    decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
 }
 
 /// If the given def ID describes a method belonging to a trait (either a
@@ -274,21 +274,21 @@ pub fn get_trait_of_method(cstore: &cstore::CStore,
                            tcx: &ty::ctxt)
                            -> Option<ast::DefId> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_trait_of_method(cdata, def_id.node, tcx)
+    decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
 }
 
 pub fn get_macro_registrar_fn(cstore: &cstore::CStore,
                               crate_num: ast::CrateNum)
                               -> Option<ast::NodeId> {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::get_macro_registrar_fn(cdata)
+    decoder::get_macro_registrar_fn(&*cdata)
 }
 
 pub fn get_exported_macros(cstore: &cstore::CStore,
                            crate_num: ast::CrateNum)
                            -> Vec<~str> {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::get_exported_macros(cdata)
+    decoder::get_exported_macros(&*cdata)
 }
 
 pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
@@ -296,5 +296,5 @@ pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
     -> Option<ast::DefId>
 {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_tuple_struct_definition_if_ctor(cdata, def_id.node)
+    decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.node)
 }
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index 2d46f92e88f..8e731a98dd7 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -30,7 +30,7 @@ use syntax::parse::token::IdentInterner;
 // local crate numbers (as generated during this session). Each external
 // crate may refer to types in other external crates, and each has their
 // own crate numbers.
-pub type cnum_map = @RefCell<HashMap<ast::CrateNum, ast::CrateNum>>;
+pub type cnum_map = HashMap<ast::CrateNum, ast::CrateNum>;
 
 pub enum MetadataBlob {
     MetadataVec(CVec<u8>),
@@ -68,7 +68,7 @@ pub struct CrateSource {
 }
 
 pub struct CStore {
-    metas: RefCell<HashMap<ast::CrateNum, @crate_metadata>>,
+    metas: RefCell<HashMap<ast::CrateNum, Rc<crate_metadata>>>,
     extern_mod_crate_map: RefCell<extern_mod_crate_map>,
     used_crate_sources: RefCell<Vec<CrateSource>>,
     used_libraries: RefCell<Vec<(~str, NativeLibaryKind)>>,
@@ -95,8 +95,8 @@ impl CStore {
         self.metas.borrow().len() as ast::CrateNum + 1
     }
 
-    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
-        *self.metas.borrow().get(&cnum)
+    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<crate_metadata> {
+        self.metas.borrow().get(&cnum).clone()
     }
 
     pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
@@ -104,13 +104,13 @@ impl CStore {
         decoder::get_crate_hash(cdata.data())
     }
 
-    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: @crate_metadata) {
+    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<crate_metadata>) {
         self.metas.borrow_mut().insert(cnum, data);
     }
 
-    pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) {
-        for (&k, &v) in self.metas.borrow().iter() {
-            i(k, v);
+    pub fn iter_crate_data(&self, i: |ast::CrateNum, &crate_metadata|) {
+        for (&k, v) in self.metas.borrow().iter() {
+            i(k, &**v);
         }
     }
 
@@ -155,7 +155,7 @@ impl CStore {
                  ordering: &mut Vec<ast::CrateNum>) {
             if ordering.as_slice().contains(&cnum) { return }
             let meta = cstore.get_crate_data(cnum);
-            for (_, &dep) in meta.cnum_map.borrow().iter() {
+            for (_, &dep) in meta.cnum_map.iter() {
                 visit(cstore, dep, ordering);
             }
             ordering.push(cnum);
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index b1cede8e410..37d9d3417c9 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -45,7 +45,7 @@ use syntax::ast;
 use syntax::codemap;
 use syntax::crateid::CrateId;
 
-pub type Cmd = @crate_metadata;
+pub type Cmd<'a> = &'a crate_metadata;
 
 // A function that takes a def_id relative to the crate being searched and
 // returns a def_id relative to the compilation environment, i.e. if we hit a
@@ -76,8 +76,6 @@ fn lookup_hash<'a>(d: ebml::Doc<'a>, eq_fn: |&[u8]| -> bool,
     ret
 }
 
-pub type GetCrateDataCb<'a> = |ast::CrateNum|: 'a -> Cmd;
-
 pub fn maybe_find_item<'a>(item_id: ast::NodeId,
                            items: ebml::Doc<'a>) -> Option<ebml::Doc<'a>> {
     fn eq_item(bytes: &[u8], item_id: ast::NodeId) -> bool {
@@ -388,7 +386,7 @@ pub fn get_trait_def(cdata: Cmd,
         generics: ty::Generics {type_param_defs: tp_defs,
                                 region_param_defs: rp_defs},
         bounds: bounds,
-        trait_ref: @item_trait_ref(item_doc, tcx, cdata)
+        trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
     }
 }
 
@@ -412,11 +410,11 @@ pub fn get_type(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
 
 pub fn get_impl_trait(cdata: Cmd,
                       id: ast::NodeId,
-                      tcx: &ty::ctxt) -> Option<@ty::TraitRef>
+                      tcx: &ty::ctxt) -> Option<Rc<ty::TraitRef>>
 {
     let item_doc = lookup_item(id, cdata.data());
     reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
-        @doc_trait_ref(tp, tcx, cdata)
+        Rc::new(doc_trait_ref(tp, tcx, cdata))
     })
 }
 
@@ -462,6 +460,8 @@ 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: ebml::Doc,
@@ -477,12 +477,17 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
 
         // This item may be in yet another crate if it was the child of a
         // reexport.
-        let other_crates_items = if child_def_id.krate == cdata.cnum {
-            reader::get_doc(reader::Doc(cdata.data()), tag_items)
+        let crate_data = if child_def_id.krate == cdata.cnum {
+            None
         } else {
-            let crate_data = get_crate_data(child_def_id.krate);
-            reader::get_doc(reader::Doc(crate_data.data()), tag_items)
+            Some(get_crate_data(child_def_id.krate))
         };
+        let crate_data = match crate_data {
+            Some(ref cdata) => &**cdata,
+            None => cdata
+        };
+
+        let other_crates_items = reader::get_doc(reader::Doc(crate_data.data()), tag_items);
 
         // Get the item.
         match maybe_find_item(child_def_id.node, other_crates_items) {
@@ -565,12 +570,17 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
         let name = name_doc.as_str_slice();
 
         // This reexport may be in yet another crate.
-        let other_crates_items = if child_def_id.krate == cdata.cnum {
-            reader::get_doc(reader::Doc(cdata.data()), tag_items)
+        let crate_data = if child_def_id.krate == cdata.cnum {
+            None
         } else {
-            let crate_data = get_crate_data(child_def_id.krate);
-            reader::get_doc(reader::Doc(crate_data.data()), tag_items)
+            Some(get_crate_data(child_def_id.krate))
         };
+        let crate_data = match crate_data {
+            Some(ref cdata) => &**cdata,
+            None => cdata
+        };
+
+        let other_crates_items = reader::get_doc(reader::Doc(crate_data.data()), tag_items);
 
         // Get the item.
         match maybe_find_item(child_def_id.node, other_crates_items) {
@@ -634,7 +644,7 @@ pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<ast_map::PathElem> {
     item_path(lookup_item(id, cdata.data()))
 }
 
-pub type DecodeInlinedItem<'a> = |cdata: @cstore::crate_metadata,
+pub type DecodeInlinedItem<'a> = |cdata: Cmd,
                                   tcx: &ty::ctxt,
                                   path: Vec<ast_map::PathElem>,
                                   par_doc: ebml::Doc|: 'a
@@ -665,27 +675,27 @@ pub fn maybe_get_item_ast(cdata: Cmd, tcx: &ty::ctxt, id: ast::NodeId,
 }
 
 pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
-                     tcx: &ty::ctxt) -> Vec<@ty::VariantInfo> {
+                     tcx: &ty::ctxt) -> Vec<Rc<ty::VariantInfo>> {
     let data = cdata.data();
     let items = reader::get_doc(reader::Doc(data), tag_items);
     let item = find_item(id, items);
-    let mut infos: Vec<@ty::VariantInfo> = Vec::new();
-    let variant_ids = enum_variant_ids(item, cdata);
     let mut disr_val = 0;
-    for did in variant_ids.iter() {
+    enum_variant_ids(item, cdata).iter().map(|did| {
         let item = find_item(did.node, items);
         let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
                                 item, tcx, cdata);
         let name = item_name(&*intr, item);
         let arg_tys = match ty::get(ctor_ty).sty {
-          ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
-          _ => Vec::new(), // Nullary enum variant.
+            ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
+            _ => Vec::new(), // Nullary enum variant.
         };
         match variant_disr_val(item) {
-          Some(val) => { disr_val = val; }
-          _         => { /* empty */ }
+            Some(val) => { disr_val = val; }
+            _         => { /* empty */ }
         }
-        infos.push(@ty::VariantInfo{
+        let old_disr_val = disr_val;
+        disr_val += 1;
+        Rc::new(ty::VariantInfo {
             args: arg_tys,
             arg_names: None,
             ctor_ty: ctor_ty,
@@ -693,11 +703,10 @@ pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
             // I'm not even sure if we encode visibility
             // for variants -- TEST -- tjc
             id: *did,
-            disr_val: disr_val,
-            vis: ast::Inherited});
-        disr_val += 1;
-    }
-    return infos;
+            disr_val: old_disr_val,
+            vis: ast::Inherited
+        })
+    }).collect()
 }
 
 fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
@@ -723,32 +732,17 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
     }
 }
 
-fn item_impl_methods(intr: Rc<IdentInterner>, cdata: Cmd, item: ebml::Doc,
-                     tcx: &ty::ctxt) -> Vec<@ty::Method> {
-    let mut rslt = Vec::new();
-    reader::tagged_docs(item, tag_item_impl_method, |doc| {
+/// Returns information about the given implementation.
+pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
+    let mut methods = Vec::new();
+    reader::tagged_docs(lookup_item(impl_id, cdata.data()),
+                        tag_item_impl_method, |doc| {
         let m_did = reader::with_doc_data(doc, parse_def_id);
-        rslt.push(@get_method(intr.clone(), cdata, m_did.node, tcx));
+        methods.push(translate_def_id(cdata, m_did));
         true
     });
 
-    rslt
-}
-
-/// Returns information about the given implementation.
-pub fn get_impl(intr: Rc<IdentInterner>, cdata: Cmd, impl_id: ast::NodeId,
-               tcx: &ty::ctxt)
-                -> ty::Impl {
-    let data = cdata.data();
-    let impl_item = lookup_item(impl_id, data);
-    ty::Impl {
-        did: ast::DefId {
-            krate: cdata.cnum,
-            node: impl_id,
-        },
-        ident: item_name(&*intr, impl_item),
-        methods: item_impl_methods(intr, cdata, impl_item, tcx),
-    }
+    methods
 }
 
 pub fn get_method_name_and_explicit_self(
@@ -821,8 +815,8 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
 }
 
 pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
-                                  id: ast::NodeId, tcx: &ty::ctxt) ->
-        Vec<@ty::Method> {
+                                  id: ast::NodeId, tcx: &ty::ctxt)
+                                  -> Vec<Rc<ty::Method>> {
     let data = cdata.data();
     let item = lookup_item(id, data);
     let mut result = Vec::new();
@@ -832,7 +826,7 @@ pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
         let mth = lookup_item(did.node, data);
 
         if item_method_sort(mth) == 'p' {
-            result.push(@get_method(intr.clone(), cdata, did.node, tcx));
+            result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx)));
         }
         true
     });
@@ -842,7 +836,7 @@ pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
 
 /// Returns the supertraits of the given trait.
 pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
-                    -> Vec<@ty::TraitRef> {
+                    -> Vec<Rc<ty::TraitRef>> {
     let mut results = Vec::new();
     let item_doc = lookup_item(id, cdata.data());
     reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| {
@@ -851,7 +845,7 @@ pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
         // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place.
         let trait_ref = doc_trait_ref(trait_doc, tcx, cdata);
         if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() {
-            results.push(@trait_ref);
+            results.push(Rc::new(trait_ref));
         }
         true
     });
@@ -1155,7 +1149,7 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
         return ast::DefId { krate: cdata.cnum, node: did.node };
     }
 
-    match cdata.cnum_map.borrow().find(&did.krate) {
+    match cdata.cnum_map.find(&did.krate) {
         Some(&n) => {
             ast::DefId {
                 krate: n,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index f4c3f564068..848fd8d362e 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -27,7 +27,7 @@ use util::nodemap::{NodeMap, NodeSet};
 
 use serialize::Encodable;
 use std::cast;
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
 use std::hash;
 use std::hash::Hash;
 use std::io::MemWriter;
@@ -52,9 +52,6 @@ use syntax::visit;
 use syntax;
 use writer = serialize::ebml::writer;
 
-// used by astencode:
-pub type abbrev_map = @RefCell<HashMap<ty::t, tyencode::ty_abbrev>>;
-
 /// A borrowed version of ast::InlinedItem.
 pub enum InlinedItemRef<'a> {
     IIItemRef(&'a ast::Item),
@@ -71,7 +68,7 @@ pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
 pub struct EncodeParams<'a> {
     pub diag: &'a SpanHandler,
     pub tcx: &'a ty::ctxt,
-    pub reexports2: middle::resolve::ExportMap2,
+    pub reexports2: &'a middle::resolve::ExportMap2,
     pub item_symbols: &'a RefCell<NodeMap<~str>>,
     pub non_inlineable_statics: &'a RefCell<NodeSet>,
     pub link_meta: &'a LinkMeta,
@@ -79,33 +76,16 @@ pub struct EncodeParams<'a> {
     pub encode_inlined_item: EncodeInlinedItem<'a>,
 }
 
-pub struct Stats {
-    inline_bytes: Cell<u64>,
-    attr_bytes: Cell<u64>,
-    dep_bytes: Cell<u64>,
-    lang_item_bytes: Cell<u64>,
-    native_lib_bytes: Cell<u64>,
-    macro_registrar_fn_bytes: Cell<u64>,
-    macro_defs_bytes: Cell<u64>,
-    impl_bytes: Cell<u64>,
-    misc_bytes: Cell<u64>,
-    item_bytes: Cell<u64>,
-    index_bytes: Cell<u64>,
-    zero_bytes: Cell<u64>,
-    total_bytes: Cell<u64>,
-}
-
 pub struct EncodeContext<'a> {
     pub diag: &'a SpanHandler,
     pub tcx: &'a ty::ctxt,
-    pub stats: @Stats,
-    pub reexports2: middle::resolve::ExportMap2,
+    pub reexports2: &'a middle::resolve::ExportMap2,
     pub item_symbols: &'a RefCell<NodeMap<~str>>,
     pub non_inlineable_statics: &'a RefCell<NodeSet>,
     pub link_meta: &'a LinkMeta,
     pub cstore: &'a cstore::CStore,
     pub encode_inlined_item: EncodeInlinedItem<'a>,
-    pub type_abbrevs: abbrev_map,
+    pub type_abbrevs: tyencode::abbrev_map,
 }
 
 fn encode_name(ebml_w: &mut Encoder, name: Name) {
@@ -134,7 +114,7 @@ fn encode_trait_ref(ebml_w: &mut Encoder,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
 
     ebml_w.start_tag(tag);
@@ -146,8 +126,8 @@ fn encode_impl_vtables(ebml_w: &mut Encoder,
                        ecx: &EncodeContext,
                        vtables: &typeck::impl_res) {
     ebml_w.start_tag(tag_item_impl_vtables);
-    astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
-    astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
+    astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
+    astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
     ebml_w.end_tag();
 }
 
@@ -170,7 +150,7 @@ fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
     for param in params.iter() {
         ebml_w.start_tag(tag);
@@ -227,7 +207,7 @@ pub fn write_type(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
     tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
 }
@@ -249,7 +229,7 @@ fn encode_method_fty(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
     tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
 
@@ -290,7 +270,7 @@ fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
 }
 
 fn encode_struct_fields(ebml_w: &mut Encoder,
-                        fields: &Vec<ty::field_ty>,
+                        fields: &[ty::field_ty],
                         origin: DefId) {
     for f in fields.iter() {
         if f.name == special_idents::unnamed_field.name {
@@ -313,7 +293,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             ebml_w: &mut Encoder,
                             id: NodeId,
                             variants: &[P<Variant>],
-                            index: @RefCell<Vec<entry<i64>> >,
+                            index: &mut Vec<entry<i64>>,
                             generics: &ast::Generics) {
     debug!("encode_enum_variant_info(id={:?})", id);
 
@@ -323,7 +303,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                                ast::DefId { krate: LOCAL_CRATE, node: id });
     for variant in variants.iter() {
         let def_id = local_def(variant.node.id);
-        index.borrow_mut().push(entry {
+        index.push(entry {
             val: variant.node.id as i64,
             pos: ebml_w.writer.tell().unwrap(),
         });
@@ -347,11 +327,10 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
                 let idx = encode_info_for_struct(ecx,
                                                  ebml_w,
-                                                 &fields,
+                                                 fields.as_slice(),
                                                  index);
-                encode_struct_fields(ebml_w, &fields, def_id);
-                let bkts = create_index(idx);
-                encode_index(ebml_w, bkts, write_i64);
+                encode_struct_fields(ebml_w, fields.as_slice(), def_id);
+                encode_index(ebml_w, idx, write_i64);
             }
         }
         if vi.get(i).disr_val != disr_val {
@@ -402,10 +381,12 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
                                          ebml_w: &mut Encoder,
                                          exp: &middle::resolve::Export2)
                                          -> bool {
+    let impl_methods = ecx.tcx.impl_methods.borrow();
     match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
         Some(implementations) => {
-            for &base_impl in implementations.borrow().iter() {
-                for &m in base_impl.methods.iter() {
+            for base_impl_did in implementations.borrow().iter() {
+                for &method_did in impl_methods.get(base_impl_did).iter() {
+                    let m = ty::method(ecx.tcx, method_did);
                     if m.explicit_self == ast::SelfStatic {
                         encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
                     }
@@ -424,7 +405,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
                                           -> bool {
     match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
         Some(methods) => {
-            for &m in methods.iter() {
+            for m in methods.iter() {
                 if m.explicit_self == ast::SelfStatic {
                     encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
                 }
@@ -666,8 +647,8 @@ fn encode_provided_source(ebml_w: &mut Encoder,
 /* Returns an index of items in this class */
 fn encode_info_for_struct(ecx: &EncodeContext,
                           ebml_w: &mut Encoder,
-                          fields: &Vec<ty::field_ty>,
-                          global_index: @RefCell<Vec<entry<i64>> >)
+                          fields: &[ty::field_ty],
+                          global_index: &mut Vec<entry<i64>>)
                           -> Vec<entry<i64>> {
     /* Each class has its own index, since different classes
        may have fields with the same name */
@@ -680,7 +661,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
         let id = field.id.node;
 
         index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
-        global_index.borrow_mut().push(entry {
+        global_index.push(entry {
             val: id as i64,
             pos: ebml_w.writer.tell().unwrap(),
         });
@@ -700,9 +681,9 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                ebml_w: &mut Encoder,
                                name: ast::Ident,
                                ctor_id: NodeId,
-                               index: @RefCell<Vec<entry<i64>> >,
+                               index: &mut Vec<entry<i64>>,
                                struct_id: NodeId) {
-    index.borrow_mut().push(entry {
+    index.push(entry {
         val: ctor_id as i64,
         pos: ebml_w.writer.tell().unwrap(),
     });
@@ -825,10 +806,10 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
                                    def_id: DefId) {
     match ecx.tcx.inherent_impls.borrow().find(&def_id) {
         None => {}
-        Some(&implementations) => {
-            for implementation in implementations.borrow().iter() {
+        Some(implementations) => {
+            for &impl_def_id in implementations.borrow().iter() {
                 ebml_w.start_tag(tag_items_data_item_inherent_impl);
-                encode_def_id(ebml_w, implementation.did);
+                encode_def_id(ebml_w, impl_def_id);
                 ebml_w.end_tag();
             }
         }
@@ -841,10 +822,10 @@ fn encode_extension_implementations(ecx: &EncodeContext,
                                     trait_def_id: DefId) {
     match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
         None => {}
-        Some(&implementations) => {
-            for implementation in implementations.borrow().iter() {
+        Some(implementations) => {
+            for &impl_def_id in implementations.borrow().iter() {
                 ebml_w.start_tag(tag_items_data_item_extension_impl);
-                encode_def_id(ebml_w, implementation.did);
+                encode_def_id(ebml_w, impl_def_id);
                 ebml_w.end_tag();
             }
         }
@@ -854,14 +835,14 @@ fn encode_extension_implementations(ecx: &EncodeContext,
 fn encode_info_for_item(ecx: &EncodeContext,
                         ebml_w: &mut Encoder,
                         item: &Item,
-                        index: @RefCell<Vec<entry<i64>> >,
+                        index: &mut Vec<entry<i64>>,
                         path: PathElems,
                         vis: ast::Visibility) {
     let tcx = ecx.tcx;
 
     fn add_to_index(item: &Item, ebml_w: &Encoder,
-                     index: @RefCell<Vec<entry<i64>> >) {
-        index.borrow_mut().push(entry {
+                    index: &mut Vec<entry<i64>>) {
+        index.push(entry {
             val: item.id as i64,
             pos: ebml_w.writer.tell().unwrap(),
         });
@@ -988,7 +969,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
            class itself */
         let idx = encode_info_for_struct(ecx,
                                          ebml_w,
-                                         &fields,
+                                         fields.as_slice(),
                                          index);
 
         /* Index the class*/
@@ -1009,7 +990,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         /* Encode def_ids for each field and method
          for methods, write all the stuff get_trait_method
         needs to know*/
-        encode_struct_fields(ebml_w, &fields, def_id);
+        encode_struct_fields(ebml_w, fields.as_slice(), def_id);
 
         (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
 
@@ -1017,8 +998,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_inherent_implementations(ecx, ebml_w, def_id);
 
         /* Each class has its own index -- encode it */
-        let bkts = create_index(idx);
-        encode_index(ebml_w, bkts, write_i64);
+        encode_index(ebml_w, idx, write_i64);
         ebml_w.end_tag();
 
         // If this is a tuple-like struct, encode the type of the constructor.
@@ -1033,8 +1013,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
       ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
-        let impls = tcx.impls.borrow();
-        let imp = impls.get(&def_id);
+        let impl_methods = tcx.impl_methods.borrow();
+        let methods = impl_methods.get(&def_id);
 
         add_to_index(item, ebml_w, index);
         ebml_w.start_tag(tag_items_data_item);
@@ -1051,16 +1031,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             _ => {}
         }
-        for method in imp.methods.iter() {
+        for &method_def_id in methods.iter() {
             ebml_w.start_tag(tag_item_impl_method);
-            let s = def_to_str(method.def_id);
+            let s = def_to_str(method_def_id);
             ebml_w.writer.write(s.as_bytes());
             ebml_w.end_tag();
         }
         for ast_trait_ref in opt_trait.iter() {
             let trait_ref = ty::node_id_to_trait_ref(
                 tcx, ast_trait_ref.ref_id);
-            encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
+            encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
         }
@@ -1072,18 +1052,18 @@ fn encode_info_for_item(ecx: &EncodeContext,
         // appear first in the impl structure, in the same order they do
         // in the ast. This is a little sketchy.
         let num_implemented_methods = ast_methods.len();
-        for (i, m) in imp.methods.iter().enumerate() {
+        for (i, &method_def_id) in methods.iter().enumerate() {
             let ast_method = if i < num_implemented_methods {
                 Some(*ast_methods.get(i))
             } else { None };
 
-            index.borrow_mut().push(entry {
-                val: m.def_id.node as i64,
+            index.push(entry {
+                val: method_def_id.node as i64,
                 pos: ebml_w.writer.tell().unwrap(),
             });
             encode_info_for_method(ecx,
                                    ebml_w,
-                                   *m,
+                                   &*ty::method(tcx, method_def_id),
                                    path.clone(),
                                    false,
                                    item.id,
@@ -1101,7 +1081,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                   trait_def.generics.type_param_defs(),
                                   tag_items_data_item_ty_param_bounds);
         encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
-        encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
+        encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
         encode_name(ebml_w, item.ident.name);
         encode_attributes(ebml_w, item.attrs.as_slice());
         encode_visibility(ebml_w, vis);
@@ -1120,7 +1100,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
         for ast_trait_ref in super_traits.iter() {
             let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
-            encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
+            encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
         }
 
         // Encode the implementations of this trait.
@@ -1135,14 +1115,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
             let method_ty = ty::method(tcx, method_def_id);
 
-            index.borrow_mut().push(entry {
+            index.push(entry {
                 val: method_def_id.node as i64,
                 pos: ebml_w.writer.tell().unwrap(),
             });
 
             ebml_w.start_tag(tag_items_data_item);
 
-            encode_method_ty_fields(ecx, ebml_w, method_ty);
+            encode_method_ty_fields(ecx, ebml_w, &*method_ty);
 
             encode_parent_item(ebml_w, def_id);
 
@@ -1202,10 +1182,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
 fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 ebml_w: &mut Encoder,
                                 nitem: &ForeignItem,
-                                index: @RefCell<Vec<entry<i64>> >,
+                                index: &mut Vec<entry<i64>>,
                                 path: PathElems,
                                 abi: abi::Abi) {
-    index.borrow_mut().push(entry {
+    index.push(entry {
         val: nitem.id as i64,
         pos: ebml_w.writer.tell().unwrap(),
     });
@@ -1244,7 +1224,7 @@ fn my_visit_expr(_e: &Expr) { }
 fn my_visit_item(i: &Item,
                  ebml_w: &mut Encoder,
                  ecx_ptr: *int,
-                 index: @RefCell<Vec<entry<i64>> >) {
+                 index: &mut Vec<entry<i64>>) {
     let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
     // See above
     let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
@@ -1256,7 +1236,7 @@ fn my_visit_item(i: &Item,
 fn my_visit_foreign_item(ni: &ForeignItem,
                          ebml_w: &mut Encoder,
                          ecx_ptr:*int,
-                         index: @RefCell<Vec<entry<i64>> >) {
+                         index: &mut Vec<entry<i64>>) {
     // See above
     let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
     debug!("writing foreign item {}::{}",
@@ -1277,7 +1257,7 @@ fn my_visit_foreign_item(ni: &ForeignItem,
 struct EncodeVisitor<'a,'b> {
     ebml_w_for_visit_item: &'a mut Encoder<'b>,
     ecx_ptr:*int,
-    index: @RefCell<Vec<entry<i64>> >,
+    index: &'a mut Vec<entry<i64>>,
 }
 
 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
@@ -1305,9 +1285,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
                          ebml_w: &mut Encoder,
                          krate: &Crate)
                          -> Vec<entry<i64>> {
-    let index = @RefCell::new(Vec::new());
+    let mut index = Vec::new();
     ebml_w.start_tag(tag_items_data);
-    index.borrow_mut().push(entry {
+    index.push(entry {
         val: CRATE_NODE_ID as i64,
         pos: ebml_w.writer.tell().unwrap(),
     });
@@ -1321,53 +1301,34 @@ fn encode_info_for_items(ecx: &EncodeContext,
 
     // See comment in `encode_side_tables_for_ii` in astencode
     let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
-    {
-        let mut visitor = EncodeVisitor {
-            index: index,
-            ecx_ptr: ecx_ptr,
-            ebml_w_for_visit_item: &mut *ebml_w,
-        };
-
-        visit::walk_crate(&mut visitor, krate, ());
-    }
+    visit::walk_crate(&mut EncodeVisitor {
+        index: &mut index,
+        ecx_ptr: ecx_ptr,
+        ebml_w_for_visit_item: &mut *ebml_w,
+    }, krate, ());
 
     ebml_w.end_tag();
-    return /*bad*/index.borrow().clone();
+    index
 }
 
 
 // Path and definition ID indexing
 
-fn create_index<T:Clone + Hash + 'static>(
-                index: Vec<entry<T>> )
-                -> Vec<@Vec<entry<T>> > {
-    let mut buckets: Vec<@RefCell<Vec<entry<T>> >> = Vec::new();
-    for _ in range(0u, 256u) {
-        buckets.push(@RefCell::new(Vec::new()));
-    }
-    for elt in index.iter() {
+fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
+                         write_fn: |&mut MemWriter, &T|) {
+    let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
+    for elt in index.move_iter() {
         let h = hash::hash(&elt.val) as uint;
-        buckets.get_mut(h % 256).borrow_mut().push((*elt).clone());
-    }
-
-    let mut buckets_frozen = Vec::new();
-    for bucket in buckets.iter() {
-        buckets_frozen.push(@/*bad*/bucket.borrow().clone());
+        buckets.get_mut(h % 256).push(elt);
     }
-    return buckets_frozen;
-}
 
-fn encode_index<T:'static>(
-                ebml_w: &mut Encoder,
-                buckets: Vec<@Vec<entry<T>> > ,
-                write_fn: |&mut MemWriter, &T|) {
     ebml_w.start_tag(tag_index);
     let mut bucket_locs = Vec::new();
     ebml_w.start_tag(tag_index_buckets);
     for bucket in buckets.iter() {
         bucket_locs.push(ebml_w.writer.tell().unwrap());
         ebml_w.start_tag(tag_index_buckets_bucket);
-        for elt in (**bucket).iter() {
+        for elt in bucket.iter() {
             ebml_w.start_tag(tag_index_buckets_bucket_elt);
             assert!(elt.pos < 0xffff_ffff);
             {
@@ -1614,7 +1575,7 @@ impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
     fn visit_item(&mut self, item: &Item, _: ()) {
         match item.node {
             ItemImpl(_, Some(ref trait_ref), _, _) => {
-                let def_map = self.ecx.tcx.def_map;
+                let def_map = &self.ecx.tcx.def_map;
                 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
                 let def_id = ast_util::def_id_of_def(trait_def);
 
@@ -1723,20 +1684,33 @@ pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
 }
 
 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
-    let stats = Stats {
-        inline_bytes: Cell::new(0),
-        attr_bytes: Cell::new(0),
-        dep_bytes: Cell::new(0),
-        lang_item_bytes: Cell::new(0),
-        native_lib_bytes: Cell::new(0),
-        macro_registrar_fn_bytes: Cell::new(0),
-        macro_defs_bytes: Cell::new(0),
-        impl_bytes: Cell::new(0),
-        misc_bytes: Cell::new(0),
-        item_bytes: Cell::new(0),
-        index_bytes: Cell::new(0),
-        zero_bytes: Cell::new(0),
-        total_bytes: Cell::new(0),
+    struct Stats {
+        attr_bytes: u64,
+        dep_bytes: u64,
+        lang_item_bytes: u64,
+        native_lib_bytes: u64,
+        macro_registrar_fn_bytes: u64,
+        macro_defs_bytes: u64,
+        impl_bytes: u64,
+        misc_bytes: u64,
+        item_bytes: u64,
+        index_bytes: u64,
+        zero_bytes: u64,
+        total_bytes: u64,
+    }
+    let mut stats = Stats {
+        attr_bytes: 0,
+        dep_bytes: 0,
+        lang_item_bytes: 0,
+        native_lib_bytes: 0,
+        macro_registrar_fn_bytes: 0,
+        macro_defs_bytes: 0,
+        impl_bytes: 0,
+        misc_bytes: 0,
+        item_bytes: 0,
+        index_bytes: 0,
+        zero_bytes: 0,
+        total_bytes: 0,
     };
     let EncodeParams {
         item_symbols,
@@ -1749,19 +1723,16 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
         non_inlineable_statics,
         ..
     } = parms;
-    let type_abbrevs = @RefCell::new(HashMap::new());
-    let stats = @stats;
     let ecx = EncodeContext {
         diag: diag,
         tcx: tcx,
-        stats: stats,
         reexports2: reexports2,
         item_symbols: item_symbols,
         non_inlineable_statics: non_inlineable_statics,
         link_meta: link_meta,
         cstore: cstore,
         encode_inlined_item: encode_inlined_item,
-        type_abbrevs: type_abbrevs,
+        type_abbrevs: RefCell::new(HashMap::new()),
      };
 
     let mut ebml_w = writer::Encoder(wr);
@@ -1772,88 +1743,86 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
     let mut i = ebml_w.writer.tell().unwrap();
     let crate_attrs = synthesize_crate_attrs(&ecx, krate);
     encode_attributes(&mut ebml_w, crate_attrs.as_slice());
-    ecx.stats.attr_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
 
     i = ebml_w.writer.tell().unwrap();
     encode_crate_deps(&mut ebml_w, ecx.cstore);
-    ecx.stats.dep_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the language items.
     i = ebml_w.writer.tell().unwrap();
     encode_lang_items(&ecx, &mut ebml_w);
-    ecx.stats.lang_item_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the native libraries used
     i = ebml_w.writer.tell().unwrap();
     encode_native_libraries(&ecx, &mut ebml_w);
-    ecx.stats.native_lib_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the macro registrar function
     i = ebml_w.writer.tell().unwrap();
     encode_macro_registrar_fn(&ecx, &mut ebml_w);
-    ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode macro definitions
     i = ebml_w.writer.tell().unwrap();
     encode_macro_defs(&ecx, krate, &mut ebml_w);
-    ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the def IDs of impls, for coherence checking.
     i = ebml_w.writer.tell().unwrap();
     encode_impls(&ecx, krate, &mut ebml_w);
-    ecx.stats.impl_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode miscellaneous info.
     i = ebml_w.writer.tell().unwrap();
     encode_misc_info(&ecx, krate, &mut ebml_w);
-    ecx.stats.misc_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode and index the items.
     ebml_w.start_tag(tag_items);
     i = ebml_w.writer.tell().unwrap();
     let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
-    ecx.stats.item_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
 
     i = ebml_w.writer.tell().unwrap();
-    let items_buckets = create_index(items_index);
-    encode_index(&mut ebml_w, items_buckets, write_i64);
-    ecx.stats.index_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    encode_index(&mut ebml_w, items_index, write_i64);
+    stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
     ebml_w.end_tag();
 
-    ecx.stats.total_bytes.set(ebml_w.writer.tell().unwrap());
+    stats.total_bytes = ebml_w.writer.tell().unwrap();
 
     if tcx.sess.meta_stats() {
         for e in ebml_w.writer.get_ref().iter() {
             if *e == 0 {
-                ecx.stats.zero_bytes.set(ecx.stats.zero_bytes.get() + 1);
+                stats.zero_bytes += 1;
             }
         }
 
         println!("metadata stats:");
-        println!("         inline bytes: {}", ecx.stats.inline_bytes.get());
-        println!("      attribute bytes: {}", ecx.stats.attr_bytes.get());
-        println!("            dep bytes: {}", ecx.stats.dep_bytes.get());
-        println!("      lang item bytes: {}", ecx.stats.lang_item_bytes.get());
-        println!("         native bytes: {}", ecx.stats.native_lib_bytes.get());
-        println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get());
-        println!("      macro def bytes: {}", ecx.stats.macro_defs_bytes.get());
-        println!("           impl bytes: {}", ecx.stats.impl_bytes.get());
-        println!("           misc bytes: {}", ecx.stats.misc_bytes.get());
-        println!("           item bytes: {}", ecx.stats.item_bytes.get());
-        println!("          index bytes: {}", ecx.stats.index_bytes.get());
-        println!("           zero bytes: {}", ecx.stats.zero_bytes.get());
-        println!("          total bytes: {}", ecx.stats.total_bytes.get());
+        println!("      attribute bytes: {}", stats.attr_bytes);
+        println!("            dep bytes: {}", stats.dep_bytes);
+        println!("      lang item bytes: {}", stats.lang_item_bytes);
+        println!("         native bytes: {}", stats.native_lib_bytes);
+        println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
+        println!("      macro def bytes: {}", stats.macro_defs_bytes);
+        println!("           impl bytes: {}", stats.impl_bytes);
+        println!("           misc bytes: {}", stats.misc_bytes);
+        println!("           item bytes: {}", stats.item_bytes);
+        println!("          index bytes: {}", stats.index_bytes);
+        println!("           zero bytes: {}", stats.zero_bytes);
+        println!("          total bytes: {}", stats.total_bytes);
     }
 }
 
 // Get the encoded string for a type
 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> ~str {
-    let cx = &tyencode::ctxt {
+    let mut wr = MemWriter::new();
+    tyencode::enc_ty(&mut wr, &tyencode::ctxt {
         diag: tcx.sess.diagnostic(),
         ds: def_to_str,
         tcx: tcx,
-        abbrevs: tyencode::ac_no_abbrevs};
-    let mut wr = MemWriter::new();
-    tyencode::enc_ty(&mut wr, cx, t);
+        abbrevs: &RefCell::new(HashMap::new())
+    }, t);
     str::from_utf8_owned(wr.get_ref().to_owned()).unwrap()
 }
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index cfa2d647ec9..3ba8dd3b30f 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -18,6 +18,7 @@
 
 use middle::ty;
 
+use std::rc::Rc;
 use std::str;
 use std::strbuf::StrBuf;
 use std::uint;
@@ -563,7 +564,7 @@ fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef
     ty::TypeParameterDef {
         ident: parse_ident(st, ':'),
         def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
-        bounds: @parse_bounds(st, |x,y| conv(x,y)),
+        bounds: Rc::new(parse_bounds(st, |x,y| conv(x,y))),
         default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)))
     }
 }
@@ -591,7 +592,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
                 param_bounds.builtin_bounds.add(ty::BoundShare);
             }
             'I' => {
-                param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
+                param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
             }
             '.' => {
                 return param_bounds;
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 1d7d43f895e..13d24e7a1d0 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -17,7 +17,6 @@ use std::cell::RefCell;
 use collections::HashMap;
 use std::io;
 use std::io::MemWriter;
-use std::str;
 use std::fmt;
 
 use middle::ty::param_ty;
@@ -39,7 +38,7 @@ pub struct ctxt<'a> {
     pub ds: fn(DefId) -> ~str,
     // The type context.
     pub tcx: &'a ty::ctxt,
-    pub abbrevs: abbrev_ctxt
+    pub abbrevs: &'a abbrev_map
 }
 
 // Compact string representation for ty.t values. API ty_str & parse_from_str.
@@ -51,61 +50,35 @@ pub struct ty_abbrev {
     s: ~str
 }
 
-pub enum abbrev_ctxt {
-    ac_no_abbrevs,
-    ac_use_abbrevs(@RefCell<HashMap<ty::t, ty_abbrev>>),
-}
+pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
 
 fn mywrite(w: &mut MemWriter, fmt: &fmt::Arguments) {
     fmt::write(&mut *w as &mut io::Writer, fmt);
 }
 
 pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
-    match cx.abbrevs {
-      ac_no_abbrevs => {
-          let result_str_opt = cx.tcx.short_names_cache.borrow()
-                                            .find(&t)
-                                            .map(|result| {
-                                                (*result).clone()
-                                            });
-          let result_str = match result_str_opt {
-            Some(s) => s,
-            None => {
-                let wr = &mut MemWriter::new();
-                enc_sty(wr, cx, &ty::get(t).sty);
-                let s = str::from_utf8(wr.get_ref()).unwrap();
-                cx.tcx.short_names_cache.borrow_mut().insert(t, s.to_str());
-                s.to_str()
-            }
-          };
-          w.write(result_str.as_bytes());
-      }
-      ac_use_abbrevs(abbrevs) => {
-          match abbrevs.borrow_mut().find(&t) {
-              Some(a) => { w.write(a.s.as_bytes()); return; }
-              None => {}
-          }
-          let pos = w.tell().unwrap();
-          enc_sty(w, cx, &ty::get(t).sty);
-          let end = w.tell().unwrap();
-          let len = end - pos;
-          fn estimate_sz(u: u64) -> u64 {
-              let mut n = u;
-              let mut len = 0;
-              while n != 0 { len += 1; n = n >> 4; }
-              return len;
-          }
-          let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
-          if abbrev_len < len {
-              // I.e. it's actually an abbreviation.
-              let s = format!("\\#{:x}:{:x}\\#", pos, len);
-              let a = ty_abbrev { pos: pos as uint,
-                                  len: len as uint,
-                                  s: s };
-              abbrevs.borrow_mut().insert(t, a);
-          }
-          return;
-      }
+    match cx.abbrevs.borrow_mut().find(&t) {
+        Some(a) => { w.write(a.s.as_bytes()); return; }
+        None => {}
+    }
+    let pos = w.tell().unwrap();
+    enc_sty(w, cx, &ty::get(t).sty);
+    let end = w.tell().unwrap();
+    let len = end - pos;
+    fn estimate_sz(u: u64) -> u64 {
+        let mut n = u;
+        let mut len = 0;
+        while n != 0 { len += 1; n = n >> 4; }
+        return len;
+    }
+    let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
+    if abbrev_len < len {
+        // I.e. it's actually an abbreviation.
+        cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
+            pos: pos as uint,
+            len: len as uint,
+            s: format!("\\#{:x}:{:x}\\#", pos, len)
+        });
     }
 }
 
@@ -393,9 +366,9 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
         }
     }
 
-    for &tp in bs.trait_bounds.iter() {
+    for tp in bs.trait_bounds.iter() {
         mywrite!(w, "I");
-        enc_trait_ref(w, cx, tp);
+        enc_trait_ref(w, cx, &**tp);
     }
 
     mywrite!(w, ".");
@@ -403,6 +376,6 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
 
 pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
     mywrite!(w, "{}:{}|", token::get_ident(v.ident), (cx.ds)(v.def_id));
-    enc_bounds(w, cx, v.bounds);
+    enc_bounds(w, cx, &*v.bounds);
     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
 }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 49a2b6326c8..08133a8b69e 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -55,13 +55,11 @@ use writer = serialize::ebml::writer;
 // Auxiliary maps of things to be encoded
 pub struct Maps {
     pub root_map: middle::borrowck::root_map,
-    pub method_map: middle::typeck::MethodMap,
-    pub vtable_map: middle::typeck::vtable_map,
     pub capture_map: RefCell<middle::moves::CaptureMap>,
 }
 
 struct DecodeContext<'a> {
-    cdata: @cstore::crate_metadata,
+    cdata: &'a cstore::crate_metadata,
     tcx: &'a ty::ctxt,
     maps: &'a Maps
 }
@@ -112,7 +110,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
            ebml_w.writer.tell());
 }
 
-pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
+pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
                            tcx: &ty::ctxt,
                            maps: &Maps,
                            path: Vec<ast_map::PathElem>,
@@ -273,7 +271,7 @@ impl<S:serialize::Encoder<E>, E> def_id_encoder_helpers for S {
 trait def_id_decoder_helpers {
     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId;
     fn read_def_id_noxcx(&mut self,
-                         cdata: @cstore::crate_metadata) -> ast::DefId;
+                         cdata: &cstore::crate_metadata) -> ast::DefId;
 }
 
 impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
@@ -283,7 +281,7 @@ impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
     }
 
     fn read_def_id_noxcx(&mut self,
-                         cdata: @cstore::crate_metadata) -> ast::DefId {
+                         cdata: &cstore::crate_metadata) -> ast::DefId {
         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
         decoder::translate_def_id(cdata, did)
     }
@@ -528,7 +526,7 @@ impl tr for ty::TraitStore {
 // ______________________________________________________________________
 // Encoding and decoding of freevar information
 
-fn encode_freevar_entry(ebml_w: &mut Encoder, fv: @freevar_entry) {
+fn encode_freevar_entry(ebml_w: &mut Encoder, fv: &freevar_entry) {
     (*fv).encode(ebml_w).unwrap();
 }
 
@@ -660,7 +658,7 @@ impl tr for MethodOrigin {
 fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
                               ebml_w: &mut Encoder,
                               autoderef: u32,
-                              dr: typeck::vtable_res) {
+                              dr: &typeck::vtable_res) {
     ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
         ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
             autoderef.encode(ebml_w)
@@ -673,19 +671,19 @@ fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
 
 pub fn encode_vtable_res(ecx: &e::EncodeContext,
                      ebml_w: &mut Encoder,
-                     dr: typeck::vtable_res) {
+                     dr: &typeck::vtable_res) {
     // can't autogenerate this code because automatic code of
     // ty::t doesn't work, and there is no way (atm) to have
     // hand-written encoding routines combine with auto-generated
     // ones.  perhaps we should fix this.
     ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
-        Ok(encode_vtable_param_res(ecx, ebml_w, *param_tables))
+        Ok(encode_vtable_param_res(ecx, ebml_w, param_tables))
     }).unwrap()
 }
 
 pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
                      ebml_w: &mut Encoder,
-                     param_tables: typeck::vtable_param_res) {
+                     param_tables: &typeck::vtable_param_res) {
     ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| {
         Ok(encode_vtable_origin(ecx, ebml_w, vtable_origin))
     }).unwrap()
@@ -697,7 +695,7 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
                         vtable_origin: &typeck::vtable_origin) {
     ebml_w.emit_enum("vtable_origin", |ebml_w| {
         match *vtable_origin {
-          typeck::vtable_static(def_id, ref tys, vtable_res) => {
+          typeck::vtable_static(def_id, ref tys, ref vtable_res) => {
             ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| {
                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
                     Ok(ebml_w.emit_def_id(def_id))
@@ -727,23 +725,23 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
 pub trait vtable_decoder_helpers {
     fn read_vtable_res_with_key(&mut self,
                                 tcx: &ty::ctxt,
-                                cdata: @cstore::crate_metadata)
+                                cdata: &cstore::crate_metadata)
                                 -> (u32, typeck::vtable_res);
     fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_res;
     fn read_vtable_param_res(&mut self,
-                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_param_res;
     fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                          tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                           -> typeck::vtable_origin;
 }
 
 impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     fn read_vtable_res_with_key(&mut self,
                                 tcx: &ty::ctxt,
-                                cdata: @cstore::crate_metadata)
+                                cdata: &cstore::crate_metadata)
                                 -> (u32, typeck::vtable_res) {
         self.read_struct("VtableWithKey", 2, |this| {
             let autoderef = this.read_struct_field("autoderef", 0, |this| {
@@ -756,27 +754,21 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_res {
-        @self.read_to_vec(|this|
-                          Ok(this.read_vtable_param_res(tcx, cdata)))
-             .unwrap()
-             .move_iter()
-             .collect()
+        self.read_to_vec(|this| Ok(this.read_vtable_param_res(tcx, cdata)))
+             .unwrap().move_iter().collect()
     }
 
     fn read_vtable_param_res(&mut self,
-                             tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                             tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_param_res {
-        @self.read_to_vec(|this|
-                          Ok(this.read_vtable_origin(tcx, cdata)))
-             .unwrap()
-             .move_iter()
-             .collect()
+        self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
+             .unwrap().move_iter().collect()
     }
 
     fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                          tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
         -> typeck::vtable_origin {
         self.read_enum("vtable_origin", |this| {
             this.read_enum_variant(["vtable_static",
@@ -828,7 +820,7 @@ impl<'a> get_ty_str_ctxt for e::EncodeContext<'a> {
             diag: self.tcx.sess.diagnostic(),
             ds: e::def_to_str,
             tcx: self.tcx,
-            abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)
+            abbrevs: &self.type_abbrevs
         }
     }
 }
@@ -1026,7 +1018,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
                 ebml_w.emit_from_vec(fv.as_slice(), |ebml_w, fv_entry| {
-                    Ok(encode_freevar_entry(ebml_w, *fv_entry))
+                    Ok(encode_freevar_entry(ebml_w, fv_entry))
                 });
             })
         })
@@ -1052,7 +1044,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
     }
 
     let method_call = MethodCall::expr(id);
-    for &method in maps.method_map.borrow().find(&method_call).iter() {
+    for &method in tcx.method_map.borrow().find(&method_call).iter() {
         ebml_w.tag(c::tag_table_method_map, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1061,21 +1053,21 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
+    for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
-                encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
+                encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, dr);
             })
         })
     }
 
-    for adj in tcx.adjustments.borrow().find(&id).iter() {
-        match ***adj {
+    for &adj in tcx.adjustments.borrow().find(&id).iter() {
+        match *adj {
             ty::AutoDerefRef(adj) => {
                 for autoderef in range(0, adj.autoderefs) {
                     let method_call = MethodCall::autoderef(id, autoderef as u32);
-                    for &method in maps.method_map.borrow().find(&method_call).iter() {
+                    for &method in tcx.method_map.borrow().find(&method_call).iter() {
                         ebml_w.tag(c::tag_table_method_map, |ebml_w| {
                             ebml_w.id(id);
                             ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1084,12 +1076,12 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
                         })
                     }
 
-                    for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
+                    for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
                         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
                             ebml_w.id(id);
                             ebml_w.tag(c::tag_table_val, |ebml_w| {
                                 encode_vtable_res_with_key(ecx, ebml_w,
-                                                           method_call.autoderef, *dr);
+                                                           method_call.autoderef, dr);
                             })
                         })
                     }
@@ -1101,7 +1093,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
-                ebml_w.emit_auto_adjustment(ecx, **adj);
+                ebml_w.emit_auto_adjustment(ecx, adj);
             })
         })
     }
@@ -1148,15 +1140,15 @@ trait ebml_decoder_decoder_helpers {
     // Versions of the type reading functions that don't need the full
     // ExtendedDecodeContext.
     fn read_ty_noxcx(&mut self,
-                     tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t;
+                     tcx: &ty::ctxt, cdata: &cstore::crate_metadata) -> ty::t;
     fn read_tys_noxcx(&mut self,
                       tcx: &ty::ctxt,
-                      cdata: @cstore::crate_metadata) -> Vec<ty::t>;
+                      cdata: &cstore::crate_metadata) -> Vec<ty::t>;
 }
 
 impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     fn read_ty_noxcx(&mut self,
-                     tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
+                     tcx: &ty::ctxt, cdata: &cstore::crate_metadata) -> ty::t {
         self.read_opaque(|_, doc| {
             Ok(tydecode::parse_ty_data(
                 doc.data,
@@ -1169,7 +1161,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
 
     fn read_tys_noxcx(&mut self,
                       tcx: &ty::ctxt,
-                      cdata: @cstore::crate_metadata) -> Vec<ty::t> {
+                      cdata: &cstore::crate_metadata) -> Vec<ty::t> {
         self.read_to_vec(|this| Ok(this.read_ty_noxcx(tcx, cdata)) )
             .unwrap()
             .move_iter()
@@ -1378,8 +1370,8 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         dcx.tcx.node_type_substs.borrow_mut().insert(id, tys);
                     }
                     c::tag_table_freevars => {
-                        let fv_info = @val_dsr.read_to_vec(|val_dsr| {
-                            Ok(@val_dsr.read_freevar_entry(xcx))
+                        let fv_info = val_dsr.read_to_vec(|val_dsr| {
+                            Ok(val_dsr.read_freevar_entry(xcx))
                         }).unwrap().move_iter().collect();
                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
                     }
@@ -1398,7 +1390,7 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                             expr_id: id,
                             autoderef: autoderef
                         };
-                        dcx.maps.method_map.borrow_mut().insert(method_call, method);
+                        dcx.tcx.method_map.borrow_mut().insert(method_call, method);
                     }
                     c::tag_table_vtable_map => {
                         let (autoderef, vtable_res) =
@@ -1408,10 +1400,10 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                             expr_id: id,
                             autoderef: autoderef
                         };
-                        dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
+                        dcx.tcx.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
                     }
                     c::tag_table_adjustments => {
-                        let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx);
+                        let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(xcx);
                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
                     }
                     c::tag_table_capture_map => {
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 5e0425141ac..e09507f5d5f 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -30,6 +30,8 @@ use syntax::visit::Visitor;
 use syntax::visit;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
+
 struct CheckLoanCtxt<'a> {
     bccx: &'a BorrowckCtxt<'a>,
     dfcx_loans: &'a LoanDataFlow<'a>,
@@ -82,7 +84,7 @@ pub fn check_loans(bccx: &BorrowckCtxt,
 #[deriving(Eq)]
 enum MoveError {
     MoveOk,
-    MoveWhileBorrowed(/*loan*/@LoanPath, /*loan*/Span)
+    MoveWhileBorrowed(/*loan*/Rc<LoanPath>, /*loan*/Span)
 }
 
 impl<'a> CheckLoanCtxt<'a> {
@@ -121,7 +123,7 @@ impl<'a> CheckLoanCtxt<'a> {
 
     pub fn each_in_scope_restriction(&self,
                                      scope_id: ast::NodeId,
-                                     loan_path: @LoanPath,
+                                     loan_path: &LoanPath,
                                      op: |&Loan, &Restriction| -> bool)
                                      -> bool {
         //! Iterates through all the in-scope restrictions for the
@@ -133,7 +135,7 @@ impl<'a> CheckLoanCtxt<'a> {
 
             let mut ret = true;
             for restr in loan.restrictions.iter() {
-                if restr.loan_path == loan_path {
+                if *restr.loan_path == *loan_path {
                     if !op(loan, restr) {
                         ret = false;
                         break;
@@ -243,7 +245,7 @@ impl<'a> CheckLoanCtxt<'a> {
                 "it".to_owned()
             } else {
                 format!("`{}`",
-                        self.bccx.loan_path_to_str(old_loan.loan_path))
+                        self.bccx.loan_path_to_str(&*old_loan.loan_path))
             };
 
             match (new_loan.kind, old_loan.kind) {
@@ -252,7 +254,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("cannot borrow `{}` as mutable \
                                 more than once at a time",
-                                self.bccx.loan_path_to_str(new_loan.loan_path)));
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path)));
                 }
 
                 (ty::UniqueImmBorrow, _) => {
@@ -260,7 +262,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("closure requires unique access to `{}` \
                                 but {} is already borrowed",
-                                self.bccx.loan_path_to_str(new_loan.loan_path),
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path),
                                 old_pronoun));
                 }
 
@@ -269,7 +271,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("cannot borrow `{}` as {} because \
                                 previous closure requires unique access",
-                                self.bccx.loan_path_to_str(new_loan.loan_path),
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path),
                                 new_loan.kind.to_user_str()));
                 }
 
@@ -278,7 +280,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("cannot borrow `{}` as {} because \
                                 {} is also borrowed as {}",
-                                self.bccx.loan_path_to_str(new_loan.loan_path),
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path),
                                 new_loan.kind.to_user_str(),
                                 old_pronoun,
                                 old_loan.kind.to_user_str()));
@@ -290,7 +292,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     self.bccx.span_note(
                         span,
                         format!("borrow occurs due to use of `{}` in closure",
-                                self.bccx.loan_path_to_str(new_loan.loan_path)));
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path)));
                 }
                 _ => { }
             }
@@ -300,21 +302,21 @@ impl<'a> CheckLoanCtxt<'a> {
                     format!("the mutable borrow prevents subsequent \
                             moves, borrows, or modification of `{0}` \
                             until the borrow ends",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
 
                 ty::ImmBorrow => {
                     format!("the immutable borrow prevents subsequent \
                             moves or mutable borrows of `{0}` \
                             until the borrow ends",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
 
                 ty::UniqueImmBorrow => {
                     format!("the unique capture prevents subsequent \
                             moves or borrows of `{0}` \
                             until the borrow ends",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
             };
 
@@ -322,12 +324,12 @@ impl<'a> CheckLoanCtxt<'a> {
                 ClosureCapture(_) => {
                     format!("previous borrow of `{}` occurs here due to \
                             use in closure",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
 
                 AddrOf | AutoRef | RefBinding => {
                     format!("previous borrow of `{}` occurs here",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
             };
 
@@ -356,7 +358,7 @@ impl<'a> CheckLoanCtxt<'a> {
                                   id: ast::NodeId,
                                   span: Span,
                                   use_kind: MovedValueUseKind,
-                                  lp: @LoanPath) {
+                                  lp: &Rc<LoanPath>) {
         /*!
          * Reports an error if `expr` (which should be a path)
          * is using a moved/uninitialized value
@@ -368,7 +370,7 @@ impl<'a> CheckLoanCtxt<'a> {
             self.bccx.report_use_of_moved_value(
                 span,
                 use_kind,
-                lp,
+                &**lp,
                 move,
                 moved_lp);
             false
@@ -378,7 +380,7 @@ impl<'a> CheckLoanCtxt<'a> {
     pub fn check_assignment(&self, expr: &ast::Expr) {
         // We don't use cat_expr() here because we don't want to treat
         // auto-ref'd parameters in overloaded operators as rvalues.
-        let cmt = match self.bccx.tcx.adjustments.borrow().find_copy(&expr.id) {
+        let cmt = match self.bccx.tcx.adjustments.borrow().find(&expr.id) {
             None => self.bccx.cat_expr_unadjusted(expr),
             Some(adj) => self.bccx.cat_expr_autoderefd(expr, adj)
         };
@@ -388,10 +390,9 @@ impl<'a> CheckLoanCtxt<'a> {
         // Mutable values can be assigned, as long as they obey loans
         // and aliasing restrictions:
         if cmt.mutbl.is_mutable() {
-            if check_for_aliasable_mutable_writes(self, expr, cmt) {
+            if check_for_aliasable_mutable_writes(self, expr, cmt.clone()) {
                 if check_for_assignment_to_restricted_or_frozen_location(
-                    self, expr, cmt)
-                {
+                    self, expr, cmt.clone()) {
                     // Safe, but record for lint pass later:
                     mark_variable_as_used_mut(self, cmt);
                 }
@@ -401,13 +402,13 @@ impl<'a> CheckLoanCtxt<'a> {
 
         // For immutable local variables, assignments are legal
         // if they cannot already have been assigned
-        if self.is_local_variable(cmt) {
+        if self.is_local_variable(cmt.clone()) {
             assert!(cmt.mutbl.is_immutable()); // no "const" locals
-            let lp = opt_loan_path(cmt).unwrap();
-            self.move_data.each_assignment_of(expr.id, lp, |assign| {
+            let lp = opt_loan_path(&cmt).unwrap();
+            self.move_data.each_assignment_of(expr.id, &lp, |assign| {
                 self.bccx.report_reassigned_immutable_variable(
                     expr.span,
-                    lp,
+                    &*lp,
                     assign);
                 false
             });
@@ -415,21 +416,21 @@ impl<'a> CheckLoanCtxt<'a> {
         }
 
         // Otherwise, just a plain error.
-        match opt_loan_path(cmt) {
+        match opt_loan_path(&cmt) {
             Some(lp) => {
                 self.bccx.span_err(
                     expr.span,
                     format!("cannot assign to {} {} `{}`",
                             cmt.mutbl.to_user_str(),
-                            self.bccx.cmt_to_str(cmt),
-                            self.bccx.loan_path_to_str(lp)));
+                            self.bccx.cmt_to_str(&*cmt),
+                            self.bccx.loan_path_to_str(&*lp)));
             }
             None => {
                 self.bccx.span_err(
                     expr.span,
                     format!("cannot assign to {} {}",
                             cmt.mutbl.to_user_str(),
-                            self.bccx.cmt_to_str(cmt)));
+                            self.bccx.cmt_to_str(&*cmt)));
             }
         }
         return;
@@ -446,7 +447,7 @@ impl<'a> CheckLoanCtxt<'a> {
             loop {
                 debug!("mark_writes_through_upvars_as_used_mut(cmt={})",
                        cmt.repr(this.tcx()));
-                match cmt.cat {
+                match cmt.cat.clone() {
                     mc::cat_local(id) | mc::cat_arg(id) => {
                         this.tcx().used_mut_nodes.borrow_mut().insert(id);
                         return;
@@ -494,10 +495,10 @@ impl<'a> CheckLoanCtxt<'a> {
             debug!("check_for_aliasable_mutable_writes(cmt={}, guarantor={})",
                    cmt.repr(this.tcx()), guarantor.repr(this.tcx()));
             match guarantor.cat {
-                mc::cat_deref(b, _, mc::BorrowedPtr(ty::MutBorrow, _)) => {
+                mc::cat_deref(ref b, _, mc::BorrowedPtr(ty::MutBorrow, _)) => {
                     // Statically prohibit writes to `&mut` when aliasable
 
-                    check_for_aliasability_violation(this, expr, b);
+                    check_for_aliasability_violation(this, expr, b.clone());
                 }
 
                 _ => {}
@@ -535,7 +536,7 @@ impl<'a> CheckLoanCtxt<'a> {
             //! Check for assignments that violate the terms of an
             //! outstanding loan.
 
-            let loan_path = match opt_loan_path(cmt) {
+            let loan_path = match opt_loan_path(&cmt) {
                 Some(lp) => lp,
                 None => { return true; /* no loan path, can't be any loans */ }
             };
@@ -571,10 +572,10 @@ impl<'a> CheckLoanCtxt<'a> {
             // owned pointer are borrowed, and hence while `v[*]` is not
             // restricted from being written, `v` is.
             let cont = this.each_in_scope_restriction(expr.id,
-                                                      loan_path,
+                                                      &*loan_path,
                                                       |loan, restr| {
                 if restr.set.intersects(RESTR_MUTATE) {
-                    this.report_illegal_mutation(expr, loan_path, loan);
+                    this.report_illegal_mutation(expr, &*loan_path, loan);
                     false
                 } else {
                     true
@@ -623,17 +624,17 @@ impl<'a> CheckLoanCtxt<'a> {
             //
             // Here the restriction that `v` not be mutated would be misapplied
             // to block the subpath `v[1]`.
-            let full_loan_path = loan_path;
+            let full_loan_path = loan_path.clone();
             let mut loan_path = loan_path;
             loop {
-                match *loan_path {
+                loan_path = match *loan_path {
                     // Peel back one layer if, for `loan_path` to be
                     // mutable, `lp_base` must be mutable. This occurs
                     // with inherited mutability and with `&mut`
                     // pointers.
-                    LpExtend(lp_base, mc::McInherited, _) |
-                    LpExtend(lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
-                        loan_path = lp_base;
+                    LpExtend(ref lp_base, mc::McInherited, _) |
+                    LpExtend(ref lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
+                        lp_base.clone()
                     }
 
                     // Otherwise stop iterating
@@ -642,12 +643,12 @@ impl<'a> CheckLoanCtxt<'a> {
                     LpVar(_) => {
                         return true;
                     }
-                }
+                };
 
                 // Check for a non-const loan of `loan_path`
                 let cont = this.each_in_scope_loan(expr.id, |loan| {
                     if loan.loan_path == loan_path {
-                        this.report_illegal_mutation(expr, full_loan_path, loan);
+                        this.report_illegal_mutation(expr, &*full_loan_path, loan);
                         false
                     } else {
                         true
@@ -700,7 +701,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     self.bccx.span_note(
                         loan_span,
                         format!("borrow of `{}` occurs here",
-                                self.bccx.loan_path_to_str(loan_path)));
+                                self.bccx.loan_path_to_str(&*loan_path)));
                 }
             }
             true
@@ -712,13 +713,12 @@ impl<'a> CheckLoanCtxt<'a> {
                                 span: Span) {
         for cap_var in self.bccx.capture_map.get(&closure_id).iter() {
             let var_id = ast_util::def_id_of_def(cap_var.def).node;
-            let var_path = @LpVar(var_id);
             self.check_if_path_is_moved(closure_id, span,
-                                        MovedInCapture, var_path);
+                                        MovedInCapture, &Rc::new(LpVar(var_id)));
             match cap_var.mode {
                 moves::CapRef | moves::CapCopy => {}
                 moves::CapMove => {
-                    check_by_move_capture(self, closure_id, cap_var, var_path);
+                    check_by_move_capture(self, closure_id, cap_var, &LpVar(var_id));
                 }
             }
         }
@@ -727,7 +727,7 @@ impl<'a> CheckLoanCtxt<'a> {
         fn check_by_move_capture(this: &CheckLoanCtxt,
                                  closure_id: ast::NodeId,
                                  cap_var: &moves::CaptureVar,
-                                 move_path: @LoanPath) {
+                                 move_path: &LoanPath) {
             let move_err = this.analyze_move_out_from(closure_id, move_path);
             match move_err {
                 MoveOk => {}
@@ -740,7 +740,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     this.bccx.span_note(
                         loan_span,
                         format!("borrow of `{}` occurs here",
-                                this.bccx.loan_path_to_str(loan_path)));
+                                this.bccx.loan_path_to_str(&*loan_path)));
                 }
             }
         }
@@ -748,7 +748,7 @@ impl<'a> CheckLoanCtxt<'a> {
 
     pub fn analyze_move_out_from(&self,
                                  expr_id: ast::NodeId,
-                                 mut move_path: @LoanPath)
+                                 move_path: &LoanPath)
                                  -> MoveError {
         debug!("analyze_move_out_from(expr_id={:?}, move_path={})",
                self.tcx().map.node_to_str(expr_id),
@@ -756,22 +756,23 @@ impl<'a> CheckLoanCtxt<'a> {
 
         // We must check every element of a move path. See
         // `borrowck-move-subcomponent.rs` for a test case.
-        loop {
-            // check for a conflicting loan:
-            let mut ret = MoveOk;
-            self.each_in_scope_restriction(expr_id, move_path, |loan, _| {
-                // Any restriction prevents moves.
-                ret = MoveWhileBorrowed(loan.loan_path, loan.span);
-                false
-            });
 
-            if ret != MoveOk {
-                return ret
-            }
+        // check for a conflicting loan:
+        let mut ret = MoveOk;
+        self.each_in_scope_restriction(expr_id, move_path, |loan, _| {
+            // Any restriction prevents moves.
+            ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span);
+            false
+        });
+
+        if ret != MoveOk {
+            return ret
+        }
 
-            match *move_path {
-                LpVar(_) => return MoveOk,
-                LpExtend(subpath, _, _) => move_path = subpath,
+        match *move_path {
+            LpVar(_) => MoveOk,
+            LpExtend(ref subpath, _, _) => {
+                self.analyze_move_out_from(expr_id, &**subpath)
             }
         }
     }
@@ -806,14 +807,13 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
     this.check_for_conflicting_loans(expr.id);
     this.check_move_out_from_expr(expr);
 
-    let method_map = this.bccx.method_map.borrow();
+    let method_map = this.bccx.tcx.method_map.borrow();
     match expr.node {
       ast::ExprPath(..) => {
           if !this.move_data.is_assignee(expr.id) {
               let cmt = this.bccx.cat_expr_unadjusted(expr);
               debug!("path cmt={}", cmt.repr(this.tcx()));
-              let r = opt_loan_path(cmt);
-              for &lp in r.iter() {
+              for lp in opt_loan_path(&cmt).iter() {
                   this.check_if_path_is_moved(expr.id, expr.span, MovedInUse, lp);
               }
           }
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index f250b105d0b..f4eee0526dd 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -23,6 +23,8 @@ use syntax::ast;
 use syntax::codemap::Span;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
+
 struct GatherMoveInfo {
     id: ast::NodeId,
     kind: MoveKind,
@@ -35,7 +37,7 @@ pub fn gather_decl(bccx: &BorrowckCtxt,
                    decl_id: ast::NodeId,
                    _decl_span: Span,
                    var_id: ast::NodeId) {
-    let loan_path = @LpVar(var_id);
+    let loan_path = Rc::new(LpVar(var_id));
     move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
 }
 
@@ -105,7 +107,7 @@ fn gather_move(bccx: &BorrowckCtxt,
            move_info.id, move_info.cmt.repr(bccx.tcx));
 
     let potentially_illegal_move =
-                check_and_get_illegal_move_origin(bccx, move_info.cmt);
+                check_and_get_illegal_move_origin(bccx, &move_info.cmt);
     match potentially_illegal_move {
         Some(illegal_move_origin) => {
             let error = MoveError::with_move_info(illegal_move_origin,
@@ -116,7 +118,7 @@ fn gather_move(bccx: &BorrowckCtxt,
         None => ()
     }
 
-    match opt_loan_path(move_info.cmt) {
+    match opt_loan_path(&move_info.cmt) {
         Some(loan_path) => {
             move_data.add_move(bccx.tcx, loan_path,
                                move_info.id, move_info.kind);
@@ -131,7 +133,7 @@ pub fn gather_assignment(bccx: &BorrowckCtxt,
                          move_data: &MoveData,
                          assignment_id: ast::NodeId,
                          assignment_span: Span,
-                         assignee_loan_path: @LoanPath,
+                         assignee_loan_path: Rc<LoanPath>,
                          assignee_id: ast::NodeId) {
     move_data.add_assignment(bccx.tcx,
                              assignee_loan_path,
@@ -145,7 +147,7 @@ pub fn gather_move_and_assignment(bccx: &BorrowckCtxt,
                                   move_data: &MoveData,
                                   assignment_id: ast::NodeId,
                                   assignment_span: Span,
-                                  assignee_loan_path: @LoanPath,
+                                  assignee_loan_path: Rc<LoanPath>,
                                   assignee_id: ast::NodeId) {
     move_data.add_assignment(bccx.tcx,
                              assignee_loan_path,
@@ -156,14 +158,14 @@ pub fn gather_move_and_assignment(bccx: &BorrowckCtxt,
 }
 
 fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
-                                     cmt: mc::cmt) -> Option<mc::cmt> {
+                                     cmt: &mc::cmt) -> Option<mc::cmt> {
     match cmt.cat {
         mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
         mc::cat_deref(_, _, mc::GcPtr) |
         mc::cat_deref(_, _, mc::UnsafePtr(..)) |
         mc::cat_upvar(..) | mc::cat_static_item |
         mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
-            Some(cmt)
+            Some(cmt.clone())
         }
 
         // Can move out of captured upvars only if the destination closure
@@ -179,12 +181,12 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
             None
         }
 
-        mc::cat_downcast(b) |
-        mc::cat_interior(b, _) => {
+        mc::cat_downcast(ref b) |
+        mc::cat_interior(ref b, _) => {
             match ty::get(b.ty).sty {
                 ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
                     if ty::has_dtor(bccx.tcx, did) {
-                        Some(cmt)
+                        Some(cmt.clone())
                     } else {
                         check_and_get_illegal_move_origin(bccx, b)
                     }
@@ -195,8 +197,8 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
             }
         }
 
-        mc::cat_deref(b, _, mc::OwnedPtr) |
-        mc::cat_discr(b, _) => {
+        mc::cat_deref(ref b, _, mc::OwnedPtr) |
+        mc::cat_discr(ref b, _) => {
             check_and_get_illegal_move_origin(bccx, b)
         }
     }
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index a04afd6d5f3..a27fe5cec22 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -39,9 +39,9 @@ pub fn guarantee_lifetime(bccx: &BorrowckCtxt,
                                          cause: cause,
                                          loan_region: loan_region,
                                          loan_kind: loan_kind,
-                                         cmt_original: cmt,
+                                         cmt_original: cmt.clone(),
                                          root_scope_id: root_scope_id};
-    ctxt.check(cmt, None)
+    ctxt.check(&cmt, None)
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -69,7 +69,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         self.bccx.tcx
     }
 
-    fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
+    fn check(&self, cmt: &mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
         //! Main routine. Walks down `cmt` until we find the "guarantor".
         debug!("guarantee_lifetime.check(cmt={}, loan_region={})",
                cmt.repr(self.bccx.tcx),
@@ -83,15 +83,14 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             mc::cat_upvar(..) |
             mc::cat_deref(_, _, mc::BorrowedPtr(..)) |  // L-Deref-Borrowed
             mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
-                let scope = self.scope(cmt);
-                self.check_scope(scope)
+                self.check_scope(self.scope(cmt))
             }
 
             mc::cat_static_item => {
                 Ok(())
             }
 
-            mc::cat_deref(base, derefs, mc::GcPtr) => {
+            mc::cat_deref(ref base, derefs, mc::GcPtr) => {
                 let base_scope = self.scope(base);
 
                 // L-Deref-Managed-Imm-User-Root
@@ -111,13 +110,13 @@ impl<'a> GuaranteeLifetimeContext<'a> {
                 }
             }
 
-            mc::cat_downcast(base) |
-            mc::cat_deref(base, _, mc::OwnedPtr) |     // L-Deref-Send
-            mc::cat_interior(base, _) => {             // L-Field
+            mc::cat_downcast(ref base) |
+            mc::cat_deref(ref base, _, mc::OwnedPtr) |     // L-Deref-Send
+            mc::cat_interior(ref base, _) => {             // L-Field
                 self.check(base, discr_scope)
             }
 
-            mc::cat_discr(base, new_discr_scope) => {
+            mc::cat_discr(ref base, new_discr_scope) => {
                 // Subtle: in a match, we must ensure that each binding
                 // variable remains valid for the duration of the arm in
                 // which it appears, presuming that this arm is taken.
@@ -176,7 +175,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
     }
 
     fn is_rvalue_or_immutable(&self,
-                              cmt: mc::cmt) -> bool {
+                              cmt: &mc::cmt) -> bool {
         //! We can omit the root on an `@T` value if the location
         //! that holds the box is either (1) an rvalue, in which case
         //! it is in a non-user-accessible temporary, or (2) an immutable
@@ -189,8 +188,8 @@ impl<'a> GuaranteeLifetimeContext<'a> {
     }
 
     fn check_root(&self,
-                  cmt_deref: mc::cmt,
-                  cmt_base: mc::cmt,
+                  cmt_deref: &mc::cmt,
+                  cmt_base: &mc::cmt,
                   derefs: uint,
                   discr_scope: Option<ast::NodeId>) -> R {
         debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, \
@@ -253,7 +252,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         }
     }
 
-    fn is_moved(&self, cmt: mc::cmt) -> bool {
+    fn is_moved(&self, cmt: &mc::cmt) -> bool {
         //! True if `cmt` is something that is potentially moved
         //! out of the current stack frame.
 
@@ -269,9 +268,9 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             mc::cat_upvar(..) => {
                 false
             }
-            r @ mc::cat_downcast(..) |
-            r @ mc::cat_interior(..) |
-            r @ mc::cat_discr(..) => {
+            ref r @ mc::cat_downcast(..) |
+            ref r @ mc::cat_interior(..) |
+            ref r @ mc::cat_discr(..) => {
                 self.tcx().sess.span_bug(
                     cmt.span,
                     format!("illegal guarantor category: {:?}", r));
@@ -279,7 +278,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         }
     }
 
-    fn scope(&self, cmt: mc::cmt) -> ty::Region {
+    fn scope(&self, cmt: &mc::cmt) -> ty::Region {
         //! Returns the maximal region scope for the which the
         //! lvalue `cmt` is guaranteed to be valid without any
         //! rooting etc, and presuming `cmt` is not mutated.
@@ -307,18 +306,18 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             mc::cat_deref(_, _, mc::BorrowedPtr(_, r)) => {
                 r
             }
-            mc::cat_downcast(cmt) |
-            mc::cat_deref(cmt, _, mc::OwnedPtr) |
-            mc::cat_deref(cmt, _, mc::GcPtr) |
-            mc::cat_interior(cmt, _) |
-            mc::cat_discr(cmt, _) => {
+            mc::cat_downcast(ref cmt) |
+            mc::cat_deref(ref cmt, _, mc::OwnedPtr) |
+            mc::cat_deref(ref cmt, _, mc::GcPtr) |
+            mc::cat_interior(ref cmt, _) |
+            mc::cat_discr(ref cmt, _) => {
                 self.scope(cmt)
             }
         }
     }
 
     fn report_error(&self, code: bckerr_code) {
-        self.bccx.report(BckError { cmt: self.cmt_original,
+        self.bccx.report(BckError { cmt: self.cmt_original.clone(),
                                     span: self.span,
                                     cause: self.cause,
                                     code: code });
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index dd9f2eb970b..7f748dffd70 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -36,6 +36,8 @@ use syntax::visit;
 use syntax::visit::{Visitor, FnKind};
 use syntax::ast::{Expr, FnDecl, Block, NodeId, Stmt, Pat, Local};
 
+use std::rc::Rc;
+
 mod lifetime;
 mod restrictions;
 mod gather_moves;
@@ -146,7 +148,7 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt,
         None => {
             // Variable declarations without initializers are considered "moves":
             let tcx = this.bccx.tcx;
-            pat_util::pat_bindings(tcx.def_map, local.pat, |_, id, span, _| {
+            pat_util::pat_bindings(&tcx.def_map, local.pat, |_, id, span, _| {
                 gather_moves::gather_decl(this.bccx,
                                           &this.move_data,
                                           id,
@@ -177,7 +179,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
 
     // If this expression is borrowed, have to ensure it remains valid:
     for &adjustments in tcx.adjustments.borrow().find(&ex.id).iter() {
-        this.guarantee_adjustments(ex, *adjustments);
+        this.guarantee_adjustments(ex, adjustments);
     }
 
     // If this expression is a move, gather it:
@@ -188,7 +190,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
     }
 
     // Special checks for various kinds of expressions:
-    let method_map = this.bccx.method_map.borrow();
+    let method_map = this.bccx.tcx.method_map.borrow();
     match ex.node {
       ast::ExprAddrOf(mutbl, base) => {
         let base_cmt = this.bccx.cat_expr(base);
@@ -228,7 +230,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
         let cmt = this.bccx.cat_expr(ex_v);
         for arm in arms.iter() {
             for pat in arm.pats.iter() {
-                this.gather_pat(cmt, *pat, Some((arm.body.id, ex.id)));
+                this.gather_pat(cmt.clone(), *pat, Some((arm.body.id, ex.id)));
             }
         }
         visit::walk_expr(this, ex, ());
@@ -296,9 +298,9 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
     }
 }
 
-fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |@LoanPath|) {
+fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |Rc<LoanPath>|) {
     let cmt = bccx.cat_expr(expr);
-    match opt_loan_path(cmt) {
+    match opt_loan_path(&cmt) {
         Some(lp) => op(lp),
         None => {
             // This can occur with e.g. `*foo() = 5`.  In such
@@ -375,14 +377,13 @@ impl<'a> GatherLoanCtxt<'a> {
     pub fn guarantee_autoderefs(&mut self,
                                 expr: &ast::Expr,
                                 autoderefs: uint) {
-        let method_map = self.bccx.method_map.borrow();
+        let method_map = self.bccx.tcx.method_map.borrow();
         for i in range(0, autoderefs) {
             match method_map.find(&MethodCall::autoderef(expr.id, i as u32)) {
                 Some(method) => {
                     // Treat overloaded autoderefs as if an AutoRef adjustment
                     // was applied on the base type, as that is always the case.
-                    let mut mc = self.bccx.mc();
-                    let cmt = match mc.cat_expr_autoderefd(expr, i) {
+                    let cmt = match self.bccx.mc().cat_expr_autoderefd(expr, i) {
                         Ok(v) => v,
                         Err(()) => self.tcx().sess.span_bug(expr.span, "Err from mc")
                     };
@@ -431,7 +432,7 @@ impl<'a> GatherLoanCtxt<'a> {
                     autoref: Some(ref autoref),
                     autoderefs}) => {
                 self.guarantee_autoderefs(expr, autoderefs);
-                let mut mc = self.bccx.mc();
+                let mc = self.bccx.mc();
                 let cmt = match mc.cat_expr_autoderefd(expr, autoderefs) {
                     Ok(v) => v,
                     Err(()) => self.tcx().sess.span_bug(expr.span, "Err from mc")
@@ -551,20 +552,20 @@ impl<'a> GatherLoanCtxt<'a> {
         // Check that the lifetime of the borrow does not exceed
         // the lifetime of the data being borrowed.
         if lifetime::guarantee_lifetime(self.bccx, self.item_ub, root_ub,
-                                        borrow_span, cause, cmt, loan_region,
+                                        borrow_span, cause, cmt.clone(), loan_region,
                                         req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of non-mutable data.
         if check_mutability(self.bccx, borrow_span, cause,
-                            cmt, req_kind).is_err() {
+                            cmt.clone(), req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of aliasable data.
         if check_aliasability(self.bccx, borrow_span, cause,
-                              cmt, req_kind).is_err() {
+                              cmt.clone(), req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
@@ -572,7 +573,7 @@ impl<'a> GatherLoanCtxt<'a> {
         // loan is safe.
         let restr = restrictions::compute_restrictions(
             self.bccx, borrow_span, cause,
-            cmt, loan_region, self.restriction_set(req_kind));
+            cmt.clone(), loan_region, self.restriction_set(req_kind));
 
         // Create the loan record (if needed).
         let loan = match restr {
@@ -612,11 +613,11 @@ impl<'a> GatherLoanCtxt<'a> {
                 let gen_scope = self.compute_gen_scope(borrow_id, loan_scope);
                 debug!("gen_scope = {:?}", gen_scope);
 
-                let kill_scope = self.compute_kill_scope(loan_scope, loan_path);
+                let kill_scope = self.compute_kill_scope(loan_scope, &*loan_path);
                 debug!("kill_scope = {:?}", kill_scope);
 
                 if req_kind == ty::MutBorrow {
-                    self.mark_loan_path_as_mutated(loan_path);
+                    self.mark_loan_path_as_mutated(&*loan_path);
                 }
 
                 Loan {
@@ -718,7 +719,7 @@ impl<'a> GatherLoanCtxt<'a> {
         }
     }
 
-    pub fn mark_loan_path_as_mutated(&self, loan_path: @LoanPath) {
+    pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
         //! For mutable loans of content whose mutability derives
         //! from a local variable, mark the mutability decl as necessary.
 
@@ -726,8 +727,8 @@ impl<'a> GatherLoanCtxt<'a> {
             LpVar(local_id) => {
                 self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
             }
-            LpExtend(base, mc::McInherited, _) => {
-                self.mark_loan_path_as_mutated(base);
+            LpExtend(ref base, mc::McInherited, _) => {
+                self.mark_loan_path_as_mutated(&**base);
             }
             LpExtend(_, mc::McDeclared, _) |
             LpExtend(_, mc::McImmutable, _) => {
@@ -752,7 +753,7 @@ impl<'a> GatherLoanCtxt<'a> {
         }
     }
 
-    pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: @LoanPath)
+    pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: &LoanPath)
                               -> ast::NodeId {
         //! Determine when the loan restrictions go out of scope.
         //! This is either when the lifetime expires or when the
@@ -793,7 +794,7 @@ impl<'a> GatherLoanCtxt<'a> {
          * `gather_pat()`.
          */
 
-        let mut mc = self.bccx.mc();
+        let mc = self.bccx.mc();
         for arg in decl.inputs.iter() {
             let arg_ty = ty::node_id_to_type(self.tcx(), arg.pat.id);
 
@@ -822,12 +823,12 @@ impl<'a> GatherLoanCtxt<'a> {
               ast::PatIdent(bm, _, _) if self.pat_is_binding(pat) => {
                 // Each match binding is effectively an assignment.
                 let tcx = self.bccx.tcx;
-                pat_util::pat_bindings(tcx.def_map, pat, |_, id, span, _| {
+                pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
                     gather_moves::gather_assignment(self.bccx,
                                                     &self.move_data,
                                                     id,
                                                     span,
-                                                    @LpVar(id),
+                                                    Rc::new(LpVar(id)),
                                                     id);
                 });
 
@@ -920,7 +921,7 @@ impl<'a> GatherLoanCtxt<'a> {
     }
 
     pub fn pat_is_binding(&self, pat: &ast::Pat) -> bool {
-        pat_util::pat_is_binding(self.bccx.tcx.def_map, pat)
+        pat_util::pat_is_binding(&self.bccx.tcx.def_map, pat)
     }
 
     pub fn report_potential_errors(&self) {
diff --git a/src/librustc/middle/borrowck/gather_loans/move_error.rs b/src/librustc/middle/borrowck/gather_loans/move_error.rs
index c9a8df0f535..24d873e0ff7 100644
--- a/src/librustc/middle/borrowck/gather_loans/move_error.rs
+++ b/src/librustc/middle/borrowck/gather_loans/move_error.rs
@@ -79,7 +79,7 @@ pub struct GroupedMoveErrors {
 fn report_move_errors(bccx: &BorrowckCtxt, errors: &Vec<MoveError>) {
     let grouped_errors = group_errors_with_same_origin(errors);
     for error in grouped_errors.iter() {
-        report_cannot_move_out_of(bccx, error.move_from);
+        report_cannot_move_out_of(bccx, error.move_from.clone());
         let mut is_first_note = true;
         for move_to in error.move_to_places.iter() {
             note_move_destination(bccx, move_to.span,
@@ -112,7 +112,7 @@ fn group_errors_with_same_origin(errors: &Vec<MoveError>)
             }
         }
         grouped_errors.push(GroupedMoveErrors {
-            move_from: error.move_from,
+            move_from: error.move_from.clone(),
             move_to_places: move_to
         })
     }
@@ -128,11 +128,11 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
             bccx.span_err(
                 move_from.span,
                 format!("cannot move out of {}",
-                        bccx.cmt_to_str(move_from)));
+                        bccx.cmt_to_str(&*move_from)));
         }
 
-        mc::cat_downcast(b) |
-        mc::cat_interior(b, _) => {
+        mc::cat_downcast(ref b) |
+        mc::cat_interior(ref b, _) => {
             match ty::get(b.ty).sty {
                 ty::ty_struct(did, _)
                 | ty::ty_enum(did, _) if ty::has_dtor(bccx.tcx, did) => {
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index 39ea9e17b26..de4ce84fb0a 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -18,9 +18,11 @@ use middle::ty;
 use syntax::codemap::Span;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
+
 pub enum RestrictionResult {
     Safe,
-    SafeIf(@LoanPath, Vec<Restriction> )
+    SafeIf(Rc<LoanPath>, Vec<Restriction>)
 }
 
 pub fn compute_restrictions(bccx: &BorrowckCtxt,
@@ -33,7 +35,7 @@ pub fn compute_restrictions(bccx: &BorrowckCtxt,
         bccx: bccx,
         span: span,
         cause: cause,
-        cmt_original: cmt,
+        cmt_original: cmt.clone(),
         loan_region: loan_region,
     };
 
@@ -59,7 +61,7 @@ impl<'a> RestrictionsContext<'a> {
                cmt.repr(self.bccx.tcx),
                restrictions.repr(self.bccx.tcx));
 
-        match cmt.cat {
+        match cmt.cat.clone() {
             mc::cat_rvalue(..) => {
                 // Effectively, rvalues are stored into a
                 // non-aliasable temporary on the stack. Since they
@@ -73,9 +75,11 @@ impl<'a> RestrictionsContext<'a> {
             mc::cat_arg(local_id) |
             mc::cat_upvar(ty::UpvarId {var_id: local_id, ..}, _) => {
                 // R-Variable
-                let lp = @LpVar(local_id);
-                SafeIf(lp, vec!(Restriction {loan_path: lp,
-                                          set: restrictions}))
+                let lp = Rc::new(LpVar(local_id));
+                SafeIf(lp.clone(), vec!(Restriction {
+                    loan_path: lp,
+                    set: restrictions
+                }))
             }
 
             mc::cat_downcast(cmt_base) => {
@@ -170,9 +174,13 @@ impl<'a> RestrictionsContext<'a> {
               restrictions: RestrictionSet) -> RestrictionResult {
         match result {
             Safe => Safe,
-            SafeIf(base_lp, base_vec) => {
-                let lp = @LpExtend(base_lp, mc, elem);
-                SafeIf(lp, base_vec.append_one(Restriction { loan_path: lp, set: restrictions }))
+            SafeIf(base_lp, mut base_vec) => {
+                let lp = Rc::new(LpExtend(base_lp, mc, elem));
+                base_vec.push(Restriction {
+                    loan_path: lp.clone(),
+                    set: restrictions
+                });
+                SafeIf(lp, base_vec)
             }
         }
     }
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 21e68e2724f..06491d36b02 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -18,14 +18,14 @@ use middle::typeck;
 use middle::moves;
 use middle::dataflow::DataFlowContext;
 use middle::dataflow::DataFlowOperator;
-use util::nodemap::NodeSet;
+use util::nodemap::{NodeMap, NodeSet};
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
-use std::cell::{Cell, RefCell};
-use collections::HashMap;
+use std::cell::RefCell;
 use std::ops::{BitOr, BitAnd};
-use std::result::Result;
+use std::rc::Rc;
 use std::strbuf::StrBuf;
+use collections::HashMap;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util;
@@ -76,7 +76,6 @@ impl<'a> Visitor<()> for BorrowckCtxt<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    moves_map: &NodeSet,
                    moved_variables_set: &NodeSet,
                    capture_map: &moves::CaptureMap,
@@ -84,41 +83,15 @@ pub fn check_crate(tcx: &ty::ctxt,
                    -> root_map {
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
-        method_map: method_map,
         moves_map: moves_map,
         moved_variables_set: moved_variables_set,
         capture_map: capture_map,
-        root_map: root_map(),
-        stats: @BorrowStats {
-            loaned_paths_same: Cell::new(0),
-            loaned_paths_imm: Cell::new(0),
-            stable_paths: Cell::new(0),
-            guaranteed_paths: Cell::new(0),
-        }
+        root_map: RefCell::new(HashMap::new())
     };
-    let bccx = &mut bccx;
-
-    visit::walk_crate(bccx, krate, ());
 
-    if tcx.sess.borrowck_stats() {
-        println!("--- borrowck stats ---");
-        println!("paths requiring guarantees: {}",
-                 bccx.stats.guaranteed_paths.get());
-        println!("paths requiring loans     : {}",
-                 make_stat(bccx, bccx.stats.loaned_paths_same.get()));
-        println!("paths requiring imm loans : {}",
-                 make_stat(bccx, bccx.stats.loaned_paths_imm.get()));
-        println!("stable paths              : {}",
-                 make_stat(bccx, bccx.stats.stable_paths.get()));
-    }
-
-    return bccx.root_map;
+    visit::walk_crate(&mut bccx, krate, ());
 
-    fn make_stat(bccx: &mut BorrowckCtxt, stat: uint) -> ~str {
-        let stat_f = stat as f64;
-        let total = bccx.stats.guaranteed_paths.get() as f64;
-        format!("{} ({:.0f}%)", stat  , stat_f * 100.0 / total)
-    }
+    return bccx.root_map.unwrap();
 }
 
 fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
@@ -149,7 +122,6 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
         gather_loans::gather_loans_in_fn(this, decl, body);
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
-                             this.method_map,
                              LoanDataFlowOperator,
                              id_range,
                              all_loans.len());
@@ -161,7 +133,6 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
     let flowed_moves = move_data::FlowedMoveData::new(move_data,
                                                       this.tcx,
-                                                      this.method_map,
                                                       id_range,
                                                       body);
 
@@ -176,21 +147,10 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
 pub struct BorrowckCtxt<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
     moves_map: &'a NodeSet,
     moved_variables_set: &'a NodeSet,
     capture_map: &'a moves::CaptureMap,
-    root_map: root_map,
-
-    // Statistics:
-    stats: @BorrowStats
-}
-
-pub struct BorrowStats {
-    loaned_paths_same: Cell<uint>,
-    loaned_paths_imm: Cell<uint>,
-    stable_paths: Cell<uint>,
-    guaranteed_paths: Cell<uint>,
+    root_map: RefCell<root_map>,
 }
 
 // The keys to the root map combine the `id` of the deref expression
@@ -226,10 +186,10 @@ pub enum PartialTotal {
 /// Record of a loan that was issued.
 pub struct Loan {
     index: uint,
-    loan_path: @LoanPath,
+    loan_path: Rc<LoanPath>,
     cmt: mc::cmt,
     kind: ty::BorrowKind,
-    restrictions: Vec<Restriction> ,
+    restrictions: Vec<Restriction>,
     gen_scope: ast::NodeId,
     kill_scope: ast::NodeId,
     span: Span,
@@ -247,7 +207,7 @@ pub enum LoanCause {
 #[deriving(Eq, TotalEq, Hash)]
 pub enum LoanPath {
     LpVar(ast::NodeId),               // `x` in doc.rs
-    LpExtend(@LoanPath, mc::MutabilityCategory, LoanPathElem)
+    LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
 }
 
 #[deriving(Eq, TotalEq, Hash)]
@@ -260,12 +220,12 @@ impl LoanPath {
     pub fn node_id(&self) -> ast::NodeId {
         match *self {
             LpVar(local_id) => local_id,
-            LpExtend(base, _, _) => base.node_id()
+            LpExtend(ref base, _, _) => base.node_id()
         }
     }
 }
 
-pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
+pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
     //! Computes the `LoanPath` (if any) for a `cmt`.
     //! Note that this logic is somewhat duplicated in
     //! the method `compute()` found in `gather_loans::restrictions`,
@@ -283,23 +243,23 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
         mc::cat_arg(id) |
         mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
         mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => {
-            Some(@LpVar(id))
+            Some(Rc::new(LpVar(id)))
         }
 
-        mc::cat_deref(cmt_base, _, pk) => {
+        mc::cat_deref(ref cmt_base, _, pk) => {
             opt_loan_path(cmt_base).map(|lp| {
-                @LpExtend(lp, cmt.mutbl, LpDeref(pk))
+                Rc::new(LpExtend(lp, cmt.mutbl, LpDeref(pk)))
             })
         }
 
-        mc::cat_interior(cmt_base, ik) => {
+        mc::cat_interior(ref cmt_base, ik) => {
             opt_loan_path(cmt_base).map(|lp| {
-                @LpExtend(lp, cmt.mutbl, LpInterior(ik))
+                Rc::new(LpExtend(lp, cmt.mutbl, LpInterior(ik)))
             })
         }
 
-        mc::cat_downcast(cmt_base) |
-        mc::cat_discr(cmt_base, _) => {
+        mc::cat_downcast(ref cmt_base) |
+        mc::cat_discr(ref cmt_base, _) => {
             opt_loan_path(cmt_base)
         }
     }
@@ -319,7 +279,7 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
 // because the restriction against moves is implied.
 
 pub struct Restriction {
-    loan_path: @LoanPath,
+    loan_path: Rc<LoanPath>,
     set: RestrictionSet
 }
 
@@ -380,11 +340,7 @@ pub struct RootInfo {
     pub scope: ast::NodeId,
 }
 
-pub type root_map = @RefCell<HashMap<root_map_key, RootInfo>>;
-
-pub fn root_map() -> root_map {
-    return @RefCell::new(HashMap::new());
-}
+pub type root_map = HashMap<root_map_key, RootInfo>;
 
 ///////////////////////////////////////////////////////////////////////////
 // Errors
@@ -437,12 +393,9 @@ impl<'a> BorrowckCtxt<'a> {
         self.moves_map.contains(&id)
     }
 
-    pub fn mc(&self) -> mc::MemCategorizationContext<TcxTyper<'a>> {
+    pub fn mc(&self) -> mc::MemCategorizationContext<&'a ty::ctxt> {
         mc::MemCategorizationContext {
-            typer: TcxTyper {
-                tcx: self.tcx,
-                method_map: self.method_map
-            }
+            typer: self.tcx,
         }
     }
 
@@ -516,14 +469,16 @@ impl<'a> BorrowckCtxt<'a> {
     }
 
     pub fn cat_discr(&self, cmt: mc::cmt, match_id: ast::NodeId) -> mc::cmt {
-        @mc::cmt_ {cat:mc::cat_discr(cmt, match_id),
-                   mutbl:cmt.mutbl.inherit(),
-                   ..*cmt}
+        Rc::new(mc::cmt_ {
+            cat: mc::cat_discr(cmt.clone(), match_id),
+            mutbl: cmt.mutbl.inherit(),
+            ..*cmt
+        })
     }
 
     pub fn cat_pattern(&self,
                        cmt: mc::cmt,
-                       pat: @ast::Pat,
+                       pat: &ast::Pat,
                        op: |mc::cmt, &ast::Pat|) {
         let r = self.mc().cat_pattern(cmt, pat, |_,x,y| op(x,y));
         assert!(r.is_ok());
@@ -532,7 +487,7 @@ impl<'a> BorrowckCtxt<'a> {
     pub fn report(&self, err: BckError) {
         self.span_err(
             err.span,
-            self.bckerr_to_str(err));
+            self.bckerr_to_str(&err));
         self.note_and_explain_bckerr(err);
     }
 
@@ -541,7 +496,7 @@ impl<'a> BorrowckCtxt<'a> {
                                      use_kind: MovedValueUseKind,
                                      lp: &LoanPath,
                                      move: &move_data::Move,
-                                     moved_lp: @LoanPath) {
+                                     moved_lp: &LoanPath) {
         let verb = match use_kind {
             MovedInUse => "use",
             MovedInCapture => "capture",
@@ -572,8 +527,7 @@ impl<'a> BorrowckCtxt<'a> {
             move_data::MoveExpr => {
                 let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
                     Some(ast_map::NodeExpr(expr)) => {
-                        (ty::expr_ty_adjusted(self.tcx, expr,
-                                              &*self.method_map.borrow()), expr.span)
+                        (ty::expr_ty_adjusted(self.tcx, expr), expr.span)
                     }
                     r => self.tcx.sess.bug(format!("MoveExpr({:?}) maps to {:?}, not Expr",
                                                    move.id, r))
@@ -599,8 +553,7 @@ impl<'a> BorrowckCtxt<'a> {
             move_data::Captured => {
                 let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
                     Some(ast_map::NodeExpr(expr)) => {
-                        (ty::expr_ty_adjusted(self.tcx, expr,
-                                              &*self.method_map.borrow()), expr.span)
+                        (ty::expr_ty_adjusted(self.tcx, expr), expr.span)
                     }
                     r => self.tcx.sess.bug(format!("Captured({:?}) maps to {:?}, not Expr",
                                                    move.id, r))
@@ -656,17 +609,17 @@ impl<'a> BorrowckCtxt<'a> {
         self.tcx.sess.span_end_note(s, m);
     }
 
-    pub fn bckerr_to_str(&self, err: BckError) -> ~str {
+    pub fn bckerr_to_str(&self, err: &BckError) -> ~str {
         match err.code {
             err_mutbl => {
-                let descr = match opt_loan_path(err.cmt) {
+                let descr = match opt_loan_path(&err.cmt) {
                     None => format!("{} {}",
                                     err.cmt.mutbl.to_user_str(),
-                                    self.cmt_to_str(err.cmt)),
+                                    self.cmt_to_str(&*err.cmt)),
                     Some(lp) => format!("{} {} `{}`",
                                         err.cmt.mutbl.to_user_str(),
-                                        self.cmt_to_str(err.cmt),
-                                        self.loan_path_to_str(lp)),
+                                        self.cmt_to_str(&*err.cmt),
+                                        self.loan_path_to_str(&*lp)),
                 };
 
                 match err.cause {
@@ -682,16 +635,16 @@ impl<'a> BorrowckCtxt<'a> {
                 format!("cannot root managed value long enough")
             }
             err_out_of_scope(..) => {
-                let msg = match opt_loan_path(err.cmt) {
+                let msg = match opt_loan_path(&err.cmt) {
                     None => format!("borrowed value"),
-                    Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
+                    Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
                 };
                 format!("{} does not live long enough", msg)
             }
             err_borrowed_pointer_too_short(..) => {
-                let descr = match opt_loan_path(err.cmt) {
-                    Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
-                    None => self.cmt_to_str(err.cmt),
+                let descr = match opt_loan_path(&err.cmt) {
+                    Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
+                    None => self.cmt_to_str(&*err.cmt),
                 };
 
                 format!("lifetime of {} is too short to guarantee \
@@ -783,9 +736,9 @@ impl<'a> BorrowckCtxt<'a> {
             }
 
             err_borrowed_pointer_too_short(loan_scope, ptr_scope, _) => {
-                let descr = match opt_loan_path(err.cmt) {
-                    Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
-                    None => self.cmt_to_str(err.cmt),
+                let descr = match opt_loan_path(&err.cmt) {
+                    Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
+                    None => self.cmt_to_str(&*err.cmt),
                 };
                 note_and_explain_region(
                     self.tcx,
@@ -809,8 +762,8 @@ impl<'a> BorrowckCtxt<'a> {
                 out.push_str(ty::local_var_name_str(self.tcx, id).get());
             }
 
-            LpExtend(lp_base, _, LpInterior(mc::InteriorField(fname))) => {
-                self.append_autoderefd_loan_path_to_str(lp_base, out);
+            LpExtend(ref lp_base, _, LpInterior(mc::InteriorField(fname))) => {
+                self.append_autoderefd_loan_path_to_str(&**lp_base, out);
                 match fname {
                     mc::NamedField(fname) => {
                         out.push_char('.');
@@ -823,14 +776,14 @@ impl<'a> BorrowckCtxt<'a> {
                 }
             }
 
-            LpExtend(lp_base, _, LpInterior(mc::InteriorElement(_))) => {
-                self.append_autoderefd_loan_path_to_str(lp_base, out);
+            LpExtend(ref lp_base, _, LpInterior(mc::InteriorElement(_))) => {
+                self.append_autoderefd_loan_path_to_str(&**lp_base, out);
                 out.push_str("[..]");
             }
 
-            LpExtend(lp_base, _, LpDeref(_)) => {
+            LpExtend(ref lp_base, _, LpDeref(_)) => {
                 out.push_char('*');
-                self.append_loan_path_to_str(lp_base, out);
+                self.append_loan_path_to_str(&**lp_base, out);
             }
         }
     }
@@ -839,11 +792,11 @@ impl<'a> BorrowckCtxt<'a> {
                                               loan_path: &LoanPath,
                                               out: &mut StrBuf) {
         match *loan_path {
-            LpExtend(lp_base, _, LpDeref(_)) => {
+            LpExtend(ref lp_base, _, LpDeref(_)) => {
                 // For a path like `(*x).f` or `(*x)[3]`, autoderef
                 // rules would normally allow users to omit the `*x`.
                 // So just serialize such paths to `x.f` or x[3]` respectively.
-                self.append_autoderefd_loan_path_to_str(lp_base, out)
+                self.append_autoderefd_loan_path_to_str(&**lp_base, out)
             }
 
             LpVar(..) | LpExtend(_, _, LpInterior(..)) => {
@@ -858,7 +811,7 @@ impl<'a> BorrowckCtxt<'a> {
         result.into_owned()
     }
 
-    pub fn cmt_to_str(&self, cmt: mc::cmt) -> ~str {
+    pub fn cmt_to_str(&self, cmt: &mc::cmt_) -> ~str {
         self.mc().cmt_to_str(cmt)
     }
 }
@@ -902,11 +855,11 @@ impl Repr for LoanPath {
                 format!("$({})", tcx.map.node_to_str(id))
             }
 
-            &LpExtend(lp, _, LpDeref(_)) => {
+            &LpExtend(ref lp, _, LpDeref(_)) => {
                 format!("{}.*", lp.repr(tcx))
             }
 
-            &LpExtend(lp, _, LpInterior(ref interior)) => {
+            &LpExtend(ref lp, _, LpInterior(ref interior)) => {
                 format!("{}.{}", lp.repr(tcx), interior.repr(tcx))
             }
         }
@@ -915,37 +868,32 @@ impl Repr for LoanPath {
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub struct TcxTyper<'a> {
-    tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
-}
-
-impl<'a> mc::Typer for TcxTyper<'a> {
+impl<'a> mc::Typer for &'a ty::ctxt {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
-        self.tcx
+        *self
     }
 
-    fn node_ty(&mut self, id: ast::NodeId) -> mc::McResult<ty::t> {
-        Ok(ty::node_id_to_type(self.tcx, id))
+    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
+        Ok(ty::node_id_to_type(*self, id))
     }
 
     fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t> {
         self.method_map.borrow().find(&method_call).map(|method| method.ty)
     }
 
-    fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
-        self.tcx.adjustments.borrow().find_copy(&id)
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+        &self.adjustments
     }
 
-    fn is_method_call(&mut self, id: ast::NodeId) -> bool {
+    fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
     }
 
-    fn temporary_scope(&mut self, id: ast::NodeId) -> Option<ast::NodeId> {
-        self.tcx.region_maps.temporary_scope(id)
+    fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
+        self.region_maps.temporary_scope(id)
     }
 
-    fn upvar_borrow(&mut self, id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.tcx.upvar_borrow_map.borrow().get_copy(&id)
+    fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
+        self.upvar_borrow_map.borrow().get_copy(&id)
     }
 }
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 0e18946a3a1..efdc103d14d 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -16,13 +16,13 @@ comments in the section "Moves and initialization" and in `doc.rs`.
 */
 
 use std::cell::RefCell;
+use std::rc::Rc;
 use std::uint;
 use collections::{HashMap, HashSet};
 use middle::borrowck::*;
 use middle::dataflow::DataFlowContext;
 use middle::dataflow::DataFlowOperator;
 use middle::ty;
-use middle::typeck;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
@@ -33,7 +33,7 @@ pub struct MoveData {
     pub paths: RefCell<Vec<MovePath>>,
 
     /// Cache of loan path to move path index, for easy lookup.
-    pub path_map: RefCell<HashMap<@LoanPath, MovePathIndex>>,
+    pub path_map: RefCell<HashMap<Rc<LoanPath>, MovePathIndex>>,
 
     /// Each move or uninitialized variable gets an entry here.
     pub moves: RefCell<Vec<Move>>,
@@ -97,7 +97,7 @@ static InvalidMoveIndex: MoveIndex =
 
 pub struct MovePath {
     /// Loan path corresponding to this move path
-    pub loan_path: @LoanPath,
+    pub loan_path: Rc<LoanPath>,
 
     /// Parent pointer, `InvalidMovePathIndex` if root
     pub parent: MovePathIndex,
@@ -182,8 +182,8 @@ impl MoveData {
         }
     }
 
-    fn path_loan_path(&self, index: MovePathIndex) -> @LoanPath {
-        self.paths.borrow().get(index.get()).loan_path
+    fn path_loan_path(&self, index: MovePathIndex) -> Rc<LoanPath> {
+        self.paths.borrow().get(index.get()).loan_path.clone()
     }
 
     fn path_parent(&self, index: MovePathIndex) -> MovePathIndex {
@@ -226,7 +226,7 @@ impl MoveData {
 
     pub fn move_path(&self,
                      tcx: &ty::ctxt,
-                     lp: @LoanPath) -> MovePathIndex {
+                     lp: Rc<LoanPath>) -> MovePathIndex {
         /*!
          * Returns the existing move path index for `lp`, if any,
          * and otherwise adds a new index for `lp` and any of its
@@ -245,7 +245,7 @@ impl MoveData {
                 let index = MovePathIndex(self.paths.borrow().len());
 
                 self.paths.borrow_mut().push(MovePath {
-                    loan_path: lp,
+                    loan_path: lp.clone(),
                     parent: InvalidMovePathIndex,
                     first_move: InvalidMoveIndex,
                     first_child: InvalidMovePathIndex,
@@ -255,8 +255,8 @@ impl MoveData {
                 index
             }
 
-            LpExtend(base, _, _) => {
-                let parent_index = self.move_path(tcx, base);
+            LpExtend(ref base, _, _) => {
+                let parent_index = self.move_path(tcx, base.clone());
 
                 let index = MovePathIndex(self.paths.borrow().len());
 
@@ -264,7 +264,7 @@ impl MoveData {
                 self.set_path_first_child(parent_index, index);
 
                 self.paths.borrow_mut().push(MovePath {
-                    loan_path: lp,
+                    loan_path: lp.clone(),
                     parent: parent_index,
                     first_move: InvalidMoveIndex,
                     first_child: InvalidMovePathIndex,
@@ -284,29 +284,26 @@ impl MoveData {
         return index;
     }
 
-    fn existing_move_path(&self,
-                          lp: @LoanPath)
+    fn existing_move_path(&self, lp: &Rc<LoanPath>)
                           -> Option<MovePathIndex> {
-        self.path_map.borrow().find_copy(&lp)
+        self.path_map.borrow().find_copy(lp)
     }
 
-    fn existing_base_paths(&self,
-                           lp: @LoanPath)
+    fn existing_base_paths(&self, lp: &Rc<LoanPath>)
                            -> Vec<MovePathIndex> {
         let mut result = vec!();
         self.add_existing_base_paths(lp, &mut result);
         result
     }
 
-    fn add_existing_base_paths(&self,
-                               lp: @LoanPath,
+    fn add_existing_base_paths(&self, lp: &Rc<LoanPath>,
                                result: &mut Vec<MovePathIndex>) {
         /*!
          * Adds any existing move path indices for `lp` and any base
          * paths of `lp` to `result`, but does not add new move paths
          */
 
-        match self.path_map.borrow().find_copy(&lp) {
+        match self.path_map.borrow().find_copy(lp) {
             Some(index) => {
                 self.each_base_path(index, |p| {
                     result.push(p);
@@ -314,9 +311,9 @@ impl MoveData {
                 });
             }
             None => {
-                match *lp {
+                match **lp {
                     LpVar(..) => { }
-                    LpExtend(b, _, _) => {
+                    LpExtend(ref b, _, _) => {
                         self.add_existing_base_paths(b, result);
                     }
                 }
@@ -327,7 +324,7 @@ impl MoveData {
 
     pub fn add_move(&self,
                     tcx: &ty::ctxt,
-                    lp: @LoanPath,
+                    lp: Rc<LoanPath>,
                     id: ast::NodeId,
                     kind: MoveKind) {
         /*!
@@ -356,7 +353,7 @@ impl MoveData {
 
     pub fn add_assignment(&self,
                           tcx: &ty::ctxt,
-                          lp: @LoanPath,
+                          lp: Rc<LoanPath>,
                           assign_id: ast::NodeId,
                           span: Span,
                           assignee_id: ast::NodeId,
@@ -369,7 +366,7 @@ impl MoveData {
         debug!("add_assignment(lp={}, assign_id={:?}, assignee_id={:?}",
                lp.repr(tcx), assign_id, assignee_id);
 
-        let path_index = self.move_path(tcx, lp);
+        let path_index = self.move_path(tcx, lp.clone());
 
         if !is_also_move {
             self.assignee_ids.borrow_mut().insert(assignee_id);
@@ -511,19 +508,16 @@ impl MoveData {
 impl<'a> FlowedMoveData<'a> {
     pub fn new(move_data: MoveData,
                tcx: &'a ty::ctxt,
-               method_map: typeck::MethodMap,
                id_range: ast_util::IdRange,
                body: &ast::Block)
                -> FlowedMoveData<'a> {
         let mut dfcx_moves =
             DataFlowContext::new(tcx,
-                                 method_map,
                                  MoveDataFlowOperator,
                                  id_range,
                                  move_data.moves.borrow().len());
         let mut dfcx_assign =
             DataFlowContext::new(tcx,
-                                 method_map,
                                  AssignDataFlowOperator,
                                  id_range,
                                  move_data.var_assignments.borrow().len());
@@ -539,7 +533,7 @@ impl<'a> FlowedMoveData<'a> {
 
     pub fn each_path_moved_by(&self,
                               id: ast::NodeId,
-                              f: |&Move, @LoanPath| -> bool)
+                              f: |&Move, &LoanPath| -> bool)
                               -> bool {
         /*!
          * Iterates through each path moved by `id`
@@ -549,14 +543,14 @@ impl<'a> FlowedMoveData<'a> {
             let move = self.move_data.moves.borrow();
             let move = move.get(index);
             let moved_path = move.path;
-            f(move, self.move_data.path_loan_path(moved_path))
+            f(move, &*self.move_data.path_loan_path(moved_path))
         })
     }
 
     pub fn each_move_of(&self,
                         id: ast::NodeId,
-                        loan_path: @LoanPath,
-                        f: |&Move, @LoanPath| -> bool)
+                        loan_path: &Rc<LoanPath>,
+                        f: |&Move, &LoanPath| -> bool)
                         -> bool {
         /*!
          * Iterates through each move of `loan_path` (or some base path
@@ -591,7 +585,7 @@ impl<'a> FlowedMoveData<'a> {
             if base_indices.iter().any(|x| x == &moved_path) {
                 // Scenario 1 or 2: `loan_path` or some base path of
                 // `loan_path` was moved.
-                if !f(move, self.move_data.path_loan_path(moved_path)) {
+                if !f(move, &*self.move_data.path_loan_path(moved_path)) {
                     ret = false;
                 }
             } else {
@@ -600,7 +594,7 @@ impl<'a> FlowedMoveData<'a> {
                         if p == loan_path_index {
                             // Scenario 3: some extension of `loan_path`
                             // was moved
-                            f(move, self.move_data.path_loan_path(moved_path))
+                            f(move, &*self.move_data.path_loan_path(moved_path))
                         } else {
                             true
                         }
@@ -621,7 +615,7 @@ impl<'a> FlowedMoveData<'a> {
 
     pub fn each_assignment_of(&self,
                               id: ast::NodeId,
-                              loan_path: @LoanPath,
+                              loan_path: &Rc<LoanPath>,
                               f: |&Assignment| -> bool)
                               -> bool {
         /*!
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 67f3b8fe906..eb52aa18de8 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -21,8 +21,6 @@ use syntax::visit::Visitor;
 use syntax::visit;
 
 pub struct CheckCrateVisitor<'a> {
-    def_map: resolve::DefMap,
-    method_map: typeck::MethodMap,
     tcx: &'a ty::ctxt,
 }
 
@@ -38,16 +36,8 @@ impl<'a> Visitor<bool> for CheckCrateVisitor<'a> {
     }
 }
 
-pub fn check_crate(krate: &Crate,
-                   def_map: resolve::DefMap,
-                   method_map: typeck::MethodMap,
-                   tcx: &ty::ctxt) {
-    let mut v = CheckCrateVisitor {
-        def_map: def_map,
-        method_map: method_map,
-        tcx: tcx,
-    };
-    visit::walk_crate(&mut v, krate, false);
+pub fn check_crate(krate: &Crate, tcx: &ty::ctxt) {
+    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx }, krate, false);
     tcx.sess.abort_if_errors();
 }
 
@@ -55,7 +45,7 @@ fn check_item(v: &mut CheckCrateVisitor, it: &Item, _is_const: bool) {
     match it.node {
         ItemStatic(_, _, ex) => {
             v.visit_expr(ex, true);
-            check_item_recursion(&v.tcx.sess, &v.tcx.map, v.def_map, it);
+            check_item_recursion(&v.tcx.sess, &v.tcx.map, &v.tcx.def_map, it);
         }
         ItemEnum(ref enum_definition, _) => {
             for var in (*enum_definition).variants.iter() {
@@ -103,7 +93,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
           ExprLit(lit) if ast_util::lit_is_str(lit) => {}
           ExprBinary(..) | ExprUnary(..) => {
             let method_call = typeck::MethodCall::expr(e.id);
-            if v.method_map.borrow().contains_key(&method_call) {
+            if v.tcx.method_map.borrow().contains_key(&method_call) {
                 v.tcx.sess.span_err(e.span, "user-defined operators are not \
                                              allowed in constant expressions");
             }
@@ -127,7 +117,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
                                     "paths in constants may only refer to \
                                      items without type parameters");
             }
-            match v.def_map.borrow().find(&e.id) {
+            match v.tcx.def_map.borrow().find(&e.id) {
               Some(&DefStatic(..)) |
               Some(&DefFn(_, _)) |
               Some(&DefVariant(_, _, _)) |
@@ -145,7 +135,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
             }
           }
           ExprCall(callee, _) => {
-            match v.def_map.borrow().find(&callee.id) {
+            match v.tcx.def_map.borrow().find(&callee.id) {
                 Some(&DefStruct(..)) => {}    // OK.
                 Some(&DefVariant(..)) => {}    // OK.
                 _ => {
@@ -188,14 +178,14 @@ struct CheckItemRecursionVisitor<'a> {
     root_it: &'a Item,
     sess: &'a Session,
     ast_map: &'a ast_map::Map,
-    def_map: resolve::DefMap,
+    def_map: &'a resolve::DefMap,
     idstack: Vec<NodeId> }
 
 // Make sure a const item doesn't recursively refer to itself
 // FIXME: Should use the dependency graph when it's available (#1356)
 pub fn check_item_recursion<'a>(sess: &'a Session,
                                 ast_map: &'a ast_map::Map,
-                                def_map: resolve::DefMap,
+                                def_map: &'a resolve::DefMap,
                                 it: &'a Item) {
 
     let mut visitor = CheckItemRecursionVisitor {
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index db1badb7d59..2ef009e36e4 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -15,7 +15,6 @@ use middle::const_eval::{eval_const_expr, const_val, const_bool, const_float};
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
-use middle::typeck::MethodMap;
 use util::nodemap::NodeSet;
 use util::ppaux::ty_to_str;
 
@@ -30,7 +29,6 @@ use syntax::visit::{Visitor, FnKind};
 
 struct MatchCheckCtxt<'a> {
     tcx: &'a ty::ctxt,
-    method_map: MethodMap,
     moves_map: &'a NodeSet
 }
 
@@ -47,12 +45,10 @@ impl<'a> Visitor<()> for MatchCheckCtxt<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: MethodMap,
                    moves_map: &NodeSet,
                    krate: &Crate) {
     let mut cx = MatchCheckCtxt {
         tcx: tcx,
-        method_map: method_map,
         moves_map: moves_map
     };
 
@@ -938,7 +934,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                                        has_guard: bool,
                                        pats: &[@Pat]) {
     let tcx = cx.tcx;
-    let def_map = tcx.def_map;
+    let def_map = &tcx.def_map;
     let mut by_ref_span = None;
     let mut any_by_move = false;
     for pat in pats.iter() {
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index d39f0721b42..cd3ab100e55 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -15,7 +15,7 @@ use middle::astencode;
 
 use middle::ty;
 use middle::typeck::astconv;
-use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
+use util::nodemap::{DefIdMap, NodeMap};
 
 use syntax::ast::*;
 use syntax::parse::token::InternedString;
@@ -127,9 +127,7 @@ pub fn lookup_variant_by_id(tcx: &ty::ctxt,
             None => {}
         }
         let maps = astencode::Maps {
-            root_map: @RefCell::new(HashMap::new()),
-            method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(FnvHashMap::new()),
+            root_map: HashMap::new(),
             capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, enum_def,
@@ -168,9 +166,7 @@ pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId)
             None => {}
         }
         let maps = astencode::Maps {
-            root_map: @RefCell::new(HashMap::new()),
-            method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(FnvHashMap::new()),
+            root_map: HashMap::new(),
             capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, def_id,
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 2b79917f9d5..742daa82ecd 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -32,7 +32,6 @@ use util::nodemap::NodeMap;
 #[deriving(Clone)]
 pub struct DataFlowContext<'a, O> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
 
     /// the data flow operator
     oper: O,
@@ -123,7 +122,6 @@ impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> {
 
 impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
     pub fn new(tcx: &'a ty::ctxt,
-               method_map: typeck::MethodMap,
                oper: O,
                id_range: IdRange,
                bits_per_id: uint) -> DataFlowContext<'a, O> {
@@ -138,7 +136,6 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
 
         DataFlowContext {
             tcx: tcx,
-            method_map: method_map,
             words_per_id: words_per_id,
             nodeid_to_bitset: NodeMap::new(),
             bits_per_id: bits_per_id,
@@ -784,7 +781,7 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> {
 
     fn is_method_call(&self, expr: &ast::Expr) -> bool {
         let method_call = typeck::MethodCall::expr(expr.id);
-        self.dfcx.method_map.borrow().contains_key(&method_call)
+        self.dfcx.tcx.method_map.borrow().contains_key(&method_call)
     }
 
     fn reset(&mut self, bits: &mut [uint]) {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 413c6a4de1d..74355357fe7 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -50,18 +50,15 @@ fn should_explore(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
 
 struct MarkSymbolVisitor<'a> {
     worklist: Vec<ast::NodeId>,
-    method_map: typeck::MethodMap,
     tcx: &'a ty::ctxt,
     live_symbols: ~HashSet<ast::NodeId>,
 }
 
 impl<'a> MarkSymbolVisitor<'a> {
     fn new(tcx: &'a ty::ctxt,
-           method_map: typeck::MethodMap,
            worklist: Vec<ast::NodeId>) -> MarkSymbolVisitor<'a> {
         MarkSymbolVisitor {
             worklist: worklist,
-            method_map: method_map,
             tcx: tcx,
             live_symbols: ~HashSet::new(),
         }
@@ -93,7 +90,7 @@ impl<'a> MarkSymbolVisitor<'a> {
     fn lookup_and_handle_method(&mut self, id: ast::NodeId,
                                 span: codemap::Span) {
         let method_call = typeck::MethodCall::expr(id);
-        match self.method_map.borrow().find(&method_call) {
+        match self.tcx.method_map.borrow().find(&method_call) {
             Some(method) => {
                 match method.origin {
                     typeck::MethodStatic(def_id) => {
@@ -285,14 +282,13 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
 }
 
 fn find_live(tcx: &ty::ctxt,
-             method_map: typeck::MethodMap,
              exported_items: &privacy::ExportedItems,
              reachable_symbols: &NodeSet,
              krate: &ast::Crate)
              -> ~HashSet<ast::NodeId> {
     let worklist = create_and_seed_worklist(tcx, exported_items,
                                             reachable_symbols, krate);
-    let mut symbol_visitor = MarkSymbolVisitor::new(tcx, method_map, worklist);
+    let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
     symbol_visitor.mark_live_symbols();
     symbol_visitor.live_symbols
 }
@@ -340,13 +336,13 @@ impl<'a> DeadVisitor<'a> {
         // This is done to handle the case where, for example, the static
         // method of a private type is used, but the type itself is never
         // called directly.
-        let def_id = local_def(id);
-        match self.tcx.inherent_impls.borrow().find(&def_id) {
+        let impl_methods = self.tcx.impl_methods.borrow();
+        match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
             None => (),
-            Some(ref impl_list) => {
-                for impl_ in impl_list.borrow().iter() {
-                    for method in impl_.methods.iter() {
-                        if self.live_symbols.contains(&method.def_id.node) {
+            Some(impl_list) => {
+                for impl_did in impl_list.borrow().iter() {
+                    for method_did in impl_methods.get(impl_did).iter() {
+                        if self.live_symbols.contains(&method_did.node) {
                             return true;
                         }
                     }
@@ -406,11 +402,10 @@ impl<'a> Visitor<()> for DeadVisitor<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    reachable_symbols: &NodeSet,
                    krate: &ast::Crate) {
-    let live_symbols = find_live(tcx, method_map, exported_items,
+    let live_symbols = find_live(tcx, exported_items,
                                  reachable_symbols, krate);
     let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
     visit::walk_crate(&mut visitor, krate, ());
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 827d07484b7..ef7c5924844 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -12,7 +12,7 @@
 /// `unsafe`.
 
 use middle::ty;
-use middle::typeck::{MethodCall, MethodMap};
+use middle::typeck::MethodCall;
 use util::ppaux;
 
 use syntax::ast;
@@ -38,8 +38,6 @@ fn type_is_unsafe_function(ty: ty::t) -> bool {
 struct EffectCheckVisitor<'a> {
     tcx: &'a ty::ctxt,
 
-    /// The method map.
-    method_map: MethodMap,
     /// Whether we're in an unsafe context.
     unsafe_context: UnsafeContext,
 }
@@ -138,7 +136,7 @@ impl<'a> Visitor<()> for EffectCheckVisitor<'a> {
         match expr.node {
             ast::ExprMethodCall(_, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
-                let base_type = self.method_map.borrow().get(&method_call).ty;
+                let base_type = self.tcx.method_map.borrow().get(&method_call).ty;
                 debug!("effect: method call case, base type is {}",
                        ppaux::ty_to_str(self.tcx, base_type));
                 if type_is_unsafe_function(base_type) {
@@ -190,10 +188,9 @@ impl<'a> Visitor<()> for EffectCheckVisitor<'a> {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt, method_map: MethodMap, krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt, krate: &ast::Crate) {
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
-        method_map: method_map,
         unsafe_context: SafeContext,
     };
 
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index d6adb19419b..83f6d5abfa4 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -29,16 +29,15 @@ pub struct freevar_entry {
     pub def: ast::Def, //< The variable being accessed free.
     pub span: Span     //< First span where it is accessed (there can be multiple)
 }
-pub type freevar_info = @Vec<@freevar_entry> ;
-pub type freevar_map = NodeMap<freevar_info>;
+pub type freevar_map = NodeMap<Vec<freevar_entry>>;
 
-struct CollectFreevarsVisitor {
+struct CollectFreevarsVisitor<'a> {
     seen: NodeSet,
-    refs: Vec<@freevar_entry> ,
-    def_map: resolve::DefMap,
+    refs: Vec<freevar_entry>,
+    def_map: &'a resolve::DefMap,
 }
 
-impl Visitor<int> for CollectFreevarsVisitor {
+impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
 
     fn visit_item(&mut self, _: &ast::Item, _: int) {
         // ignore_item
@@ -65,7 +64,7 @@ impl Visitor<int> for CollectFreevarsVisitor {
                         if i == depth { // Made it to end of loop
                             let dnum = ast_util::def_id_of_def(def).node;
                             if !self.seen.contains(&dnum) {
-                                self.refs.push(@freevar_entry {
+                                self.refs.push(freevar_entry {
                                     def: def,
                                     span: expr.span,
                                 });
@@ -87,30 +86,23 @@ impl Visitor<int> for CollectFreevarsVisitor {
 // Since we want to be able to collect upvars in some arbitrary piece
 // of the AST, we take a walker function that we invoke with a visitor
 // in order to start the search.
-fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block) -> freevar_info {
-    let seen = NodeSet::new();
-    let refs = Vec::new();
-
+fn collect_freevars(def_map: &resolve::DefMap, blk: &ast::Block) -> Vec<freevar_entry> {
     let mut v = CollectFreevarsVisitor {
-        seen: seen,
-        refs: refs,
+        seen: NodeSet::new(),
+        refs: Vec::new(),
         def_map: def_map,
     };
 
     v.visit_block(blk, 1);
-    let CollectFreevarsVisitor {
-        refs,
-        ..
-    } = v;
-    return @refs;
+    v.refs
 }
 
-struct AnnotateFreevarsVisitor {
-    def_map: resolve::DefMap,
+struct AnnotateFreevarsVisitor<'a> {
+    def_map: &'a resolve::DefMap,
     freevars: freevar_map,
 }
 
-impl Visitor<()> for AnnotateFreevarsVisitor {
+impl<'a> Visitor<()> for AnnotateFreevarsVisitor<'a> {
     fn visit_fn(&mut self, fk: &visit::FnKind, fd: &ast::FnDecl,
                 blk: &ast::Block, s: Span, nid: ast::NodeId, _: ()) {
         let vars = collect_freevars(self.def_map, blk);
@@ -124,7 +116,7 @@ impl Visitor<()> for AnnotateFreevarsVisitor {
 // efficient as it fully recomputes the free variables at every
 // node of interest rather than building up the free variables in
 // one pass. This could be improved upon if it turns out to matter.
-pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) ->
+pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate) ->
    freevar_map {
     let mut visitor = AnnotateFreevarsVisitor {
         def_map: def_map,
@@ -132,16 +124,12 @@ pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) ->
     };
     visit::walk_crate(&mut visitor, krate, ());
 
-    let AnnotateFreevarsVisitor {
-        freevars,
-        ..
-    } = visitor;
-    freevars
+    visitor.freevars
 }
 
-pub fn get_freevars(tcx: &ty::ctxt, fid: ast::NodeId) -> freevar_info {
+pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| -> T) -> T {
     match tcx.freevars.borrow().find(&fid) {
-        None => fail!("get_freevars: {} has no freevars", fid),
-        Some(&d) => return d
+        None => fail!("with_freevars: {} has no freevars", fid),
+        Some(d) => f(d.as_slice())
     }
 }
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index a152e06eb06..e6c885e56f1 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -47,7 +47,6 @@ use syntax::visit::Visitor;
 #[deriving(Clone)]
 pub struct Context<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
 }
 
 impl<'a> Visitor<()> for Context<'a> {
@@ -70,11 +69,9 @@ impl<'a> Visitor<()> for Context<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    krate: &Crate) {
     let mut ctx = Context {
         tcx: tcx,
-        method_map: method_map,
     };
     visit::walk_crate(&mut ctx, krate, ());
     tcx.sess.abort_if_errors();
@@ -115,9 +112,9 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t
                               .find(&trait_ref.ref_id)
                               .expect("trait ref not in def map!");
     let trait_def_id = ast_util::def_id_of_def(ast_trait_def);
-    let trait_def = *cx.tcx.trait_defs.borrow()
-                           .find(&trait_def_id)
-                           .expect("trait def not in trait-defs map!");
+    let trait_def = cx.tcx.trait_defs.borrow()
+                          .find_copy(&trait_def_id)
+                          .expect("trait def not in trait-defs map!");
 
     // If this trait has builtin-kind supertraits, meet them.
     let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id);
@@ -166,7 +163,7 @@ fn check_item(cx: &mut Context, item: &Item) {
 // closure.
 fn with_appropriate_checker(cx: &Context,
                             id: NodeId,
-                            b: |checker: |&Context, @freevar_entry||) {
+                            b: |checker: |&Context, &freevar_entry||) {
     fn check_for_uniq(cx: &Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
         // all captured data must be owned, regardless of whether it is
         // moved in or copied in.
@@ -187,7 +184,7 @@ fn with_appropriate_checker(cx: &Context,
                              bounds, Some(var_t));
     }
 
-    fn check_for_bare(cx: &Context, fv: @freevar_entry) {
+    fn check_for_bare(cx: &Context, fv: &freevar_entry) {
         cx.tcx.sess.span_err(
             fv.span,
             "can't capture dynamic environment in a fn item; \
@@ -226,10 +223,11 @@ fn check_fn(
 
     // Check kinds on free variables:
     with_appropriate_checker(cx, fn_id, |chk| {
-        let r = freevars::get_freevars(cx.tcx, fn_id);
-        for fv in r.iter() {
-            chk(cx, *fv);
-        }
+        freevars::with_freevars(cx.tcx, fn_id, |r| {
+            for fv in r.iter() {
+                chk(cx, fv);
+            }
+        })
     });
 
     visit::walk_fn(cx, fk, decl, body, sp, fn_id, ());
@@ -240,7 +238,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
 
     // Handle any kind bounds on type parameters
     {
-        let method_map = cx.method_map.borrow();
+        let method_map = cx.tcx.method_map.borrow();
         let method = method_map.find(&typeck::MethodCall::expr(e.id));
         let node_type_substs = cx.tcx.node_type_substs.borrow();
         let r = match method {
@@ -309,11 +307,10 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
     // Search for auto-adjustments to find trait coercions.
     match cx.tcx.adjustments.borrow().find(&e.id) {
         Some(adjustment) => {
-            match **adjustment {
+            match *adjustment {
                 ty::AutoObject(..) => {
                     let source_ty = ty::expr_ty(cx.tcx, e);
-                    let target_ty = ty::expr_ty_adjusted(cx.tcx, e,
-                                                         &*cx.method_map.borrow());
+                    let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
                     check_trait_cast(cx, source_ty, target_ty, e.span);
                 }
                 ty::AutoAddEnv(..) |
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 7fca0e56aa2..42ef8b9d51b 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -195,12 +195,12 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
 }
 
 pub fn collect_language_items(krate: &ast::Crate,
-                              session: &Session) -> @LanguageItems {
+                              session: &Session) -> LanguageItems {
     let mut collector = LanguageItemCollector::new(session);
     collector.collect(krate);
     let LanguageItemCollector { items, .. } = collector;
     session.abort_if_errors();
-    @items
+    items
 }
 
 // End of the macro
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 6ce815d9bc4..d1cc7d7bc40 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -53,6 +53,7 @@ use std::i16;
 use std::i32;
 use std::i64;
 use std::i8;
+use std::rc::Rc;
 use std::to_str::ToStr;
 use std::u16;
 use std::u32;
@@ -423,23 +424,16 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
   '-' to '_' in command-line flags
  */
 pub fn get_lint_dict() -> LintDict {
-    let mut map = HashMap::new();
-    for &(k, v) in lint_table.iter() {
-        map.insert(k, v);
-    }
-    return map;
+    lint_table.iter().map(|&(k, v)| (k, v)).collect()
 }
 
 struct Context<'a> {
     // All known lint modes (string versions)
-    dict: @LintDict,
+    dict: LintDict,
     // Current levels of each lint warning
     cur: SmallIntMap<(level, LintSource)>,
     // context we're checking in (used to access fields like sess)
     tcx: &'a ty::ctxt,
-    // maps from an expression id that corresponds to a method call to the
-    // details of the method to be invoked
-    method_map: typeck::MethodMap,
     // Items exported by the crate; used by the missing_doc lint.
     exported_items: &'a privacy::ExportedItems,
     // The id of the current `ast::StructDef` being walked.
@@ -685,7 +679,7 @@ impl<'a> AstConv for Context<'a>{
         ty::lookup_item_type(self.tcx, id)
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
         ty::lookup_trait_def(self.tcx, id)
     }
 
@@ -1340,7 +1334,7 @@ fn check_unsafe_block(cx: &Context, e: &ast::Expr) {
 fn check_unused_mut_pat(cx: &Context, p: &ast::Pat) {
     match p.node {
         ast::PatIdent(ast::BindByValue(ast::MutMutable),
-                      ref path, _) if pat_util::pat_is_binding(cx.tcx.def_map, p)=> {
+                      ref path, _) if pat_util::pat_is_binding(&cx.tcx.def_map, p) => {
             // `let mut _a = 1;` doesn't need a warning.
             let initial_underscore = if path.segments.len() == 1 {
                 token::get_ident(path.segments
@@ -1390,7 +1384,7 @@ fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
         cx.span_lint(UnnecessaryAllocation, e.span, msg);
     };
 
-    match cx.tcx.adjustments.borrow().find_copy(&e.id) {
+    match cx.tcx.adjustments.borrow().find(&e.id) {
         Some(adjustment) => {
             match *adjustment {
                 ty::AutoDerefRef(ty::AutoDerefRef { autoref, .. }) => {
@@ -1472,7 +1466,7 @@ fn check_missing_doc_method(cx: &Context, m: &ast::Method) {
         node: m.id
     };
 
-    match cx.tcx.methods.borrow().find(&did).map(|method| *method) {
+    match cx.tcx.methods.borrow().find_copy(&did) {
         None => cx.tcx.sess.span_bug(m.span, "missing method descriptor?!"),
         Some(md) => {
             match md.container {
@@ -1537,7 +1531,7 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
         }
         ast::ExprMethodCall(..) => {
             let method_call = typeck::MethodCall::expr(e.id);
-            match cx.method_map.borrow().find(&method_call) {
+            match cx.tcx.method_map.borrow().find(&method_call) {
                 Some(method) => {
                     match method.origin {
                         typeck::MethodStatic(def_id) => {
@@ -1775,14 +1769,12 @@ impl<'a> IdVisitingOperation for Context<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    krate: &ast::Crate) {
     let mut cx = Context {
-        dict: @get_lint_dict(),
+        dict: get_lint_dict(),
         cur: SmallIntMap::new(),
         tcx: tcx,
-        method_map: method_map,
         exported_items: exported_items,
         cur_struct_def_id: -1,
         is_doc_hidden: false,
@@ -1793,7 +1785,9 @@ pub fn check_crate(tcx: &ty::ctxt,
     // Install default lint levels, followed by the command line levels, and
     // then actually visit the whole crate.
     for (_, spec) in cx.dict.iter() {
-        cx.set_level(spec.lint, spec.default, Default);
+        if spec.default != allow {
+            cx.cur.insert(spec.lint as uint, (spec.default, Default));
+        }
     }
     for &(lint, level) in tcx.sess.opts.lint_opts.iter() {
         cx.set_level(lint, level, CommandLine);
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index a189b977635..4be9992367d 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -106,7 +106,6 @@
 use middle::lint::{UnusedVariable, DeadAssignment};
 use middle::pat_util;
 use middle::ty;
-use middle::typeck;
 use middle::moves;
 use util::nodemap::NodeMap;
 
@@ -171,10 +170,9 @@ impl<'a> Visitor<()> for IrMaps<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    capture_map: &moves::CaptureMap,
                    krate: &Crate) {
-    visit::walk_crate(&mut IrMaps(tcx, method_map, capture_map), krate, ());
+    visit::walk_crate(&mut IrMaps(tcx, capture_map), krate, ());
     tcx.sess.abort_if_errors();
 }
 
@@ -247,7 +245,6 @@ enum VarKind {
 
 struct IrMaps<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
     capture_map: &'a moves::CaptureMap,
 
     num_live_nodes: uint,
@@ -260,12 +257,10 @@ struct IrMaps<'a> {
 }
 
 fn IrMaps<'a>(tcx: &'a ty::ctxt,
-              method_map: typeck::MethodMap,
               capture_map: &'a moves::CaptureMap)
               -> IrMaps<'a> {
     IrMaps {
         tcx: tcx,
-        method_map: method_map,
         capture_map: capture_map,
         num_live_nodes: 0,
         num_vars: 0,
@@ -366,14 +361,14 @@ fn visit_fn(ir: &mut IrMaps,
     let _i = ::util::common::indenter();
 
     // swap in a new set of IR maps for this function body:
-    let mut fn_maps = IrMaps(ir.tcx, ir.method_map, ir.capture_map);
+    let mut fn_maps = IrMaps(ir.tcx, ir.capture_map);
 
     unsafe {
         debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(&fn_maps));
     }
 
     for arg in decl.inputs.iter() {
-        pat_util::pat_bindings(ir.tcx.def_map,
+        pat_util::pat_bindings(&ir.tcx.def_map,
                                arg.pat,
                                |_bm, arg_id, _x, path| {
             debug!("adding argument {}", arg_id);
@@ -407,7 +402,7 @@ fn visit_fn(ir: &mut IrMaps,
 }
 
 fn visit_local(ir: &mut IrMaps, local: &Local) {
-    pat_util::pat_bindings(ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
+    pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
         debug!("adding local variable {}", p_id);
         let name = ast_util::path_to_ident(path);
         ir.add_live_node_for_node(p_id, VarDefNode(sp));
@@ -431,7 +426,7 @@ fn visit_local(ir: &mut IrMaps, local: &Local) {
 
 fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
     for pat in arm.pats.iter() {
-        pat_util::pat_bindings(ir.tcx.def_map, *pat, |bm, p_id, sp, path| {
+        pat_util::pat_bindings(&ir.tcx.def_map, *pat, |bm, p_id, sp, path| {
             debug!("adding local variable {} from match with bm {:?}",
                    p_id, bm);
             let name = ast_util::path_to_ident(path);
@@ -601,7 +596,7 @@ impl<'a> Liveness<'a> {
     fn pat_bindings(&mut self,
                     pat: &Pat,
                     f: |&mut Liveness<'a>, LiveNode, Variable, Span, NodeId|) {
-        pat_util::pat_bindings(self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
+        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);
             f(self, ln, var, sp, p_id);
@@ -1529,7 +1524,7 @@ impl<'a> Liveness<'a> {
 
     fn warn_about_unused_args(&self, decl: &FnDecl, entry_ln: LiveNode) {
         for arg in decl.inputs.iter() {
-            pat_util::pat_bindings(self.ir.tcx.def_map,
+            pat_util::pat_bindings(&self.ir.tcx.def_map,
                                    arg.pat,
                                    |_bm, p_id, sp, path| {
                 let var = self.variable(p_id, sp);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 84e9151c11c..35124aa9916 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -64,6 +64,7 @@
 
 use middle::ty;
 use middle::typeck;
+use util::nodemap::NodeMap;
 use util::ppaux::{ty_to_str, Repr};
 
 use syntax::ast::{MutImmutable, MutMutable};
@@ -72,7 +73,10 @@ use syntax::codemap::Span;
 use syntax::print::pprust;
 use syntax::parse::token;
 
-#[deriving(Eq)]
+use std::cell::RefCell;
+use std::rc::Rc;
+
+#[deriving(Clone, Eq)]
 pub enum categorization {
     cat_rvalue(ty::Region),            // temporary val, argument is its scope
     cat_static_item,
@@ -88,14 +92,14 @@ pub enum categorization {
     // (*1) downcast is only required if the enum has more than one variant
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct CopiedUpvar {
     pub upvar_id: ast::NodeId,
     pub onceness: ast::Onceness,
 }
 
 // different kinds of pointers:
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum PointerKind {
     OwnedPtr,
     GcPtr,
@@ -105,26 +109,26 @@ pub enum PointerKind {
 
 // We use the term "interior" to mean "something reachable from the
 // base without a pointer dereference", e.g. a field
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum InteriorKind {
     InteriorField(FieldName),
     InteriorElement(ElementKind),
 }
 
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum FieldName {
     NamedField(ast::Name),
     PositionalField(uint)
 }
 
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum ElementKind {
     VecElement,
     StrElement,
     OtherElement,
 }
 
-#[deriving(Eq, TotalEq, Hash, Show)]
+#[deriving(Clone, Eq, TotalEq, Hash, Show)]
 pub enum MutabilityCategory {
     McImmutable, // Immutable.
     McDeclared,  // Directly declared as mutable.
@@ -145,7 +149,7 @@ pub enum MutabilityCategory {
 // dereference, but its type is the type *before* the dereference
 // (`@T`). So use `cmt.type` to find the type of the value in a consistent
 // fashion. For more details, see the method `cat_pattern`
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct cmt_ {
     pub id: ast::NodeId,          // id of expr/pat producing this value
     pub span: Span,                // span of same expr/pat
@@ -154,7 +158,7 @@ pub struct cmt_ {
     pub ty: ty::t                  // type of the expr (*see WARNING above*)
 }
 
-pub type cmt = @cmt_;
+pub type cmt = Rc<cmt_>;
 
 // We pun on *T to mean both actual deref of a ptr as well
 // as accessing of components:
@@ -263,12 +267,12 @@ pub type McResult<T> = Result<T, ()>;
  */
 pub trait Typer {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt;
-    fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t>;
+    fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t>;
     fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t>;
-    fn adjustment(&mut self, node_id: ast::NodeId) -> Option<@ty::AutoAdjustment>;
-    fn is_method_call(&mut self, id: ast::NodeId) -> bool;
-    fn temporary_scope(&mut self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
-    fn upvar_borrow(&mut self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>>;
+    fn is_method_call(&self, id: ast::NodeId) -> bool;
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
 }
 
 impl MutabilityCategory {
@@ -350,31 +354,27 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         self.typer.tcx()
     }
 
-    fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
-        self.typer.adjustment(id)
-    }
-
-    fn expr_ty(&mut self, expr: &ast::Expr) -> McResult<ty::t> {
+    fn expr_ty(&self, expr: &ast::Expr) -> McResult<ty::t> {
         self.typer.node_ty(expr.id)
     }
 
-    fn expr_ty_adjusted(&mut self, expr: &ast::Expr) -> McResult<ty::t> {
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<ty::t> {
         let unadjusted_ty = if_ok!(self.expr_ty(expr));
-        let adjustment = self.adjustment(expr.id);
-        Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, adjustment,
+        Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
+                         self.typer.adjustments().borrow().find(&expr.id),
                          |method_call| self.typer.node_method_ty(method_call)))
     }
 
-    fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t> {
+    fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
         self.typer.node_ty(id)
     }
 
-    fn pat_ty(&mut self, pat: @ast::Pat) -> McResult<ty::t> {
+    fn pat_ty(&self, pat: &ast::Pat) -> McResult<ty::t> {
         self.typer.node_ty(pat.id)
     }
 
-    pub fn cat_expr(&mut self, expr: &ast::Expr) -> McResult<cmt> {
-        match self.adjustment(expr.id) {
+    pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt> {
+        match self.typer.adjustments().borrow().find(&expr.id) {
             None => {
                 // No adjustments.
                 self.cat_expr_unadjusted(expr)
@@ -386,8 +386,9 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                         // Implicity casts a concrete object to trait object
                         // so just patch up the type
                         let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
-                        let expr_cmt = if_ok!(self.cat_expr_unadjusted(expr));
-                        Ok(@cmt_ {ty: expr_ty, ..*expr_cmt})
+                        let mut expr_cmt = (*if_ok!(self.cat_expr_unadjusted(expr))).clone();
+                        expr_cmt.ty = expr_ty;
+                        Ok(Rc::new(expr_cmt))
                     }
 
                     ty::AutoAddEnv(..) => {
@@ -417,7 +418,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_expr_autoderefd(&mut self, expr: &ast::Expr, autoderefs: uint)
+    pub fn cat_expr_autoderefd(&self, expr: &ast::Expr, autoderefs: uint)
                                -> McResult<cmt> {
         let mut cmt = if_ok!(self.cat_expr_unadjusted(expr));
         for deref in range(1u, autoderefs + 1) {
@@ -426,7 +427,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         return Ok(cmt);
     }
 
-    pub fn cat_expr_unadjusted(&mut self, expr: &ast::Expr) -> McResult<cmt> {
+    pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt> {
         debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
 
         let expr_ty = if_ok!(self.expr_ty(expr));
@@ -475,7 +476,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_def(&mut self,
+    pub fn cat_def(&self,
                    id: ast::NodeId,
                    span: Span,
                    expr_ty: ty::t,
@@ -493,23 +494,23 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           ast::DefUse(_) | ast::DefTrait(_) | ast::DefTy(_) | ast::DefPrimTy(_) |
           ast::DefTyParam(..) | ast::DefTyParamBinder(..) | ast::DefRegion(_) |
           ast::DefLabel(_) | ast::DefSelfTy(..) | ast::DefMethod(..) => {
-              Ok(@cmt_ {
+              Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
                   mutbl: McImmutable,
                   ty:expr_ty
-              })
+              }))
           }
 
           ast::DefStatic(_, true) => {
-              Ok(@cmt_ {
+              Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
                   mutbl: McDeclared,
                   ty:expr_ty
-              })
+              }))
           }
 
           ast::DefArg(vid, binding_mode) => {
@@ -521,13 +522,13 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 ast::BindByValue(ast::MutMutable) => McDeclared,
                 _ => McImmutable
             };
-            Ok(@cmt_ {
+            Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_arg(vid),
                 mutbl: m,
                 ty:expr_ty
-            })
+            }))
           }
 
           ast::DefUpvar(var_id, _, fn_node_id, _) => {
@@ -551,7 +552,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                           self.cat_upvar(id, span, var_id, fn_node_id)
                       } else {
                           // FIXME #2152 allow mutation of moved upvars
-                          Ok(@cmt_ {
+                          Ok(Rc::new(cmt_ {
                               id:id,
                               span:span,
                               cat:cat_copied_upvar(CopiedUpvar {
@@ -559,7 +560,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                                   onceness: closure_ty.onceness}),
                               mutbl:McImmutable,
                               ty:expr_ty
-                          })
+                          }))
                       }
                   }
                   _ => {
@@ -579,18 +580,18 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 _ => McImmutable
             };
 
-            Ok(@cmt_ {
+            Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_local(vid),
                 mutbl: m,
                 ty: expr_ty
-            })
+            }))
           }
         }
     }
 
-    fn cat_upvar(&mut self,
+    fn cat_upvar(&self,
                  id: ast::NodeId,
                  span: Span,
                  var_id: ast::NodeId,
@@ -619,28 +620,28 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         // give err type. Nobody should be inspecting this type anyhow.
         let upvar_ty = ty::mk_err();
 
-        let base_cmt = @cmt_ {
+        let base_cmt = Rc::new(cmt_ {
             id:id,
             span:span,
             cat:cat_upvar(upvar_id, upvar_borrow),
             mutbl:McImmutable,
             ty:upvar_ty,
-        };
+        });
 
         let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region);
 
-        let deref_cmt = @cmt_ {
+        let deref_cmt = Rc::new(cmt_ {
             id:id,
             span:span,
             cat:cat_deref(base_cmt, 0, ptr),
             mutbl:MutabilityCategory::from_borrow_kind(upvar_borrow.kind),
             ty:var_ty,
-        };
+        });
 
         Ok(deref_cmt)
     }
 
-    pub fn cat_rvalue_node(&mut self,
+    pub fn cat_rvalue_node(&self,
                            id: ast::NodeId,
                            span: Span,
                            expr_ty: ty::t)
@@ -655,40 +656,40 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_rvalue(&mut self,
+    pub fn cat_rvalue(&self,
                       cmt_id: ast::NodeId,
                       span: Span,
                       temp_scope: ty::Region,
                       expr_ty: ty::t) -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id:cmt_id,
             span:span,
             cat:cat_rvalue(temp_scope),
             mutbl:McDeclared,
             ty:expr_ty
-        }
+        })
     }
 
-    pub fn cat_field<N:ast_node>(&mut self,
+    pub fn cat_field<N:ast_node>(&self,
                                  node: &N,
                                  base_cmt: cmt,
                                  f_name: ast::Ident,
                                  f_ty: ty::t)
                                  -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
             mutbl: base_cmt.mutbl.inherit(),
+            cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
             ty: f_ty
-        }
+        })
     }
 
-    pub fn cat_deref_obj<N:ast_node>(&mut self, node: &N, base_cmt: cmt) -> cmt {
+    pub fn cat_deref_obj<N:ast_node>(&self, node: &N, base_cmt: cmt) -> cmt {
         self.cat_deref_common(node, base_cmt, 0, ty::mk_nil())
     }
 
-    fn cat_deref<N:ast_node>(&mut self,
+    fn cat_deref<N:ast_node>(&self,
                              node: &N,
                              base_cmt: cmt,
                              deref_cnt: uint)
@@ -720,7 +721,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    fn cat_deref_common<N:ast_node>(&mut self,
+    fn cat_deref_common<N:ast_node>(&self,
                                     node: &N,
                                     base_cmt: cmt,
                                     deref_cnt: uint,
@@ -737,16 +738,16 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 (base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
             }
         };
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
             cat: cat,
             mutbl: m,
             ty: deref_ty
-        }
+        })
     }
 
-    pub fn cat_index<N:ast_node>(&mut self,
+    pub fn cat_index<N:ast_node>(&self,
                                  elt: &N,
                                  base_cmt: cmt,
                                  derefs: uint)
@@ -799,13 +800,13 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
             let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
 
             // the deref is explicit in the resulting cmt
-            let deref_cmt = @cmt_ {
+            let deref_cmt = Rc::new(cmt_ {
                 id:elt.id(),
                 span:elt.span(),
-                cat:cat_deref(base_cmt, derefs, ptr),
+                cat:cat_deref(base_cmt.clone(), derefs, ptr),
                 mutbl:m,
                 ty:element_ty
-            };
+            });
 
             interior(elt, deref_cmt, base_cmt.ty, m.inherit(), element_ty)
           }
@@ -813,7 +814,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           deref_interior(_) => {
             // fixed-length vectors have no deref
             let m = base_cmt.mutbl.inherit();
-            interior(elt, base_cmt, base_cmt.ty, m, element_ty)
+            interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
           }
         };
 
@@ -823,19 +824,19 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                                  mutbl: MutabilityCategory,
                                  element_ty: ty::t) -> cmt
         {
-            @cmt_ {
+            Rc::new(cmt_ {
                 id:elt.id(),
                 span:elt.span(),
                 cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
                 mutbl:mutbl,
                 ty:element_ty
-            }
+            })
         }
     }
 
-    pub fn cat_slice_pattern(&mut self,
+    pub fn cat_slice_pattern(&self,
                              vec_cmt: cmt,
-                             slice_pat: @ast::Pat)
+                             slice_pat: &ast::Pat)
                              -> McResult<(cmt, ast::Mutability, ty::Region)> {
         /*!
          * Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is
@@ -855,7 +856,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         return Ok((cmt_slice, slice_mutbl, slice_r));
 
         fn vec_slice_info(tcx: &ty::ctxt,
-                          pat: @ast::Pat,
+                          pat: &ast::Pat,
                           slice_ty: ty::t)
                           -> (ast::Mutability, ty::Region) {
             /*!
@@ -880,41 +881,41 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_imm_interior<N:ast_node>(&mut self,
+    pub fn cat_imm_interior<N:ast_node>(&self,
                                         node: &N,
                                         base_cmt: cmt,
                                         interior_ty: ty::t,
                                         interior: InteriorKind)
                                         -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat_interior(base_cmt, interior),
             mutbl: base_cmt.mutbl.inherit(),
+            cat: cat_interior(base_cmt, interior),
             ty: interior_ty
-        }
+        })
     }
 
-    pub fn cat_downcast<N:ast_node>(&mut self,
+    pub fn cat_downcast<N:ast_node>(&self,
                                     node: &N,
                                     base_cmt: cmt,
                                     downcast_ty: ty::t)
                                     -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat_downcast(base_cmt),
             mutbl: base_cmt.mutbl.inherit(),
+            cat: cat_downcast(base_cmt),
             ty: downcast_ty
-        }
+        })
     }
 
-    pub fn cat_pattern(&mut self,
+    pub fn cat_pattern(&self,
                        cmt: cmt,
-                       pat: @ast::Pat,
-                       op: |&mut MemCategorizationContext<TYPER>,
+                       pat: &ast::Pat,
+                       op: |&MemCategorizationContext<TYPER>,
                             cmt,
-                            @ast::Pat|)
+                            &ast::Pat|)
                        -> McResult<()> {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
@@ -965,7 +966,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                pat.id, pprust::pat_to_str(pat),
                cmt.repr(self.tcx()));
 
-        op(self, cmt, pat);
+        op(self, cmt.clone(), pat);
 
         match pat.node {
           ast::PatWild | ast::PatWildMulti => {
@@ -984,7 +985,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                         if ty::enum_is_univariant(self.tcx(), enum_did) {
                             cmt // univariant, no downcast needed
                         } else {
-                            self.cat_downcast(pat, cmt, cmt.ty)
+                            self.cat_downcast(pat, cmt.clone(), cmt.ty)
                         }
                     };
 
@@ -993,7 +994,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
 
                         let subcmt =
                             self.cat_imm_interior(
-                                pat, downcast_cmt, subpat_ty,
+                                pat, downcast_cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
 
                         if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
@@ -1005,14 +1006,14 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                         let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
                         let cmt_field =
                             self.cat_imm_interior(
-                                pat, cmt, subpat_ty,
+                                pat, cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
                         if_ok!(self.cat_pattern(cmt_field, subpat, |x,y,z| op(x,y,z)));
                     }
                 }
                 Some(&ast::DefStatic(..)) => {
                     for &subpat in subpats.iter() {
-                        if_ok!(self.cat_pattern(cmt, subpat, |x,y,z| op(x,y,z)));
+                        if_ok!(self.cat_pattern(cmt.clone(), subpat, |x,y,z| op(x,y,z)));
                     }
                 }
                 _ => {
@@ -1035,7 +1036,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
             // {f1: p1, ..., fN: pN}
             for fp in field_pats.iter() {
                 let field_ty = if_ok!(self.pat_ty(fp.pat)); // see (*2)
-                let cmt_field = self.cat_field(pat, cmt, fp.ident, field_ty);
+                let cmt_field = self.cat_field(pat, cmt.clone(), fp.ident, field_ty);
                 if_ok!(self.cat_pattern(cmt_field, fp.pat, |x,y,z| op(x,y,z)));
             }
           }
@@ -1046,7 +1047,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
                 let subcmt =
                     self.cat_imm_interior(
-                        pat, cmt, subpat_ty,
+                        pat, cmt.clone(), subpat_ty,
                         InteriorField(PositionalField(i)));
                 if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
             }
@@ -1061,7 +1062,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           ast::PatVec(ref before, slice, ref after) => {
               let elt_cmt = self.cat_index(pat, cmt, 0);
               for &before_pat in before.iter() {
-                  if_ok!(self.cat_pattern(elt_cmt, before_pat, |x,y,z| op(x,y,z)));
+                  if_ok!(self.cat_pattern(elt_cmt.clone(), before_pat, |x,y,z| op(x,y,z)));
               }
               for &slice_pat in slice.iter() {
                   let slice_ty = if_ok!(self.pat_ty(slice_pat));
@@ -1069,7 +1070,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                   if_ok!(self.cat_pattern(slice_cmt, slice_pat, |x,y,z| op(x,y,z)));
               }
               for &after_pat in after.iter() {
-                  if_ok!(self.cat_pattern(elt_cmt, after_pat, |x,y,z| op(x,y,z)));
+                  if_ok!(self.cat_pattern(elt_cmt.clone(), after_pat, |x,y,z| op(x,y,z)));
               }
           }
 
@@ -1081,7 +1082,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         Ok(())
     }
 
-    pub fn cmt_to_str(&self, cmt: cmt) -> ~str {
+    pub fn cmt_to_str(&self, cmt: &cmt_) -> ~str {
         match cmt.cat {
           cat_static_item => {
               "static item".to_owned()
@@ -1098,7 +1099,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           cat_arg(..) => {
               "argument".to_owned()
           }
-          cat_deref(base, _, pk) => {
+          cat_deref(ref base, _, pk) => {
               match base.cat {
                   cat_upvar(..) => {
                       format!("captured outer variable")
@@ -1126,11 +1127,11 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           cat_upvar(..) => {
               "captured outer variable".to_owned()
           }
-          cat_discr(cmt, _) => {
-            self.cmt_to_str(cmt)
+          cat_discr(ref cmt, _) => {
+            self.cmt_to_str(&**cmt)
           }
-          cat_downcast(cmt) => {
-            self.cmt_to_str(cmt)
+          cat_downcast(ref cmt) => {
+            self.cmt_to_str(&**cmt)
           }
         }
     }
@@ -1150,7 +1151,7 @@ pub enum AliasableReason {
 }
 
 impl cmt_ {
-    pub fn guarantor(self) -> cmt {
+    pub fn guarantor(&self) -> cmt {
         //! Returns `self` after stripping away any owned pointer derefs or
         //! interior content. The return value is basically the `cmt` which
         //! determines how long the value in `self` remains live.
@@ -1165,12 +1166,12 @@ impl cmt_ {
             cat_deref(_, _, GcPtr(..)) |
             cat_deref(_, _, BorrowedPtr(..)) |
             cat_upvar(..) => {
-                @self
+                Rc::new((*self).clone())
             }
-            cat_downcast(b) |
-            cat_discr(b, _) |
-            cat_interior(b, _) |
-            cat_deref(b, _, OwnedPtr) => {
+            cat_downcast(ref b) |
+            cat_discr(ref b, _) |
+            cat_interior(ref b, _) |
+            cat_deref(ref b, _, OwnedPtr) => {
                 b.guarantor()
             }
         }
@@ -1187,12 +1188,12 @@ impl cmt_ {
         // aliased and eventually recused.
 
         match self.cat {
-            cat_deref(b, _, BorrowedPtr(ty::MutBorrow, _)) |
-            cat_deref(b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
-            cat_downcast(b) |
-            cat_deref(b, _, OwnedPtr) |
-            cat_interior(b, _) |
-            cat_discr(b, _) => {
+            cat_deref(ref b, _, BorrowedPtr(ty::MutBorrow, _)) |
+            cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
+            cat_downcast(ref b) |
+            cat_deref(ref b, _, OwnedPtr) |
+            cat_interior(ref b, _) |
+            cat_discr(ref b, _) => {
                 // Aliasability depends on base cmt
                 b.freely_aliasable(ctxt)
             }
@@ -1256,21 +1257,21 @@ impl Repr for categorization {
             cat_arg(..) => {
                 format!("{:?}", *self)
             }
-            cat_deref(cmt, derefs, ptr) => {
+            cat_deref(ref cmt, derefs, ptr) => {
                 format!("{}-{}{}->",
                         cmt.cat.repr(tcx),
                         ptr_sigil(ptr),
                         derefs)
             }
-            cat_interior(cmt, interior) => {
+            cat_interior(ref cmt, interior) => {
                 format!("{}.{}",
                      cmt.cat.repr(tcx),
                      interior.repr(tcx))
             }
-            cat_downcast(cmt) => {
+            cat_downcast(ref cmt) => {
                 format!("{}->(enum)", cmt.cat.repr(tcx))
             }
-            cat_discr(cmt, _) => {
+            cat_discr(ref cmt, _) => {
                 cmt.cat.repr(tcx)
             }
         }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 2029df38b10..53d3dec6713 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -130,7 +130,7 @@ and so on.
 use middle::pat_util::{pat_bindings};
 use middle::freevars;
 use middle::ty;
-use middle::typeck::{MethodCall, MethodMap};
+use middle::typeck::MethodCall;
 use util::ppaux;
 use util::ppaux::Repr;
 use util::common::indenter;
@@ -177,7 +177,6 @@ pub struct MoveMaps {
 #[deriving(Clone)]
 struct VisitContext<'a> {
     tcx: &'a ty::ctxt,
-    method_map: MethodMap,
     move_maps: MoveMaps
 }
 
@@ -202,13 +201,9 @@ impl<'a> visit::Visitor<()> for VisitContext<'a> {
     fn visit_ty(&mut self, _t: &Ty, _: ()) {}
 }
 
-pub fn compute_moves(tcx: &ty::ctxt,
-                     method_map: MethodMap,
-                     krate: &Crate) -> MoveMaps
-{
+pub fn compute_moves(tcx: &ty::ctxt, krate: &Crate) -> MoveMaps {
     let mut visit_cx = VisitContext {
         tcx: tcx,
-        method_map: method_map,
         move_maps: MoveMaps {
             moves_map: NodeSet::new(),
             moved_variables_set: NodeSet::new(),
@@ -274,8 +269,7 @@ impl<'a> VisitContext<'a> {
         debug!("consume_expr(expr={})",
                expr.repr(self.tcx));
 
-        let expr_ty = ty::expr_ty_adjusted(self.tcx, expr,
-                                           &*self.method_map.borrow());
+        let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
         if ty::type_moves_by_default(self.tcx, expr_ty) {
             self.move_maps.moves_map.insert(expr.id);
             self.use_expr(expr, Move);
@@ -318,7 +312,7 @@ impl<'a> VisitContext<'a> {
         // reading the underlying expression, not moving it.
         let comp_mode = match self.tcx.adjustments.borrow().find(&expr.id) {
             Some(adjustment) => {
-                match **adjustment {
+                match *adjustment {
                     ty::AutoDerefRef(ty::AutoDerefRef {
                         autoref: Some(_),
                         ..
@@ -550,7 +544,7 @@ impl<'a> VisitContext<'a> {
                     self.use_pat(a.pat);
                 }
                 let cap_vars = self.compute_captures(expr.id);
-                self.move_maps.capture_map.insert(expr.id, cap_vars);
+                self.move_maps.capture_map.insert(expr.id, Rc::new(cap_vars));
                 self.consume_block(body);
             }
 
@@ -577,7 +571,7 @@ impl<'a> VisitContext<'a> {
                                    arg_exprs: &[@Expr])
                                    -> bool {
         let method_call = MethodCall::expr(expr.id);
-        if !self.method_map.borrow().contains_key(&method_call) {
+        if !self.tcx.method_map.borrow().contains_key(&method_call) {
             return false;
         }
 
@@ -611,7 +605,7 @@ impl<'a> VisitContext<'a> {
          * into itself or not based on its type and annotation.
          */
 
-        pat_bindings(self.tcx.def_map, pat, |bm, id, _span, path| {
+        pat_bindings(&self.tcx.def_map, pat, |bm, id, _span, path| {
             let binding_moves = match bm {
                 BindByRef(_) => false,
                 BindByValue(_) => {
@@ -645,34 +639,35 @@ impl<'a> VisitContext<'a> {
         self.consume_expr(arg_expr)
     }
 
-    pub fn compute_captures(&mut self, fn_expr_id: NodeId) -> Rc<Vec<CaptureVar> > {
+    fn compute_captures(&mut self, fn_expr_id: NodeId) -> Vec<CaptureVar> {
         debug!("compute_capture_vars(fn_expr_id={:?})", fn_expr_id);
         let _indenter = indenter();
 
         let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id);
-        let freevars = freevars::get_freevars(self.tcx, fn_expr_id);
-        Rc::new(match ty::ty_closure_store(fn_ty) {
-            ty::RegionTraitStore(..) => {
-                // || captures everything by ref
-                freevars.iter()
-                        .map(|fvar| CaptureVar {def: fvar.def, span: fvar.span, mode: CapRef})
-                        .collect()
-            }
-            ty::UniqTraitStore => {
-                // proc captures by copy or by move depending on type
-                freevars.iter()
-                        .map(|fvar| {
-                    let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
-                    let fvar_ty = ty::node_id_to_type(self.tcx, fvar_def_id);
-                    debug!("fvar_def_id={:?} fvar_ty={}",
-                        fvar_def_id, ppaux::ty_to_str(self.tcx, fvar_ty));
-                    let mode = if ty::type_moves_by_default(self.tcx, fvar_ty) {
-                        CapMove
-                    } else {
-                        CapCopy
-                    };
-                    CaptureVar {def: fvar.def, span: fvar.span, mode:mode}
-                }).collect()
+        freevars::with_freevars(self.tcx, fn_expr_id, |freevars| {
+            match ty::ty_closure_store(fn_ty) {
+                ty::RegionTraitStore(..) => {
+                    // || captures everything by ref
+                    freevars.iter()
+                            .map(|fvar| CaptureVar {def: fvar.def, span: fvar.span, mode: CapRef})
+                            .collect()
+                }
+                ty::UniqTraitStore => {
+                    // proc captures by copy or by move depending on type
+                    freevars.iter()
+                            .map(|fvar| {
+                        let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
+                        let fvar_ty = ty::node_id_to_type(self.tcx, fvar_def_id);
+                        debug!("fvar_def_id={:?} fvar_ty={}",
+                            fvar_def_id, ppaux::ty_to_str(self.tcx, fvar_ty));
+                        let mode = if ty::type_moves_by_default(self.tcx, fvar_ty) {
+                            CapMove
+                        } else {
+                            CapCopy
+                        };
+                        CaptureVar {def: fvar.def, span: fvar.span, mode:mode}
+                    }).collect()
+                }
             }
         })
     }
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 2d50d2e0f77..842d3bae6a7 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -20,7 +20,7 @@ pub type PatIdMap = HashMap<Ident, NodeId>;
 
 // This is used because same-named variables in alternative patterns need to
 // use the NodeId of their namesake in the first pattern.
-pub fn pat_id_map(dm: resolve::DefMap, pat: &Pat) -> PatIdMap {
+pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
     let mut map = HashMap::new();
     pat_bindings(dm, pat, |_bm, p_id, _s, n| {
       map.insert(path_to_ident(n), p_id);
@@ -28,7 +28,7 @@ pub fn pat_id_map(dm: resolve::DefMap, pat: &Pat) -> PatIdMap {
     map
 }
 
-pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_variant_or_struct(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatEnum(_, _) | PatIdent(_, _, None) | PatStruct(..) => {
             match dm.borrow().find(&pat.id) {
@@ -40,7 +40,7 @@ pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: &Pat) -> bool {
     }
 }
 
-pub fn pat_is_const(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_const(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(_, _, None) | PatEnum(..) => {
             match dm.borrow().find(&pat.id) {
@@ -52,7 +52,7 @@ pub fn pat_is_const(dm: resolve::DefMap, pat: &Pat) -> bool {
     }
 }
 
-pub fn pat_is_binding(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_binding(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(..) => {
             !pat_is_variant_or_struct(dm, pat) &&
@@ -62,7 +62,7 @@ pub fn pat_is_binding(dm: resolve::DefMap, pat: &Pat) -> bool {
     }
 }
 
-pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(..) => pat_is_binding(dm, pat),
         PatWild | PatWildMulti => true,
@@ -72,7 +72,7 @@ pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: &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,
+pub fn pat_bindings(dm: &resolve::DefMap,
                     pat: &Pat,
                     it: |BindingMode, NodeId, Span, &Path|) {
     walk_pat(pat, |p| {
@@ -88,7 +88,7 @@ pub fn pat_bindings(dm: resolve::DefMap,
 
 /// Checks if the pattern contains any patterns that bind something to
 /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
-pub fn pat_contains_bindings(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool {
     let mut contains_bindings = false;
     walk_pat(pat, |p| {
         if pat_is_binding(dm, p) {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 1e160df1061..427a7f406b0 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -254,7 +254,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
                     _ => true,
                 };
                 let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
-                let public_trait = tr.map_or(false, |tr| {
+                let public_trait = tr.clone().map_or(false, |tr| {
                     !is_local(tr.def_id) ||
                      self.exported_items.contains(&tr.def_id.node)
                 });
@@ -337,7 +337,6 @@ struct PrivacyVisitor<'a> {
     curitem: ast::NodeId,
     in_fn: bool,
     in_foreign: bool,
-    method_map: &'a MethodMap,
     parents: NodeMap<ast::NodeId>,
     external_exports: resolve::ExternalExports,
     last_private_map: resolve::LastPrivateMap,
@@ -775,8 +774,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
     fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
         match expr.node {
             ast::ExprField(base, ident, _) => {
-                match ty::get(ty::expr_ty_adjusted(self.tcx, base,
-                                                   &*self.method_map.borrow())).sty {
+                match ty::get(ty::expr_ty_adjusted(self.tcx, base)).sty {
                     ty::ty_struct(id, _) => {
                         self.check_field(expr.span, id, NamedField(ident));
                     }
@@ -785,7 +783,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
             }
             ast::ExprMethodCall(ident, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
-                match self.method_map.borrow().find(&method_call) {
+                match self.tcx.method_map.borrow().find(&method_call) {
                     None => {
                         self.tcx.sess.span_bug(expr.span,
                                                 "method call not in \
@@ -1404,7 +1402,6 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: &MethodMap,
                    exp_map2: &resolve::ExportMap2,
                    external_exports: resolve::ExternalExports,
                    last_private_map: resolve::LastPrivateMap,
@@ -1423,7 +1420,6 @@ pub fn check_crate(tcx: &ty::ctxt,
         in_foreign: false,
         tcx: tcx,
         parents: visitor.parents,
-        method_map: method_map,
         external_exports: external_exports,
         last_private_map: last_private_map,
     };
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 839f1d6039c..6e2edb4e8b2 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -84,9 +84,6 @@ fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
 struct ReachableContext<'a> {
     // The type context.
     tcx: &'a ty::ctxt,
-    // The method map, which links node IDs of method call expressions to the
-    // methods they've been resolved to.
-    method_map: typeck::MethodMap,
     // The set of items which must be exported in the linkage sense.
     reachable_symbols: NodeSet,
     // A worklist of item IDs. Each item ID in this worklist will be inlined
@@ -133,7 +130,7 @@ impl<'a> Visitor<()> for ReachableContext<'a> {
             }
             ast::ExprMethodCall(..) => {
                 let method_call = typeck::MethodCall::expr(expr.id);
-                match self.method_map.borrow().get(&method_call).origin {
+                match self.tcx.method_map.borrow().get(&method_call).origin {
                     typeck::MethodStatic(def_id) => {
                         if is_local(def_id) {
                             if self.def_id_represents_local_inlined_item(def_id) {
@@ -159,10 +156,9 @@ impl<'a> Visitor<()> for ReachableContext<'a> {
 
 impl<'a> ReachableContext<'a> {
     // Creates a new reachability computation context.
-    fn new(tcx: &'a ty::ctxt, method_map: typeck::MethodMap) -> ReachableContext<'a> {
+    fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
         ReachableContext {
             tcx: tcx,
-            method_map: method_map,
             reachable_symbols: NodeSet::new(),
             worklist: Vec::new(),
         }
@@ -339,10 +335,9 @@ impl<'a> ReachableContext<'a> {
 }
 
 pub fn find_reachable(tcx: &ty::ctxt,
-                      method_map: typeck::MethodMap,
                       exported_items: &privacy::ExportedItems)
                       -> NodeSet {
-    let mut reachable_context = ReachableContext::new(tcx, method_map);
+    let mut reachable_context = ReachableContext::new(tcx);
 
     // Step 1: Seed the worklist with all nodes which were found to be public as
     //         a result of the privacy pass along with all local lang items. If
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index cd9d88537b4..d645b628aff 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -16,7 +16,7 @@ use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use middle::lang_items::LanguageItems;
 use middle::lint::{UnnecessaryQualification, UnusedImports};
 use middle::pat_util::pat_bindings;
-use util::nodemap::{NodeMap, DefIdSet};
+use util::nodemap::{NodeMap, DefIdSet, FnvHashSet};
 
 use syntax::ast::*;
 use syntax::ast;
@@ -34,11 +34,12 @@ use syntax::visit::Visitor;
 use collections::{HashMap, HashSet};
 use std::cell::{Cell, RefCell};
 use std::mem::replace;
+use std::rc::{Rc, Weak};
 use std::strbuf::StrBuf;
 use std::uint;
 
 // Definition mapping
-pub type DefMap = @RefCell<NodeMap<Def>>;
+pub type DefMap = RefCell<NodeMap<Def>>;
 
 struct binding_info {
     span: Span,
@@ -53,7 +54,7 @@ pub type TraitMap = NodeMap<Vec<DefId> >;
 
 // This is the replacement export map. It maps a module to all of the exports
 // within.
-pub type ExportMap2 = @RefCell<NodeMap<Vec<Export2> >>;
+pub type ExportMap2 = RefCell<NodeMap<Vec<Export2> >>;
 
 pub struct Export2 {
     pub name: ~str,        // The name of the target.
@@ -125,6 +126,7 @@ enum NamespaceError {
 /// A NamespaceResult represents the result of resolving an import in
 /// a particular namespace. The result is either definitely-resolved,
 /// definitely- unresolved, or unknown.
+#[deriving(Clone)]
 enum NamespaceResult {
     /// Means that resolve hasn't gathered enough information yet to determine
     /// whether the name is bound in this namespace. (That is, it hasn't
@@ -135,7 +137,7 @@ enum NamespaceResult {
     UnboundResult,
     /// Means that resolve has determined that the name is bound in the Module
     /// argument, and specified by the NameBindings argument.
-    BoundResult(@Module, @NameBindings)
+    BoundResult(Rc<Module>, Rc<NameBindings>)
 }
 
 impl NamespaceResult {
@@ -189,14 +191,14 @@ enum ImportDirectiveSubclass {
 /// The context that we thread through while building the reduced graph.
 #[deriving(Clone)]
 enum ReducedGraphParent {
-    ModuleReducedGraphParent(@Module)
+    ModuleReducedGraphParent(Rc<Module>)
 }
 
 impl ReducedGraphParent {
-    fn module(&self) -> @Module {
+    fn module(&self) -> Rc<Module> {
         match *self {
-            ModuleReducedGraphParent(m) => {
-                m
+            ModuleReducedGraphParent(ref m) => {
+                m.clone()
             }
         }
     }
@@ -279,7 +281,7 @@ enum SearchThroughModulesFlag {
 
 enum ModulePrefixResult {
     NoPrefixFound,
-    PrefixFound(@Module, uint)
+    PrefixFound(Rc<Module>, uint)
 }
 
 #[deriving(Eq)]
@@ -326,8 +328,8 @@ impl Rib {
 
 /// One import directive.
 struct ImportDirective {
-    module_path: Vec<Ident> ,
-    subclass: @ImportDirectiveSubclass,
+    module_path: Vec<Ident>,
+    subclass: ImportDirectiveSubclass,
     span: Span,
     id: NodeId,
     is_public: bool, // see note in ImportResolution about how to use this
@@ -335,7 +337,7 @@ struct ImportDirective {
 
 impl ImportDirective {
     fn new(module_path: Vec<Ident> ,
-           subclass: @ImportDirectiveSubclass,
+           subclass: ImportDirectiveSubclass,
            span: Span,
            id: NodeId,
            is_public: bool)
@@ -353,12 +355,12 @@ impl ImportDirective {
 /// The item that an import resolves to.
 #[deriving(Clone)]
 struct Target {
-    target_module: @Module,
-    bindings: @NameBindings,
+    target_module: Rc<Module>,
+    bindings: Rc<NameBindings>,
 }
 
 impl Target {
-    fn new(target_module: @Module, bindings: @NameBindings) -> Target {
+    fn new(target_module: Rc<Module>, bindings: Rc<NameBindings>) -> Target {
         Target {
             target_module: target_module,
             bindings: bindings
@@ -372,63 +374,60 @@ struct ImportResolution {
     /// should *not* be used whenever resolution is being performed, this is
     /// only looked at for glob imports statements currently. Privacy testing
     /// occurs during a later phase of compilation.
-    is_public: Cell<bool>,
+    is_public: bool,
 
     // The number of outstanding references to this name. When this reaches
     // zero, outside modules can count on the targets being correct. Before
     // then, all bets are off; future imports could override this name.
-    outstanding_references: Cell<uint>,
+    outstanding_references: uint,
 
     /// The value that this `use` directive names, if there is one.
-    value_target: RefCell<Option<Target>>,
+    value_target: Option<Target>,
     /// The source node of the `use` directive leading to the value target
     /// being non-none
-    value_id: Cell<NodeId>,
+    value_id: NodeId,
 
     /// The type that this `use` directive names, if there is one.
-    type_target: RefCell<Option<Target>>,
+    type_target: Option<Target>,
     /// The source node of the `use` directive leading to the type target
     /// being non-none
-    type_id: Cell<NodeId>,
-}
-
-fn get<T: Clone>(cell: &RefCell<T>) -> T {
-    cell.borrow().clone()
+    type_id: NodeId,
 }
 
 impl ImportResolution {
     fn new(id: NodeId, is_public: bool) -> ImportResolution {
         ImportResolution {
-            type_id: Cell::new(id),
-            value_id: Cell::new(id),
-            outstanding_references: Cell::new(0),
-            value_target: RefCell::new(None),
-            type_target: RefCell::new(None),
-            is_public: Cell::new(is_public),
+            type_id: id,
+            value_id: id,
+            outstanding_references: 0,
+            value_target: None,
+            type_target: None,
+            is_public: is_public,
         }
     }
 
     fn target_for_namespace(&self, namespace: Namespace)
                                 -> Option<Target> {
         match namespace {
-            TypeNS      => return self.type_target.borrow().clone(),
-            ValueNS     => return self.value_target.borrow().clone(),
+            TypeNS  => self.type_target.clone(),
+            ValueNS => self.value_target.clone(),
         }
     }
 
     fn id(&self, namespace: Namespace) -> NodeId {
         match namespace {
-            TypeNS  => self.type_id.get(),
-            ValueNS => self.value_id.get(),
+            TypeNS  => self.type_id,
+            ValueNS => self.value_id,
         }
     }
 }
 
 /// The link from a module up to its nearest parent node.
+#[deriving(Clone)]
 enum ParentLink {
     NoParentLink,
-    ModuleParentLink(@Module, Ident),
-    BlockParentLink(@Module, NodeId)
+    ModuleParentLink(Weak<Module>, Ident),
+    BlockParentLink(Weak<Module>, NodeId)
 }
 
 /// The type of module this is.
@@ -448,12 +447,12 @@ struct Module {
     kind: Cell<ModuleKind>,
     is_public: bool,
 
-    children: RefCell<HashMap<Name, @NameBindings>>,
-    imports: RefCell<Vec<@ImportDirective> >,
+    children: RefCell<HashMap<Name, Rc<NameBindings>>>,
+    imports: RefCell<Vec<ImportDirective>>,
 
     // The external module children of this node that were declared with
     // `extern crate`.
-    external_module_children: RefCell<HashMap<Name, @Module>>,
+    external_module_children: RefCell<HashMap<Name, Rc<Module>>>,
 
     // The anonymous children of this node. Anonymous children are pseudo-
     // modules that are implicitly created around items contained within
@@ -469,10 +468,10 @@ struct Module {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-    anonymous_children: RefCell<NodeMap<@Module>>,
+    anonymous_children: RefCell<NodeMap<Rc<Module>>>,
 
     // The status of resolving each import in this module.
-    import_resolutions: RefCell<HashMap<Name, @ImportResolution>>,
+    import_resolutions: RefCell<HashMap<Name, ImportResolution>>,
 
     // The number of unresolved globs that this module exports.
     glob_count: Cell<uint>,
@@ -518,7 +517,7 @@ impl Module {
 #[deriving(Clone)]
 struct TypeNsDef {
     is_public: bool, // see note in ImportResolution about how to use this
-    module_def: Option<@Module>,
+    module_def: Option<Rc<Module>>,
     type_def: Option<Def>,
     type_span: Option<Span>
 }
@@ -555,8 +554,8 @@ impl NameBindings {
                      is_public: bool,
                      sp: Span) {
         // Merges the module with the existing type def or creates a new one.
-        let module_ = @Module::new(parent_link, def_id, kind, external,
-                                       is_public);
+        let module_ = Rc::new(Module::new(parent_link, def_id, kind, external,
+                                          is_public));
         let type_def = self.type_def.borrow().clone();
         match type_def {
             None => {
@@ -589,11 +588,11 @@ impl NameBindings {
         let type_def = self.type_def.borrow().clone();
         match type_def {
             None => {
-                let module = @Module::new(parent_link, def_id, kind,
-                                              external, is_public);
+                let module = Module::new(parent_link, def_id, kind,
+                                         external, is_public);
                 *self.type_def.borrow_mut() = Some(TypeNsDef {
                     is_public: is_public,
-                    module_def: Some(module),
+                    module_def: Some(Rc::new(module)),
                     type_def: None,
                     type_span: None,
                 });
@@ -601,14 +600,14 @@ impl NameBindings {
             Some(type_def) => {
                 match type_def.module_def {
                     None => {
-                        let module = @Module::new(parent_link,
-                                                      def_id,
-                                                      kind,
-                                                      external,
-                                                      is_public);
+                        let module = Module::new(parent_link,
+                                                 def_id,
+                                                 kind,
+                                                 external,
+                                                 is_public);
                         *self.type_def.borrow_mut() = Some(TypeNsDef {
                             is_public: is_public,
-                            module_def: Some(module),
+                            module_def: Some(Rc::new(module)),
                             type_def: type_def.type_def,
                             type_span: None,
                         });
@@ -653,9 +652,9 @@ impl NameBindings {
     }
 
     /// Returns the module node if applicable.
-    fn get_module_if_available(&self) -> Option<@Module> {
+    fn get_module_if_available(&self) -> Option<Rc<Module>> {
         match *self.type_def.borrow() {
-            Some(ref type_def) => (*type_def).module_def,
+            Some(ref type_def) => type_def.module_def.clone(),
             None => None
         }
     }
@@ -664,7 +663,7 @@ impl NameBindings {
      * Returns the module node. Fails if this node does not have a module
      * definition.
      */
-    fn get_module(&self) -> @Module {
+    fn get_module(&self) -> Rc<Module> {
         match self.get_module_if_available() {
             None => {
                 fail!("get_module called on a node with no module \
@@ -684,10 +683,10 @@ impl NameBindings {
     fn defined_in_public_namespace(&self, namespace: Namespace) -> bool {
         match namespace {
             TypeNS => match *self.type_def.borrow() {
-                Some(def) => def.is_public, None => false
+                Some(ref def) => def.is_public, None => false
             },
             ValueNS => match *self.value_def.borrow() {
-                Some(def) => def.is_public, None => false
+                Some(ref def) => def.is_public, None => false
             }
         }
     }
@@ -697,12 +696,12 @@ impl NameBindings {
             TypeNS => {
                 match *self.type_def.borrow() {
                     None => None,
-                    Some(type_def) => {
+                    Some(ref type_def) => {
                         match type_def.type_def {
                             Some(type_def) => Some(type_def),
                             None => {
                                 match type_def.module_def {
-                                    Some(module) => {
+                                    Some(ref module) => {
                                         match module.def_id.get() {
                                             Some(did) => Some(DefMod(did)),
                                             None => None,
@@ -730,13 +729,13 @@ impl NameBindings {
                 TypeNS  => {
                     match *self.type_def.borrow() {
                         None => None,
-                        Some(type_def) => type_def.type_span
+                        Some(ref type_def) => type_def.type_span
                     }
                 }
                 ValueNS => {
                     match *self.value_def.borrow() {
                         None => None,
-                        Some(value_def) => value_def.value_span
+                        Some(ref value_def) => value_def.value_span
                     }
                 }
             }
@@ -799,9 +798,9 @@ fn namespace_error_to_str(ns: NamespaceError) -> &'static str {
 }
 
 fn Resolver<'a>(session: &'a Session,
-                lang_items: @LanguageItems,
+                lang_items: &'a LanguageItems,
                 crate_span: Span) -> Resolver<'a> {
-    let graph_root = @NameBindings();
+    let graph_root = NameBindings();
 
     graph_root.define_module(NoParentLink,
                              Some(DefId { krate: 0, node: 0 }),
@@ -821,27 +820,27 @@ fn Resolver<'a>(session: &'a Session,
 
         graph_root: graph_root,
 
-        method_map: @RefCell::new(HashMap::new()),
+        method_set: RefCell::new(FnvHashSet::new()),
         structs: HashSet::new(),
 
         unresolved_imports: 0,
 
         current_module: current_module,
-        value_ribs: @RefCell::new(Vec::new()),
-        type_ribs: @RefCell::new(Vec::new()),
-        label_ribs: @RefCell::new(Vec::new()),
+        value_ribs: RefCell::new(Vec::new()),
+        type_ribs: RefCell::new(Vec::new()),
+        label_ribs: RefCell::new(Vec::new()),
 
         current_trait_refs: None,
 
         self_ident: special_idents::self_,
         type_self_ident: special_idents::type_self,
 
-        primitive_type_table: @PrimitiveTypeTable(),
+        primitive_type_table: PrimitiveTypeTable(),
 
         namespaces: vec!(TypeNS, ValueNS),
 
-        def_map: @RefCell::new(NodeMap::new()),
-        export_map2: @RefCell::new(NodeMap::new()),
+        def_map: RefCell::new(NodeMap::new()),
+        export_map2: RefCell::new(NodeMap::new()),
         trait_map: NodeMap::new(),
         used_imports: HashSet::new(),
         external_exports: DefIdSet::new(),
@@ -856,28 +855,28 @@ fn Resolver<'a>(session: &'a Session,
 /// The main resolver class.
 struct Resolver<'a> {
     session: &'a Session,
-    lang_items: @LanguageItems,
+    lang_items: &'a LanguageItems,
 
-    graph_root: @NameBindings,
+    graph_root: NameBindings,
 
-    method_map: @RefCell<HashMap<Name, HashSet<DefId>>>,
+    method_set: RefCell<FnvHashSet<(Name, DefId)>>,
     structs: HashSet<DefId>,
 
     // The number of imports that are currently unresolved.
     unresolved_imports: uint,
 
     // The module that represents the current item scope.
-    current_module: @Module,
+    current_module: Rc<Module>,
 
     // The current set of local scopes, for values.
     // FIXME #4948: Reuse ribs to avoid allocation.
-    value_ribs: @RefCell<Vec<@Rib> >,
+    value_ribs: RefCell<Vec<Rib>>,
 
     // The current set of local scopes, for types.
-    type_ribs: @RefCell<Vec<@Rib> >,
+    type_ribs: RefCell<Vec<Rib>>,
 
     // The current set of local scopes, for labels.
-    label_ribs: @RefCell<Vec<@Rib> >,
+    label_ribs: RefCell<Vec<Rib>>,
 
     // The trait that the current context can refer to.
     current_trait_refs: Option<Vec<DefId> >,
@@ -888,7 +887,7 @@ struct Resolver<'a> {
     type_self_ident: Ident,
 
     // The idents for the primitive types.
-    primitive_type_table: @PrimitiveTypeTable,
+    primitive_type_table: PrimitiveTypeTable,
 
     // The four namespaces.
     namespaces: Vec<Namespace> ,
@@ -921,10 +920,10 @@ impl<'a, 'b> Visitor<ReducedGraphParent> for BuildReducedGraphVisitor<'a, 'b> {
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem,
                           context: ReducedGraphParent) {
         self.resolver.build_reduced_graph_for_foreign_item(foreign_item,
-                                                           context,
-                                                           |r, c| {
+                                                           context.clone(),
+                                                           |r| {
             let mut v = BuildReducedGraphVisitor{ resolver: r };
-            visit::walk_foreign_item(&mut v, foreign_item, c);
+            visit::walk_foreign_item(&mut v, foreign_item, context.clone());
         })
     }
 
@@ -982,17 +981,6 @@ impl<'a> Resolver<'a> {
         visit::walk_crate(&mut visitor, krate, initial_parent);
     }
 
-    /// Returns the current module tracked by the reduced graph parent.
-    fn get_module_from_parent(&mut self,
-                                  reduced_graph_parent: ReducedGraphParent)
-                                  -> @Module {
-        match reduced_graph_parent {
-            ModuleReducedGraphParent(module_) => {
-                return module_;
-            }
-        }
-    }
-
     /**
      * Adds a new child item to the module definition of the parent node and
      * returns its corresponding name bindings as well as the current parent.
@@ -1003,32 +991,26 @@ impl<'a> Resolver<'a> {
      * If this node does not have a module definition and we are not inside
      * a block, fails.
      */
-    fn add_child(&mut self,
-                     name: Ident,
-                     reduced_graph_parent: ReducedGraphParent,
-                     duplicate_checking_mode: DuplicateCheckingMode,
-                     // For printing errors
-                     sp: Span)
-                     -> (@NameBindings, ReducedGraphParent) {
+    fn add_child(&self,
+                 name: Ident,
+                 reduced_graph_parent: ReducedGraphParent,
+                 duplicate_checking_mode: DuplicateCheckingMode,
+                 // For printing errors
+                 sp: Span)
+                 -> Rc<NameBindings> {
         // If this is the immediate descendant of a module, then we add the
         // child name directly. Otherwise, we create or reuse an anonymous
         // module and add the child to that.
 
-        let module_;
-        match reduced_graph_parent {
-            ModuleReducedGraphParent(parent_module) => {
-                module_ = parent_module;
-            }
-        }
+        let module_ = reduced_graph_parent.module();
 
         // Add or reuse the child.
-        let new_parent = ModuleReducedGraphParent(module_);
-        let child_opt = module_.children.borrow().find_copy(&name.name);
-        match child_opt {
+        let child = module_.children.borrow().find_copy(&name.name);
+        match child {
             None => {
-                let child = @NameBindings();
-                module_.children.borrow_mut().insert(name.name, child);
-                return (child, new_parent);
+                let child = Rc::new(NameBindings());
+                module_.children.borrow_mut().insert(name.name, child.clone());
+                child
             }
             Some(child) => {
                 // Enforce the duplicate checking mode:
@@ -1105,7 +1087,7 @@ impl<'a> Resolver<'a> {
                         }
                     }
                 }
-                return (child, new_parent);
+                child
             }
         }
     }
@@ -1145,7 +1127,7 @@ impl<'a> Resolver<'a> {
                            -> ParentLink {
         match parent {
             ModuleReducedGraphParent(module_) => {
-                return ModuleParentLink(module_, name);
+                return ModuleParentLink(module_.downgrade(), name);
             }
         }
     }
@@ -1162,10 +1144,10 @@ impl<'a> Resolver<'a> {
 
         match item.node {
             ItemMod(..) => {
-                let (name_bindings, new_parent) =
-                    self.add_child(ident, parent, ForbidDuplicateModules, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateModules, sp);
 
-                let parent_link = self.get_parent_link(new_parent, ident);
+                let parent_link = self.get_parent_link(parent, ident);
                 let def_id = DefId { krate: 0, node: item.id };
                 name_bindings.define_module(parent_link,
                                             Some(def_id),
@@ -1181,8 +1163,8 @@ impl<'a> Resolver<'a> {
 
             // These items live in the value namespace.
             ItemStatic(_, m, _) => {
-                let (name_bindings, _) =
-                    self.add_child(ident, parent, ForbidDuplicateValues, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateValues, sp);
                 let mutbl = m == ast::MutMutable;
 
                 name_bindings.define_value
@@ -1190,18 +1172,18 @@ impl<'a> Resolver<'a> {
                 parent
             }
             ItemFn(_, fn_style, _, _, _) => {
-              let (name_bindings, new_parent) =
-                self.add_child(ident, parent, ForbidDuplicateValues, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateValues, sp);
 
                 let def = DefFn(local_def(item.id), fn_style);
                 name_bindings.define_value(def, sp, is_public);
-                new_parent
+                parent
             }
 
             // These items live in the type namespace.
             ItemTy(..) => {
-                let (name_bindings, _) =
-                    self.add_child(ident, parent, ForbidDuplicateTypes, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
 
                 name_bindings.define_type
                     (DefTy(local_def(item.id)), sp, is_public);
@@ -1209,8 +1191,8 @@ impl<'a> Resolver<'a> {
             }
 
             ItemEnum(ref enum_definition, _) => {
-                let (name_bindings, new_parent) =
-                    self.add_child(ident, parent, ForbidDuplicateTypes, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
 
                 name_bindings.define_type
                     (DefTy(local_def(item.id)), sp, is_public);
@@ -1219,7 +1201,7 @@ impl<'a> Resolver<'a> {
                     self.build_reduced_graph_for_variant(
                         variant,
                         local_def(item.id),
-                        new_parent,
+                        parent.clone(),
                         is_public);
                 }
                 parent
@@ -1233,7 +1215,7 @@ impl<'a> Resolver<'a> {
                     None            => (ForbidDuplicateTypes, None)
                 };
 
-                let (name_bindings, new_parent) = self.add_child(ident, parent, forbid, sp);
+                let name_bindings = self.add_child(ident, parent.clone(), forbid, sp);
 
                 // Define a name in the type namespace.
                 name_bindings.define_type(DefTy(local_def(item.id)), sp, is_public);
@@ -1249,7 +1231,7 @@ impl<'a> Resolver<'a> {
                 // Record the def ID of this struct.
                 self.structs.insert(local_def(item.id));
 
-                new_parent
+                parent
             }
 
             ItemImpl(_, None, ty, ref methods) => {
@@ -1270,7 +1252,7 @@ impl<'a> Resolver<'a> {
                                                .find_copy(&name.name);
                         let new_parent = match parent_opt {
                             // It already exists
-                            Some(child) if child.get_module_if_available()
+                            Some(ref child) if child.get_module_if_available()
                                                 .is_some() &&
                                            child.get_module().kind.get() ==
                                                 ImplModuleKind => {
@@ -1278,14 +1260,14 @@ impl<'a> Resolver<'a> {
                             }
                             // Create the module
                             _ => {
-                                let (name_bindings, new_parent) =
+                                let name_bindings =
                                     self.add_child(name,
-                                                   parent,
+                                                   parent.clone(),
                                                    ForbidDuplicateModules,
                                                    sp);
 
                                 let parent_link =
-                                    self.get_parent_link(new_parent, ident);
+                                    self.get_parent_link(parent.clone(), ident);
                                 let def_id = local_def(item.id);
                                 let ns = TypeNS;
                                 let is_public =
@@ -1308,9 +1290,9 @@ impl<'a> Resolver<'a> {
                         for method in methods.iter() {
                             // Add the method to the module.
                             let ident = method.ident;
-                            let (method_name_bindings, _) =
+                            let method_name_bindings =
                                 self.add_child(ident,
-                                               new_parent,
+                                               new_parent.clone(),
                                                ForbidDuplicateValues,
                                                method.span);
                             let def = match method.explicit_self.node {
@@ -1344,11 +1326,11 @@ impl<'a> Resolver<'a> {
             ItemImpl(_, Some(_), _, _) => parent,
 
             ItemTrait(_, _, ref methods) => {
-                let (name_bindings, new_parent) =
-                    self.add_child(ident, parent, ForbidDuplicateTypes, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
 
                 // Add all the methods within to a new module.
-                let parent_link = self.get_parent_link(parent, ident);
+                let parent_link = self.get_parent_link(parent.clone(), ident);
                 name_bindings.define_module(parent_link,
                                             Some(local_def(item.id)),
                                             TraitModuleKind,
@@ -1358,8 +1340,9 @@ impl<'a> Resolver<'a> {
                 let module_parent = ModuleReducedGraphParent(name_bindings.
                                                              get_module());
 
+                let def_id = local_def(item.id);
+
                 // Add the names of all the methods to the trait info.
-                let mut method_names = HashMap::new();
                 for method in methods.iter() {
                     let ty_m = trait_method_to_ty_method(method);
 
@@ -1380,36 +1363,21 @@ impl<'a> Resolver<'a> {
                         }
                     };
 
-                    let (method_name_bindings, _) =
+                    let method_name_bindings =
                         self.add_child(ident,
-                                       module_parent,
+                                       module_parent.clone(),
                                        ForbidDuplicateValues,
                                        ty_m.span);
                     method_name_bindings.define_value(def, ty_m.span, true);
 
                     // Add it to the trait info if not static.
-                    match ty_m.explicit_self.node {
-                        SelfStatic => {}
-                        _ => {
-                            method_names.insert(ident.name, ());
-                        }
-                    }
-                }
-
-                let def_id = local_def(item.id);
-                for (name, _) in method_names.iter() {
-                    let mut method_map = self.method_map.borrow_mut();
-                    if !method_map.contains_key(name) {
-                        method_map.insert(*name, HashSet::new());
-                    }
-                    match method_map.find_mut(name) {
-                        Some(s) => { s.insert(def_id); },
-                        _ => fail!("can't happen"),
+                    if ty_m.explicit_self.node != SelfStatic {
+                        self.method_set.borrow_mut().insert((ident.name, def_id));
                     }
                 }
 
                 name_bindings.define_type(DefTrait(def_id), sp, is_public);
-                new_parent
+                parent
             }
             ItemMac(..) => parent
         }
@@ -1426,15 +1394,15 @@ impl<'a> Resolver<'a> {
 
         match variant.node.kind {
             TupleVariantKind(_) => {
-                let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues,
-                                                variant.span);
+                let child = self.add_child(ident, parent, ForbidDuplicateValues, variant.span);
                 child.define_value(DefVariant(item_id,
                                               local_def(variant.node.id), false),
                                    variant.span, is_public);
             }
             StructVariantKind(_) => {
-                let (child, _) = self.add_child(ident, parent, ForbidDuplicateTypesAndValues,
-                                                variant.span);
+                let child = self.add_child(ident, parent,
+                                           ForbidDuplicateTypesAndValues,
+                                           variant.span);
                 child.define_type(DefVariant(item_id,
                                              local_def(variant.node.id), true),
                                   variant.span, is_public);
@@ -1478,15 +1446,15 @@ impl<'a> Resolver<'a> {
                     }
 
                     // Build up the import directives.
-                    let module_ = self.get_module_from_parent(parent);
+                    let module_ = parent.module();
                     let is_public = view_item.vis == ast::Public;
                     match view_path.node {
                         ViewPathSimple(binding, ref full_path, id) => {
                             let source_ident =
                                 full_path.segments.last().unwrap().identifier;
-                            let subclass = @SingleImport(binding,
-                                                         source_ident);
-                            self.build_import_directive(module_,
+                            let subclass = SingleImport(binding,
+                                                        source_ident);
+                            self.build_import_directive(&*module_,
                                                         module_path,
                                                         subclass,
                                                         view_path.span,
@@ -1496,20 +1464,19 @@ impl<'a> Resolver<'a> {
                         ViewPathList(_, ref source_idents, _) => {
                             for source_ident in source_idents.iter() {
                                 let name = source_ident.node.name;
-                                let subclass = @SingleImport(name, name);
                                 self.build_import_directive(
-                                    module_,
+                                    &*module_,
                                     module_path.clone(),
-                                    subclass,
+                                    SingleImport(name, name),
                                     source_ident.span,
                                     source_ident.node.id,
                                     is_public);
                             }
                         }
                         ViewPathGlob(_, id) => {
-                            self.build_import_directive(module_,
+                            self.build_import_directive(&*module_,
                                                         module_path,
-                                                        @GlobImport,
+                                                        GlobImport,
                                                         view_path.span,
                                                         id,
                                                         is_public);
@@ -1525,16 +1492,16 @@ impl<'a> Resolver<'a> {
                         let def_id = DefId { krate: crate_id, node: 0 };
                         self.external_exports.insert(def_id);
                         let parent_link = ModuleParentLink
-                            (self.get_module_from_parent(parent), name);
-                        let external_module = @Module::new(parent_link,
-                                                          Some(def_id),
-                                                          NormalModuleKind,
-                                                          false,
-                                                          true);
+                            (parent.module().downgrade(), name);
+                        let external_module = Rc::new(Module::new(parent_link,
+                                                                  Some(def_id),
+                                                                  NormalModuleKind,
+                                                                  false,
+                                                                  true));
 
                         parent.module().external_module_children
                               .borrow_mut().insert(name.name,
-                                                   external_module);
+                                                   external_module.clone());
 
                         self.build_reduced_graph_for_external_crate(
                             external_module);
@@ -1549,11 +1516,10 @@ impl<'a> Resolver<'a> {
     fn build_reduced_graph_for_foreign_item(&mut self,
                                             foreign_item: &ForeignItem,
                                             parent: ReducedGraphParent,
-                                            f: |&mut Resolver,
-                                                ReducedGraphParent|) {
+                                            f: |&mut Resolver|) {
         let name = foreign_item.ident;
         let is_public = foreign_item.vis == ast::Public;
-        let (name_bindings, new_parent) =
+        let name_bindings =
             self.add_child(name, parent, ForbidDuplicateValues,
                            foreign_item.span);
 
@@ -1567,13 +1533,13 @@ impl<'a> Resolver<'a> {
                                       foreign_item.id,
                                       0,
                                       NormalRibKind),
-                    |this| f(this, new_parent));
+                    f);
             }
             ForeignItemStatic(_, m) => {
                 let def = DefStatic(local_def(foreign_item.id), m);
                 name_bindings.define_value(def, foreign_item.span, is_public);
 
-                f(self, new_parent)
+                f(self)
             }
         }
     }
@@ -1590,15 +1556,15 @@ impl<'a> Resolver<'a> {
                     anonymous module for block {}",
                    block_id);
 
-            let parent_module = self.get_module_from_parent(parent);
-            let new_module = @Module::new(
-                BlockParentLink(parent_module, block_id),
+            let parent_module = parent.module();
+            let new_module = Rc::new(Module::new(
+                BlockParentLink(parent_module.downgrade(), block_id),
                 None,
                 AnonymousModuleKind,
                 false,
-                false);
+                false));
             parent_module.anonymous_children.borrow_mut()
-                         .insert(block_id, new_module);
+                         .insert(block_id, new_module.clone());
             ModuleReducedGraphParent(new_module)
         } else {
             parent
@@ -1608,7 +1574,7 @@ impl<'a> Resolver<'a> {
     fn handle_external_def(&mut self,
                            def: Def,
                            vis: Visibility,
-                           child_name_bindings: @NameBindings,
+                           child_name_bindings: &NameBindings,
                            final_ident: &str,
                            ident: Ident,
                            new_parent: ReducedGraphParent) {
@@ -1617,7 +1583,7 @@ impl<'a> Resolver<'a> {
                vis);
         let is_public = vis == ast::Public;
         let is_exported = is_public && match new_parent {
-            ModuleReducedGraphParent(module) => {
+            ModuleReducedGraphParent(ref module) => {
                 match module.def_id.get() {
                     None => true,
                     Some(did) => self.external_exports.contains(&did)
@@ -1641,7 +1607,7 @@ impl<'a> Resolver<'a> {
                 debug!("(building reduced graph for \
                         external crate) building module \
                         {}", final_ident);
-                let parent_link = self.get_parent_link(new_parent, ident);
+                let parent_link = self.get_parent_link(new_parent.clone(), ident);
 
                 child_name_bindings.define_module(parent_link,
                                                   Some(def_id),
@@ -1685,7 +1651,6 @@ impl<'a> Resolver<'a> {
 
               let method_def_ids =
                 csearch::get_trait_method_def_ids(&self.session.cstore, def_id);
-              let mut interned_method_names = HashSet::new();
               for &method_def_id in method_def_ids.iter() {
                   let (method_name, explicit_self) =
                       csearch::get_method_name_and_explicit_self(&self.session.cstore,
@@ -1698,22 +1663,12 @@ impl<'a> Resolver<'a> {
 
                   // Add it to the trait info if not static.
                   if explicit_self != SelfStatic {
-                      interned_method_names.insert(method_name.name);
+                      self.method_set.borrow_mut().insert((method_name.name, def_id));
                   }
                   if is_exported {
                       self.external_exports.insert(method_def_id);
                   }
               }
-              for name in interned_method_names.iter() {
-                  let mut method_map = self.method_map.borrow_mut();
-                  if !method_map.contains_key(name) {
-                      method_map.insert(*name, HashSet::new());
-                  }
-                  match method_map.find_mut(name) {
-                      Some(s) => { s.insert(def_id); },
-                      _ => fail!("can't happen"),
-                  }
-              }
 
               child_name_bindings.define_type(def, DUMMY_SP, is_public);
 
@@ -1758,7 +1713,7 @@ impl<'a> Resolver<'a> {
 
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_def(&mut self,
-                                                  root: @Module,
+                                                  root: Rc<Module>,
                                                   def_like: DefLike,
                                                   ident: Ident,
                                                   visibility: Visibility) {
@@ -1775,25 +1730,25 @@ impl<'a> Resolver<'a> {
                                                      child_ident,
                                                      vis| {
                             self.build_reduced_graph_for_external_crate_def(
-                                root,
+                                root.clone(),
                                 def_like,
                                 child_ident,
                                 vis)
                         });
                     }
                     _ => {
-                        let (child_name_bindings, new_parent) =
+                        let child_name_bindings =
                             self.add_child(ident,
-                                           ModuleReducedGraphParent(root),
+                                           ModuleReducedGraphParent(root.clone()),
                                            OverwriteDuplicates,
                                            DUMMY_SP);
 
                         self.handle_external_def(def,
                                                  visibility,
-                                                 child_name_bindings,
+                                                 &*child_name_bindings,
                                                  token::get_ident(ident).get(),
                                                  ident,
-                                                 new_parent);
+                                                 ModuleReducedGraphParent(root));
                     }
                 }
             }
@@ -1812,10 +1767,10 @@ impl<'a> Resolver<'a> {
                                         static methods for type name {}",
                                         token::get_ident(final_ident));
 
-                                let (child_name_bindings, new_parent) =
+                                let child_name_bindings =
                                     self.add_child(
                                         final_ident,
-                                        ModuleReducedGraphParent(root),
+                                        ModuleReducedGraphParent(root.clone()),
                                         OverwriteDuplicates,
                                         DUMMY_SP);
 
@@ -1838,7 +1793,7 @@ impl<'a> Resolver<'a> {
                                     }
                                     Some(_) | None => {
                                         let parent_link =
-                                            self.get_parent_link(new_parent,
+                                            self.get_parent_link(ModuleReducedGraphParent(root),
                                                                  final_ident);
                                         child_name_bindings.define_module(
                                             parent_link,
@@ -1864,9 +1819,9 @@ impl<'a> Resolver<'a> {
                                              static method '{}'",
                                            token::get_ident(ident));
 
-                                    let (method_name_bindings, _) =
+                                    let method_name_bindings =
                                         self.add_child(ident,
-                                                       new_parent,
+                                                       new_parent.clone(),
                                                        OverwriteDuplicates,
                                                        DUMMY_SP);
                                     let def = DefFn(
@@ -1893,9 +1848,9 @@ impl<'a> Resolver<'a> {
     }
 
     /// Builds the reduced graph rooted at the given external module.
-    fn populate_external_module(&mut self, module: @Module) {
+    fn populate_external_module(&mut self, module: Rc<Module>) {
         debug!("(populating external module) attempting to populate {}",
-               self.module_to_str(module));
+               self.module_to_str(&*module));
 
         let def_id = match module.def_id.get() {
             None => {
@@ -1910,7 +1865,7 @@ impl<'a> Resolver<'a> {
                                     |def_like, child_ident, visibility| {
             debug!("(populating external module) ... found ident: {}",
                    token::get_ident(child_ident));
-            self.build_reduced_graph_for_external_crate_def(module,
+            self.build_reduced_graph_for_external_crate_def(module.clone(),
                                                             def_like,
                                                             child_ident,
                                                             visibility)
@@ -1920,24 +1875,23 @@ impl<'a> Resolver<'a> {
 
     /// Ensures that the reduced graph rooted at the given external module
     /// is built, building it if it is not.
-    fn populate_module_if_necessary(&mut self, module: @Module) {
+    fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
         if !module.populated.get() {
-            self.populate_external_module(module)
+            self.populate_external_module(module.clone())
         }
         assert!(module.populated.get())
     }
 
     /// Builds the reduced graph rooted at the 'use' directive for an external
     /// crate.
-    fn build_reduced_graph_for_external_crate(&mut self,
-                                              root: @Module) {
+    fn build_reduced_graph_for_external_crate(&mut self, root: Rc<Module>) {
         csearch::each_top_level_item_of_crate(&self.session.cstore,
                                               root.def_id
                                                   .get()
                                                   .unwrap()
                                                   .krate,
                                               |def_like, ident, visibility| {
-            self.build_reduced_graph_for_external_crate_def(root,
+            self.build_reduced_graph_for_external_crate_def(root.clone(),
                                                             def_like,
                                                             ident,
                                                             visibility)
@@ -1946,47 +1900,48 @@ impl<'a> Resolver<'a> {
 
     /// Creates and adds an import directive to the given module.
     fn build_import_directive(&mut self,
-                              module_: @Module,
+                              module_: &Module,
                               module_path: Vec<Ident> ,
-                              subclass: @ImportDirectiveSubclass,
+                              subclass: ImportDirectiveSubclass,
                               span: Span,
                               id: NodeId,
                               is_public: bool) {
-        let directive = @ImportDirective::new(module_path,
-                                              subclass, span, id,
-                                              is_public);
-        module_.imports.borrow_mut().push(directive);
+        module_.imports.borrow_mut().push(ImportDirective::new(module_path,
+                                                               subclass,
+                                                               span, id,
+                                                               is_public));
+        self.unresolved_imports += 1;
         // Bump the reference count on the name. Or, if this is a glob, set
         // the appropriate flag.
 
-        match *subclass {
+        match subclass {
             SingleImport(target, _) => {
                 debug!("(building import directive) building import \
                         directive: {}::{}",
-                       self.idents_to_str(directive.module_path.as_slice()),
+                       self.idents_to_str(module_.imports.borrow().last().unwrap()
+                                                 .module_path.as_slice()),
                        token::get_ident(target));
 
                 let mut import_resolutions = module_.import_resolutions
                                                     .borrow_mut();
-                match import_resolutions.find(&target.name) {
-                    Some(&resolution) => {
+                match import_resolutions.find_mut(&target.name) {
+                    Some(resolution) => {
                         debug!("(building import directive) bumping \
                                 reference");
-                        resolution.outstanding_references.set(
-                            resolution.outstanding_references.get() + 1);
+                        resolution.outstanding_references += 1;
 
                         // the source of this name is different now
-                        resolution.type_id.set(id);
-                        resolution.value_id.set(id);
-                        resolution.is_public.set(is_public);
-                    }
-                    None => {
-                        debug!("(building import directive) creating new");
-                        let resolution = @ImportResolution::new(id, is_public);
-                        resolution.outstanding_references.set(1);
-                        import_resolutions.insert(target.name, resolution);
+                        resolution.type_id = id;
+                        resolution.value_id = id;
+                        resolution.is_public = is_public;
+                        return;
                     }
+                    None => {}
                 }
+                debug!("(building import directive) creating new");
+                let mut resolution = ImportResolution::new(id, is_public);
+                resolution.outstanding_references = 1;
+                import_resolutions.insert(target.name, resolution);
             }
             GlobImport => {
                 // Set the glob flag. This tells us that we don't know the
@@ -1995,8 +1950,6 @@ impl<'a> Resolver<'a> {
                 module_.glob_count.set(module_.glob_count.get() + 1);
             }
         }
-
-        self.unresolved_imports += 1;
     }
 
     // Import resolution
@@ -2017,7 +1970,7 @@ impl<'a> Resolver<'a> {
                    i, self.unresolved_imports);
 
             let module_root = self.graph_root.get_module();
-            self.resolve_imports_for_module_subtree(module_root);
+            self.resolve_imports_for_module_subtree(module_root.clone());
 
             if self.unresolved_imports == 0 {
                 debug!("(resolving imports) success");
@@ -2036,14 +1989,13 @@ impl<'a> Resolver<'a> {
 
     /// Attempts to resolve imports for the given module and all of its
     /// submodules.
-    fn resolve_imports_for_module_subtree(&mut self,
-                                              module_: @Module) {
+    fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
         debug!("(resolving imports for module subtree) resolving {}",
-               self.module_to_str(module_));
-        self.resolve_imports_for_module(module_);
+               self.module_to_str(&*module_));
+        self.resolve_imports_for_module(module_.clone());
 
-        self.populate_module_if_necessary(module_);
-        for (_, &child_node) in module_.children.borrow().iter() {
+        self.populate_module_if_necessary(&module_);
+        for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
                     // Nothing to do.
@@ -2054,17 +2006,17 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for (_, &child_module) in module_.anonymous_children.borrow().iter() {
-            self.resolve_imports_for_module_subtree(child_module);
+        for (_, child_module) in module_.anonymous_children.borrow().iter() {
+            self.resolve_imports_for_module_subtree(child_module.clone());
         }
     }
 
     /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_for_module(&mut self, module: @Module) {
+    fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
         if module.all_imports_resolved() {
             debug!("(resolving imports for module) all imports resolved for \
                    {}",
-                   self.module_to_str(module));
+                   self.module_to_str(&*module));
             return;
         }
 
@@ -2072,15 +2024,15 @@ impl<'a> Resolver<'a> {
         let import_count = imports.len();
         while module.resolved_import_count.get() < import_count {
             let import_index = module.resolved_import_count.get();
-            let import_directive = *imports.get(import_index);
-            match self.resolve_import_for_module(module, import_directive) {
+            let import_directive = imports.get(import_index);
+            match self.resolve_import_for_module(module.clone(), import_directive) {
                 Failed => {
                     // We presumably emitted an error. Continue.
                     let msg = format!("failed to resolve import `{}`",
                                    self.import_path_to_str(
                                        import_directive.module_path
                                                        .as_slice(),
-                                       *import_directive.subclass));
+                                       import_directive.subclass));
                     self.resolve_error(import_directive.span, msg);
                 }
                 Indeterminate => {
@@ -2149,8 +2101,8 @@ impl<'a> Resolver<'a> {
     /// currently-unresolved imports, or success if we know the name exists.
     /// If successful, the resolved bindings are written into the module.
     fn resolve_import_for_module(&mut self,
-                                 module_: @Module,
-                                 import_directive: @ImportDirective)
+                                 module_: Rc<Module>,
+                                 import_directive: &ImportDirective)
                                  -> ResolveResult<()> {
         let mut resolution_result = Failed;
         let module_path = &import_directive.module_path;
@@ -2158,14 +2110,14 @@ impl<'a> Resolver<'a> {
         debug!("(resolving import for module) resolving import `{}::...` in \
                 `{}`",
                self.idents_to_str(module_path.as_slice()),
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // First, resolve the module path for the directive, if necessary.
         let container = if module_path.len() == 0 {
             // Use the crate root.
             Some((self.graph_root.get_module(), LastMod(AllPublic)))
         } else {
-            match self.resolve_module_path(module_,
+            match self.resolve_module_path(module_.clone(),
                                            module_path.as_slice(),
                                            DontUseLexicalScope,
                                            import_directive.span,
@@ -2186,10 +2138,10 @@ impl<'a> Resolver<'a> {
                 // We found the module that the target is contained
                 // within. Attempt to resolve the import within it.
 
-                match *import_directive.subclass {
+                match import_directive.subclass {
                     SingleImport(target, source) => {
                         resolution_result =
-                            self.resolve_single_import(module_,
+                            self.resolve_single_import(&*module_,
                                                        containing_module,
                                                        target,
                                                        source,
@@ -2198,7 +2150,7 @@ impl<'a> Resolver<'a> {
                     }
                     GlobImport => {
                         resolution_result =
-                            self.resolve_glob_import(module_,
+                            self.resolve_glob_import(&*module_,
                                                      containing_module,
                                                      import_directive.id,
                                                      import_directive.is_public,
@@ -2225,7 +2177,7 @@ impl<'a> Resolver<'a> {
         // resolve_imports_for_module.)
 
         if !resolution_result.indeterminate() {
-            match *import_directive.subclass {
+            match import_directive.subclass {
                 GlobImport => {
                     assert!(module_.glob_count.get() >= 1);
                     module_.glob_count.set(module_.glob_count.get() - 1);
@@ -2239,7 +2191,7 @@ impl<'a> Resolver<'a> {
         return resolution_result;
     }
 
-    fn create_name_bindings_from_module(module: @Module) -> NameBindings {
+    fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
         NameBindings {
             type_def: RefCell::new(Some(TypeNsDef {
                 is_public: false,
@@ -2252,8 +2204,8 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_single_import(&mut self,
-                             module_: @Module,
-                             containing_module: @Module,
+                             module_: &Module,
+                             containing_module: Rc<Module>,
                              target: Ident,
                              source: Ident,
                              directive: &ImportDirective,
@@ -2262,7 +2214,7 @@ impl<'a> Resolver<'a> {
         debug!("(resolving single import) resolving `{}` = `{}::{}` from \
                 `{}` id {}, last private {:?}",
                token::get_ident(target),
-               self.module_to_str(containing_module),
+               self.module_to_str(&*containing_module),
                token::get_ident(source),
                self.module_to_str(module_),
                directive.id,
@@ -2281,22 +2233,22 @@ impl<'a> Resolver<'a> {
         let mut type_result = UnknownResult;
 
         // Search for direct children of the containing module.
-        self.populate_module_if_necessary(containing_module);
+        self.populate_module_if_necessary(&containing_module);
 
         match containing_module.children.borrow().find(&source.name) {
             None => {
                 // Continue.
             }
-            Some(child_name_bindings) => {
+            Some(ref child_name_bindings) => {
                 if child_name_bindings.defined_in_namespace(ValueNS) {
                     debug!("(resolving single import) found value binding");
-                    value_result = BoundResult(containing_module,
-                                               *child_name_bindings);
+                    value_result = BoundResult(containing_module.clone(),
+                                               (*child_name_bindings).clone());
                 }
                 if child_name_bindings.defined_in_namespace(TypeNS) {
                     debug!("(resolving single import) found type binding");
-                    type_result = BoundResult(containing_module,
-                                              *child_name_bindings);
+                    type_result = BoundResult(containing_module.clone(),
+                                              (*child_name_bindings).clone());
                 }
             }
         }
@@ -2305,7 +2257,7 @@ impl<'a> Resolver<'a> {
         // search imports as well.
         let mut value_used_reexport = false;
         let mut type_used_reexport = false;
-        match (value_result, type_result) {
+        match (value_result.clone(), type_result.clone()) {
             (BoundResult(..), BoundResult(..)) => {} // Continue.
             _ => {
                 // If there is an unresolved glob at this point in the
@@ -2318,12 +2270,8 @@ impl<'a> Resolver<'a> {
                     return Indeterminate;
                 }
 
-                // Now search the exported imports within the containing
-                // module.
-
-                let import_resolutions = containing_module.import_resolutions
-                                                          .borrow();
-                match import_resolutions.find(&source.name) {
+                // Now search the exported imports within the containing module.
+                match containing_module.import_resolutions.borrow().find(&source.name) {
                     None => {
                         debug!("(resolving single import) no import");
                         // The containing module definitely doesn't have an
@@ -2339,32 +2287,30 @@ impl<'a> Resolver<'a> {
                         }
                     }
                     Some(import_resolution)
-                            if import_resolution.outstanding_references.get()
-                                == 0 => {
+                            if import_resolution.outstanding_references == 0 => {
 
                         fn get_binding(this: &mut Resolver,
-                                       import_resolution: @ImportResolution,
+                                       import_resolution: &ImportResolution,
                                        namespace: Namespace)
                                     -> NamespaceResult {
 
                             // Import resolutions must be declared with "pub"
                             // in order to be exported.
-                            if !import_resolution.is_public.get() {
+                            if !import_resolution.is_public {
                                 return UnboundResult;
                             }
 
-                            match (*import_resolution).
+                            match import_resolution.
                                     target_for_namespace(namespace) {
                                 None => {
                                     return UnboundResult;
                                 }
-                                Some(target) => {
+                                Some(Target {target_module, bindings}) => {
                                     debug!("(resolving single import) found \
                                             import in ns {:?}", namespace);
                                     let id = import_resolution.id(namespace);
                                     this.used_imports.insert((id, namespace));
-                                    return BoundResult(target.target_module,
-                                                       target.bindings);
+                                    return BoundResult(target_module, bindings);
                                 }
                             }
                         }
@@ -2372,14 +2318,14 @@ impl<'a> Resolver<'a> {
                         // The name is an import which has been fully
                         // resolved. We can, therefore, just follow it.
                         if value_result.is_unknown() {
-                            value_result = get_binding(self, *import_resolution,
+                            value_result = get_binding(self, import_resolution,
                                                        ValueNS);
-                            value_used_reexport = import_resolution.is_public.get();
+                            value_used_reexport = import_resolution.is_public;
                         }
                         if type_result.is_unknown() {
-                            type_result = get_binding(self, *import_resolution,
+                            type_result = get_binding(self, import_resolution,
                                                       TypeNS);
-                            type_used_reexport = import_resolution.is_public.get();
+                            type_used_reexport = import_resolution.is_public;
                         }
 
                     }
@@ -2407,9 +2353,9 @@ impl<'a> Resolver<'a> {
                         debug!("(resolving single import) found external \
                                 module");
                         let name_bindings =
-                            @Resolver::create_name_bindings_from_module(
-                                module);
-                        type_result = BoundResult(containing_module,
+                            Rc::new(Resolver::create_name_bindings_from_module(
+                                module));
+                        type_result = BoundResult(containing_module.clone(),
                                                   name_bindings);
                         type_used_public = true;
                     }
@@ -2418,18 +2364,15 @@ impl<'a> Resolver<'a> {
         }
 
         // We've successfully resolved the import. Write the results in.
-        let import_resolution = {
-            let import_resolutions = module_.import_resolutions.borrow();
-            assert!(import_resolutions.contains_key(&target.name));
-            import_resolutions.get_copy(&target.name)
-        };
+        let mut import_resolutions = module_.import_resolutions.borrow_mut();
+        let import_resolution = import_resolutions.get_mut(&target.name);
 
         match value_result {
-            BoundResult(target_module, name_bindings) => {
+            BoundResult(ref target_module, ref name_bindings) => {
                 debug!("(resolving single import) found value target");
-                *import_resolution.value_target.borrow_mut() =
-                    Some(Target::new(target_module, name_bindings));
-                import_resolution.value_id.set(directive.id);
+                import_resolution.value_target = Some(Target::new(target_module.clone(),
+                                                                  name_bindings.clone()));
+                import_resolution.value_id = directive.id;
                 value_used_public = name_bindings.defined_in_public_namespace(ValueNS);
             }
             UnboundResult => { /* Continue. */ }
@@ -2438,12 +2381,12 @@ impl<'a> Resolver<'a> {
             }
         }
         match type_result {
-            BoundResult(target_module, name_bindings) => {
+            BoundResult(ref target_module, ref name_bindings) => {
                 debug!("(resolving single import) found type target: {:?}",
                        { name_bindings.type_def.borrow().clone().unwrap().type_def });
-                *import_resolution.type_target.borrow_mut() =
-                    Some(Target::new(target_module, name_bindings));
-                import_resolution.type_id.set(directive.id);
+                import_resolution.type_target =
+                    Some(Target::new(target_module.clone(), name_bindings.clone()));
+                import_resolution.type_id = directive.id;
                 type_used_public = name_bindings.defined_in_public_namespace(TypeNS);
             }
             UnboundResult => { /* Continue. */ }
@@ -2456,22 +2399,21 @@ impl<'a> Resolver<'a> {
             let msg = format!("unresolved import: there is no \
                                `{}` in `{}`",
                               token::get_ident(source),
-                              self.module_to_str(containing_module));
+                              self.module_to_str(&*containing_module));
             self.resolve_error(directive.span, msg);
             return Failed;
         }
         let value_used_public = value_used_reexport || value_used_public;
         let type_used_public = type_used_reexport || type_used_public;
 
-        assert!(import_resolution.outstanding_references.get() >= 1);
-        import_resolution.outstanding_references.set(
-            import_resolution.outstanding_references.get() - 1);
+        assert!(import_resolution.outstanding_references >= 1);
+        import_resolution.outstanding_references -= 1;
 
         // record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
-        let value_private = match *import_resolution.value_target.borrow() {
-            Some(target) => {
+        let value_private = match import_resolution.value_target {
+            Some(ref target) => {
                 let def = target.bindings.def_for_namespace(ValueNS).unwrap();
                 self.def_map.borrow_mut().insert(directive.id, def);
                 let did = def_id_of_def(def);
@@ -2481,8 +2423,8 @@ impl<'a> Resolver<'a> {
             // _exists is false.
             None => None,
         };
-        let type_private = match *import_resolution.type_target.borrow() {
-            Some(target) => {
+        let type_private = match import_resolution.type_target {
+            Some(ref target) => {
                 let def = target.bindings.def_for_namespace(TypeNS).unwrap();
                 self.def_map.borrow_mut().insert(directive.id, def);
                 let did = def_id_of_def(def);
@@ -2504,8 +2446,8 @@ impl<'a> Resolver<'a> {
     // succeeds or bails out (as importing * from an empty module or a module
     // that exports nothing is valid).
     fn resolve_glob_import(&mut self,
-                           module_: @Module,
-                           containing_module: @Module,
+                           module_: &Module,
+                           containing_module: Rc<Module>,
                            id: NodeId,
                            is_public: bool,
                            lp: LastPrivate)
@@ -2531,70 +2473,71 @@ impl<'a> Resolver<'a> {
         for (ident, target_import_resolution) in import_resolutions.iter() {
             debug!("(resolving glob import) writing module resolution \
                     {:?} into `{}`",
-                   target_import_resolution.type_target.borrow().is_none(),
+                   target_import_resolution.type_target.is_none(),
                    self.module_to_str(module_));
 
-            if !target_import_resolution.is_public.get() {
+            if !target_import_resolution.is_public {
                 debug!("(resolving glob import) nevermind, just kidding");
                 continue
             }
 
             // Here we merge two import resolutions.
             let mut import_resolutions = module_.import_resolutions.borrow_mut();
-            match import_resolutions.find(ident) {
-                None => {
-                    // Simple: just copy the old import resolution.
-                    let new_import_resolution =
-                        @ImportResolution::new(id, is_public);
-                    *new_import_resolution.value_target.borrow_mut() =
-                        get(&target_import_resolution.value_target);
-                    *new_import_resolution.type_target.borrow_mut() =
-                        get(&target_import_resolution.type_target);
-
-                    import_resolutions.insert
-                        (*ident, new_import_resolution);
-                }
-                Some(&dest_import_resolution) => {
+            match import_resolutions.find_mut(ident) {
+                Some(dest_import_resolution) => {
                     // Merge the two import resolutions at a finer-grained
                     // level.
 
-                    match *target_import_resolution.value_target.borrow() {
+                    match target_import_resolution.value_target {
                         None => {
                             // Continue.
                         }
-                        Some(value_target) => {
-                            *dest_import_resolution.value_target.borrow_mut() = Some(value_target);
+                        Some(ref value_target) => {
+                            dest_import_resolution.value_target =
+                                Some(value_target.clone());
                         }
                     }
-                    match *target_import_resolution.type_target.borrow() {
+                    match target_import_resolution.type_target {
                         None => {
                             // Continue.
                         }
-                        Some(type_target) => {
-                            *dest_import_resolution.type_target.borrow_mut() = Some(type_target);
+                        Some(ref type_target) => {
+                            dest_import_resolution.type_target =
+                                Some(type_target.clone());
                         }
                     }
-                    dest_import_resolution.is_public.set(is_public);
+                    dest_import_resolution.is_public = is_public;
+                    continue;
                 }
+                None => {}
             }
+
+            // Simple: just copy the old import resolution.
+            let mut new_import_resolution = ImportResolution::new(id, is_public);
+            new_import_resolution.value_target =
+                target_import_resolution.value_target.clone();
+            new_import_resolution.type_target =
+                target_import_resolution.type_target.clone();
+
+            import_resolutions.insert(*ident, new_import_resolution);
         }
 
         // Add all children from the containing module.
-        self.populate_module_if_necessary(containing_module);
+        self.populate_module_if_necessary(&containing_module);
 
         for (&name, name_bindings) in containing_module.children
                                                        .borrow().iter() {
-            self.merge_import_resolution(module_, containing_module,
+            self.merge_import_resolution(module_, containing_module.clone(),
                                          id, is_public,
-                                         name, *name_bindings);
+                                         name, name_bindings.clone());
         }
 
         // Add external module children from the containing module.
         for (&name, module) in containing_module.external_module_children
                                                 .borrow().iter() {
             let name_bindings =
-                @Resolver::create_name_bindings_from_module(*module);
-            self.merge_import_resolution(module_, containing_module,
+                Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
+            self.merge_import_resolution(module_, containing_module.clone(),
                                          id, is_public,
                                          name, name_bindings);
         }
@@ -2613,58 +2556,49 @@ impl<'a> Resolver<'a> {
     }
 
     fn merge_import_resolution(&mut self,
-                               module_: @Module,
-                               containing_module: @Module,
+                               module_: &Module,
+                               containing_module: Rc<Module>,
                                id: NodeId,
                                is_public: bool,
                                name: Name,
-                               name_bindings: @NameBindings) {
-        let dest_import_resolution;
+                               name_bindings: Rc<NameBindings>) {
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        match import_resolutions.find(&name) {
-            None => {
-                // Create a new import resolution from this child.
-                dest_import_resolution =
-                    @ImportResolution::new(id, is_public);
-                import_resolutions.insert(name,
-                                                dest_import_resolution);
-            }
-            Some(&existing_import_resolution) => {
-                dest_import_resolution = existing_import_resolution;
-            }
-        }
+        let dest_import_resolution = import_resolutions.find_or_insert_with(name, |_| {
+            // Create a new import resolution from this child.
+            ImportResolution::new(id, is_public)
+        });
 
         debug!("(resolving glob import) writing resolution `{}` in `{}` \
                to `{}`",
                token::get_name(name).get().to_str(),
-               self.module_to_str(containing_module),
+               self.module_to_str(&*containing_module),
                self.module_to_str(module_));
 
         // Merge the child item into the import resolution.
         if name_bindings.defined_in_public_namespace(ValueNS) {
             debug!("(resolving glob import) ... for value target");
-            *dest_import_resolution.value_target.borrow_mut() =
-                Some(Target::new(containing_module, name_bindings));
-            dest_import_resolution.value_id.set(id);
+            dest_import_resolution.value_target =
+                Some(Target::new(containing_module.clone(), name_bindings.clone()));
+            dest_import_resolution.value_id = id;
         }
         if name_bindings.defined_in_public_namespace(TypeNS) {
             debug!("(resolving glob import) ... for type target");
-            *dest_import_resolution.type_target.borrow_mut() =
-                Some(Target::new(containing_module, name_bindings));
-            dest_import_resolution.type_id.set(id);
+            dest_import_resolution.type_target =
+                Some(Target::new(containing_module, name_bindings.clone()));
+            dest_import_resolution.type_id = id;
         }
-        dest_import_resolution.is_public.set(is_public);
+        dest_import_resolution.is_public = is_public;
     }
 
     /// Resolves the given module path from the given root `module_`.
     fn resolve_module_path_from_root(&mut self,
-                                     module_: @Module,
+                                     module_: Rc<Module>,
                                      module_path: &[Ident],
                                      index: uint,
                                      span: Span,
                                      name_search_type: NameSearchType,
                                      lp: LastPrivate)
-                                -> ResolveResult<(@Module, LastPrivate)> {
+                                -> ResolveResult<(Rc<Module>, LastPrivate)> {
         let mut search_module = module_;
         let mut index = index;
         let module_path_len = module_path.len();
@@ -2675,14 +2609,14 @@ impl<'a> Resolver<'a> {
         // modules as we go.
         while index < module_path_len {
             let name = module_path[index];
-            match self.resolve_name_in_module(search_module,
+            match self.resolve_name_in_module(search_module.clone(),
                                               name,
                                               TypeNS,
                                               name_search_type,
                                               false) {
                 Failed => {
                     let segment_name = token::get_ident(name);
-                    let module_name = self.module_to_str(search_module);
+                    let module_name = self.module_to_str(&*search_module);
                     if "???" == module_name {
                         let span = Span {
                             lo: span.lo,
@@ -2710,7 +2644,7 @@ impl<'a> Resolver<'a> {
                     // Check to see whether there are type bindings, and, if
                     // so, whether there is a module within.
                     match *target.bindings.type_def.borrow() {
-                        Some(type_def) => {
+                        Some(ref type_def) => {
                             match type_def.module_def {
                                 None => {
                                     // Not a module.
@@ -2718,7 +2652,7 @@ impl<'a> Resolver<'a> {
                                                                  token::get_ident(name)));
                                     return Failed;
                                 }
-                                Some(module_def) => {
+                                Some(ref module_def) => {
                                     // If we're doing the search for an
                                     // import, do not allow traits and impls
                                     // to be selected.
@@ -2733,7 +2667,7 @@ impl<'a> Resolver<'a> {
                                             return Failed;
                                         }
                                         (_, _) => {
-                                            search_module = module_def;
+                                            search_module = module_def.clone();
 
                                             // Keep track of the closest
                                             // private module used when
@@ -2777,22 +2711,22 @@ impl<'a> Resolver<'a> {
     /// On success, returns the resolved module, and the closest *private*
     /// module found to the destination when resolving this path.
     fn resolve_module_path(&mut self,
-                           module_: @Module,
+                           module_: Rc<Module>,
                            module_path: &[Ident],
                            use_lexical_scope: UseLexicalScopeFlag,
                            span: Span,
                            name_search_type: NameSearchType)
-                               -> ResolveResult<(@Module, LastPrivate)> {
+                               -> ResolveResult<(Rc<Module>, LastPrivate)> {
         let module_path_len = module_path.len();
         assert!(module_path_len > 0);
 
         debug!("(resolving module path for import) processing `{}` rooted at \
                `{}`",
                self.idents_to_str(module_path),
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // Resolve the module prefix, if any.
-        let module_prefix_result = self.resolve_module_prefix(module_,
+        let module_prefix_result = self.resolve_module_prefix(module_.clone(),
                                                               module_path);
 
         let search_module;
@@ -2857,8 +2791,8 @@ impl<'a> Resolver<'a> {
                     }
                 }
             }
-            Success(PrefixFound(containing_module, index)) => {
-                search_module = containing_module;
+            Success(PrefixFound(ref containing_module, index)) => {
+                search_module = containing_module.clone();
                 start_index = index;
                 last_private = LastMod(DependsOn(containing_module.def_id
                                                                   .get()
@@ -2877,7 +2811,7 @@ impl<'a> Resolver<'a> {
     /// Invariant: This must only be called during main resolution, not during
     /// import resolution.
     fn resolve_item_in_lexical_scope(&mut self,
-                                     module_: @Module,
+                                     module_: Rc<Module>,
                                      name: Ident,
                                      namespace: Namespace,
                                      search_through_modules:
@@ -2887,17 +2821,17 @@ impl<'a> Resolver<'a> {
                 namespace {:?} in `{}`",
                token::get_ident(name),
                namespace,
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // The current module node is handled specially. First, check for
         // its immediate children.
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
 
         match module_.children.borrow().find(&name.name) {
             Some(name_bindings)
                     if name_bindings.defined_in_namespace(namespace) => {
                 debug!("top name bindings succeeded");
-                return Success((Target::new(module_, *name_bindings),
+                return Success((Target::new(module_.clone(), name_bindings.clone()),
                                false));
             }
             Some(_) | None => { /* Not found; continue. */ }
@@ -2935,7 +2869,7 @@ impl<'a> Resolver<'a> {
                 None => {}
                 Some(module) => {
                     let name_bindings =
-                        @Resolver::create_name_bindings_from_module(module);
+                        Rc::new(Resolver::create_name_bindings_from_module(module));
                     debug!("lower name bindings succeeded");
                     return Success((Target::new(module_, name_bindings), false));
                 }
@@ -2946,7 +2880,7 @@ impl<'a> Resolver<'a> {
         let mut search_module = module_;
         loop {
             // Go to the next parent.
-            match search_module.parent_link {
+            match search_module.parent_link.clone() {
                 NoParentLink => {
                     // No more parents. This module was unresolved.
                     debug!("(resolving item in lexical scope) unresolved \
@@ -2969,22 +2903,22 @@ impl<'a> Resolver<'a> {
                                 TraitModuleKind |
                                 ImplModuleKind |
                                 AnonymousModuleKind => {
-                                    search_module = parent_module_node;
+                                    search_module = parent_module_node.upgrade().unwrap();
                                 }
                             }
                         }
                         SearchThroughModules => {
-                            search_module = parent_module_node;
+                            search_module = parent_module_node.upgrade().unwrap();
                         }
                     }
                 }
-                BlockParentLink(parent_module_node, _) => {
-                    search_module = parent_module_node;
+                BlockParentLink(ref parent_module_node, _) => {
+                    search_module = parent_module_node.upgrade().unwrap();
                 }
             }
 
             // Resolve the name in the parent module.
-            match self.resolve_name_in_module(search_module,
+            match self.resolve_name_in_module(search_module.clone(),
                                               name,
                                               namespace,
                                               PathSearch,
@@ -3012,9 +2946,9 @@ impl<'a> Resolver<'a> {
 
     /// Resolves a module name in the current lexical scope.
     fn resolve_module_in_lexical_scope(&mut self,
-                                       module_: @Module,
+                                       module_: Rc<Module>,
                                        name: Ident)
-                                -> ResolveResult<@Module> {
+                                -> ResolveResult<Rc<Module>> {
         // If this module is an anonymous module, resolve the item in the
         // lexical scope. Otherwise, resolve the item from the crate root.
         let resolve_result = self.resolve_item_in_lexical_scope(
@@ -3023,7 +2957,7 @@ impl<'a> Resolver<'a> {
             Success((target, _)) => {
                 let bindings = &*target.bindings;
                 match *bindings.type_def.borrow() {
-                    Some(type_def) => {
+                    Some(ref type_def) => {
                         match type_def.module_def {
                             None => {
                                 error!("!!! (resolving module in lexical \
@@ -3031,8 +2965,8 @@ impl<'a> Resolver<'a> {
                                         module!");
                                 return Failed;
                             }
-                            Some(module_def) => {
-                                return Success(module_def);
+                            Some(ref module_def) => {
+                                return Success(module_def.clone());
                             }
                         }
                     }
@@ -3057,14 +2991,15 @@ impl<'a> Resolver<'a> {
     }
 
     /// Returns the nearest normal module parent of the given module.
-    fn get_nearest_normal_module_parent(&mut self, module_: @Module)
-                                            -> Option<@Module> {
+    fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>)
+                                            -> Option<Rc<Module>> {
         let mut module_ = module_;
         loop {
-            match module_.parent_link {
+            match module_.parent_link.clone() {
                 NoParentLink => return None,
                 ModuleParentLink(new_module, _) |
                 BlockParentLink(new_module, _) => {
+                    let new_module = new_module.upgrade().unwrap();
                     match new_module.kind.get() {
                         NormalModuleKind => return Some(new_module),
                         ExternModuleKind |
@@ -3079,15 +3014,15 @@ impl<'a> Resolver<'a> {
 
     /// Returns the nearest normal module parent of the given module, or the
     /// module itself if it is a normal module.
-    fn get_nearest_normal_module_parent_or_self(&mut self, module_: @Module)
-                                                -> @Module {
+    fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>)
+                                                -> Rc<Module> {
         match module_.kind.get() {
             NormalModuleKind => return module_,
             ExternModuleKind |
             TraitModuleKind |
             ImplModuleKind |
             AnonymousModuleKind => {
-                match self.get_nearest_normal_module_parent(module_) {
+                match self.get_nearest_normal_module_parent(module_.clone()) {
                     None => module_,
                     Some(new_module) => new_module
                 }
@@ -3099,7 +3034,7 @@ impl<'a> Resolver<'a> {
     /// (b) some chain of `super::`.
     /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
     fn resolve_module_prefix(&mut self,
-                             module_: @Module,
+                             module_: Rc<Module>,
                              module_path: &[Ident])
                                  -> ResolveResult<ModulePrefixResult> {
         // Start at the current module if we see `self` or `super`, or at the
@@ -3126,7 +3061,7 @@ impl<'a> Resolver<'a> {
                 break
             }
             debug!("(resolving module prefix) resolving `super` at {}",
-                   self.module_to_str(containing_module));
+                   self.module_to_str(&*containing_module));
             match self.get_nearest_normal_module_parent(containing_module) {
                 None => return Failed,
                 Some(new_module) => {
@@ -3137,7 +3072,7 @@ impl<'a> Resolver<'a> {
         }
 
         debug!("(resolving module prefix) finished resolving prefix at {}",
-               self.module_to_str(containing_module));
+               self.module_to_str(&*containing_module));
 
         return Success(PrefixFound(containing_module, i));
     }
@@ -3149,7 +3084,7 @@ impl<'a> Resolver<'a> {
     /// The boolean returned on success is an indicator of whether this lookup
     /// passed through a public re-export proxy.
     fn resolve_name_in_module(&mut self,
-                              module_: @Module,
+                              module_: Rc<Module>,
                               name: Ident,
                               namespace: Namespace,
                               name_search_type: NameSearchType,
@@ -3157,16 +3092,16 @@ impl<'a> Resolver<'a> {
                               -> ResolveResult<(Target, bool)> {
         debug!("(resolving name in module) resolving `{}` in `{}`",
                token::get_ident(name),
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // First, check the direct children of the module.
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
 
         match module_.children.borrow().find(&name.name) {
             Some(name_bindings)
                     if name_bindings.defined_in_namespace(namespace) => {
                 debug!("(resolving name in module) found node as child");
-                return Success((Target::new(module_, *name_bindings),
+                return Success((Target::new(module_.clone(), name_bindings.clone()),
                                false));
             }
             Some(_) | None => {
@@ -3185,10 +3120,10 @@ impl<'a> Resolver<'a> {
         // Check the list of resolved imports.
         match module_.import_resolutions.borrow().find(&name.name) {
             Some(import_resolution) if allow_private_imports ||
-                                       import_resolution.is_public.get() => {
+                                       import_resolution.is_public => {
 
-                if import_resolution.is_public.get() &&
-                        import_resolution.outstanding_references.get() != 0 {
+                if import_resolution.is_public &&
+                        import_resolution.outstanding_references != 0 {
                     debug!("(resolving name in module) import \
                            unresolved; bailing out");
                     return Indeterminate;
@@ -3216,7 +3151,7 @@ impl<'a> Resolver<'a> {
                 None => {}
                 Some(module) => {
                     let name_bindings =
-                        @Resolver::create_name_bindings_from_module(module);
+                        Rc::new(Resolver::create_name_bindings_from_module(module));
                     return Success((Target::new(module_, name_bindings), false));
                 }
             }
@@ -3228,7 +3163,7 @@ impl<'a> Resolver<'a> {
         return Failed;
     }
 
-    fn report_unresolved_imports(&mut self, module_: @Module) {
+    fn report_unresolved_imports(&mut self, module_: Rc<Module>) {
         let index = module_.resolved_import_count.get();
         let imports = module_.imports.borrow();
         let import_count = imports.len();
@@ -3248,9 +3183,9 @@ impl<'a> Resolver<'a> {
         }
 
         // Descend into children and anonymous children.
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
 
-        for (_, &child_node) in module_.children.borrow().iter() {
+        for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
                     // Continue.
@@ -3261,8 +3196,8 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for (_, &module_) in module_.anonymous_children.borrow().iter() {
-            self.report_unresolved_imports(module_);
+        for (_, module_) in module_.anonymous_children.borrow().iter() {
+            self.report_unresolved_imports(module_.clone());
         }
     }
 
@@ -3281,7 +3216,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn record_exports_for_module_subtree(&mut self,
-                                             module_: @Module) {
+                                             module_: Rc<Module>) {
         // If this isn't a local krate, then bail out. We don't need to record
         // exports for nonlocal crates.
 
@@ -3290,27 +3225,27 @@ impl<'a> Resolver<'a> {
                 // OK. Continue.
                 debug!("(recording exports for module subtree) recording \
                         exports for local module `{}`",
-                       self.module_to_str(module_));
+                       self.module_to_str(&*module_));
             }
             None => {
                 // Record exports for the root module.
                 debug!("(recording exports for module subtree) recording \
                         exports for root module `{}`",
-                       self.module_to_str(module_));
+                       self.module_to_str(&*module_));
             }
             Some(_) => {
                 // Bail out.
                 debug!("(recording exports for module subtree) not recording \
                         exports for `{}`",
-                       self.module_to_str(module_));
+                       self.module_to_str(&*module_));
                 return;
             }
         }
 
-        self.record_exports_for_module(module_);
-        self.populate_module_if_necessary(module_);
+        self.record_exports_for_module(&*module_);
+        self.populate_module_if_necessary(&module_);
 
-        for (_, &child_name_bindings) in module_.children.borrow().iter() {
+        for (_, child_name_bindings) in module_.children.borrow().iter() {
             match child_name_bindings.get_module_if_available() {
                 None => {
                     // Nothing to do.
@@ -3321,12 +3256,12 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for (_, &child_module) in module_.anonymous_children.borrow().iter() {
-            self.record_exports_for_module_subtree(child_module);
+        for (_, child_module) in module_.anonymous_children.borrow().iter() {
+            self.record_exports_for_module_subtree(child_module.clone());
         }
     }
 
-    fn record_exports_for_module(&mut self, module_: @Module) {
+    fn record_exports_for_module(&mut self, module_: &Module) {
         let mut exports2 = Vec::new();
 
         self.add_exports_for_module(&mut exports2, module_);
@@ -3343,7 +3278,7 @@ impl<'a> Resolver<'a> {
     fn add_exports_of_namebindings(&mut self,
                                    exports2: &mut Vec<Export2> ,
                                    name: Name,
-                                   namebindings: @NameBindings,
+                                   namebindings: &NameBindings,
                                    ns: Namespace) {
         match namebindings.def_for_namespace(ns) {
             Some(d) => {
@@ -3363,9 +3298,9 @@ impl<'a> Resolver<'a> {
 
     fn add_exports_for_module(&mut self,
                               exports2: &mut Vec<Export2> ,
-                              module_: @Module) {
+                              module_: &Module) {
         for (name, importresolution) in module_.import_resolutions.borrow().iter() {
-            if !importresolution.is_public.get() {
+            if !importresolution.is_public {
                 continue
             }
             let xs = [TypeNS, ValueNS];
@@ -3376,7 +3311,7 @@ impl<'a> Resolver<'a> {
                                token::get_name(*name));
                         self.add_exports_of_namebindings(exports2,
                                                          *name,
-                                                         target.bindings,
+                                                         &*target.bindings,
                                                          ns)
                     }
                     _ => ()
@@ -3404,7 +3339,7 @@ impl<'a> Resolver<'a> {
     // implementations thus found, for compatibility with old resolve pass.
 
     fn with_scope(&mut self, name: Option<Ident>, f: |&mut Resolver|) {
-        let orig_module = self.current_module;
+        let orig_module = self.current_module.clone();
 
         // Move down in the graph.
         match name {
@@ -3412,13 +3347,13 @@ impl<'a> Resolver<'a> {
                 // Nothing to do.
             }
             Some(name) => {
-                self.populate_module_if_necessary(orig_module);
+                self.populate_module_if_necessary(&orig_module);
 
                 match orig_module.children.borrow().find(&name.name) {
                     None => {
                         debug!("!!! (with scope) didn't find `{}` in `{}`",
                                token::get_ident(name),
-                               self.module_to_str(orig_module));
+                               self.module_to_str(&*orig_module));
                     }
                     Some(name_bindings) => {
                         match (*name_bindings).get_module_if_available() {
@@ -3426,7 +3361,7 @@ impl<'a> Resolver<'a> {
                                 debug!("!!! (with scope) didn't find module \
                                         for `{}` in `{}`",
                                        token::get_ident(name),
-                                       self.module_to_str(orig_module));
+                                       self.module_to_str(&*orig_module));
                             }
                             Some(module_) => {
                                 self.current_module = module_;
@@ -3444,12 +3379,12 @@ impl<'a> Resolver<'a> {
 
     /// Wraps the given definition in the appropriate number of `def_upvar`
     /// wrappers.
-    fn upvarify(&mut self,
-                    ribs: &mut Vec<@Rib> ,
-                    rib_index: uint,
-                    def_like: DefLike,
-                    span: Span)
-                    -> Option<DefLike> {
+    fn upvarify(&self,
+                ribs: &[Rib],
+                rib_index: uint,
+                def_like: DefLike,
+                span: Span)
+                -> Option<DefLike> {
         let mut def;
         let is_ty_param;
 
@@ -3470,7 +3405,7 @@ impl<'a> Resolver<'a> {
 
         let mut rib_index = rib_index + 1;
         while rib_index < ribs.len() {
-            match ribs.get(rib_index).kind {
+            match ribs[rib_index].kind {
                 NormalRibKind => {
                     // Nothing to do. Continue.
                 }
@@ -3560,18 +3495,18 @@ impl<'a> Resolver<'a> {
         return Some(DlDef(def));
     }
 
-    fn search_ribs(&mut self,
-                       ribs: &mut Vec<@Rib> ,
-                       name: Name,
-                       span: Span)
-                       -> Option<DefLike> {
+    fn search_ribs(&self,
+                   ribs: &[Rib],
+                   name: Name,
+                   span: Span)
+                   -> Option<DefLike> {
         // FIXME #4950: This should not use a while loop.
         // FIXME #4950: Try caching?
 
         let mut i = ribs.len();
         while i != 0 {
             i -= 1;
-            let binding_opt = ribs.get(i).bindings.borrow().find_copy(&name);
+            let binding_opt = ribs[i].bindings.borrow().find_copy(&name);
             match binding_opt {
                 Some(def_like) => {
                     return self.upvarify(ribs, i, def_like, span);
@@ -3645,12 +3580,12 @@ impl<'a> Resolver<'a> {
 
             ItemTrait(ref generics, ref traits, ref methods) => {
                 // Create a new rib for the self type.
-                let self_type_rib = @Rib::new(NormalRibKind);
-                self.type_ribs.borrow_mut().push(self_type_rib);
+                let self_type_rib = Rib::new(NormalRibKind);
                 // plain insert (no renaming)
                 let name = self.type_self_ident.name;
                 self_type_rib.bindings.borrow_mut()
                              .insert(name, DlDef(DefSelfTy(item.id)));
+                self.type_ribs.borrow_mut().push(self_type_rib);
 
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics,
@@ -3772,8 +3707,7 @@ impl<'a> Resolver<'a> {
             HasTypeParameters(generics, node_id, initial_index,
                               rib_kind) => {
 
-                let function_type_rib = @Rib::new(rib_kind);
-                self.type_ribs.borrow_mut().push(function_type_rib);
+                let function_type_rib = Rib::new(rib_kind);
 
                 for (index, type_parameter) in generics.ty_params.iter().enumerate() {
                     let ident = type_parameter.ident;
@@ -3790,6 +3724,7 @@ impl<'a> Resolver<'a> {
                     function_type_rib.bindings.borrow_mut()
                                      .insert(ident.name, def_like);
                 }
+                self.type_ribs.borrow_mut().push(function_type_rib);
             }
 
             NoTypeParameters => {
@@ -3806,14 +3741,14 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_label_rib(&mut self, f: |&mut Resolver|) {
-        self.label_ribs.borrow_mut().push(@Rib::new(NormalRibKind));
+        self.label_ribs.borrow_mut().push(Rib::new(NormalRibKind));
         f(self);
         self.label_ribs.borrow_mut().pop();
     }
 
     fn with_constant_rib(&mut self, f: |&mut Resolver|) {
-        self.value_ribs.borrow_mut().push(@Rib::new(ConstantItemRibKind));
-        self.type_ribs.borrow_mut().push(@Rib::new(ConstantItemRibKind));
+        self.value_ribs.borrow_mut().push(Rib::new(ConstantItemRibKind));
+        self.type_ribs.borrow_mut().push(Rib::new(ConstantItemRibKind));
         f(self);
         self.type_ribs.borrow_mut().pop();
         self.value_ribs.borrow_mut().pop();
@@ -3825,11 +3760,11 @@ impl<'a> Resolver<'a> {
                         type_parameters: TypeParameters,
                         block: P<Block>) {
         // Create a value rib for the function.
-        let function_value_rib = @Rib::new(rib_kind);
+        let function_value_rib = Rib::new(rib_kind);
         self.value_ribs.borrow_mut().push(function_value_rib);
 
         // Create a label rib for the function.
-        let function_label_rib = @Rib::new(rib_kind);
+        let function_label_rib = Rib::new(rib_kind);
         self.label_ribs.borrow_mut().push(function_label_rib);
 
         // If this function has type parameters, add them now.
@@ -3980,7 +3915,7 @@ impl<'a> Resolver<'a> {
     // to be NormalRibKind?
     fn resolve_method(&mut self,
                       rib_kind: RibKind,
-                      method: @Method,
+                      method: &Method,
                       outer_type_parameter_count: uint) {
         let method_generics = &method.generics;
         let type_parameters =
@@ -4093,9 +4028,9 @@ impl<'a> Resolver<'a> {
     // this is done hygienically. This could arise for a macro
     // that expands into an or-pattern where one 'x' was from the
     // user and one 'x' came from the macro.
-    fn binding_mode_map(&mut self, pat: @Pat) -> BindingMap {
+    fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
         let mut result = HashMap::new();
-        pat_bindings(self.def_map, pat, |binding_mode, _id, sp, path| {
+        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| {
             let name = mtwt::resolve(path_to_ident(path));
             result.insert(name,
                           binding_info {span: sp,
@@ -4151,7 +4086,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_arm(&mut self, arm: &Arm) {
-        self.value_ribs.borrow_mut().push(@Rib::new(NormalRibKind));
+        self.value_ribs.borrow_mut().push(Rib::new(NormalRibKind));
 
         let mut bindings_list = HashMap::new();
         for pattern in arm.pats.iter() {
@@ -4172,19 +4107,16 @@ impl<'a> Resolver<'a> {
 
     fn resolve_block(&mut self, block: &Block) {
         debug!("(resolving block) entering block");
-        self.value_ribs.borrow_mut().push(@Rib::new(NormalRibKind));
+        self.value_ribs.borrow_mut().push(Rib::new(NormalRibKind));
 
         // Move down in the graph, if there's an anonymous module rooted here.
-        let orig_module = self.current_module;
-        let anonymous_children = self.current_module
-                                     .anonymous_children
-                                     .borrow();
-        match anonymous_children.find(&block.id) {
+        let orig_module = self.current_module.clone();
+        match orig_module.anonymous_children.borrow().find(&block.id) {
             None => { /* Nothing to do. */ }
-            Some(&anonymous_module) => {
+            Some(anonymous_module) => {
                 debug!("(resolving block) found anonymous module, moving \
                         down");
-                self.current_module = anonymous_module;
+                self.current_module = anonymous_module.clone();
             }
         }
 
@@ -4302,7 +4234,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_pattern(&mut self,
-                       pattern: @Pat,
+                       pattern: &Pat,
                        mode: PatternBindingMode,
                        // Maps idents to the node ID for the (outermost)
                        // pattern that binds them
@@ -4553,9 +4485,9 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_bare_identifier_pattern(&mut self, name: Ident)
-                                           ->
-                                           BareIdentifierPatternResolution {
-        match self.resolve_item_in_lexical_scope(self.current_module,
+                                       -> BareIdentifierPatternResolution {
+        let module = self.current_module.clone();
+        match self.resolve_item_in_lexical_scope(module,
                                                  name,
                                                  ValueNS,
                                                  SearchThroughModules) {
@@ -4668,12 +4600,12 @@ impl<'a> Resolver<'a> {
 
     // FIXME #4952: Merge me with resolve_name_in_module?
     fn resolve_definition_of_name_in_module(&mut self,
-                                            containing_module: @Module,
+                                            containing_module: Rc<Module>,
                                             name: Ident,
                                             namespace: Namespace)
                                                 -> NameDefinition {
         // First, search children.
-        self.populate_module_if_necessary(containing_module);
+        self.populate_module_if_necessary(&containing_module);
 
         match containing_module.children.borrow().find(&name.name) {
             Some(child_name_bindings) => {
@@ -4695,7 +4627,7 @@ impl<'a> Resolver<'a> {
 
         // Next, search import resolutions.
         match containing_module.import_resolutions.borrow().find(&name.name) {
-            Some(import_resolution) if import_resolution.is_public.get() => {
+            Some(import_resolution) if import_resolution.is_public => {
                 match (*import_resolution).target_for_namespace(namespace) {
                     Some(target) => {
                         match target.bindings.def_for_namespace(namespace) {
@@ -4750,7 +4682,8 @@ impl<'a> Resolver<'a> {
 
         let containing_module;
         let last_private;
-        match self.resolve_module_path(self.current_module,
+        let module = self.current_module.clone();
+        match self.resolve_module_path(module,
                                        module_path_idents.as_slice(),
                                        UseLexicalScope,
                                        path.span,
@@ -4773,7 +4706,7 @@ impl<'a> Resolver<'a> {
         }
 
         let ident = path.segments.last().unwrap().identifier;
-        let def = match self.resolve_definition_of_name_in_module(containing_module,
+        let def = match self.resolve_definition_of_name_in_module(containing_module.clone(),
                                                         ident,
                                                         namespace) {
             NoNameDefinition => {
@@ -4786,22 +4719,17 @@ impl<'a> Resolver<'a> {
         };
         match containing_module.kind.get() {
             TraitModuleKind | ImplModuleKind => {
-                match self.method_map.borrow().find(&ident.name) {
-                    Some(s) => {
-                        match containing_module.def_id.get() {
-                            Some(def_id) if s.contains(&def_id) => {
-                                debug!("containing module was a trait or impl \
-                                        and name was a method -> not resolved");
-                                return None;
-                            },
-                            _ => (),
-                        }
+                match containing_module.def_id.get() {
+                    Some(def_id) if self.method_set.borrow().contains(&(ident.name, def_id)) => {
+                        debug!("containing module was a trait or impl \
+                                and name was a method -> not resolved");
+                        return None;
                     },
-                    None => (),
+                    _ => (),
                 }
             },
             _ => (),
-        };
+        }
         return Some(def);
     }
 
@@ -4865,12 +4793,12 @@ impl<'a> Resolver<'a> {
         let search_result = match namespace {
             ValueNS => {
                 let renamed = mtwt::resolve(ident);
-                self.search_ribs(&mut *self.value_ribs.borrow_mut(),
+                self.search_ribs(self.value_ribs.borrow().as_slice(),
                                  renamed, span)
             }
             TypeNS => {
                 let name = ident.name;
-                self.search_ribs(&mut *self.type_ribs.borrow_mut(), name, span)
+                self.search_ribs(self.type_ribs.borrow().as_slice(), name, span)
             }
         };
 
@@ -4893,7 +4821,8 @@ impl<'a> Resolver<'a> {
                                                    namespace: Namespace)
                                                 -> Option<(Def, LastPrivate)> {
         // Check the items.
-        match self.resolve_item_in_lexical_scope(self.current_module,
+        let module = self.current_module.clone();
+        match self.resolve_item_in_lexical_scope(module,
                                                  ident,
                                                  namespace,
                                                  DontSearchThroughModules) {
@@ -4936,7 +4865,7 @@ impl<'a> Resolver<'a> {
         rs
     }
 
-    fn resolve_error(&mut self, span: Span, s: &str) {
+    fn resolve_error(&self, span: Span, s: &str) {
         if self.emit_errors {
             self.session.span_err(span, s);
         }
@@ -5115,9 +5044,9 @@ impl<'a> Resolver<'a> {
             ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
 
             ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
-                let mut label_ribs = self.label_ribs.borrow_mut();
                 let renamed = mtwt::resolve(label);
-                match self.search_ribs(&mut *label_ribs, renamed, expr.span) {
+                match self.search_ribs(self.label_ribs.borrow().as_slice(),
+                                       renamed, expr.span) {
                     None =>
                         self.resolve_error(expr.span,
                                               format!("use of undeclared label `{}`",
@@ -5147,14 +5076,14 @@ impl<'a> Resolver<'a> {
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.search_for_traits_containing_method(ident);
+                let traits = self.search_for_traits_containing_method(ident.name);
                 self.trait_map.insert(expr.id, traits);
             }
             ExprMethodCall(ident, _, _) => {
                 debug!("(recording candidate traits for expr) recording \
                         traits for {}",
                        expr.id);
-                let traits = self.search_for_traits_containing_method(ident);
+                let traits = self.search_for_traits_containing_method(ident.name);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -5163,34 +5092,44 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn search_for_traits_containing_method(&mut self, name: Ident) -> Vec<DefId> {
+    fn search_for_traits_containing_method(&mut self, name: Name) -> Vec<DefId> {
         debug!("(searching for traits containing method) looking for '{}'",
-               token::get_ident(name));
+               token::get_name(name));
+
+        fn add_trait_info(found_traits: &mut Vec<DefId>,
+                          trait_def_id: DefId,
+                          name: Name) {
+            debug!("(adding trait info) found trait {}:{} for method '{}'",
+                trait_def_id.krate,
+                trait_def_id.node,
+                token::get_name(name));
+            found_traits.push(trait_def_id);
+        }
 
         let mut found_traits = Vec::new();
-        let mut search_module = self.current_module;
-        match self.method_map.borrow().find(&name.name) {
-            Some(candidate_traits) => loop {
-                // Look for the current trait.
-                match self.current_trait_refs {
-                    Some(ref trait_def_ids) => {
-                        for trait_def_id in trait_def_ids.iter() {
-                            if candidate_traits.contains(trait_def_id) {
-                                self.add_trait_info(&mut found_traits,
-                                                    *trait_def_id,
-                                                    name);
-                            }
+        let mut search_module = self.current_module.clone();
+        loop {
+            // Look for the current trait.
+            match self.current_trait_refs {
+                Some(ref trait_def_ids) => {
+                    let method_set = self.method_set.borrow();
+                    for &trait_def_id in trait_def_ids.iter() {
+                        if method_set.contains(&(name, trait_def_id)) {
+                            add_trait_info(&mut found_traits, trait_def_id, name);
                         }
                     }
-                    None => {
-                        // Nothing to do.
-                    }
                 }
+                None => {
+                    // Nothing to do.
+                }
+            }
 
-                // Look for trait children.
-                self.populate_module_if_necessary(search_module);
+            // Look for trait children.
+            self.populate_module_if_necessary(&search_module);
 
-                for (_, &child_names) in search_module.children.borrow().iter() {
+            {
+                let method_set = self.method_set.borrow();
+                for (_, child_names) in search_module.children.borrow().iter() {
                     let def = match child_names.def_for_namespace(TypeNS) {
                         Some(def) => def,
                         None => continue
@@ -5199,52 +5138,37 @@ impl<'a> Resolver<'a> {
                         DefTrait(trait_def_id) => trait_def_id,
                         _ => continue,
                     };
-                    if candidate_traits.contains(&trait_def_id) {
-                        self.add_trait_info(&mut found_traits, trait_def_id,
-                                            name);
+                    if method_set.contains(&(name, trait_def_id)) {
+                        add_trait_info(&mut found_traits, trait_def_id, name);
                     }
                 }
+            }
 
-                // Look for imports.
-                let import_resolutions = search_module.import_resolutions
-                                                      .borrow();
-                for (_, &import) in import_resolutions.iter() {
-                    let target = match import.target_for_namespace(TypeNS) {
-                        None => continue,
-                        Some(target) => target,
-                    };
-                    let did = match target.bindings.def_for_namespace(TypeNS) {
-                        Some(DefTrait(trait_def_id)) => trait_def_id,
-                        Some(..) | None => continue,
-                    };
-                    if candidate_traits.contains(&did) {
-                        self.add_trait_info(&mut found_traits, did, name);
-                        self.used_imports.insert((import.type_id.get(), TypeNS));
-                    }
+            // Look for imports.
+            for (_, import) in search_module.import_resolutions.borrow().iter() {
+                let target = match import.target_for_namespace(TypeNS) {
+                    None => continue,
+                    Some(target) => target,
+                };
+                let did = match target.bindings.def_for_namespace(TypeNS) {
+                    Some(DefTrait(trait_def_id)) => trait_def_id,
+                    Some(..) | None => continue,
+                };
+                if self.method_set.borrow().contains(&(name, did)) {
+                    add_trait_info(&mut found_traits, did, name);
+                    self.used_imports.insert((import.type_id, TypeNS));
                 }
+            }
 
-                match search_module.parent_link {
-                    NoParentLink | ModuleParentLink(..) => break,
-                    BlockParentLink(parent_module, _) => {
-                        search_module = parent_module;
-                    }
+            match search_module.parent_link.clone() {
+                NoParentLink | ModuleParentLink(..) => break,
+                BlockParentLink(parent_module, _) => {
+                    search_module = parent_module.upgrade().unwrap();
                 }
-            },
-            _ => ()
+            }
         }
 
-        return found_traits;
-    }
-
-    fn add_trait_info(&self,
-                          found_traits: &mut Vec<DefId> ,
-                          trait_def_id: DefId,
-                          name: Ident) {
-        debug!("(adding trait info) found trait {}:{} for method '{}'",
-               trait_def_id.krate,
-               trait_def_id.node,
-               token::get_ident(name));
-        found_traits.push(trait_def_id);
+        found_traits
     }
 
     fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
@@ -5381,40 +5305,38 @@ impl<'a> Resolver<'a> {
     //
 
     /// A somewhat inefficient routine to obtain the name of a module.
-    fn module_to_str(&mut self, module_: @Module) -> ~str {
+    fn module_to_str(&mut self, module: &Module) -> ~str {
         let mut idents = Vec::new();
-        let mut current_module = module_;
-        loop {
-            match current_module.parent_link {
-                NoParentLink => {
-                    break;
-                }
-                ModuleParentLink(module_, name) => {
+
+        fn collect_mod(idents: &mut Vec<ast::Ident>, module: &Module) {
+            match module.parent_link {
+                NoParentLink => {}
+                ModuleParentLink(ref module, name) => {
                     idents.push(name);
-                    current_module = module_;
+                    collect_mod(idents, &*module.upgrade().unwrap());
                 }
-                BlockParentLink(module_, _) => {
+                BlockParentLink(ref module, _) => {
                     idents.push(special_idents::opaque);
-                    current_module = module_;
+                    collect_mod(idents, &*module.upgrade().unwrap());
                 }
             }
         }
+        collect_mod(&mut idents, module);
 
         if idents.len() == 0 {
             return "???".to_owned();
         }
-        return self.idents_to_str(idents.move_iter()
-                                        .rev()
-                                        .collect::<Vec<ast::Ident>>()
-                                        .as_slice());
+        self.idents_to_str(idents.move_iter().rev()
+                                 .collect::<Vec<ast::Ident>>()
+                                 .as_slice())
     }
 
     #[allow(dead_code)]   // useful for debugging
-    fn dump_module(&mut self, module_: @Module) {
-        debug!("Dump of module `{}`:", self.module_to_str(module_));
+    fn dump_module(&mut self, module_: Rc<Module>) {
+        debug!("Dump of module `{}`:", self.module_to_str(&*module_));
 
         debug!("Children:");
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
         for (&name, _) in module_.children.borrow().iter() {
             debug!("* {}", token::get_name(name));
         }
@@ -5455,7 +5377,7 @@ pub struct CrateMap {
 
 /// Entry point to crate resolution.
 pub fn resolve_crate(session: &Session,
-                     lang_items: @LanguageItems,
+                     lang_items: &LanguageItems,
                      krate: &Crate)
                   -> CrateMap {
     let mut resolver = Resolver(session, lang_items, krate.span);
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index bab7a227572..55f8b3d1fd2 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -225,6 +225,7 @@ use util::ppaux::{Repr, vec_map_to_str};
 
 use collections::HashMap;
 use std::cell::Cell;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::ast::Ident;
 use syntax::ast_util::path_to_ident;
@@ -250,7 +251,7 @@ pub enum VecLenOpt {
 // range)
 enum Opt {
     lit(Lit),
-    var(ty::Disr, @adt::Repr),
+    var(ty::Disr, Rc<adt::Repr>),
     range(@ast::Expr, @ast::Expr),
     vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
@@ -351,8 +352,8 @@ fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
             let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id);
             return single_result(rslt(bcx, llval));
         }
-        var(disr_val, repr) => {
-            return adt::trans_case(bcx, repr, disr_val);
+        var(disr_val, ref repr) => {
+            return adt::trans_case(bcx, &**repr, disr_val);
         }
         range(l1, l2) => {
             let (l1, _) = consts::const_expr(ccx, l1, true);
@@ -417,15 +418,10 @@ struct BindingInfo {
 
 type BindingsMap = HashMap<Ident, BindingInfo>;
 
-struct ArmData<'a,'b> {
+struct ArmData<'a, 'b> {
     bodycx: &'b Block<'b>,
     arm: &'a ast::Arm,
-    bindings_map: @BindingsMap
-}
-
-// FIXME #11820: method resolution is unreliable with &
-impl<'a,'b> Clone for ArmData<'a, 'b> {
-    fn clone(&self) -> ArmData<'a, 'b> { *self }
+    bindings_map: BindingsMap
 }
 
 /**
@@ -434,14 +430,13 @@ impl<'a,'b> Clone for ArmData<'a, 'b> {
  * As we proceed `bound_ptrs` are filled with pointers to values to be bound,
  * these pointers are stored in llmatch variables just before executing `data` arm.
  */
-#[deriving(Clone)]
-struct Match<'a,'b> {
-    pats: Vec<@ast::Pat> ,
-    data: ArmData<'a,'b>,
+struct Match<'a, 'b> {
+    pats: Vec<@ast::Pat>,
+    data: &'a ArmData<'a, 'b>,
     bound_ptrs: Vec<(Ident, ValueRef)>
 }
 
-impl<'a,'b> Repr for Match<'a,'b> {
+impl<'a, 'b> Repr for Match<'a, 'b> {
     fn repr(&self, tcx: &ty::ctxt) -> ~str {
         if tcx.sess.verbose() {
             // for many programs, this just take too long to serialize
@@ -462,12 +457,12 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool {
     return false;
 }
 
-fn expand_nested_bindings<'r,'b>(
+fn expand_nested_bindings<'a, 'b>(
                           bcx: &'b Block<'b>,
-                          m: &[Match<'r,'b>],
+                          m: &'a [Match<'a, 'b>],
                           col: uint,
                           val: ValueRef)
-                          -> Vec<Match<'r,'b>> {
+                          -> Vec<Match<'a, 'b>> {
     debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -482,21 +477,25 @@ fn expand_nested_bindings<'r,'b>(
                            .append((vec!(inner))
                                    .append(br.pats.slice(col + 1u, br.pats.len())).as_slice());
 
-                let mut res = Match {
+                let mut bound_ptrs = br.bound_ptrs.clone();
+                bound_ptrs.push((path_to_ident(path), val));
+                Match {
                     pats: pats,
-                    data: br.data.clone(),
-                    bound_ptrs: br.bound_ptrs.clone()
-                };
-                res.bound_ptrs.push((path_to_ident(path), val));
-                res
+                    data: &*br.data,
+                    bound_ptrs: bound_ptrs
+                }
+            }
+            _ => Match {
+                pats: br.pats.clone(),
+                data: &*br.data,
+                bound_ptrs: br.bound_ptrs.clone()
             }
-            _ => (*br).clone(),
         }
     }).collect()
 }
 
 fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
-    if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
+    if !pat_is_binding_or_wild(&bcx.tcx().def_map, p) {
         bcx.sess().span_bug(
             p.span,
             format!("expected an identifier pattern but found p: {}",
@@ -506,14 +505,14 @@ fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
 
 type enter_pat<'a> = |@ast::Pat|: 'a -> Option<Vec<@ast::Pat>>;
 
-fn enter_match<'r,'b>(
+fn enter_match<'a, 'b>(
                bcx: &'b Block<'b>,
-               dm: DefMap,
-               m: &[Match<'r,'b>],
+               dm: &DefMap,
+               m: &'a [Match<'a, 'b>],
                col: uint,
                val: ValueRef,
                e: enter_pat)
-               -> Vec<Match<'r,'b>> {
+               -> Vec<Match<'a, 'b>> {
     debug!("enter_match(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -521,47 +520,39 @@ fn enter_match<'r,'b>(
            bcx.val_to_str(val));
     let _indenter = indenter();
 
-    let mut result = Vec::new();
-    for br in m.iter() {
-        match e(*br.pats.get(col)) {
-            Some(sub) => {
-                let pats = sub.append(br.pats.slice(0u, col))
-                              .append(br.pats.slice(col + 1u, br.pats.len()));
-
-                let this = *br.pats.get(col);
-                let mut bound_ptrs = br.bound_ptrs.clone();
-                match this.node {
-                    ast::PatIdent(_, ref path, None) => {
-                        if pat_is_binding(dm, this) {
-                            bound_ptrs.push((path_to_ident(path), val));
-                        }
+    m.iter().filter_map(|br| {
+        e(*br.pats.get(col)).map(|sub| {
+            let pats = sub.append(br.pats.slice(0u, col))
+                            .append(br.pats.slice(col + 1u, br.pats.len()));
+
+            let this = *br.pats.get(col);
+            let mut bound_ptrs = br.bound_ptrs.clone();
+            match this.node {
+                ast::PatIdent(_, ref path, None) => {
+                    if pat_is_binding(dm, this) {
+                        bound_ptrs.push((path_to_ident(path), val));
                     }
-                    _ => {}
                 }
-
-                result.push(Match {
-                    pats: pats,
-                    data: br.data.clone(),
-                    bound_ptrs: bound_ptrs
-                });
+                _ => {}
             }
-            None => ()
-        }
-    }
-
-    debug!("result={}", result.repr(bcx.tcx()));
 
-    return result;
+            Match {
+                pats: pats,
+                data: br.data,
+                bound_ptrs: bound_ptrs
+            }
+        })
+    }).collect()
 }
 
-fn enter_default<'r,'b>(
+fn enter_default<'a, 'b>(
                  bcx: &'b Block<'b>,
-                 dm: DefMap,
-                 m: &[Match<'r,'b>],
+                 dm: &DefMap,
+                 m: &'a [Match<'a, 'b>],
                  col: uint,
                  val: ValueRef,
                  chk: &FailureHandler)
-                 -> Vec<Match<'r,'b>> {
+                 -> Vec<Match<'a, 'b>> {
     debug!("enter_default(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -625,14 +616,14 @@ fn enter_default<'r,'b>(
 // <nmatsakis> so all patterns must either be records (resp. tuples) or
 //             wildcards
 
-fn enter_opt<'r,'b>(
+fn enter_opt<'a, 'b>(
              bcx: &'b Block<'b>,
-             m: &[Match<'r,'b>],
+             m: &'a [Match<'a, 'b>],
              opt: &Opt,
              col: uint,
              variant_size: uint,
              val: ValueRef)
-             -> Vec<Match<'r,'b>> {
+             -> Vec<Match<'a, 'b>> {
     debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -657,10 +648,10 @@ fn enter_opt<'r,'b>(
     // "column" of arm patterns and the algorithm will converge.
     let guarded = m.iter().any(|x| x.data.arm.guard.is_some());
     let multi_pats = m.len() > 0 && m[0].pats.len() > 1;
-    enter_match(bcx, tcx.def_map, m, col, val, |p| {
+    enter_match(bcx, &tcx.def_map, m, col, val, |p| {
         let answer = match p.node {
             ast::PatEnum(..) |
-            ast::PatIdent(_, _, None) if pat_is_const(tcx.def_map, p) => {
+            ast::PatIdent(_, _, None) if pat_is_const(&tcx.def_map, p) => {
                 let const_def = tcx.def_map.borrow().get_copy(&p.id);
                 let const_def_id = ast_util::def_id_of_def(const_def);
                 let konst = lit(ConstLit(const_def_id));
@@ -684,7 +675,7 @@ fn enter_opt<'r,'b>(
                 }
             }
             ast::PatIdent(_, _, None)
-                    if pat_is_variant_or_struct(tcx.def_map, p) => {
+                    if pat_is_variant_or_struct(&tcx.def_map, p) => {
                 if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
                     Some(Vec::new())
                 } else {
@@ -799,14 +790,14 @@ fn enter_opt<'r,'b>(
     })
 }
 
-fn enter_rec_or_struct<'r,'b>(
+fn enter_rec_or_struct<'a, 'b>(
                        bcx: &'b Block<'b>,
-                       dm: DefMap,
-                       m: &[Match<'r,'b>],
+                       dm: &DefMap,
+                       m: &'a [Match<'a, 'b>],
                        col: uint,
                        fields: &[ast::Ident],
                        val: ValueRef)
-                       -> Vec<Match<'r,'b>> {
+                       -> Vec<Match<'a, 'b>> {
     debug!("enter_rec_or_struct(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -835,14 +826,14 @@ fn enter_rec_or_struct<'r,'b>(
     })
 }
 
-fn enter_tup<'r,'b>(
+fn enter_tup<'a, 'b>(
              bcx: &'b Block<'b>,
-             dm: DefMap,
-             m: &[Match<'r,'b>],
+             dm: &DefMap,
+             m: &'a [Match<'a, 'b>],
              col: uint,
              val: ValueRef,
              n_elts: uint)
-             -> Vec<Match<'r,'b>> {
+             -> Vec<Match<'a, 'b>> {
     debug!("enter_tup(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -868,14 +859,14 @@ fn enter_tup<'r,'b>(
     })
 }
 
-fn enter_tuple_struct<'r,'b>(
+fn enter_tuple_struct<'a, 'b>(
                       bcx: &'b Block<'b>,
-                      dm: DefMap,
-                      m: &[Match<'r,'b>],
+                      dm: &DefMap,
+                      m: &'a [Match<'a, 'b>],
                       col: uint,
                       val: ValueRef,
                       n_elts: uint)
-                      -> Vec<Match<'r,'b>> {
+                      -> Vec<Match<'a, 'b>> {
     debug!("enter_tuple_struct(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -897,13 +888,13 @@ fn enter_tuple_struct<'r,'b>(
     })
 }
 
-fn enter_uniq<'r,'b>(
+fn enter_uniq<'a, 'b>(
               bcx: &'b Block<'b>,
-              dm: DefMap,
-              m: &[Match<'r,'b>],
+              dm: &DefMap,
+              m: &'a [Match<'a, 'b>],
               col: uint,
               val: ValueRef)
-              -> Vec<Match<'r,'b>> {
+              -> Vec<Match<'a, 'b>> {
     debug!("enter_uniq(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -925,14 +916,13 @@ fn enter_uniq<'r,'b>(
     })
 }
 
-fn enter_region<'r,
-                'b>(
+fn enter_region<'a, 'b>(
                 bcx: &'b Block<'b>,
-                dm: DefMap,
-                m: &[Match<'r,'b>],
+                dm: &DefMap,
+                m: &'a [Match<'a, 'b>],
                 col: uint,
                 val: ValueRef)
-                -> Vec<Match<'r,'b>> {
+                -> Vec<Match<'a, 'b>> {
     debug!("enter_region(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -1170,7 +1160,7 @@ fn pats_require_rooting(bcx: &Block, m: &[Match], col: uint) -> bool {
     m.iter().any(|br| {
         let pat_id = br.pats.get(col).id;
         let key = root_map_key {id: pat_id, derefs: 0u };
-        bcx.ccx().maps.root_map.borrow().contains_key(&key)
+        bcx.ccx().maps.root_map.contains_key(&key)
     })
 }
 
@@ -1424,12 +1414,11 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
     bcx
 }
 
-fn compile_guard<'r,
-                 'b>(
+fn compile_guard<'a, 'b>(
                  bcx: &'b Block<'b>,
                  guard_expr: &ast::Expr,
                  data: &ArmData,
-                 m: &[Match<'r,'b>],
+                 m: &'a [Match<'a, 'b>],
                  vals: &[ValueRef],
                  chk: &FailureHandler)
                  -> &'b Block<'b> {
@@ -1445,9 +1434,9 @@ fn compile_guard<'r,
     let temp_scope = bcx.fcx.push_custom_cleanup_scope();
 
     let mut bcx = bcx;
-    bcx = store_non_ref_bindings(bcx, data.bindings_map,
+    bcx = store_non_ref_bindings(bcx, &data.bindings_map,
                                  Some(cleanup::CustomScope(temp_scope)));
-    bcx = insert_lllocals(bcx, data.bindings_map,
+    bcx = insert_lllocals(bcx, &data.bindings_map,
                           cleanup::CustomScope(temp_scope));
 
     let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
@@ -1482,10 +1471,9 @@ fn compile_guard<'r,
     }
 }
 
-fn compile_submatch<'r,
-                    'b>(
+fn compile_submatch<'a, 'b>(
                     bcx: &'b Block<'b>,
-                    m: &[Match<'r,'b>],
+                    m: &'a [Match<'a, 'b>],
                     vals: &[ValueRef],
                     chk: &FailureHandler) {
     debug!("compile_submatch(bcx={}, m={}, vals={})",
@@ -1514,7 +1502,7 @@ fn compile_submatch<'r,
             Some(guard_expr) => {
                 bcx = compile_guard(bcx,
                                     guard_expr,
-                                    &m[0].data,
+                                    m[0].data,
                                     m.slice(1, m.len()),
                                     vals,
                                     chk);
@@ -1541,17 +1529,16 @@ fn compile_submatch<'r,
     }
 }
 
-fn compile_submatch_continue<'r,
-                             'b>(
+fn compile_submatch_continue<'a, 'b>(
                              mut bcx: &'b Block<'b>,
-                             m: &[Match<'r,'b>],
+                             m: &'a [Match<'a, 'b>],
                              vals: &[ValueRef],
                              chk: &FailureHandler,
                              col: uint,
                              val: ValueRef) {
     let fcx = bcx.fcx;
     let tcx = bcx.tcx();
-    let dm = tcx.def_map;
+    let dm = &tcx.def_map;
 
     let vals_left = Vec::from_slice(vals.slice(0u, col)).append(vals.slice(col + 1u, vals.len()));
     let ccx = bcx.fcx.ccx;
@@ -1575,7 +1562,7 @@ fn compile_submatch_continue<'r,
             expr::with_field_tys(tcx, pat_ty, Some(pat_id), |discr, field_tys| {
                 let rec_vals = rec_fields.iter().map(|field_name| {
                         let ix = ty::field_idx_strict(tcx, field_name.name, field_tys);
-                        adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
+                        adt::trans_field_ptr(bcx, &*pat_repr, val, discr, ix)
                         }).collect::<Vec<_>>();
                 compile_submatch(
                         bcx,
@@ -1601,7 +1588,7 @@ fn compile_submatch_continue<'r,
           _ => ccx.sess().bug("non-tuple type in tuple pattern")
         };
         let tup_vals = Vec::from_fn(n_tup_elts, |i| {
-            adt::trans_field_ptr(bcx, tup_repr, val, 0, i)
+            adt::trans_field_ptr(bcx, &*tup_repr, val, 0, i)
         });
         compile_submatch(bcx,
                          enter_tup(bcx,
@@ -1630,7 +1617,7 @@ fn compile_submatch_continue<'r,
 
         let struct_repr = adt::represent_type(bcx.ccx(), struct_ty);
         let llstructvals = Vec::from_fn(struct_element_count, |i| {
-            adt::trans_field_ptr(bcx, struct_repr, val, 0, i)
+            adt::trans_field_ptr(bcx, &*struct_repr, val, 0, i)
         });
         compile_submatch(bcx,
                          enter_tuple_struct(bcx, dm, m, col, val,
@@ -1666,8 +1653,8 @@ fn compile_submatch_continue<'r,
     debug!("test_val={}", bcx.val_to_str(test_val));
     if opts.len() > 0u {
         match *opts.get(0) {
-            var(_, repr) => {
-                let (the_kind, val_opt) = adt::trans_switch(bcx, repr, val);
+            var(_, ref repr) => {
+                let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val);
                 kind = the_kind;
                 for &tval in val_opt.iter() { test_val = tval; }
             }
@@ -1813,9 +1800,9 @@ fn compile_submatch_continue<'r,
         let mut size = 0u;
         let mut unpacked = Vec::new();
         match *opt {
-            var(disr_val, repr) => {
+            var(disr_val, ref repr) => {
                 let ExtractedBlock {vals: argvals, bcx: new_bcx} =
-                    extract_variant_args(opt_cx, repr, disr_val, val);
+                    extract_variant_args(opt_cx, &**repr, disr_val, val);
                 size = argvals.len();
                 unpacked = argvals;
                 opt_cx = new_bcx;
@@ -1885,7 +1872,7 @@ fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap {
     let ccx = bcx.ccx();
     let tcx = bcx.tcx();
     let mut bindings_map = HashMap::new();
-    pat_bindings(tcx.def_map, pat, |bm, p_id, span, path| {
+    pat_bindings(&tcx.def_map, pat, |bm, p_id, span, path| {
         let ident = path_to_ident(path);
         let variable_ty = node_id_type(bcx, p_id);
         let llvariable_ty = type_of::type_of(ccx, variable_ty);
@@ -1933,26 +1920,6 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
         return bcx;
     }
 
-    let mut arm_datas = Vec::new();
-    let mut matches = Vec::new();
-    for arm in arms.iter() {
-        let body = fcx.new_id_block("case_body", arm.body.id);
-        let bindings_map = create_bindings_map(bcx, *arm.pats.get(0));
-        let arm_data = ArmData {
-            bodycx: body,
-            arm: arm,
-            bindings_map: @bindings_map
-        };
-        arm_datas.push(arm_data.clone());
-        for p in arm.pats.iter() {
-            matches.push(Match {
-                pats: vec!(*p),
-                data: arm_data.clone(),
-                bound_ptrs: Vec::new(),
-            });
-        }
-    }
-
     let t = node_id_type(bcx, discr_expr.id);
     let chk = {
         if ty::type_is_empty(tcx, t) {
@@ -1970,8 +1937,23 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
             Infallible
         }
     };
-    let lldiscr = discr_datum.val;
-    compile_submatch(bcx, matches.as_slice(), [lldiscr], &chk);
+
+    let arm_datas: Vec<ArmData> = arms.iter().map(|arm| ArmData {
+        bodycx: fcx.new_id_block("case_body", arm.body.id),
+        arm: arm,
+        bindings_map: create_bindings_map(bcx, *arm.pats.get(0))
+    }).collect();
+
+    let mut matches = Vec::new();
+    for arm_data in arm_datas.iter() {
+        matches.extend(arm_data.arm.pats.iter().map(|p| Match {
+            pats: vec!(*p),
+            data: arm_data,
+            bound_ptrs: Vec::new(),
+        }));
+    }
+
+    compile_submatch(bcx, matches.as_slice(), [discr_datum.val], &chk);
 
     let mut arm_cxs = Vec::new();
     for arm_data in arm_datas.iter() {
@@ -1982,12 +1964,12 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
         // is just to reduce code space.  See extensive comment at the start
         // of the file for more details.
         if arm_data.arm.guard.is_none() {
-            bcx = store_non_ref_bindings(bcx, arm_data.bindings_map, None);
+            bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None);
         }
 
         // insert bindings into the lllocals map and add cleanups
         let cleanup_scope = fcx.push_custom_cleanup_scope();
-        bcx = insert_lllocals(bcx, arm_data.bindings_map,
+        bcx = insert_lllocals(bcx, &arm_data.bindings_map,
                               cleanup::CustomScope(cleanup_scope));
         bcx = expr::trans_into(bcx, arm_data.arm.body, dest);
         bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
@@ -2066,7 +2048,7 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
         // create dummy memory for the variables if we have no
         // value to store into them immediately
         let tcx = bcx.tcx();
-        pat_bindings(tcx.def_map, pat, |_, p_id, _, path| {
+        pat_bindings(&tcx.def_map, pat, |_, p_id, _, path| {
                 let scope = cleanup::var_scope(tcx, p_id);
                 bcx = mk_binding_alloca(
                     bcx, p_id, path, BindLocal, scope, (),
@@ -2199,7 +2181,7 @@ fn bind_irrefutable_pat<'a>(
     let ccx = bcx.ccx();
     match pat.node {
         ast::PatIdent(pat_binding_mode, ref path, inner) => {
-            if pat_is_binding(tcx.def_map, pat) {
+            if pat_is_binding(&tcx.def_map, pat) {
                 // Allocate the stack slot where the value of this
                 // binding will live and place it into the appropriate
                 // map.
@@ -2238,7 +2220,7 @@ fn bind_irrefutable_pat<'a>(
                                                          enum_id,
                                                          var_id);
                     let args = extract_variant_args(bcx,
-                                                    repr,
+                                                    &*repr,
                                                     vinfo.disr_val,
                                                     val);
                     for sub_pat in sub_pats.iter() {
@@ -2259,7 +2241,7 @@ fn bind_irrefutable_pat<'a>(
                             // This is the tuple struct case.
                             let repr = adt::represent_node(bcx, pat.id);
                             for (i, elem) in elems.iter().enumerate() {
-                                let fldptr = adt::trans_field_ptr(bcx, repr,
+                                let fldptr = adt::trans_field_ptr(bcx, &*repr,
                                                                   val, 0, i);
                                 bcx = bind_irrefutable_pat(bcx, *elem,
                                                            fldptr, binding_mode,
@@ -2282,7 +2264,7 @@ fn bind_irrefutable_pat<'a>(
             expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| {
                 for f in fields.iter() {
                     let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
-                    let fldptr = adt::trans_field_ptr(bcx, pat_repr, val,
+                    let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val,
                                                       discr, ix);
                     bcx = bind_irrefutable_pat(bcx, f.pat, fldptr,
                                                binding_mode, cleanup_scope);
@@ -2292,7 +2274,7 @@ fn bind_irrefutable_pat<'a>(
         ast::PatTup(ref elems) => {
             let repr = adt::represent_node(bcx, pat.id);
             for (i, elem) in elems.iter().enumerate() {
-                let fldptr = adt::trans_field_ptr(bcx, repr, val, 0, i);
+                let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i);
                 bcx = bind_irrefutable_pat(bcx, *elem, fldptr,
                                            binding_mode, cleanup_scope);
             }
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index da78b650852..fbd638b6191 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -45,8 +45,8 @@
 
 use std::container::Map;
 use libc::c_ulonglong;
-use std::option::{Option, Some, None};
 use std::num::{Bitwise};
+use std::rc::Rc;
 
 use lib::llvm::{ValueRef, True, IntEQ, IntNE};
 use middle::trans::_match;
@@ -115,22 +115,22 @@ pub struct Struct {
  * these, for places in trans where the `ty::t` isn't directly
  * available.
  */
-pub fn represent_node(bcx: &Block, node: ast::NodeId) -> @Repr {
+pub fn represent_node(bcx: &Block, node: ast::NodeId) -> Rc<Repr> {
     represent_type(bcx.ccx(), node_id_type(bcx, node))
 }
 
 /// Decides how to represent a given type.
-pub fn represent_type(cx: &CrateContext, t: ty::t) -> @Repr {
+pub fn represent_type(cx: &CrateContext, t: ty::t) -> Rc<Repr> {
     debug!("Representing: {}", ty_to_str(cx.tcx(), t));
     match cx.adt_reprs.borrow().find(&t) {
-        Some(repr) => return *repr,
+        Some(repr) => return repr.clone(),
         None => {}
     }
 
-    let repr = @represent_type_uncached(cx, t);
+    let repr = Rc::new(represent_type_uncached(cx, t));
     debug!("Represented as: {:?}", repr)
-    cx.adt_reprs.borrow_mut().insert(t, repr);
-    return repr;
+    cx.adt_reprs.borrow_mut().insert(t, repr.clone());
+    repr
 }
 
 fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
@@ -267,7 +267,19 @@ impl Case {
         mk_struct(cx, self.tys.as_slice(), false).size == 0
     }
     fn find_ptr(&self) -> Option<uint> {
-        self.tys.iter().position(|&ty| mono_data_classify(ty) == MonoNonNull)
+        self.tys.iter().position(|&ty| {
+            match ty::get(ty).sty {
+                ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+                    ty::ty_vec(_, None) => false,
+                    _ => true,
+                },
+                ty::ty_uniq(..) | ty::ty_box(..) |
+                ty::ty_str(ty::VstoreUniq) |
+                ty::ty_bare_fn(..) => true,
+                // Is that everything?  Would closures or slices qualify?
+                _ => false
+            }
+        })
     }
 }
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 92a6bb73c8e..fda51e744ce 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -75,6 +75,7 @@ use libc::c_uint;
 use std::c_str::ToCStr;
 use std::cell::{Cell, RefCell};
 use std::local_data;
+use std::rc::Rc;
 use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
 use syntax::ast_util::{local_def, is_local};
 use syntax::attr::AttrMetaMethods;
@@ -398,17 +399,17 @@ pub fn malloc_raw_dyn_managed<'a>(
 
 // Type descriptor and type glue stuff
 
-pub fn get_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
+pub fn get_tydesc(ccx: &CrateContext, t: ty::t) -> Rc<tydesc_info> {
     match ccx.tydescs.borrow().find(&t) {
-        Some(&inf) => return inf,
+        Some(inf) => return inf.clone(),
         _ => { }
     }
 
     ccx.stats.n_static_tydescs.set(ccx.stats.n_static_tydescs.get() + 1u);
-    let inf = glue::declare_tydesc(ccx, t);
+    let inf = Rc::new(glue::declare_tydesc(ccx, t));
 
-    ccx.tydescs.borrow_mut().insert(t, inf);
-    return inf;
+    ccx.tydescs.borrow_mut().insert(t, inf.clone());
+    inf
 }
 
 #[allow(dead_code)] // useful
@@ -637,7 +638,7 @@ pub fn iter_structural_ty<'r,
                     cx: &'b Block<'b>,
                     repr: &adt::Repr,
                     av: ValueRef,
-                    variant: @ty::VariantInfo,
+                    variant: &ty::VariantInfo,
                     tps: &[ty::t],
                     f: val_and_ty_fn<'r,'b>)
                     -> &'b Block<'b> {
@@ -659,7 +660,7 @@ pub fn iter_structural_ty<'r,
           let repr = adt::represent_type(cx.ccx(), t);
           expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| {
               for (i, field_ty) in field_tys.iter().enumerate() {
-                  let llfld_a = adt::trans_field_ptr(cx, repr, av, discr, i);
+                  let llfld_a = adt::trans_field_ptr(cx, &*repr, av, discr, i);
                   cx = f(cx, llfld_a, field_ty.mt.ty);
               }
           })
@@ -677,7 +678,7 @@ pub fn iter_structural_ty<'r,
       ty::ty_tup(ref args) => {
           let repr = adt::represent_type(cx.ccx(), t);
           for (i, arg) in args.iter().enumerate() {
-              let llfld_a = adt::trans_field_ptr(cx, repr, av, 0, i);
+              let llfld_a = adt::trans_field_ptr(cx, &*repr, av, 0, i);
               cx = f(cx, llfld_a, *arg);
           }
       }
@@ -692,9 +693,9 @@ pub fn iter_structural_ty<'r,
           // NB: we must hit the discriminant first so that structural
           // comparison know not to proceed when the discriminants differ.
 
-          match adt::trans_switch(cx, repr, av) {
+          match adt::trans_switch(cx, &*repr, av) {
               (_match::single, None) => {
-                  cx = iter_variant(cx, repr, av, *variants.get(0),
+                  cx = iter_variant(cx, &*repr, av, &**variants.get(0),
                                     substs.tps.as_slice(), f);
               }
               (_match::switch, Some(lldiscrim_a)) => {
@@ -709,7 +710,7 @@ pub fn iter_structural_ty<'r,
                       let variant_cx =
                           fcx.new_temp_block("enum-iter-variant-".to_owned() +
                                              variant.disr_val.to_str());
-                      match adt::trans_case(cx, repr, variant.disr_val) {
+                      match adt::trans_case(cx, &*repr, variant.disr_val) {
                           _match::single_result(r) => {
                               AddCase(llswitch, r.val, variant_cx.llbb)
                           }
@@ -718,9 +719,9 @@ pub fn iter_structural_ty<'r,
                       }
                       let variant_cx =
                           iter_variant(variant_cx,
-                                       repr,
+                                       &*repr,
                                        av,
-                                       *variant,
+                                       &**variant,
                                        substs.tps.as_slice(),
                                        |x,y,z| f(x,y,z));
                       Br(variant_cx, next_cx.llbb);
@@ -1112,7 +1113,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
                        id: ast::NodeId,
                        has_env: bool,
                        output_type: ty::t,
-                       param_substs: Option<@param_substs>,
+                       param_substs: Option<&'a param_substs>,
                        sp: Option<Span>,
                        block_arena: &'a TypedArena<Block<'a>>)
                        -> FunctionContext<'a> {
@@ -1120,7 +1121,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
 
     debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
            if id == -1 { "".to_owned() } else { ccx.tcx.map.path_to_str(id) },
-           id, param_substs.repr(ccx.tcx()));
+           id, param_substs.map(|s| s.repr(ccx.tcx())));
 
     let substd_output_type = match param_substs {
         None => output_type,
@@ -1166,11 +1167,9 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
 
 /// Performs setup on a newly created function, creating the entry scope block
 /// and allocating space for the return pointer.
-pub fn init_function<'a>(
-                     fcx: &'a FunctionContext<'a>,
-                     skip_retptr: bool,
-                     output_type: ty::t,
-                     param_substs: Option<@param_substs>) {
+pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
+                         skip_retptr: bool,
+                         output_type: ty::t) {
     let entry_bcx = fcx.new_temp_block("entry-block");
 
     *fcx.entry_bcx.borrow_mut() = Some(entry_bcx);
@@ -1182,7 +1181,9 @@ pub fn init_function<'a>(
         llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
     }));
 
-    let substd_output_type = match param_substs {
+    // This shouldn't need to recompute the return type,
+    // as new_fn_ctxt did it already.
+    let substd_output_type = match fcx.param_substs {
         None => output_type,
         Some(substs) => {
             ty::subst_tps(fcx.ccx.tcx(),
@@ -1329,7 +1330,7 @@ pub fn trans_closure(ccx: &CrateContext,
                      decl: &ast::FnDecl,
                      body: &ast::Block,
                      llfndecl: ValueRef,
-                     param_substs: Option<@param_substs>,
+                     param_substs: Option<&param_substs>,
                      id: ast::NodeId,
                      _attributes: &[ast::Attribute],
                      output_type: ty::t,
@@ -1340,7 +1341,7 @@ pub fn trans_closure(ccx: &CrateContext,
     set_uwtable(llfndecl);
 
     debug!("trans_closure(..., param_substs={})",
-           param_substs.repr(ccx.tcx()));
+           param_substs.map(|s| s.repr(ccx.tcx())));
 
     let has_env = match ty::get(ty::node_id_to_type(ccx.tcx(), id)).sty {
         ty::ty_closure(_) => true,
@@ -1353,10 +1354,10 @@ pub fn trans_closure(ccx: &CrateContext,
                           id,
                           has_env,
                           output_type,
-                          param_substs,
+                          param_substs.map(|s| &*s),
                           Some(body.span),
                           &arena);
-    init_function(&fcx, false, output_type, param_substs);
+    init_function(&fcx, false, output_type);
 
     // cleanup scope for the incoming arguments
     let arg_scope = fcx.push_custom_cleanup_scope();
@@ -1429,11 +1430,11 @@ pub fn trans_fn(ccx: &CrateContext,
                 decl: &ast::FnDecl,
                 body: &ast::Block,
                 llfndecl: ValueRef,
-                param_substs: Option<@param_substs>,
+                param_substs: Option<&param_substs>,
                 id: ast::NodeId,
                 attrs: &[ast::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id));
-    debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
+    debug!("trans_fn(param_substs={})", param_substs.map(|s| s.repr(ccx.tcx())));
     let _icx = push_ctxt("trans_fn");
     let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), id));
     trans_closure(ccx, decl, body, llfndecl,
@@ -1445,7 +1446,7 @@ pub fn trans_enum_variant(ccx: &CrateContext,
                           variant: &ast::Variant,
                           _args: &[ast::VariantArg],
                           disr: ty::Disr,
-                          param_substs: Option<@param_substs>,
+                          param_substs: Option<&param_substs>,
                           llfndecl: ValueRef) {
     let _icx = push_ctxt("trans_enum_variant");
 
@@ -1460,7 +1461,7 @@ pub fn trans_enum_variant(ccx: &CrateContext,
 pub fn trans_tuple_struct(ccx: &CrateContext,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
-                          param_substs: Option<@param_substs>,
+                          param_substs: Option<&param_substs>,
                           llfndecl: ValueRef) {
     let _icx = push_ctxt("trans_tuple_struct");
 
@@ -1475,24 +1476,20 @@ pub fn trans_tuple_struct(ccx: &CrateContext,
 fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
                                            ctor_id: ast::NodeId,
                                            disr: ty::Disr,
-                                           param_substs: Option<@param_substs>,
+                                           param_substs: Option<&param_substs>,
                                            llfndecl: ValueRef) {
-    let no_substs: &[ty::t] = [];
-    let ty_param_substs = match param_substs {
-        Some(ref substs) => {
-            let v: &[ty::t] = substs.tys.as_slice();
-            v
-        }
-        None => {
-            let v: &[ty::t] = no_substs;
-            v
-        }
-    };
+    let ctor_ty = {
+        let no_substs: &[ty::t] = [];
+        let ty_param_substs: &[ty::t] = match param_substs {
+            Some(substs) => substs.tys.as_slice(),
+            None => no_substs
+        };
 
-    let ctor_ty = ty::subst_tps(ccx.tcx(),
-                                ty_param_substs,
-                                None,
-                                ty::node_id_to_type(ccx.tcx(), ctor_id));
+        ty::subst_tps(ccx.tcx(),
+                      ty_param_substs,
+                      None,
+                      ty::node_id_to_type(ccx.tcx(), ctor_id))
+    };
 
     let result_ty = match ty::get(ctor_ty).sty {
         ty::ty_bare_fn(ref bft) => bft.sig.output,
@@ -1504,8 +1501,8 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
-                          param_substs, None, &arena);
-    init_function(&fcx, false, result_ty, param_substs);
+                          param_substs.map(|s| &*s), None, &arena);
+    init_function(&fcx, false, result_ty);
 
     let arg_tys = ty::ty_fn_args(ctor_ty);
 
@@ -1515,10 +1512,10 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     if !type_is_zero_size(fcx.ccx, result_ty) {
         let repr = adt::represent_type(ccx, result_ty);
-        adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
+        adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
         for (i, arg_datum) in arg_datums.move_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
-                                                 repr,
+                                                 &*repr,
                                                  fcx.llretptr.get().unwrap(),
                                                  disr,
                                                  i);
@@ -1529,11 +1526,11 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
     finish_fn(&fcx, bcx);
 }
 
-pub fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
-                      id: ast::NodeId, vi: @Vec<@ty::VariantInfo>,
-                      i: &mut uint) {
+fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
+                  id: ast::NodeId, vi: &[Rc<ty::VariantInfo>],
+                  i: &mut uint) {
     for &variant in enum_definition.variants.iter() {
-        let disr_val = vi.get(*i).disr_val;
+        let disr_val = vi[*i].disr_val;
         *i += 1;
 
         match variant.node.kind {
@@ -1596,7 +1593,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         if !generics.is_type_parameterized() {
             let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
             let mut i = 0;
-            trans_enum_def(ccx, enum_definition, item.id, vi, &mut i);
+            trans_enum_def(ccx, enum_definition, item.id, vi.as_slice(), &mut i);
         }
       }
       ast::ItemStatic(_, m, expr) => {
@@ -2056,17 +2053,13 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
 
 pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
     -> encoder::EncodeParams<'r> {
-
-        let diag = cx.sess().diagnostic();
-        let item_symbols = &cx.item_symbols;
-        let link_meta = &cx.link_meta;
         encoder::EncodeParams {
-            diag: diag,
+            diag: cx.sess().diagnostic(),
             tcx: cx.tcx(),
-            reexports2: cx.exp_map2,
-            item_symbols: item_symbols,
+            reexports2: &cx.exp_map2,
+            item_symbols: &cx.item_symbols,
             non_inlineable_statics: &cx.non_inlineable_statics,
-            link_meta: link_meta,
+            link_meta: &cx.link_meta,
             cstore: &cx.sess().cstore,
             encode_inlined_item: ie,
         }
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 7002d09beca..642ae86a979 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -176,14 +176,14 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
            def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
            vtables.repr(bcx.tcx()));
     trans_fn_ref_with_vtables(bcx, def_id, node,
-                              type_params.as_slice(),
+                              type_params,
                               vtables)
 }
 
 fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
                                            def_id: ast::DefId,
                                            ref_id: ast::NodeId,
-                                           type_params: &[ty::t],
+                                           type_params: Vec<ty::t>,
                                            vtables: Option<typeck::vtable_res>)
                                            -> Callee<'a> {
     Callee {bcx: bcx,
@@ -203,32 +203,35 @@ fn resolve_default_method_vtables(bcx: &Block,
 
     // Build up a param_substs that we are going to resolve the
     // trait_vtables under.
-    let param_substs = Some(@param_substs {
+    let param_substs = param_substs {
         tys: substs.tps.clone(),
         self_ty: substs.self_ty,
-        vtables: impl_vtables,
+        vtables: impl_vtables.clone(),
         self_vtables: None
-    });
+    };
 
-    let trait_vtables_fixed = resolve_vtables_under_param_substs(
-        bcx.tcx(), param_substs, impl_res.trait_vtables);
+    let mut param_vtables = resolve_vtables_under_param_substs(
+        bcx.tcx(), Some(&param_substs), impl_res.trait_vtables.as_slice());
 
     // Now we pull any vtables for parameters on the actual method.
     let num_method_vtables = method.generics.type_param_defs().len();
-    let method_vtables = match impl_vtables {
-        Some(vtables) => {
+    match impl_vtables {
+        Some(ref vtables) => {
             let num_impl_type_parameters =
                 vtables.len() - num_method_vtables;
-            Vec::from_slice(vtables.tailn(num_impl_type_parameters))
+            param_vtables.push_all(vtables.tailn(num_impl_type_parameters))
         },
-        None => Vec::from_elem(num_method_vtables, @Vec::new())
-    };
-
-    let method_vtables = method_vtables.as_slice();
-    let param_vtables = @((*trait_vtables_fixed).clone().append(method_vtables));
+        None => {
+            param_vtables.extend(range(0, num_method_vtables).map(
+                |_| -> typeck::vtable_param_res {
+                    Vec::new()
+                }
+            ))
+        }
+    }
 
     let self_vtables = resolve_param_vtables_under_param_substs(
-        bcx.tcx(), param_substs, impl_res.self_vtables);
+        bcx.tcx(), Some(&param_substs), impl_res.self_vtables.as_slice());
 
     (param_vtables, self_vtables)
 }
@@ -238,7 +241,7 @@ pub fn trans_fn_ref_with_vtables(
         bcx: &Block,       //
         def_id: ast::DefId,   // def id of fn
         node: ExprOrMethodCall,  // node id of use of fn; may be zero if N/A
-        type_params: &[ty::t], // values for fn's ty params
+        type_params: Vec<ty::t>, // values for fn's ty params
         vtables: Option<typeck::vtable_res>) // vtables for the call
      -> ValueRef {
     /*!
@@ -273,9 +276,11 @@ pub fn trans_fn_ref_with_vtables(
     // Polytype of the function item (may have type params)
     let fn_tpt = ty::lookup_item_type(tcx, def_id);
 
-    let substs = ty::substs { regions: ty::ErasedRegions,
-                              self_ty: None,
-                              tps: /*bad*/ Vec::from_slice(type_params) };
+    let substs = ty::substs {
+        regions: ty::ErasedRegions,
+        self_ty: None,
+        tps: type_params
+    };
 
     // Load the info for the appropriate trait if necessary.
     match ty::trait_of_method(tcx, def_id) {
@@ -313,24 +318,25 @@ pub fn trans_fn_ref_with_vtables(
 
             // Compute the first substitution
             let first_subst = make_substs_for_receiver_types(
-                tcx, impl_id, trait_ref, method);
+                tcx, impl_id, &*trait_ref, &*method);
 
             // And compose them
             let new_substs = first_subst.subst(tcx, &substs);
 
+            debug!("trans_fn_with_vtables - default method: \
+                    substs = {}, trait_subst = {}, \
+                    first_subst = {}, new_subst = {}, \
+                    vtables = {}",
+                   substs.repr(tcx), trait_ref.substs.repr(tcx),
+                   first_subst.repr(tcx), new_substs.repr(tcx),
+                   vtables.repr(tcx));
 
             let (param_vtables, self_vtables) =
                 resolve_default_method_vtables(bcx, impl_id,
-                                               method, &substs, vtables);
+                                               &*method, &substs, vtables);
 
             debug!("trans_fn_with_vtables - default method: \
-                    substs = {}, trait_subst = {}, \
-                    first_subst = {}, new_subst = {}, \
-                    vtables = {}, \
                     self_vtable = {}, param_vtables = {}",
-                   substs.repr(tcx), trait_ref.substs.repr(tcx),
-                   first_subst.repr(tcx), new_substs.repr(tcx),
-                   vtables.repr(tcx),
                    self_vtables.repr(tcx), param_vtables.repr(tcx));
 
             (true, source_id,
@@ -352,7 +358,7 @@ pub fn trans_fn_ref_with_vtables(
     // intrinsic, or is a default method.  In particular, if we see an
     // intrinsic that is inlined from a different crate, we want to reemit the
     // intrinsic instead of trying to call it in the other crate.
-    let must_monomorphise = if type_params.len() > 0 || is_default {
+    let must_monomorphise = if substs.tps.len() > 0 || is_default {
         true
     } else if def_id.krate == ast::LOCAL_CRATE {
         let map_node = session::expect(
@@ -391,7 +397,7 @@ pub fn trans_fn_ref_with_vtables(
             let ref_ty = match node {
                 ExprId(id) => node_id_type(bcx, id),
                 MethodCall(method_call) => {
-                    let t = bcx.ccx().maps.method_map.borrow().get(&method_call).ty;
+                    let t = bcx.tcx().method_map.borrow().get(&method_call).ty;
                     monomorphize_type(bcx, t)
                 }
             };
@@ -474,7 +480,7 @@ pub fn trans_method_call<'a>(
     let _icx = push_ctxt("trans_method_call");
     debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx()));
     let method_call = MethodCall::expr(call_ex.id);
-    let method_ty = bcx.ccx().maps.method_map.borrow().get(&method_call).ty;
+    let method_ty = bcx.tcx().method_map.borrow().get(&method_call).ty;
     trans_call_inner(
         bcx,
         Some(common::expr_info(call_ex)),
@@ -504,7 +510,7 @@ pub fn trans_lang_call<'a>(
                                 trans_fn_ref_with_vtables_to_callee(bcx,
                                                                     did,
                                                                     0,
-                                                                    [],
+                                                                    vec!(),
                                                                     None)
                              },
                              ArgVals(args),
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 68744643ca6..df17fb516a7 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -466,7 +466,7 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output, None, None, &arena);
-    init_function(&fcx, true, f.sig.output, None);
+    init_function(&fcx, true, f.sig.output);
     let bcx = fcx.entry_bcx.borrow().clone().unwrap();
 
     let args = create_datums_for_fn_args(&fcx,
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 72e716d0c3c..edb98db416a 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -154,21 +154,6 @@ pub fn expr_info(expr: &ast::Expr) -> NodeInfo {
     NodeInfo { id: expr.id, span: expr.span }
 }
 
-pub struct Stats {
-    pub n_static_tydescs: Cell<uint>,
-    pub n_glues_created: Cell<uint>,
-    pub n_null_glues: Cell<uint>,
-    pub n_real_glues: Cell<uint>,
-    pub n_fns: Cell<uint>,
-    pub n_monos: Cell<uint>,
-    pub n_inlines: Cell<uint>,
-    pub n_closures: Cell<uint>,
-    pub n_llvm_insns: Cell<uint>,
-    pub llvm_insns: RefCell<HashMap<~str, uint>>,
-    // (ident, time-in-ms, llvm-instructions)
-    pub fn_stats: RefCell<Vec<(~str, uint, uint)> >,
-}
-
 pub struct BuilderRef_res {
     pub b: BuilderRef,
 }
@@ -274,7 +259,7 @@ pub struct FunctionContext<'a> {
 
     // If this function is being monomorphized, this contains the type
     // substitutions used.
-    pub param_substs: Option<@param_substs>,
+    pub param_substs: Option<&'a param_substs>,
 
     // The source span and nesting context where this function comes from, for
     // error reporting and symbol generation.
@@ -686,53 +671,9 @@ pub fn is_null(val: ValueRef) -> bool {
     }
 }
 
-// Used to identify cached monomorphized functions and vtables
-#[deriving(Eq, TotalEq, Hash)]
-pub enum mono_param_id {
-    mono_precise(ty::t, Option<@Vec<mono_id> >),
-    mono_any,
-    mono_repr(uint /* size */,
-              uint /* align */,
-              MonoDataClass,
-              datum::RvalueMode),
-}
-
-#[deriving(Eq, TotalEq, Hash)]
-pub enum MonoDataClass {
-    MonoBits,    // Anything not treated differently from arbitrary integer data
-    MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
-    // FIXME(#3547)---scalars and floats are
-    // treated differently in most ABIs.  But we
-    // should be doing something more detailed
-    // here.
-    MonoFloat
-}
-
-pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
-    match ty::get(t).sty {
-        ty::ty_float(_) => MonoFloat,
-        ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
-            ty::ty_vec(_, None) => MonoBits,
-            _ => MonoNonNull,
-        },
-        ty::ty_uniq(..) | ty::ty_box(..) |
-        ty::ty_str(ty::VstoreUniq) |
-        ty::ty_bare_fn(..) => MonoNonNull,
-        // Is that everything?  Would closures or slices qualify?
-        _ => MonoBits
-    }
-}
-
-#[deriving(Eq, TotalEq, Hash)]
-pub struct mono_id_ {
-    pub def: ast::DefId,
-    pub params: Vec<mono_param_id> }
-
-pub type mono_id = @mono_id_;
-
 pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
     match bcx.fcx.param_substs {
-        Some(substs) => {
+        Some(ref substs) => {
             ty::subst_tps(bcx.tcx(), substs.tys.as_slice(), substs.self_ty, t)
         }
         _ => {
@@ -754,9 +695,7 @@ pub fn expr_ty(bcx: &Block, ex: &ast::Expr) -> ty::t {
 }
 
 pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
-    let tcx = bcx.tcx();
-    let t = ty::expr_ty_adjusted(tcx, ex, &*bcx.ccx().maps.method_map.borrow());
-    monomorphize_type(bcx, t)
+    monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
 }
 
 // Key used to lookup values supplied for type parameters in an expr.
@@ -774,7 +713,7 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
     let params = match node {
         ExprId(id) => ty::node_id_to_type_params(tcx, id),
         MethodCall(method_call) => {
-            bcx.ccx().maps.method_map.borrow().get(&method_call).substs.tps.clone()
+            tcx.method_map.borrow().get(&method_call).substs.tps.clone()
         }
     };
 
@@ -788,62 +727,63 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
     }
 
     match bcx.fcx.param_substs {
-      Some(substs) => {
-        params.iter().map(|t| {
-            ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
-        }).collect()
-      }
-      _ => params
+        Some(ref substs) => {
+            params.iter().map(|t| {
+                ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
+            }).collect()
+        }
+        _ => params
     }
 }
 
 pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
                  -> Option<typeck::vtable_res> {
-    let vtable_map = bcx.ccx().maps.vtable_map.borrow();
-    let raw_vtables = vtable_map.find(&id);
-    raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
+    bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
+        resolve_vtables_in_fn_ctxt(bcx.fcx, vts.as_slice())
+    })
 }
 
 // Apply the typaram substitutions in the FunctionContext to some
 // vtables. This should eliminate any vtable_params.
-pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
-    -> typeck::vtable_res {
+pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
+                                  vts: &[typeck::vtable_param_res])
+                                  -> typeck::vtable_res {
     resolve_vtables_under_param_substs(fcx.ccx.tcx(),
                                        fcx.param_substs,
                                        vts)
 }
 
 pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
-                                          param_substs: Option<@param_substs>,
-                                          vts: typeck::vtable_res)
-    -> typeck::vtable_res {
-    @vts.iter().map(|ds|
+                                          param_substs: Option<&param_substs>,
+                                          vts: &[typeck::vtable_param_res])
+                                          -> typeck::vtable_res {
+    vts.iter().map(|ds| {
       resolve_param_vtables_under_param_substs(tcx,
                                                param_substs,
-                                               *ds))
-        .collect()
+                                               ds.as_slice())
+    }).collect()
 }
 
 pub fn resolve_param_vtables_under_param_substs(
     tcx: &ty::ctxt,
-    param_substs: Option<@param_substs>,
-    ds: typeck::vtable_param_res)
+    param_substs: Option<&param_substs>,
+    ds: &[typeck::vtable_origin])
     -> typeck::vtable_param_res {
-    @ds.iter().map(
-        |d| resolve_vtable_under_param_substs(tcx,
-                                              param_substs,
-                                              d))
-        .collect()
+    ds.iter().map(|d| {
+        resolve_vtable_under_param_substs(tcx,
+                                          param_substs,
+                                          d)
+    }).collect()
 }
 
 
 
 pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
-                                         param_substs: Option<@param_substs>,
+                                         param_substs: Option<&param_substs>,
                                          vt: &typeck::vtable_origin)
                                          -> typeck::vtable_origin {
     match *vt {
-        typeck::vtable_static(trait_id, ref tys, sub) => {
+        typeck::vtable_static(trait_id, ref tys, ref sub) => {
             let tys = match param_substs {
                 Some(substs) => {
                     tys.iter().map(|t| {
@@ -857,7 +797,7 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
             };
             typeck::vtable_static(
                 trait_id, tys,
-                resolve_vtables_under_param_substs(tcx, param_substs, sub))
+                resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
         }
         typeck::vtable_param(n_param, n_bound) => {
             match param_substs {
@@ -883,11 +823,11 @@ pub fn find_vtable(tcx: &ty::ctxt,
            n_param, n_bound, ps.repr(tcx));
 
     let param_bounds = match n_param {
-        typeck::param_self => ps.self_vtables.expect("self vtables missing"),
+        typeck::param_self => ps.self_vtables.as_ref().expect("self vtables missing"),
         typeck::param_numbered(n) => {
-            let tables = ps.vtables
+            let tables = ps.vtables.as_ref()
                 .expect("vtables missing where they are needed");
-            *tables.get(n)
+            tables.get(n)
         }
     };
     param_bounds.get(n_bound).clone()
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 8848feb8889..759e48e633f 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -130,7 +130,7 @@ fn const_deref_ptr(cx: &CrateContext, v: ValueRef) -> ValueRef {
 fn const_deref_newtype(cx: &CrateContext, v: ValueRef, t: ty::t)
     -> ValueRef {
     let repr = adt::represent_type(cx, t);
-    adt::const_get_field(cx, repr, v, 0, 0)
+    adt::const_get_field(cx, &*repr, v, 0, 0)
 }
 
 fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool)
@@ -187,13 +187,12 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
     let mut llconst = llconst;
     let mut inlineable = inlineable;
     let ety = ty::expr_ty(cx.tcx(), e);
-    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e,
-                                            &*cx.maps.method_map.borrow());
+    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e);
     let opt_adj = cx.tcx.adjustments.borrow().find_copy(&e.id);
     match opt_adj {
         None => { }
         Some(adj) => {
-            match *adj {
+            match adj {
                 ty::AutoAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => {
                     let def = ty::resolve_expr(cx.tcx(), e);
                     let wrapper = closure::get_wrapper_for_bare_fn(cx,
@@ -414,19 +413,17 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
             }, true)
           }
           ast::ExprField(base, field, _) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx(), base,
-                                            &*cx.maps.method_map.borrow());
+              let bt = ty::expr_ty_adjusted(cx.tcx(), base);
               let brepr = adt::represent_type(cx, bt);
               let (bv, inlineable) = const_expr(cx, base, is_local);
               expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
                   let ix = ty::field_idx_strict(cx.tcx(), field.name, field_tys);
-                  (adt::const_get_field(cx, brepr, bv, discr, ix), inlineable)
+                  (adt::const_get_field(cx, &*brepr, bv, discr, ix), inlineable)
               })
           }
 
           ast::ExprIndex(base, index) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx(), base,
-                                            &*cx.maps.method_map.borrow());
+              let bt = ty::expr_ty_adjusted(cx.tcx(), base);
               let (bv, inlineable) = const_expr(cx, base, is_local);
               let iv = match const_eval::eval_const_expr(cx.tcx(), index) {
                   const_eval::const_int(i) => i as u64,
@@ -494,7 +491,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               (expr::cast_enum, expr::cast_integral) |
               (expr::cast_enum, expr::cast_float)  => {
                 let repr = adt::represent_type(cx, basety);
-                let discr = adt::const_get_discrim(cx, repr, v);
+                let discr = adt::const_get_discrim(cx, &*repr, v);
                 let iv = C_integral(cx.int_type, discr, false);
                 let ety_cast = expr::cast_type_kind(ety);
                 match ety_cast {
@@ -527,7 +524,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               let ety = ty::expr_ty(cx.tcx(), e);
               let repr = adt::represent_type(cx, ety);
               let (vals, inlineable) = map_list(es.as_slice());
-              (adt::trans_const(cx, repr, 0, vals.as_slice()), inlineable)
+              (adt::trans_const(cx, &*repr, 0, vals.as_slice()), inlineable)
           }
           ast::ExprStruct(_, ref fs, ref base_opt) => {
               let ety = ty::expr_ty(cx.tcx(), e);
@@ -547,7 +544,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                           None => {
                               match base_val {
                                 Some((bv, inlineable)) => {
-                                    (adt::const_get_field(cx, repr, bv, discr, ix),
+                                    (adt::const_get_field(cx, &*repr, bv, discr, ix),
                                      inlineable)
                                 }
                                 None => cx.sess().span_bug(e.span, "missing struct field")
@@ -555,7 +552,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                           }
                       }
                   }));
-                  (adt::trans_const(cx, repr, discr, cs),
+                  (adt::trans_const(cx, &*repr, discr, cs),
                    inlineable.iter().fold(true, |a, &b| a && b))
               })
           }
@@ -635,7 +632,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                     let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                          enum_did,
                                                          variant_did);
-                    (adt::trans_const(cx, repr, vinfo.disr_val, []), true)
+                    (adt::trans_const(cx, &*repr, vinfo.disr_val, []), true)
                 }
                 Some(ast::DefStruct(_)) => {
                     let ety = ty::expr_ty(cx.tcx(), e);
@@ -654,7 +651,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                       let ety = ty::expr_ty(cx.tcx(), e);
                       let repr = adt::represent_type(cx, ety);
                       let (arg_vals, inlineable) = map_list(args.as_slice());
-                      (adt::trans_const(cx, repr, 0, arg_vals.as_slice()),
+                      (adt::trans_const(cx, &*repr, 0, arg_vals.as_slice()),
                        inlineable)
                   }
                   Some(ast::DefVariant(enum_did, variant_did, _)) => {
@@ -665,7 +662,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                                                            variant_did);
                       let (arg_vals, inlineable) = map_list(args.as_slice());
                       (adt::trans_const(cx,
-                                        repr,
+                                        &*repr,
                                         vinfo.disr_val,
                                         arg_vals.as_slice()), inlineable)
                   }
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index 4aad1cded1e..119750cd9ce 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -20,8 +20,9 @@ use middle::resolve;
 use middle::trans::adt;
 use middle::trans::base;
 use middle::trans::builder::Builder;
-use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
+use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res};
 use middle::trans::debuginfo;
+use middle::trans::monomorphize::MonoId;
 use middle::trans::type_::Type;
 use middle::ty;
 use util::sha2::Sha256;
@@ -30,10 +31,26 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap};
 use std::cell::{Cell, RefCell};
 use std::c_str::ToCStr;
 use std::ptr;
+use std::rc::Rc;
 use collections::{HashMap, HashSet};
 use syntax::ast;
 use syntax::parse::token::InternedString;
 
+pub struct Stats {
+    pub n_static_tydescs: Cell<uint>,
+    pub n_glues_created: Cell<uint>,
+    pub n_null_glues: Cell<uint>,
+    pub n_real_glues: Cell<uint>,
+    pub n_fns: Cell<uint>,
+    pub n_monos: Cell<uint>,
+    pub n_inlines: Cell<uint>,
+    pub n_closures: Cell<uint>,
+    pub n_llvm_insns: Cell<uint>,
+    pub llvm_insns: RefCell<HashMap<~str, uint>>,
+    // (ident, time-in-ms, llvm-instructions)
+    pub fn_stats: RefCell<Vec<(~str, uint, uint)> >,
+}
+
 pub struct CrateContext {
     pub llmod: ModuleRef,
     pub llcx: ContextRef,
@@ -47,7 +64,7 @@ pub struct CrateContext {
     pub item_symbols: RefCell<NodeMap<~str>>,
     pub link_meta: LinkMeta,
     pub drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
-    pub tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
+    pub tydescs: RefCell<HashMap<ty::t, Rc<tydesc_info>>>,
     /// Set when running emit_tydescs to enforce that no more tydescs are
     /// created.
     pub finished_tydescs: Cell<bool>,
@@ -61,10 +78,10 @@ pub struct CrateContext {
     /// that is generated
     pub non_inlineable_statics: RefCell<NodeSet>,
     /// Cache instances of monomorphized functions
-    pub monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
+    pub monomorphized: RefCell<HashMap<MonoId, ValueRef>>,
     pub monomorphizing: RefCell<DefIdMap<uint>>,
     /// Cache generated vtables
-    pub vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
+    pub vtables: RefCell<HashMap<(ty::t, MonoId), ValueRef>>,
     /// Cache of constant strings,
     pub const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,
 
@@ -91,13 +108,13 @@ pub struct CrateContext {
 
     pub lltypes: RefCell<HashMap<ty::t, Type>>,
     pub llsizingtypes: RefCell<HashMap<ty::t, Type>>,
-    pub adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
+    pub adt_reprs: RefCell<HashMap<ty::t, Rc<adt::Repr>>>,
     pub symbol_hasher: RefCell<Sha256>,
     pub type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
     pub all_llvm_symbols: RefCell<HashSet<~str>>,
     pub tcx: ty::ctxt,
     pub maps: astencode::Maps,
-    pub stats: @Stats,
+    pub stats: Stats,
     pub int_type: Type,
     pub opaque_vec_type: Type,
     pub builder: BuilderRef_res,
@@ -179,7 +196,7 @@ impl CrateContext {
                 all_llvm_symbols: RefCell::new(HashSet::new()),
                 tcx: tcx,
                 maps: maps,
-                stats: @Stats {
+                stats: Stats {
                     n_static_tydescs: Cell::new(0u),
                     n_glues_created: Cell::new(0u),
                     n_null_glues: Cell::new(0u),
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index c5739960a19..4dd929e16f7 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -57,7 +57,7 @@ For example, the following simple type for a singly-linked list...
 ```
 struct List {
     value: int,
-    tail: Option<@List>,
+    tail: Option<~List>,
 }
 ```
 
@@ -66,8 +66,8 @@ will generate the following callstack with a naive DFS algorithm:
 ```
 describe(t = List)
   describe(t = int)
-  describe(t = Option<@List>)
-    describe(t = @List)
+  describe(t = Option<~List>)
+    describe(t = ~List)
       describe(t = List) // at the beginning again...
       ...
 ```
@@ -144,6 +144,7 @@ use util::ppaux;
 
 use std::c_str::{CString, ToCStr};
 use std::cell::{Cell, RefCell};
+use std::rc::{Rc, Weak};
 use collections::HashMap;
 use collections::HashSet;
 use libc::{c_uint, c_ulonglong, c_longlong};
@@ -180,7 +181,7 @@ pub struct CrateDebugContext {
     created_files: RefCell<HashMap<~str, DIFile>>,
     created_types: RefCell<HashMap<uint, DIType>>,
     created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
-    namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
+    namespace_map: RefCell<HashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
     // This collection is used to assert that composite types (structs, enums, ...) have their
     // members only set once:
     composite_types_completed: RefCell<HashSet<DIType>>,
@@ -369,7 +370,7 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
     }
 
     let cx = bcx.ccx();
-    let def_map = cx.tcx.def_map;
+    let def_map = &cx.tcx.def_map;
 
     pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
         let var_ident = ast_util::path_to_ident(path_ref);
@@ -509,7 +510,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
     let fcx = bcx.fcx;
     let cx = fcx.ccx;
 
-    let def_map = cx.tcx.def_map;
+    let def_map = &cx.tcx.def_map;
     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
 
     pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
@@ -609,7 +610,7 @@ pub fn start_emitting_source_locations(fcx: &FunctionContext) {
 /// indicates why no debuginfo should be created for the function.
 pub fn create_function_debug_context(cx: &CrateContext,
                                      fn_ast_id: ast::NodeId,
-                                     param_substs: Option<@param_substs>,
+                                     param_substs: Option<&param_substs>,
                                      llfn: ValueRef) -> FunctionDebugContext {
     if cx.sess().opts.debuginfo == NoDebugInfo {
         return FunctionDebugContext { repr: DebugInfoDisabled };
@@ -775,7 +776,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
     fn get_function_signature(cx: &CrateContext,
                               fn_ast_id: ast::NodeId,
                               fn_decl: &ast::FnDecl,
-                              param_substs: Option<@param_substs>,
+                              param_substs: Option<&param_substs>,
                               error_span: Span) -> DIArray {
         if cx.sess().opts.debuginfo == LimitedDebugInfo {
             return create_DIArray(DIB(cx), []);
@@ -828,7 +829,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
 
     fn get_template_parameters(cx: &CrateContext,
                                generics: &ast::Generics,
-                               param_substs: Option<@param_substs>,
+                               param_substs: Option<&param_substs>,
                                file_metadata: DIFile,
                                name_to_append_suffix_to: &mut StrBuf)
                                -> DIArray {
@@ -1388,8 +1389,8 @@ fn prepare_tuple_metadata(cx: &CrateContext,
 }
 
 struct GeneralMemberDescriptionFactory {
-    type_rep: @adt::Repr,
-    variants: @Vec<@ty::VariantInfo> ,
+    type_rep: Rc<adt::Repr>,
+    variants: Rc<Vec<Rc<ty::VariantInfo>>>,
     discriminant_type_metadata: ValueRef,
     containing_scope: DIScope,
     file_metadata: DIFile,
@@ -1412,7 +1413,7 @@ impl GeneralMemberDescriptionFactory {
                 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
                     describe_enum_variant(cx,
                                           struct_def,
-                                          *self.variants.get(i),
+                                          &**self.variants.get(i),
                                           Some(self.discriminant_type_metadata),
                                           self.containing_scope,
                                           self.file_metadata,
@@ -1617,7 +1618,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                  member_description_factory) =
                     describe_enum_variant(cx,
                                           struct_def,
-                                          *variants.get(0),
+                                          &**variants.get(0),
                                           None,
                                           containing_scope,
                                           file_metadata,
@@ -1661,7 +1662,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                 llvm_type: enum_llvm_type,
                 file_metadata: file_metadata,
                 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
-                    type_rep: type_rep,
+                    type_rep: type_rep.clone(),
                     variants: variants,
                     discriminant_type_metadata: discriminant_type_metadata,
                     containing_scope: containing_scope,
@@ -1676,7 +1677,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                  member_description_factory) =
                     describe_enum_variant(cx,
                                           struct_def,
-                                          *variants.get(nndiscr as uint),
+                                          &**variants.get(nndiscr as uint),
                                           None,
                                           containing_scope,
                                           file_metadata,
@@ -2381,7 +2382,7 @@ fn populate_scope_map(cx: &CrateContext,
                       fn_entry_block: &ast::Block,
                       fn_metadata: DISubprogram,
                       scope_map: &mut HashMap<ast::NodeId, DIScope>) {
-    let def_map = cx.tcx.def_map;
+    let def_map = &cx.tcx.def_map;
 
     struct ScopeStackEntry {
         scope_metadata: DIScope,
@@ -2494,7 +2495,7 @@ fn populate_scope_map(cx: &CrateContext,
                     scope_stack: &mut Vec<ScopeStackEntry> ,
                     scope_map: &mut HashMap<ast::NodeId, DIScope>) {
 
-        let def_map = cx.tcx.def_map;
+        let def_map = &cx.tcx.def_map;
 
         // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
         // because we have to visit *all* nodes in order to put them into the scope map. The above
@@ -2830,14 +2831,14 @@ fn populate_scope_map(cx: &CrateContext,
 struct NamespaceTreeNode {
     name: ast::Name,
     scope: DIScope,
-    parent: Option<@NamespaceTreeNode>,
+    parent: Option<Weak<NamespaceTreeNode>>,
 }
 
 impl NamespaceTreeNode {
     fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
         fn fill_nested(node: &NamespaceTreeNode, output: &mut StrBuf) {
             match node.parent {
-                Some(parent) => fill_nested(parent, output),
+                Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
                 None => {}
             }
             let string = token::get_name(node.name);
@@ -2854,7 +2855,7 @@ impl NamespaceTreeNode {
     }
 }
 
-fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
+fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
     ty::with_path(cx.tcx(), def_id, |path| {
         // prepend crate name if not already present
         let krate = if def_id.krate == ast::LOCAL_CRATE {
@@ -2866,7 +2867,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
         let mut path = krate.move_iter().chain(path).peekable();
 
         let mut current_key = Vec::new();
-        let mut parent_node: Option<@NamespaceTreeNode> = None;
+        let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
 
         // Create/Lookup namespace for each element of the path.
         loop {
@@ -2890,7 +2891,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
                 None => {
                     // create and insert
                     let parent_scope = match parent_node {
-                        Some(node) => node.scope,
+                        Some(ref node) => node.scope,
                         None => ptr::null()
                     };
                     let namespace_name = token::get_name(name);
@@ -2907,14 +2908,14 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
                         }
                     });
 
-                    let node = @NamespaceTreeNode {
+                    let node = Rc::new(NamespaceTreeNode {
                         name: name,
                         scope: scope,
-                        parent: parent_node,
-                    };
+                        parent: parent_node.map(|parent| parent.downgrade()),
+                    });
 
                     debug_context(cx).namespace_map.borrow_mut()
-                                     .insert(current_key.clone(), node);
+                                     .insert(current_key.clone(), node.clone());
 
                     node
                 }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 4e850b8990a..3c1dfedcac6 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -118,7 +118,7 @@ pub fn trans_into<'a>(bcx: &'a Block<'a>,
 
     bcx.fcx.push_ast_cleanup_scope(expr.id);
 
-    let kind = ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr);
+    let kind = ty::expr_kind(bcx.tcx(), expr);
     bcx = match kind {
         ty::LvalueExpr | ty::RvalueDatumExpr => {
             trans_unadjusted(bcx, expr).store_to_dest(dest, expr.id)
@@ -175,7 +175,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
     };
     debug!("unadjusted datum for expr {}: {}",
            expr.id, datum.to_str(bcx.ccx()));
-    match *adjustment {
+    match adjustment {
         AutoAddEnv(..) => {
             datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
         }
@@ -205,8 +205,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
             };
         }
         AutoObject(..) => {
-            let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr,
-                                                   &*bcx.ccx().maps.method_map.borrow());
+            let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr);
             let scratch = rvalue_scratch_datum(bcx, adjusted_ty, "__adjust");
             bcx = meth::trans_trait_cast(
                 bcx, datum, expr.id, SaveIn(scratch.val));
@@ -323,7 +322,7 @@ fn trans_unadjusted<'a>(bcx: &'a Block<'a>,
 
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
-    return match ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr) {
+    return match ty::expr_kind(bcx.tcx(), expr) {
         ty::LvalueExpr | ty::RvalueDatumExpr => {
             let datum = unpack_datum!(bcx, {
                 trans_datum_unadjusted(bcx, expr)
@@ -444,7 +443,7 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>,
             let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
             let d = base_datum.get_element(
                 field_tys[ix].mt.ty,
-                |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, ix));
+                |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
         })
 }
@@ -680,7 +679,7 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
             let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
             let numbered_fields: Vec<(uint, @ast::Expr)> =
                 args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
-            trans_adt(bcx, repr, 0, numbered_fields.as_slice(), None, dest)
+            trans_adt(bcx, &*repr, 0, numbered_fields.as_slice(), None, dest)
         }
         ast::ExprLit(lit) => {
             match lit.node {
@@ -798,7 +797,7 @@ fn trans_def_dps_unadjusted<'a>(
                 // Nullary variant.
                 let ty = expr_ty(bcx, ref_expr);
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                adt::trans_start_init(bcx, repr, lldest,
+                adt::trans_start_init(bcx, &*repr, lldest,
                                       variant_info.disr_val);
                 return bcx;
             }
@@ -808,7 +807,7 @@ fn trans_def_dps_unadjusted<'a>(
             match ty::get(ty).sty {
                 ty::ty_struct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
-                    adt::trans_start_init(bcx, repr, lldest, 0);
+                    adt::trans_start_init(bcx, &*repr, lldest, 0);
                 }
                 _ => {}
             }
@@ -1005,7 +1004,7 @@ fn trans_rec_or_struct<'a>(
         };
 
         let repr = adt::represent_type(bcx.ccx(), ty);
-        trans_adt(bcx, repr, discr, numbered_fields.as_slice(), optbase, dest)
+        trans_adt(bcx, &*repr, discr, numbered_fields.as_slice(), optbase, dest)
     })
 }
 
@@ -1118,7 +1117,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
     // Otherwise, we should be in the RvalueDpsExpr path.
     assert!(
         op == ast::UnDeref ||
-        !ccx.maps.method_map.borrow().contains_key(&method_call));
+        !ccx.tcx.method_map.borrow().contains_key(&method_call));
 
     let un_ty = expr_ty(bcx, expr);
 
@@ -1240,8 +1239,8 @@ fn trans_gc<'a>(mut bcx: &'a Block<'a>,
         SaveIn(addr) => {
             let expr_ty = expr_ty(bcx, expr);
             let repr = adt::represent_type(bcx.ccx(), expr_ty);
-            adt::trans_start_init(bcx, repr, addr, 0);
-            let field_dest = adt::trans_field_ptr(bcx, repr, addr, 0, 0);
+            adt::trans_start_init(bcx, &*repr, addr, 0);
+            let field_dest = adt::trans_field_ptr(bcx, &*repr, addr, 0, 0);
             contents_datum.store_to(bcx, field_dest)
         }
     }
@@ -1403,7 +1402,7 @@ fn trans_binary<'a>(bcx: &'a Block<'a>,
     let ccx = bcx.ccx();
 
     // if overloaded, would be RvalueDpsExpr
-    assert!(!ccx.maps.method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
+    assert!(!ccx.tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
 
     match op {
         ast::BiAnd => {
@@ -1443,7 +1442,7 @@ fn trans_overloaded_op<'a, 'b>(
                        rhs: Option<(Datum<Expr>, ast::NodeId)>,
                        dest: Option<Dest>)
                        -> Result<'a> {
-    let method_ty = bcx.ccx().maps.method_map.borrow().get(&method_call).ty;
+    let method_ty = bcx.tcx().method_map.borrow().get(&method_call).ty;
     callee::trans_call_inner(bcx,
                              Some(expr_info(expr)),
                              monomorphize_type(bcx, method_ty),
@@ -1581,7 +1580,7 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
                 bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
             let llexpr_ptr = datum.to_llref();
             let lldiscrim_a =
-                adt::trans_get_discr(bcx, repr, llexpr_ptr, Some(Type::i64(ccx)));
+                adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
             match k_out {
                 cast_integral => int_cast(bcx, ll_t_out,
                                           val_ty(lldiscrim_a),
@@ -1614,7 +1613,7 @@ fn trans_assign_op<'a>(
     debug!("trans_assign_op(expr={})", bcx.expr_to_str(expr));
 
     // User-defined operator methods cannot be used with `+=` etc right now
-    assert!(!bcx.ccx().maps.method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
+    assert!(!bcx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
 
     // Evaluate LHS (destination), which should be an lvalue
     let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
@@ -1692,7 +1691,7 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
         expr_id: expr.id,
         autoderef: derefs as u32
     };
-    let method_ty = ccx.maps.method_map.borrow()
+    let method_ty = ccx.tcx.method_map.borrow()
                        .find(&method_call).map(|method| method.ty);
     let datum = match method_ty {
         Some(method_ty) => {
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 98e09b2fd31..8488261db9c 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -145,39 +145,34 @@ pub fn get_drop_glue(ccx: &CrateContext, t: ty::t) -> ValueRef {
     glue
 }
 
-pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: @tydesc_info) {
+pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: &tydesc_info) -> ValueRef {
     let _icx = push_ctxt("lazily_emit_visit_glue");
 
     let llfnty = Type::glue_fn(ccx, type_of(ccx, ti.ty).ptr_to());
 
     match ti.visit_glue.get() {
-        Some(_) => (),
+        Some(visit_glue) => visit_glue,
         None => {
             debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
             let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
             ti.visit_glue.set(Some(glue_fn));
             make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
             debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
+            glue_fn
         }
     }
 }
 
 // See [Note-arg-mode]
 pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef,
-                       static_ti: Option<@tydesc_info>) {
+                       static_ti: Option<&tydesc_info>) {
     let _icx = push_ctxt("call_tydesc_glue_full");
     let ccx = bcx.ccx();
     // NB: Don't short-circuit even if this block is unreachable because
     // GC-based cleanup needs to the see that the roots are live.
     if bcx.unreachable.get() && !ccx.sess().no_landing_pads() { return; }
 
-    let static_glue_fn = match static_ti {
-        None => None,
-        Some(sti) => {
-            lazily_emit_visit_glue(ccx, sti);
-            sti.visit_glue.get()
-        }
-    };
+    let static_glue_fn = static_ti.map(|sti| lazily_emit_visit_glue(ccx, sti));
 
     // When static type info is available, avoid casting to a generic pointer.
     let llrawptr = if static_glue_fn.is_none() {
@@ -224,7 +219,7 @@ fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>,
                               substs: &ty::substs)
                               -> &'a Block<'a> {
     let repr = adt::represent_type(bcx.ccx(), t);
-    let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
+    let drop_flag = adt::trans_drop_flag_ptr(bcx, &*repr, v0);
     with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag)), |cx| {
         trans_struct_drop(cx, t, v0, dtor_did, class_did, substs)
     })
@@ -265,7 +260,7 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
     // this scope.
     let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
     for (i, fld) in field_tys.iter().enumerate() {
-        let llfld_a = adt::trans_field_ptr(bcx, repr, v0, 0, i);
+        let llfld_a = adt::trans_field_ptr(bcx, &*repr, v0, 0, i);
         bcx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
                                   llfld_a,
                                   fld.mt.ty);
@@ -404,7 +399,7 @@ fn incr_refcnt_of_boxed<'a>(bcx: &'a Block<'a>,
 
 
 // Generates the declaration for (but doesn't emit) a type descriptor.
-pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
+pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> tydesc_info {
     // If emit_tydescs already ran, then we shouldn't be creating any new
     // tydescs.
     assert!(!ccx.finished_tydescs.get());
@@ -430,16 +425,15 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
     let ty_name = token::intern_and_get_ident(ppaux::ty_to_str(ccx.tcx(), t));
     let ty_name = C_str_slice(ccx, ty_name);
 
-    let inf = @tydesc_info {
+    debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx(), t));
+    tydesc_info {
         ty: t,
         tydesc: gvar,
         size: llsize,
         align: llalign,
         name: ty_name,
         visit_glue: Cell::new(None),
-    };
-    debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx(), t));
-    return inf;
+    }
 }
 
 fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
@@ -466,7 +460,7 @@ fn make_generic_glue(ccx: &CrateContext,
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(), None, None, &arena);
 
-    init_function(&fcx, false, ty::mk_nil(), None);
+    init_function(&fcx, false, ty::mk_nil());
 
     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u);
@@ -491,9 +485,7 @@ pub fn emit_tydescs(ccx: &CrateContext) {
     // As of this point, allow no more tydescs to be created.
     ccx.finished_tydescs.set(true);
     let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to();
-    for (_, &val) in ccx.tydescs.borrow().iter() {
-        let ti = val;
-
+    for (_, ti) in ccx.tydescs.borrow().iter() {
         // Each of the glue functions needs to be cast to a generic type
         // before being put into the tydesc because we only have a singleton
         // tydesc type. Then we'll recast each function to its real type when
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index 9e5213e6a99..3a0083ba5c6 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -85,7 +85,7 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti
 pub fn trans_intrinsic(ccx: &CrateContext,
                        decl: ValueRef,
                        item: &ast::ForeignItem,
-                       substs: @param_substs,
+                       substs: &param_substs,
                        ref_id: Option<ast::NodeId>) {
     debug!("trans_intrinsic(item.ident={})", token::get_ident(item.ident));
 
@@ -194,8 +194,8 @@ pub fn trans_intrinsic(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, decl, item.id, false, output_type,
-                          Some(substs), Some(item.span), &arena);
-    init_function(&fcx, true, output_type, Some(substs));
+                          Some(&*substs), Some(item.span), &arena);
+    init_function(&fcx, true, output_type);
 
     set_always_inline(fcx.llfn);
 
@@ -328,7 +328,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
         "get_tydesc" => {
             let tp_ty = *substs.tys.get(0);
             let static_ti = get_tydesc(ccx, tp_ty);
-            glue::lazily_emit_visit_glue(ccx, static_ti);
+            glue::lazily_emit_visit_glue(ccx, &*static_ti);
 
             // FIXME (#3730): ideally this shouldn't need a cast,
             // but there's a circularity between translating rust types to llvm
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 851f8207cb6..d122edb7678 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -83,7 +83,7 @@ pub fn trans_method_callee<'a>(
                            -> Callee<'a> {
     let _icx = push_ctxt("meth::trans_method_callee");
 
-    let (origin, method_ty) = match bcx.ccx().maps.method_map
+    let (origin, method_ty) = match bcx.tcx().method_map
                                        .borrow().find(&method_call) {
         Some(method) => {
             debug!("trans_method_callee({:?}, method={})",
@@ -193,21 +193,21 @@ pub fn trans_static_method_callee(bcx: &Block,
             name={}", method_id, expr_id, token::get_name(mname));
 
     let vtable_key = MethodCall::expr(expr_id);
-    let vtbls = ccx.maps.vtable_map.borrow().get_copy(&vtable_key);
-    let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
+    let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, ccx.tcx.vtable_map.borrow()
+                                                       .get(&vtable_key).as_slice());
 
-    match vtbls.get(bound_index).get(0) {
-        &typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
+    match vtbls.move_iter().nth(bound_index).unwrap().move_iter().nth(0).unwrap() {
+        typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
             assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
             let mth_id = method_with_name(ccx, impl_did, mname);
             let (callee_substs, callee_origins) =
                 combine_impl_and_methods_tps(
                     bcx, mth_id, ExprId(expr_id),
-                    rcvr_substs.as_slice(), rcvr_origins);
+                    rcvr_substs, rcvr_origins);
 
             let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id),
-                                                 callee_substs.as_slice(),
+                                                 callee_substs,
                                                  Some(callee_origins));
 
             let callee_ty = node_id_type(bcx, expr_id);
@@ -221,22 +221,22 @@ pub fn trans_static_method_callee(bcx: &Block,
     }
 }
 
-pub fn method_with_name(ccx: &CrateContext,
-                        impl_id: ast::DefId,
-                        name: ast::Name) -> ast::DefId {
+fn method_with_name(ccx: &CrateContext,
+                    impl_id: ast::DefId,
+                    name: ast::Name) -> ast::DefId {
     match ccx.impl_method_cache.borrow().find_copy(&(impl_id, name)) {
         Some(m) => return m,
         None => {}
     }
 
-    let imp = ccx.tcx.impls.borrow();
-    let imp = imp.find(&impl_id)
-                 .expect("could not find impl while translating");
-    let meth = imp.methods.iter().find(|m| m.ident.name == name)
-                  .expect("could not find method while translating");
+    let methods = ccx.tcx.impl_methods.borrow();
+    let methods = methods.find(&impl_id)
+                         .expect("could not find impl while translating");
+    let meth_did = methods.iter().find(|&did| ty::method(&ccx.tcx, *did).ident.name == name)
+                                 .expect("could not find method while translating");
 
-    ccx.impl_method_cache.borrow_mut().insert((impl_id, name), meth.def_id);
-    meth.def_id
+    ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did);
+    *meth_did
 }
 
 fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
@@ -247,7 +247,7 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
                                   -> Callee<'a> {
     let _icx = push_ctxt("meth::trans_monomorphized_callee");
     match vtbl {
-      typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
+      typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
           let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
           let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
@@ -257,13 +257,13 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
           let (callee_substs, callee_origins) =
               combine_impl_and_methods_tps(
                   bcx, mth_id,  MethodCall(method_call),
-                  rcvr_substs.as_slice(), rcvr_origins);
+                  rcvr_substs, rcvr_origins);
 
           // translate the function
           let llfn = trans_fn_ref_with_vtables(bcx,
                                                mth_id,
                                                MethodCall(method_call),
-                                               callee_substs.as_slice(),
+                                               callee_substs,
                                                Some(callee_origins));
 
           Callee { bcx: bcx, data: Fn(llfn) }
@@ -277,9 +277,9 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
 fn combine_impl_and_methods_tps(bcx: &Block,
                                 mth_did: ast::DefId,
                                 node: ExprOrMethodCall,
-                                rcvr_substs: &[ty::t],
+                                rcvr_substs: Vec<ty::t>,
                                 rcvr_origins: typeck::vtable_res)
-                                -> (Vec<ty::t> , typeck::vtable_res) {
+                                -> (Vec<ty::t>, typeck::vtable_res) {
     /*!
     *
     * Creates a concatenated set of substitutions which includes
@@ -302,10 +302,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
     let n_m_tps = method.generics.type_param_defs().len();
     let node_substs = node_id_type_params(bcx, node);
     debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
-    let ty_substs
-        = Vec::from_slice(rcvr_substs).append(node_substs.tailn(node_substs.len() - n_m_tps));
-    debug!("n_m_tps={:?}", n_m_tps);
     debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
+    let mut ty_substs = rcvr_substs;
+    {
+        let start = node_substs.len() - n_m_tps;
+        ty_substs.extend(node_substs.move_iter().skip(start));
+    }
+    debug!("n_m_tps={:?}", n_m_tps);
     debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx()));
 
 
@@ -315,14 +318,20 @@ fn combine_impl_and_methods_tps(bcx: &Block,
         ExprId(id) => MethodCall::expr(id),
         MethodCall(method_call) => method_call
     };
-    let vtables = node_vtables(bcx, vtable_key);
-    let r_m_origins = match vtables {
-        Some(vt) => vt,
-        None => @Vec::from_elem(node_substs.len(), @Vec::new())
-    };
-    let vtables
-        = @Vec::from_slice(rcvr_origins.as_slice())
-                           .append(r_m_origins.tailn(r_m_origins.len() - n_m_tps));
+    let mut vtables = rcvr_origins;
+    match node_vtables(bcx, vtable_key) {
+        Some(vt) => {
+            let start = vt.len() - n_m_tps;
+            vtables.extend(vt.move_iter().skip(start));
+        }
+        None => {
+            vtables.extend(range(0, n_m_tps).map(
+                |_| -> typeck::vtable_param_res {
+                    Vec::new()
+                }
+            ));
+        }
+    }
 
     (ty_substs, vtables)
 }
@@ -418,83 +427,50 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
     };
 }
 
-pub fn vtable_id(ccx: &CrateContext,
-                 origin: &typeck::vtable_origin)
-              -> mono_id {
-    match origin {
-        &typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
-            let psubsts = param_substs {
-                tys: (*substs).clone(),
-                vtables: Some(sub_vtables),
-                self_ty: None,
-                self_vtables: None
-            };
-
-            monomorphize::make_mono_id(
-                ccx,
-                impl_id,
-                &psubsts)
-        }
-
-        // can't this be checked at the callee?
-        _ => fail!("vtable_id")
-    }
-}
-
 /// Creates a returns a dynamic vtable for the given type and vtable origin.
 /// This is used only for objects.
-pub fn get_vtable(bcx: &Block,
-                  self_ty: ty::t,
-                  origins: typeck::vtable_param_res)
-                  -> ValueRef {
+fn get_vtable(bcx: &Block,
+              self_ty: ty::t,
+              origins: typeck::vtable_param_res)
+              -> ValueRef {
     let ccx = bcx.ccx();
     let _icx = push_ctxt("meth::get_vtable");
 
     // Check the cache.
-    let hash_id = (self_ty, vtable_id(ccx, origins.get(0)));
+    let hash_id = (self_ty, monomorphize::make_vtable_id(ccx, origins.get(0)));
     match ccx.vtables.borrow().find(&hash_id) {
         Some(&val) => { return val }
         None => { }
     }
 
     // Not in the cache. Actually build it.
-    let mut methods = Vec::new();
-    for origin in origins.iter() {
-        match *origin {
-            typeck::vtable_static(id, ref substs, sub_vtables) => {
-                let vtable_methods = emit_vtable_methods(bcx,
-                                                         id,
-                                                         substs.as_slice(),
-                                                         sub_vtables);
-                for vtable_method in vtable_methods.move_iter() {
-                    methods.push(vtable_method)
-                }
+    let methods = origins.move_iter().flat_map(|origin| {
+        match origin {
+            typeck::vtable_static(id, substs, sub_vtables) => {
+                emit_vtable_methods(bcx, id, substs, sub_vtables).move_iter()
             }
             _ => ccx.sess().bug("get_vtable: expected a static origin"),
         }
-    }
+    });
 
     // Generate a destructor for the vtable.
     let drop_glue = glue::get_drop_glue(ccx, self_ty);
-    let vtable = make_vtable(ccx, drop_glue, methods.as_slice());
+    let vtable = make_vtable(ccx, drop_glue, methods);
 
     ccx.vtables.borrow_mut().insert(hash_id, vtable);
-    return vtable;
+    vtable
 }
 
 /// Helper function to declare and initialize the vtable.
-pub fn make_vtable(ccx: &CrateContext,
-                   drop_glue: ValueRef,
-                   ptrs: &[ValueRef])
-                   -> ValueRef {
-    unsafe {
-        let _icx = push_ctxt("meth::make_vtable");
+pub fn make_vtable<I: Iterator<ValueRef>>(ccx: &CrateContext,
+                                          drop_glue: ValueRef,
+                                          ptrs: I)
+                                          -> ValueRef {
+    let _icx = push_ctxt("meth::make_vtable");
 
-        let mut components = vec!(drop_glue);
-        for &ptr in ptrs.iter() {
-            components.push(ptr)
-        }
+    let components: Vec<_> = Some(drop_glue).move_iter().chain(ptrs).collect();
 
+    unsafe {
         let tbl = C_struct(ccx, components.as_slice(), false);
         let sym = token::gensym("vtable");
         let vt_gvar = format!("vtable{}", sym).with_c_str(|buf| {
@@ -509,7 +485,7 @@ pub fn make_vtable(ccx: &CrateContext,
 
 fn emit_vtable_methods(bcx: &Block,
                        impl_id: ast::DefId,
-                       substs: &[ty::t],
+                       substs: Vec<ty::t>,
                        vtables: typeck::vtable_res)
                        -> Vec<ValueRef> {
     let ccx = bcx.ccx();
@@ -539,7 +515,8 @@ fn emit_vtable_methods(bcx: &Block,
                    token::get_ident(ident));
             C_null(Type::nil(ccx).ptr_to())
         } else {
-            trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), substs, Some(vtables))
+            trans_fn_ref_with_vtables(bcx, m_id, ExprId(0),
+                                      substs.clone(), Some(vtables.clone()))
         }
     }).collect()
 }
@@ -576,8 +553,12 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
     bcx = datum.store_to(bcx, llboxdest);
 
     // Store the vtable into the second half of pair.
-    let res = *ccx.maps.vtable_map.borrow().get(&MethodCall::expr(id));
-    let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0);
+    let origins = {
+        let vtable_map = ccx.tcx.vtable_map.borrow();
+        resolve_param_vtables_under_param_substs(ccx.tcx(),
+            bcx.fcx.param_substs,
+            vtable_map.get(&MethodCall::expr(id)).get(0).as_slice())
+    };
     let vtable = get_vtable(bcx, v_ty, origins);
     let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
     let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 7d7ea5a2211..aa6e2dafd83 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -16,7 +16,6 @@ use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use middle::trans::base::{trans_fn, decl_internal_rust_fn};
 use middle::trans::base;
 use middle::trans::common::*;
-use middle::trans::meth;
 use middle::trans::intrinsic;
 use middle::ty;
 use middle::typeck;
@@ -26,7 +25,7 @@ use syntax::abi;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::local_def;
-use std::hash::sip;
+use std::hash::{sip, Hash};
 
 pub fn monomorphic_fn(ccx: &CrateContext,
                       fn_id: ast::DefId,
@@ -47,26 +46,51 @@ pub fn monomorphic_fn(ccx: &CrateContext,
            self_vtables.repr(ccx.tcx()),
            ref_id);
 
-    assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
+    assert!(real_substs.tps.iter().all(|t| {
+        !ty::type_needs_infer(*t) && !ty::type_has_params(*t)
+    }));
+
     let _icx = push_ctxt("monomorphic_fn");
-    let mut must_cast = false;
 
-    let psubsts = @param_substs {
+    let substs_iter = real_substs.self_ty.iter().chain(real_substs.tps.iter());
+    let param_ids: Vec<MonoParamId> = match vtables {
+        Some(ref vts) => {
+            debug!("make_mono_id vtables={} psubsts={}",
+                   vts.repr(ccx.tcx()), real_substs.tps.repr(ccx.tcx()));
+            let vts_iter = self_vtables.iter().chain(vts.iter());
+            vts_iter.zip(substs_iter).map(|(vtable, subst)| MonoParamId {
+                subst: *subst,
+                // Do we really need the vtables to be hashed? Isn't the type enough?
+                vtables: vtable.iter().map(|vt| make_vtable_id(ccx, vt)).collect()
+            }).collect()
+        }
+        None => substs_iter.map(|subst| MonoParamId {
+            subst: *subst,
+            vtables: Vec::new()
+        }).collect()
+    };
+
+    let hash_id = MonoId {
+        def: fn_id,
+        params: param_ids
+    };
+
+    match ccx.monomorphized.borrow().find(&hash_id) {
+        Some(&val) => {
+            debug!("leaving monomorphic fn {}",
+            ty::item_path_str(ccx.tcx(), fn_id));
+            return (val, false);
+        }
+        None => ()
+    }
+
+    let psubsts = param_substs {
         tys: real_substs.tps.clone(),
         vtables: vtables,
         self_ty: real_substs.self_ty.clone(),
         self_vtables: self_vtables
     };
 
-    for s in real_substs.tps.iter() { assert!(!ty::type_has_params(*s)); }
-    for s in psubsts.tys.iter() { assert!(!ty::type_has_params(*s)); }
-
-    let hash_id = make_mono_id(ccx, fn_id, &*psubsts);
-    if hash_id.params.iter().any(
-                |p| match *p { mono_precise(_, _) => false, _ => true }) {
-        must_cast = true;
-    }
-
     debug!("monomorphic_fn(\
             fn_id={}, \
             psubsts={}, \
@@ -75,15 +99,6 @@ pub fn monomorphic_fn(ccx: &CrateContext,
            psubsts.repr(ccx.tcx()),
            hash_id);
 
-    match ccx.monomorphized.borrow().find(&hash_id) {
-        Some(&val) => {
-            debug!("leaving monomorphic fn {}",
-            ty::item_path_str(ccx.tcx(), fn_id));
-            return (val, must_cast);
-        }
-        None => ()
-    }
-
     let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
     let llitem_ty = tpt.ty;
 
@@ -122,8 +137,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
 
     debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
     let mono_ty = match is_static_provided {
-        None => ty::subst_tps(ccx.tcx(), psubsts.tys.as_slice(),
-                              psubsts.self_ty, llitem_ty),
+        None => ty::subst_tps(ccx.tcx(), real_substs.tps.as_slice(),
+                              real_substs.self_ty, llitem_ty),
         Some(num_method_ty_params) => {
             // Static default methods are a little unfortunate, in
             // that the "internal" and "external" type of them differ.
@@ -139,9 +154,9 @@ pub fn monomorphic_fn(ccx: &CrateContext,
             // stick a substitution for the self type in.
             // This is a bit unfortunate.
 
-            let idx = psubsts.tys.len() - num_method_ty_params;
-            let substs = psubsts.tys.slice(0, idx) +
-                &[psubsts.self_ty.unwrap()] + psubsts.tys.tailn(idx);
+            let idx = real_substs.tps.len() - num_method_ty_params;
+            let substs = real_substs.tps.slice(0, idx) +
+            &[real_substs.self_ty.unwrap()] + real_substs.tps.tailn(idx);
             debug!("static default: changed substitution to {}",
                    substs.repr(ccx.tcx()));
 
@@ -178,16 +193,22 @@ pub fn monomorphic_fn(ccx: &CrateContext,
     }
 
     let s = ccx.tcx.map.with_path(fn_id.node, |path| {
-        exported_name(path, format!("h{}", sip::hash(&(hash_id, mono_ty))),
+        let mut state = sip::SipState::new();
+        hash_id.hash(&mut state);
+        mono_ty.hash(&mut state);
+
+        exported_name(path, format!("h{}", state.result()),
                       ccx.link_meta.crateid.version_or_default())
     });
     debug!("monomorphize_fn mangled to {}", s);
 
+    // This shouldn't need to option dance.
+    let mut hash_id = Some(hash_id);
     let mk_lldecl = || {
         let lldecl = decl_internal_rust_fn(ccx, false,
                                            f.sig.inputs.as_slice(),
                                            f.sig.output, s);
-        ccx.monomorphized.borrow_mut().insert(hash_id, lldecl);
+        ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
         lldecl
     };
 
@@ -200,7 +221,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
               } => {
                   let d = mk_lldecl();
                   set_llvm_fn_attrs(i.attrs.as_slice(), d);
-                  trans_fn(ccx, decl, body, d, Some(psubsts), fn_id.node, []);
+                  trans_fn(ccx, decl, body, d, Some(&psubsts), fn_id.node, []);
                   d
               }
               _ => {
@@ -214,7 +235,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                 Some(decl) => decl,
                 None => {
                     let d = mk_lldecl();
-                    intrinsic::trans_intrinsic(ccx, d, i, psubsts, ref_id);
+                    intrinsic::trans_intrinsic(ccx, d, i, &psubsts, ref_id);
                     d
                 }
             }
@@ -222,7 +243,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeVariant(v) => {
             let parent = ccx.tcx.map.get_parent(fn_id.node);
             let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
-            let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
+            let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
             let d = mk_lldecl();
             set_inline_hint(d);
             match v.node.kind {
@@ -232,7 +253,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                                        v,
                                        args.as_slice(),
                                        this_tv.disr_val,
-                                       Some(psubsts),
+                                       Some(&psubsts),
                                        d);
                 }
                 ast::StructVariantKind(_) =>
@@ -243,7 +264,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeMethod(mth) => {
             let d = mk_lldecl();
             set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-            trans_fn(ccx, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
+            trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
             d
         }
         ast_map::NodeTraitMethod(method) => {
@@ -251,7 +272,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                 ast::Provided(mth) => {
                     let d = mk_lldecl();
                     set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-                    trans_fn(ccx, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
+                    trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
                     d
                 }
                 _ => {
@@ -267,7 +288,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                                      struct_def.fields.as_slice(),
                                      struct_def.ctor_id.expect("ast-mapped tuple struct \
                                                                 didn't have a ctor id"),
-                                     Some(psubsts),
+                                     Some(&psubsts),
                                      d);
             d
         }
@@ -286,32 +307,41 @@ pub fn monomorphic_fn(ccx: &CrateContext,
     ccx.monomorphizing.borrow_mut().insert(fn_id, depth);
 
     debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
-    (lldecl, must_cast)
+    (lldecl, false)
 }
 
-pub fn make_mono_id(ccx: &CrateContext,
-                    item: ast::DefId,
-                    substs: &param_substs) -> mono_id {
-    // FIXME (possibly #5801): Need a lot of type hints to get
-    // .collect() to work.
-    let substs_iter = substs.self_ty.iter().chain(substs.tys.iter());
-    let precise_param_ids: Vec<(ty::t, Option<@Vec<mono_id> >)> = match substs.vtables {
-      Some(vts) => {
-        debug!("make_mono_id vtables={} substs={}",
-               vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx()));
-        let vts_iter = substs.self_vtables.iter().chain(vts.iter());
-        vts_iter.zip(substs_iter).map(|(vtable, subst)| {
-            let v = vtable.iter().map(|vt| meth::vtable_id(ccx, vt)).collect::<Vec<_>>();
-            (*subst, if !v.is_empty() { Some(@v) } else { None })
-        }).collect()
-      }
-      None => substs_iter.map(|subst| (*subst, None::<@Vec<mono_id> >)).collect()
-    };
+// Used to identify cached monomorphized functions and vtables
+#[deriving(Eq, TotalEq, Hash)]
+pub struct MonoParamId {
+    pub subst: ty::t,
+    // Do we really need the vtables to be hashed? Isn't the type enough?
+    pub vtables: Vec<MonoId>
+}
 
+#[deriving(Eq, TotalEq, Hash)]
+pub struct MonoId {
+    pub def: ast::DefId,
+    pub params: Vec<MonoParamId>
+}
 
-    let param_ids = precise_param_ids.iter().map(|x| {
-        let (a, b) = *x;
-        mono_precise(a, b)
-    }).collect();
-    @mono_id_ {def: item, params: param_ids}
+pub fn make_vtable_id(ccx: &CrateContext,
+                      origin: &typeck::vtable_origin)
+                      -> MonoId {
+    match origin {
+        &typeck::vtable_static(impl_id, ref substs, ref sub_vtables) => {
+            MonoId {
+                def: impl_id,
+                params: sub_vtables.iter().zip(substs.iter()).map(|(vtable, subst)| {
+                    MonoParamId {
+                        subst: *subst,
+                        // Do we really need the vtables to be hashed? Isn't the type enough?
+                        vtables: vtable.iter().map(|vt| make_vtable_id(ccx, vt)).collect()
+                    }
+                }).collect()
+            }
+        }
+
+        // can't this be checked at the callee?
+        _ => fail!("make_vtable_id needs vtable_static")
+    }
 }
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 7dc4641e97f..a1752862715 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -25,6 +25,7 @@ use middle::trans::type_of::*;
 use middle::ty;
 use util::ppaux::ty_to_str;
 
+use std::rc::Rc;
 use arena::TypedArena;
 use libc::c_uint;
 use syntax::ast::DefId;
@@ -33,15 +34,15 @@ use syntax::ast_map;
 use syntax::parse::token::{InternedString, special_idents};
 use syntax::parse::token;
 
-pub struct Reflector<'a> {
+pub struct Reflector<'a, 'b> {
     visitor_val: ValueRef,
-    visitor_methods: @Vec<@ty::Method> ,
-    final_bcx: &'a Block<'a>,
+    visitor_methods: &'a [Rc<ty::Method>],
+    final_bcx: &'b Block<'b>,
     tydesc_ty: Type,
-    bcx: &'a Block<'a>
+    bcx: &'b Block<'b>
 }
 
-impl<'a> Reflector<'a> {
+impl<'a, 'b> Reflector<'a, 'b> {
     pub fn c_uint(&mut self, u: uint) -> ValueRef {
         C_uint(self.bcx.ccx(), u)
     }
@@ -75,7 +76,7 @@ impl<'a> Reflector<'a> {
     pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef {
         let bcx = self.bcx;
         let static_ti = get_tydesc(bcx.ccx(), t);
-        glue::lazily_emit_visit_glue(bcx.ccx(), static_ti);
+        glue::lazily_emit_visit_glue(bcx.ccx(), &*static_ti);
         PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to())
     }
 
@@ -92,7 +93,7 @@ impl<'a> Reflector<'a> {
                 format!("couldn't find visit method for {}", ty_name));
         let mth_ty =
             ty::mk_bare_fn(tcx,
-                           self.visitor_methods.get(mth_idx).fty.clone());
+                           self.visitor_methods[mth_idx].fty.clone());
         let v = self.visitor_val;
         debug!("passing {} args:", args.len());
         let mut bcx = self.bcx;
@@ -307,7 +308,7 @@ impl<'a> Reflector<'a> {
                 let arena = TypedArena::new();
                 let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
                                       ty::mk_u64(), None, None, &arena);
-                init_function(&fcx, false, ty::mk_u64(), None);
+                init_function(&fcx, false, ty::mk_u64());
 
                 let arg = unsafe {
                     //
@@ -319,7 +320,7 @@ impl<'a> Reflector<'a> {
                 };
                 let bcx = fcx.entry_bcx.borrow().clone().unwrap();
                 let arg = BitCast(bcx, arg, llptrty);
-                let ret = adt::trans_get_discr(bcx, repr, arg, Some(Type::i64(ccx)));
+                let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx)));
                 Store(bcx, ret, fcx.llretptr.get().unwrap());
                 match fcx.llreturn.get() {
                     Some(llreturn) => Br(bcx, llreturn),
@@ -344,7 +345,7 @@ impl<'a> Reflector<'a> {
                         for (j, a) in v.args.iter().enumerate() {
                             let bcx = this.bcx;
                             let null = C_null(llptrty);
-                            let ptr = adt::trans_field_ptr(bcx, repr, null, v.disr_val, j);
+                            let ptr = adt::trans_field_ptr(bcx, &*repr, null, v.disr_val, j);
                             let offset = p2i(ccx, ptr);
                             let field_args = [this.c_uint(j),
                                                offset,
@@ -401,9 +402,10 @@ pub fn emit_calls_to_trait_visit_ty<'a>(
     let final = fcx.new_temp_block("final");
     let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
+    let visitor_methods = ty::trait_methods(bcx.tcx(), visitor_trait_id);
     let mut r = Reflector {
         visitor_val: visitor_val,
-        visitor_methods: ty::trait_methods(bcx.tcx(), visitor_trait_id),
+        visitor_methods: visitor_methods.as_slice(),
         final_bcx: final,
         tydesc_ty: tydesc_ty,
         bcx: bcx
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 48c25fb985d..0a539d5e6c6 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -142,7 +142,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
 
         ty::ty_tup(..) | ty::ty_enum(..) => {
             let repr = adt::represent_type(cx, t);
-            adt::sizing_type_of(cx, repr)
+            adt::sizing_type_of(cx, &*repr)
         }
 
         ty::ty_struct(..) => {
@@ -152,7 +152,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
                 Type::vector(&type_of(cx, et), n as u64)
             } else {
                 let repr = adt::represent_type(cx, t);
-                adt::sizing_type_of(cx, repr)
+                adt::sizing_type_of(cx, &*repr)
             }
         }
 
@@ -213,7 +213,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
         // of the enum's variants refers to the enum itself.
         let repr = adt::represent_type(cx, t);
         let name = llvm_type_name(cx, an_enum, did, substs.tps.as_slice());
-        adt::incomplete_type_of(cx, repr, name)
+        adt::incomplete_type_of(cx, &*repr, name)
       }
       ty::ty_box(typ) => {
           Type::at_box(cx, type_of(cx, typ)).ptr_to()
@@ -259,7 +259,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       ty::ty_trait(..) => Type::opaque_trait(cx),
       ty::ty_tup(..) => {
           let repr = adt::represent_type(cx, t);
-          adt::type_of(cx, repr)
+          adt::type_of(cx, &*repr)
       }
       ty::ty_struct(did, ref substs) => {
           if ty::type_is_simd(cx.tcx(), t) {
@@ -275,7 +275,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
                                         a_struct,
                                         did,
                                         substs.tps.as_slice());
-              adt::incomplete_type_of(cx, repr, name)
+              adt::incomplete_type_of(cx, &*repr, name)
           }
       }
 
@@ -297,7 +297,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
     match ty::get(t).sty {
         ty::ty_enum(..) | ty::ty_struct(..) if !ty::type_is_simd(cx.tcx(), t) => {
             let repr = adt::represent_type(cx, t);
-            adt::finish_type_of(cx, repr, &mut llty);
+            adt::finish_type_of(cx, &*repr, &mut llty);
         }
         _ => ()
     }
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index 565805446f7..8f114827bfd 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -34,7 +34,7 @@ pub fn root_and_write_guard<'a, K:KindOps>(datum: &Datum<K>,
     //
     // (Note: root'd values are always boxes)
     let ccx = bcx.ccx();
-    match ccx.maps.root_map.borrow().find(&key) {
+    match ccx.maps.root_map.find(&key) {
         None => bcx,
         Some(&root_info) => root(datum, bcx, span, key, root_info)
     }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 379ec57affc..9a3bdcc1e15 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -22,7 +22,7 @@ use middle::resolve_lifetime;
 use middle::ty;
 use middle::subst::Subst;
 use middle::typeck;
-use middle::typeck::{MethodCall, MethodCallee, MethodMap};
+use middle::typeck::MethodCall;
 use middle::ty_fold;
 use middle::ty_fold::TypeFolder;
 use middle;
@@ -38,9 +38,11 @@ use std::cmp;
 use std::fmt::Show;
 use std::fmt;
 use std::hash::{Hash, sip};
+use std::iter::AdditiveIterator;
 use std::ops;
 use std::rc::Rc;
 use collections::{HashMap, HashSet};
+use syntax::abi;
 use syntax::ast::*;
 use syntax::ast_util::{is_local, lit_is_str};
 use syntax::ast_util;
@@ -51,7 +53,7 @@ use syntax::parse::token;
 use syntax::parse::token::InternedString;
 use syntax::{ast, ast_map};
 use syntax::owned_slice::OwnedSlice;
-use syntax::abi;
+use syntax::util::small_vector::SmallVector;
 use collections::enum_set::{EnumSet, CLike};
 
 pub type Disr = u64;
@@ -116,12 +118,6 @@ impl Method {
     }
 }
 
-pub struct Impl {
-    pub did: DefId,
-    pub ident: Ident,
-    pub methods: Vec<@Method>,
-}
-
 #[deriving(Clone, Eq, TotalEq, Hash)]
 pub struct mt {
     pub ty: t,
@@ -212,6 +208,7 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
+#[deriving(Clone)]
 pub enum AutoAdjustment {
     AutoAddEnv(ty::TraitStore),
     AutoDerefRef(AutoDerefRef),
@@ -221,13 +218,13 @@ pub enum AutoAdjustment {
                ty::substs /* Trait substitutions */)
 }
 
-#[deriving(Decodable, Encodable)]
+#[deriving(Clone, Decodable, Encodable)]
 pub struct AutoDerefRef {
     pub autoderefs: uint,
     pub autoref: Option<AutoRef>
 }
 
-#[deriving(Decodable, Encodable, Eq, Show)]
+#[deriving(Clone, Decodable, Encodable, Eq, Show)]
 pub enum AutoRef {
     /// Convert from T to &T
     AutoPtr(Region, ast::Mutability),
@@ -272,18 +269,18 @@ pub struct ctxt {
     pub node_type_substs: RefCell<NodeMap<Vec<t>>>,
 
     // Maps from a method to the method "descriptor"
-    pub methods: RefCell<DefIdMap<@Method>>,
+    pub methods: RefCell<DefIdMap<Rc<Method>>>,
 
     // Maps from a trait def-id to a list of the def-ids of its methods
-    pub trait_method_def_ids: RefCell<DefIdMap<@Vec<DefId> >>,
+    pub trait_method_def_ids: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
 
     // A cache for the trait_methods() routine
-    pub trait_methods_cache: RefCell<DefIdMap<@Vec<@Method> >>,
+    pub trait_methods_cache: RefCell<DefIdMap<Rc<Vec<Rc<Method>>>>>,
 
-    pub impl_trait_cache: RefCell<DefIdMap<Option<@ty::TraitRef>>>,
+    pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
 
-    pub trait_refs: RefCell<NodeMap<@TraitRef>>,
-    pub trait_defs: RefCell<DefIdMap<@TraitDef>>,
+    pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
+    pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
 
     pub map: ast_map::Map,
     pub intrinsic_defs: RefCell<DefIdMap<t>>,
@@ -294,20 +291,20 @@ pub struct ctxt {
     pub needs_unwind_cleanup_cache: RefCell<HashMap<t, bool>>,
     pub tc_cache: RefCell<HashMap<uint, TypeContents>>,
     pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry>>,
-    pub enum_var_cache: RefCell<DefIdMap<@Vec<@VariantInfo> >>,
+    pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo>>>>>,
     pub ty_param_defs: RefCell<NodeMap<TypeParameterDef>>,
-    pub adjustments: RefCell<NodeMap<@AutoAdjustment>>,
+    pub adjustments: RefCell<NodeMap<AutoAdjustment>>,
     pub normalized_cache: RefCell<HashMap<t, t>>,
-    pub lang_items: @middle::lang_items::LanguageItems,
+    pub lang_items: middle::lang_items::LanguageItems,
     // A mapping of fake provided method def_ids to the default implementation
     pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
-    pub supertraits: RefCell<DefIdMap<@Vec<@TraitRef> >>,
+    pub supertraits: RefCell<DefIdMap<Rc<Vec<Rc<TraitRef>>>>>,
     pub superstructs: RefCell<DefIdMap<Option<ast::DefId>>>,
-    pub struct_fields: RefCell<DefIdMap<@Vec<field_ty>>>,
+    pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
 
     // Maps from def-id of a type or region parameter to its
     // (inferred) variance.
-    pub item_variance_map: RefCell<DefIdMap<@ItemVariances>>,
+    pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
 
     // A mapping from the def ID of an enum or struct type to the def ID
     // of the method that implements its destructor. If the type is not
@@ -319,18 +316,18 @@ pub struct ctxt {
     pub destructors: RefCell<DefIdSet>,
 
     // Maps a trait onto a list of impls of that trait.
-    pub trait_impls: RefCell<DefIdMap<@RefCell<Vec<@Impl> >>>,
+    pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
 
-    // Maps a def_id of a type to a list of its inherent impls.
+    // Maps a DefId of a type to a list of its inherent impls.
     // Contains implementations of methods that are inherent to a type.
     // Methods in these implementations don't need to be exported.
-    pub inherent_impls: RefCell<DefIdMap<@RefCell<Vec<@Impl> >>>,
+    pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
 
-    // Maps a def_id of an impl to an Impl structure.
+    // Maps a DefId of an impl to a list of its methods.
     // Note that this contains all of the impls that we know about,
     // including ones in other crates. It's not clear that this is the best
     // way to do it.
-    pub impls: RefCell<DefIdMap<@Impl>>,
+    pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
 
     // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
     // present in this set can be warned about.
@@ -359,6 +356,9 @@ pub struct ctxt {
     // and variants that are found.
     pub extern_const_statics: RefCell<DefIdMap<Option<@ast::Expr>>>,
     pub extern_const_variants: RefCell<DefIdMap<Option<@ast::Expr>>>,
+
+    pub method_map: typeck::MethodMap,
+    pub vtable_map: typeck::vtable_map,
 }
 
 pub enum tbox_flag {
@@ -816,7 +816,6 @@ pub enum type_err {
     terr_regions_overly_polymorphic(BoundRegion, Region),
     terr_vstores_differ(terr_vstore_kind, expected_found<Vstore>),
     terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
-    terr_in_field(@type_err, ast::Ident),
     terr_sorts(expected_found<t>),
     terr_integer_as_char,
     terr_int_mismatch(expected_found<IntVarValue>),
@@ -829,7 +828,8 @@ pub enum type_err {
 #[deriving(Eq, TotalEq, Hash)]
 pub struct ParamBounds {
     pub builtin_bounds: BuiltinBounds,
-    pub trait_bounds: Vec<@TraitRef> }
+    pub trait_bounds: Vec<Rc<TraitRef>>
+}
 
 pub type BuiltinBounds = EnumSet<BuiltinBound>;
 
@@ -983,7 +983,7 @@ impl fmt::Show for IntVarValue {
 pub struct TypeParameterDef {
     pub ident: ast::Ident,
     pub def_id: ast::DefId,
-    pub bounds: @ParamBounds,
+    pub bounds: Rc<ParamBounds>,
     pub default: Option<ty::t>
 }
 
@@ -1038,7 +1038,7 @@ pub struct ParameterEnvironment {
     pub free_substs: ty::substs,
 
     /// Bound on the Self parameter
-    pub self_param_bound: Option<@TraitRef>,
+    pub self_param_bound: Option<Rc<TraitRef>>,
 
     /// Bounds on each numbered type parameter
     pub type_param_bounds: Vec<ParamBounds> ,
@@ -1064,7 +1064,7 @@ pub struct ty_param_bounds_and_ty {
 pub struct TraitDef {
     pub generics: Generics,
     pub bounds: BuiltinBounds,
-    pub trait_ref: @ty::TraitRef,
+    pub trait_ref: Rc<ty::TraitRef>,
 }
 
 pub struct ty_param_substs_and_ty {
@@ -1082,7 +1082,7 @@ pub fn mk_ctxt(s: Session,
                map: ast_map::Map,
                freevars: freevars::freevar_map,
                region_maps: middle::region::RegionMaps,
-               lang_items: @middle::lang_items::LanguageItems)
+               lang_items: middle::lang_items::LanguageItems)
             -> ctxt {
     ctxt {
         named_region_map: named_region_map,
@@ -1122,7 +1122,7 @@ pub fn mk_ctxt(s: Session,
         destructors: RefCell::new(DefIdSet::new()),
         trait_impls: RefCell::new(DefIdMap::new()),
         inherent_impls: RefCell::new(DefIdMap::new()),
-        impls: RefCell::new(DefIdMap::new()),
+        impl_methods: RefCell::new(DefIdMap::new()),
         used_unsafe: RefCell::new(NodeSet::new()),
         used_mut_nodes: RefCell::new(NodeSet::new()),
         impl_vtables: RefCell::new(DefIdMap::new()),
@@ -1131,6 +1131,8 @@ pub fn mk_ctxt(s: Session,
         upvar_borrow_map: RefCell::new(HashMap::new()),
         extern_const_statics: RefCell::new(DefIdMap::new()),
         extern_const_variants: RefCell::new(DefIdMap::new()),
+        method_map: RefCell::new(FnvHashMap::new()),
+        vtable_map: RefCell::new(FnvHashMap::new()),
     }
 }
 
@@ -2174,7 +2176,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
                 // Self may be bounded if the associated trait has builtin kinds
                 // for supertraits. If so we can use those bounds.
                 let trait_def = lookup_trait_def(cx, def_id);
-                let traits = [trait_def.trait_ref];
+                let traits = [trait_def.trait_ref.clone()];
                 kind_bounds_to_contents(cx, trait_def.bounds, traits)
             }
 
@@ -2271,7 +2273,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
 
     fn kind_bounds_to_contents(cx: &ctxt,
                                bounds: BuiltinBounds,
-                               traits: &[@TraitRef])
+                               traits: &[Rc<TraitRef>])
                                -> TypeContents {
         let _i = indenter();
         let mut tc = TC::All;
@@ -2290,7 +2292,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
         // those inherited from traits with builtin-kind-supertraits.
         fn each_inherited_builtin_bound(cx: &ctxt,
                                         bounds: BuiltinBounds,
-                                        traits: &[@TraitRef],
+                                        traits: &[Rc<TraitRef>],
                                         f: |BuiltinBound|) {
             for bound in bounds.iter() {
                 f(bound);
@@ -2656,12 +2658,12 @@ pub fn index(t: t) -> Option<mt> {
     }
 }
 
-pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> @ty::TraitRef {
+pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> Rc<ty::TraitRef> {
     match cx.trait_refs.borrow().find(&id) {
-       Some(&t) => t,
-       None => cx.sess.bug(
-           format!("node_id_to_trait_ref: no trait ref for node `{}`",
-               cx.map.node_to_str(id)))
+        Some(t) => t.clone(),
+        None => cx.sess.bug(
+            format!("node_id_to_trait_ref: no trait ref for node `{}`",
+                cx.map.node_to_str(id)))
     }
 }
 
@@ -2791,10 +2793,7 @@ pub fn expr_ty_opt(cx: &ctxt, expr: &ast::Expr) -> Option<t> {
     return node_id_to_type_opt(cx, expr.id);
 }
 
-pub fn expr_ty_adjusted(cx: &ctxt,
-                        expr: &ast::Expr,
-                        method_map: &FnvHashMap<MethodCall, MethodCallee>)
-                        -> t {
+pub fn expr_ty_adjusted(cx: &ctxt, expr: &ast::Expr) -> t {
     /*!
      *
      * Returns the type of `expr`, considering any `AutoAdjustment`
@@ -2808,11 +2807,9 @@ pub fn expr_ty_adjusted(cx: &ctxt,
      * task at hand! -nmatsakis
      */
 
-    let unadjusted_ty = expr_ty(cx, expr);
-    let adjustment = cx.adjustments.borrow().find_copy(&expr.id);
-    adjust_ty(cx, expr.span, expr.id, unadjusted_ty, adjustment, |method_call| {
-        method_map.find(&method_call).map(|method| method.ty)
-    })
+    adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
+              cx.adjustments.borrow().find(&expr.id),
+              |method_call| cx.method_map.borrow().find(&method_call).map(|method| method.ty))
 }
 
 pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
@@ -2857,8 +2854,8 @@ pub fn adjust_ty(cx: &ctxt,
                  span: Span,
                  expr_id: ast::NodeId,
                  unadjusted_ty: ty::t,
-                 adjustment: Option<@AutoAdjustment>,
-                 method_type: |MethodCall| -> Option<ty::t>)
+                 adjustment: Option<&AutoAdjustment>,
+                 method_type: |typeck::MethodCall| -> Option<ty::t>)
                  -> ty::t {
     /*! See `expr_ty_adjusted` */
 
@@ -2890,7 +2887,8 @@ pub fn adjust_ty(cx: &ctxt,
 
                     if !ty::type_is_error(adjusted_ty) {
                         for i in range(0, adj.autoderefs) {
-                            match method_type(MethodCall::autoderef(expr_id, i as u32)) {
+                            let method_call = typeck::MethodCall::autoderef(expr_id, i as u32);
+                            match method_type(method_call) {
                                 Some(method_ty) => {
                                     adjusted_ty = ty_fn_ret(method_ty);
                                 }
@@ -3051,8 +3049,8 @@ pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
             // method bounds, so we must preprend the tps from the
             // trait itself.  This ought to be harmonized.
             let trait_type_param_defs =
-                lookup_trait_def(tcx, trt_id).generics.type_param_defs();
-            Rc::new(Vec::from_slice(trait_type_param_defs).append(
+                Vec::from_slice(lookup_trait_def(tcx, trt_id).generics.type_param_defs());
+            Rc::new(trait_type_param_defs.append(
                         ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs()))
         }
     }
@@ -3068,10 +3066,8 @@ pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> ast::Def {
     }
 }
 
-pub fn expr_is_lval(tcx: &ctxt,
-                    method_map: MethodMap,
-                    e: &ast::Expr) -> bool {
-    match expr_kind(tcx, method_map, e) {
+pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
+    match expr_kind(tcx, e) {
         LvalueExpr => true,
         RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
     }
@@ -3089,10 +3085,8 @@ pub enum ExprKind {
     RvalueStmtExpr
 }
 
-pub fn expr_kind(tcx: &ctxt,
-                 method_map: MethodMap,
-                 expr: &ast::Expr) -> ExprKind {
-    if method_map.borrow().contains_key(&MethodCall::expr(expr.id)) {
+pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
+    if tcx.method_map.borrow().contains_key(&typeck::MethodCall::expr(expr.id)) {
         // Overloaded operations are generally calls, and hence they are
         // generated via DPS, but there are two exceptions:
         return match expr.node {
@@ -3236,7 +3230,7 @@ pub fn expr_kind(tcx: &ctxt,
             }
         }
 
-        ast::ExprParen(e) => expr_kind(tcx, method_map, e),
+        ast::ExprParen(e) => expr_kind(tcx, e),
 
         ast::ExprMac(..) => {
             tcx.sess.span_bug(
@@ -3265,7 +3259,7 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
         fields.iter().map(|f| token::get_ident(f.ident).get().to_str()).collect::<Vec<~str>>()));
 }
 
-pub fn method_idx(id: ast::Ident, meths: &[@Method]) -> Option<uint> {
+pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
     meths.iter().position(|m| m.ident == id)
 }
 
@@ -3417,10 +3411,6 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~str {
                  trait_store_to_str(cx, (*values).expected),
                  trait_store_to_str(cx, (*values).found))
         }
-        terr_in_field(err, fname) => {
-            format!("in field `{}`, {}", token::get_ident(fname),
-                 type_err_to_str(cx, err))
-        }
         terr_sorts(values) => {
             format!("expected {} but found {}",
                  ty_sort_str(cx, values.expected),
@@ -3500,42 +3490,29 @@ pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
     cx.provided_method_sources.borrow().find(&id).map(|x| *x)
 }
 
-pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<@Method> {
+pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
     if is_local(id) {
-        {
-            match cx.map.find(id.node) {
-                Some(ast_map::NodeItem(item)) => {
-                    match item.node {
-                        ItemTrait(_, _, ref ms) => {
-                            let (_, p) =
-                                ast_util::split_trait_methods(ms.as_slice());
-                            p.iter()
-                             .map(|m| method(cx, ast_util::local_def(m.id)))
-                             .collect()
-                        }
-                        _ => {
-                            cx.sess.bug(format!("provided_trait_methods: \
-                                                 `{:?}` is not a trait",
-                                                id))
-                        }
+        match cx.map.find(id.node) {
+            Some(ast_map::NodeItem(item)) => {
+                match item.node {
+                    ItemTrait(_, _, ref ms) => {
+                        let (_, p) = ast_util::split_trait_methods(ms.as_slice());
+                        p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
                     }
-                }
-                _ => {
-                    cx.sess.bug(format!("provided_trait_methods: `{:?}` is not \
-                                         a trait",
-                                        id))
+                    _ => cx.sess.bug(format!("provided_trait_methods: `{}` is not a trait", id))
                 }
             }
+            _ => cx.sess.bug(format!("provided_trait_methods: `{}` is not a trait", id))
         }
     } else {
         csearch::get_provided_trait_methods(cx, id)
     }
 }
 
-pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
+pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<TraitRef>>> {
     // Check the cache.
     match cx.supertraits.borrow().find(&id) {
-        Some(&trait_refs) => { return trait_refs; }
+        Some(trait_refs) => { return trait_refs.clone(); }
         None => {}  // Continue.
     }
 
@@ -3545,12 +3522,12 @@ pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
 
     // Get the supertraits out of the metadata and create the
     // TraitRef for each.
-    let result = @csearch::get_supertraits(cx, id);
-    cx.supertraits.borrow_mut().insert(id, result);
-    return result;
+    let result = Rc::new(csearch::get_supertraits(cx, id));
+    cx.supertraits.borrow_mut().insert(id, result.clone());
+    result
 }
 
-pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec<@TraitRef> {
+pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec<Rc<TraitRef>> {
     let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
     supertrait_refs.iter().map(
         |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs)).collect()
@@ -3584,44 +3561,46 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
     v
 }
 
-pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> @Method {
+pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc<Method> {
     let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
     ty::method(cx, method_def_id)
 }
 
 
-pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> @Vec<@Method> {
+pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> Rc<Vec<Rc<Method>>> {
     let mut trait_methods = cx.trait_methods_cache.borrow_mut();
-    match trait_methods.find(&trait_did) {
-        Some(&methods) => methods,
+    match trait_methods.find_copy(&trait_did) {
+        Some(methods) => methods,
         None => {
             let def_ids = ty::trait_method_def_ids(cx, trait_did);
-            let methods = @def_ids.iter().map(|d| ty::method(cx, *d)).collect();
-            trait_methods.insert(trait_did, methods);
+            let methods: Rc<Vec<Rc<Method>>> = Rc::new(def_ids.iter().map(|d| {
+                ty::method(cx, *d)
+            }).collect());
+            trait_methods.insert(trait_did, methods.clone());
             methods
         }
     }
 }
 
-pub fn method(cx: &ctxt, id: ast::DefId) -> @Method {
+pub fn method(cx: &ctxt, id: ast::DefId) -> Rc<Method> {
     lookup_locally_or_in_crate_store("methods", id,
                                      &mut *cx.methods.borrow_mut(), || {
-        @csearch::get_method(cx, id)
+        Rc::new(csearch::get_method(cx, id))
     })
 }
 
-pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> @Vec<DefId> {
+pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> Rc<Vec<DefId>> {
     lookup_locally_or_in_crate_store("trait_method_def_ids",
                                      id,
                                      &mut *cx.trait_method_def_ids.borrow_mut(),
                                      || {
-        @csearch::get_trait_method_def_ids(&cx.sess.cstore, id)
+        Rc::new(csearch::get_trait_method_def_ids(&cx.sess.cstore, id))
     })
 }
 
-pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<@TraitRef> {
+pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<Rc<TraitRef>> {
     match cx.impl_trait_cache.borrow().find(&id) {
-        Some(&ret) => { return ret; }
+        Some(ret) => { return ret.clone(); }
         None => {}
     }
 
@@ -3647,8 +3626,8 @@ pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<@TraitRef> {
         csearch::get_impl_trait(cx, id)
     };
 
-    cx.impl_trait_cache.borrow_mut().insert(id, ret);
-    return ret;
+    cx.impl_trait_cache.borrow_mut().insert(id, ret.clone());
+    ret
 }
 
 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
@@ -3751,18 +3730,18 @@ impl VariantInfo {
 pub fn substd_enum_variants(cx: &ctxt,
                             id: ast::DefId,
                             substs: &substs)
-                         -> Vec<@VariantInfo> {
+                         -> Vec<Rc<VariantInfo>> {
     enum_variants(cx, id).iter().map(|variant_info| {
         let substd_args = variant_info.args.iter()
             .map(|aty| subst(cx, substs, *aty)).collect();
 
         let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
 
-        @VariantInfo {
+        Rc::new(VariantInfo {
             args: substd_args,
             ctor_ty: substd_ctor_ty,
             ..(**variant_info).clone()
-        }
+        })
     }).collect()
 }
 
@@ -3831,27 +3810,26 @@ pub fn type_is_empty(cx: &ctxt, t: t) -> bool {
      }
 }
 
-pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
+pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
     match cx.enum_var_cache.borrow().find(&id) {
-        Some(&variants) => return variants,
+        Some(variants) => return variants.clone(),
         _ => { /* fallthrough */ }
     }
 
     let result = if ast::LOCAL_CRATE != id.krate {
-        @csearch::get_enum_variants(cx, id)
+        Rc::new(csearch::get_enum_variants(cx, id))
     } else {
         /*
           Although both this code and check_enum_variants in typeck/check
           call eval_const_expr, it should never get called twice for the same
           expr, since check_enum_variants also updates the enum_var_cache
          */
-        {
-            match cx.map.get(id.node) {
-              ast_map::NodeItem(item) => {
-                  match item.node {
+        match cx.map.get(id.node) {
+            ast_map::NodeItem(item) => {
+                match item.node {
                     ast::ItemEnum(ref enum_definition, _) => {
                         let mut last_discriminant: Option<Disr> = None;
-                        @enum_definition.variants.iter().map(|&variant| {
+                        Rc::new(enum_definition.variants.iter().map(|&variant| {
 
                             let mut discriminant = match last_discriminant {
                                 Some(val) => val + 1,
@@ -3869,40 +3847,33 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
                                     Ok(_) => {
                                         cx.sess
                                           .span_err(e.span,
-                                                    "expected signed integer \
-                                                     constant");
+                                                    "expected signed integer constant");
                                     }
                                     Err(ref err) => {
                                         cx.sess
                                           .span_err(e.span,
-                                                    format!("expected \
-                                                             constant: {}",
+                                                    format!("expected constant: {}",
                                                             *err));
                                     }
                                 },
                                 None => {}
                             };
 
-                            let variant_info =
-                                @VariantInfo::from_ast_variant(cx,
-                                                               variant,
-                                                               discriminant);
                             last_discriminant = Some(discriminant);
-                            variant_info
-
-                        }).collect()
+                            Rc::new(VariantInfo::from_ast_variant(cx, variant,
+                                                                  discriminant))
+                        }).collect())
                     }
                     _ => {
                         cx.sess.bug("enum_variants: id not bound to an enum")
                     }
-                  }
-              }
-              _ => cx.sess.bug("enum_variants: id not bound to an enum")
+                }
             }
+            _ => cx.sess.bug("enum_variants: id not bound to an enum")
         }
     };
 
-    cx.enum_var_cache.borrow_mut().insert(id, result);
+    cx.enum_var_cache.borrow_mut().insert(id, result.clone());
     result
 }
 
@@ -3911,17 +3882,11 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
 pub fn enum_variant_with_id(cx: &ctxt,
                             enum_id: ast::DefId,
                             variant_id: ast::DefId)
-                         -> @VariantInfo {
-    let variants = enum_variants(cx, enum_id);
-    let mut i = 0;
-    while i < variants.len() {
-        let variant = *variants.get(i);
-        if variant.id == variant_id {
-            return variant
-        }
-        i += 1;
-    }
-    cx.sess.bug("enum_variant_with_id(): no variant exists with that ID");
+                         -> Rc<VariantInfo> {
+    enum_variants(cx, enum_id).iter()
+                              .find(|variant| variant.id == variant_id)
+                              .expect("enum_variant_with_id(): no variant exists with that ID")
+                              .clone()
 }
 
 
@@ -3944,19 +3909,19 @@ pub fn lookup_impl_vtables(cx: &ctxt,
 }
 
 /// Given the did of a trait, returns its canonical trait ref.
-pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> @ty::TraitDef {
+pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc<ty::TraitDef> {
     let mut trait_defs = cx.trait_defs.borrow_mut();
-    match trait_defs.find(&did) {
-        Some(&trait_def) => {
+    match trait_defs.find_copy(&did) {
+        Some(trait_def) => {
             // The item is in this crate. The caller should have added it to the
             // type cache already
-            return trait_def;
+            trait_def
         }
         None => {
             assert!(did.krate != ast::LOCAL_CRATE);
-            let trait_def = @csearch::get_trait_def(cx, did);
-            trait_defs.insert(did, trait_def);
-            return trait_def;
+            let trait_def = Rc::new(csearch::get_trait_def(cx, did));
+            trait_defs.insert(did, trait_def.clone());
+            trait_def
         }
     }
 }
@@ -3964,7 +3929,7 @@ pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> @ty::TraitDef {
 /// Iterate over meta_items 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: |@MetaItem| -> bool) -> bool {
+pub fn each_attr(tcx: &ctxt, did: DefId, f: |@ast::MetaItem| -> bool) -> bool {
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
         item.attrs.iter().advance(|attr| f(attr.node.value))
@@ -4038,20 +4003,21 @@ pub fn lookup_field_type(tcx: &ctxt,
 
 // Lookup all ancestor structs of a struct indicated by did. That is the reflexive,
 // transitive closure of doing a single lookup in cx.superstructs.
-fn lookup_super_structs(cx: &ctxt,
-                            did: ast::DefId) -> Vec<DefId> {
-    let mut this_result: Vec<DefId> = vec!(did);
-    match cx.superstructs.borrow().find(&did) {
-        Some(&Some(def_id)) => {
-            let ss: Vec<DefId> = lookup_super_structs(cx, def_id);
-            this_result.extend(ss.move_iter());
-            this_result
-        },
-        Some(&None) => this_result,
-        None => {
-            cx.sess.bug(
-                format!("ID not mapped to super-struct: {}",
-                    cx.map.node_to_str(did.node)));
+fn each_super_struct(cx: &ctxt, mut did: ast::DefId, f: |ast::DefId|) {
+    let superstructs = cx.superstructs.borrow();
+
+    loop {
+        f(did);
+        match superstructs.find(&did) {
+            Some(&Some(def_id)) => {
+                did = def_id;
+            },
+            Some(&None) => break,
+            None => {
+                cx.sess.bug(
+                    format!("ID not mapped to super-struct: {}",
+                        cx.map.node_to_str(did.node)));
+            }
         }
     }
 }
@@ -4064,26 +4030,22 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
         // we have to walk the inheritance chain of the struct to get all the
         // structs (explicit and inherited) for a struct. If this is expensive
         // we could cache the whole list of fields here.
-        let structs = lookup_super_structs(cx, did);
         let struct_fields = cx.struct_fields.borrow();
-        let results: Vec<&@Vec<field_ty>> = structs.iter().map(|s| {
-            match struct_fields.find(s) {
-                Some(fields) => fields,
+        let mut results: SmallVector<&[field_ty]> = SmallVector::zero();
+        each_super_struct(cx, did, |s| {
+            match struct_fields.find(&s) {
+                Some(fields) => results.push(fields.as_slice()),
                 _ => {
                     cx.sess.bug(
                         format!("ID not mapped to struct fields: {}",
                             cx.map.node_to_str(did.node)));
                 }
             }
-        }).collect();
+        });
 
-        let len = results.iter().map(|x| x.len()).fold(0, |a, b| a + b);
+        let len = results.as_slice().iter().map(|x| x.len()).sum();
         let mut result: Vec<field_ty> = Vec::with_capacity(len);
-        for rs in results.iter() {
-            for r in rs.iter() {
-                result.push(*r);
-            }
-        }
+        result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|&f| f)));
         assert!(result.len() == len);
         result
     } else {
@@ -4314,31 +4276,31 @@ pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::Expr) ->
 // relation on the supertraits from each bounded trait's constraint
 // list.
 pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
-                                        bounds: &[@TraitRef],
-                                        f: |@TraitRef| -> bool)
+                                        bounds: &[Rc<TraitRef>],
+                                        f: |Rc<TraitRef>| -> bool)
                                         -> bool {
-    for &bound_trait_ref in bounds.iter() {
+    for bound_trait_ref in bounds.iter() {
         let mut supertrait_set = HashMap::new();
         let mut trait_refs = Vec::new();
         let mut i = 0;
 
         // Seed the worklist with the trait from the bound
         supertrait_set.insert(bound_trait_ref.def_id, ());
-        trait_refs.push(bound_trait_ref);
+        trait_refs.push(bound_trait_ref.clone());
 
         // Add the given trait ty to the hash map
         while i < trait_refs.len() {
             debug!("each_bound_trait_and_supertraits(i={:?}, trait_ref={})",
                    i, trait_refs.get(i).repr(tcx));
 
-            if !f(*trait_refs.get(i)) {
+            if !f(trait_refs.get(i).clone()) {
                 return false;
             }
 
             // Add supertraits to supertrait_set
             let supertrait_refs = trait_ref_supertraits(tcx,
-                                                        *trait_refs.get(i));
-            for &supertrait_ref in supertrait_refs.iter() {
+                                                        &**trait_refs.get(i));
+            for supertrait_ref in supertrait_refs.iter() {
                 debug!("each_bound_trait_and_supertraits(supertrait_ref={})",
                        supertrait_ref.repr(tcx));
 
@@ -4346,7 +4308,7 @@ pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
                 if !supertrait_set.contains_key(&d_id) {
                     // FIXME(#5527) Could have same trait multiple times
                     supertrait_set.insert(d_id, ());
-                    trait_refs.push(supertrait_ref);
+                    trait_refs.push(supertrait_ref.clone());
                 }
             }
 
@@ -4371,7 +4333,7 @@ pub fn get_opaque_ty(tcx: &ctxt) -> Result<t, ~str> {
 }
 
 pub fn visitor_object_ty(tcx: &ctxt,
-                         region: ty::Region) -> Result<(@TraitRef, t), ~str> {
+                         region: ty::Region) -> Result<(Rc<TraitRef>, t), ~str> {
     let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
         Ok(id) => id,
         Err(s) => { return Err(s); }
@@ -4381,8 +4343,8 @@ pub fn visitor_object_ty(tcx: &ctxt,
         self_ty: None,
         tps: Vec::new()
     };
-    let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
-    Ok((trait_ref,
+    let trait_ref = Rc::new(TraitRef { def_id: trait_lang_item, substs: substs });
+    Ok((trait_ref.clone(),
         mk_trait(tcx,
                  trait_ref.def_id,
                  trait_ref.substs.clone(),
@@ -4390,29 +4352,24 @@ pub fn visitor_object_ty(tcx: &ctxt,
                  EmptyBuiltinBounds())))
 }
 
-pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> @ItemVariances {
+pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
     lookup_locally_or_in_crate_store(
         "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
-        || @csearch::get_item_variances(&tcx.sess.cstore, item_id))
+        || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
 }
 
 /// Records a trait-to-implementation mapping.
-fn record_trait_implementation(tcx: &ctxt,
-                               trait_def_id: DefId,
-                               implementation: @Impl) {
-    let implementation_list;
-    let mut trait_impls = tcx.trait_impls.borrow_mut();
-    match trait_impls.find(&trait_def_id) {
-        None => {
-            implementation_list = @RefCell::new(Vec::new());
-            trait_impls.insert(trait_def_id, implementation_list);
-        }
-        Some(&existing_implementation_list) => {
-            implementation_list = existing_implementation_list
+pub fn record_trait_implementation(tcx: &ctxt,
+                                   trait_def_id: DefId,
+                                   impl_def_id: DefId) {
+    match tcx.trait_impls.borrow().find(&trait_def_id) {
+        Some(impls_for_trait) => {
+            impls_for_trait.borrow_mut().push(impl_def_id);
+            return;
         }
+        None => {}
     }
-
-    implementation_list.borrow_mut().push(implementation);
+    tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
 }
 
 /// Populates the type context with all the implementations for the given type
@@ -4427,45 +4384,38 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
     }
 
     csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
-            |implementation_def_id| {
-        let implementation = @csearch::get_impl(tcx, implementation_def_id);
+            |impl_def_id| {
+        let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
 
         // Record the trait->implementation mappings, if applicable.
-        let associated_traits = csearch::get_impl_trait(tcx,
-                                                        implementation.did);
+        let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
         for trait_ref in associated_traits.iter() {
-            record_trait_implementation(tcx,
-                                        trait_ref.def_id,
-                                        implementation);
+            record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for method in implementation.methods.iter() {
-            for source in method.provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut()
-                   .insert(method.def_id, *source);
+        for &method_def_id in methods.iter() {
+            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
+                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
             }
         }
 
+        // Store the implementation info.
+        tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
+
         // If this is an inherent implementation, record it.
         if associated_traits.is_none() {
-            let implementation_list;
-            let mut inherent_impls = tcx.inherent_impls.borrow_mut();
-            match inherent_impls.find(&type_id) {
-                None => {
-                    implementation_list = @RefCell::new(Vec::new());
-                    inherent_impls.insert(type_id, implementation_list);
-                }
-                Some(&existing_implementation_list) => {
-                    implementation_list = existing_implementation_list;
+            match tcx.inherent_impls.borrow().find(&type_id) {
+                Some(implementation_list) => {
+                    implementation_list.borrow_mut().push(impl_def_id);
+                    return;
                 }
+                None => {}
             }
-            implementation_list.borrow_mut().push(implementation);
+            tcx.inherent_impls.borrow_mut().insert(type_id,
+                                                   Rc::new(RefCell::new(vec!(impl_def_id))));
         }
-
-        // Store the implementation info.
-        tcx.impls.borrow_mut().insert(implementation_def_id, implementation);
     });
 
     tcx.populated_external_types.borrow_mut().insert(type_id);
@@ -4485,22 +4435,21 @@ pub fn populate_implementations_for_trait_if_necessary(
 
     csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
             |implementation_def_id| {
-        let implementation = @csearch::get_impl(tcx, implementation_def_id);
+        let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
 
         // Record the trait->implementation mapping.
-        record_trait_implementation(tcx, trait_id, implementation);
+        record_trait_implementation(tcx, trait_id, implementation_def_id);
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for method in implementation.methods.iter() {
-            for source in method.provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut()
-                   .insert(method.def_id, *source);
+        for &method_def_id in methods.iter() {
+            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
+                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
             }
         }
 
         // Store the implementation info.
-        tcx.impls.borrow_mut().insert(implementation_def_id, implementation);
+        tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
     });
 
     tcx.populated_external_traits.borrow_mut().insert(trait_id);
@@ -4535,7 +4484,7 @@ pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
     if def_id.krate != LOCAL_CRATE {
         return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
     }
-    match tcx.methods.borrow().find(&def_id).map(|m| *m) {
+    match tcx.methods.borrow().find_copy(&def_id) {
         Some(method) => {
             match method.container {
                 TraitContainer(def_id) => Some(def_id),
@@ -4555,7 +4504,7 @@ pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
 pub fn trait_method_of_method(tcx: &ctxt,
                               def_id: ast::DefId) -> Option<ast::DefId> {
     let method = match tcx.methods.borrow().find(&def_id) {
-        Some(&m) => m,
+        Some(m) => m.clone(),
         None => return None,
     };
     let name = method.ident.name;
@@ -4724,7 +4673,7 @@ impl Variance {
 
 pub fn construct_parameter_environment(
     tcx: &ctxt,
-    self_bound: Option<@TraitRef>,
+    self_bound: Option<Rc<TraitRef>>,
     item_type_params: &[TypeParameterDef],
     method_type_params: &[TypeParameterDef],
     item_region_params: &[RegionParameterDef],
@@ -4739,7 +4688,7 @@ pub fn construct_parameter_environment(
     //
 
     // map Self => Self
-    let self_ty = self_bound.map(|t| ty::mk_self(tcx, t.def_id));
+    let self_ty = self_bound.as_ref().map(|t| ty::mk_self(tcx, t.def_id));
 
     // map A => A
     let num_item_type_params = item_type_params.len();
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 5de2a60114a..6ae68bdbad1 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -60,6 +60,7 @@ use middle::typeck::rscope::{RegionScope};
 use middle::typeck::lookup_def_tcx;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
 use syntax::abi;
 use syntax::{ast, ast_util};
 use syntax::codemap::Span;
@@ -69,7 +70,7 @@ use syntax::print::pprust::{lifetime_to_str, path_to_str};
 pub trait AstConv {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt;
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef;
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef>;
 
     // what type should we use when a type is omitted?
     fn ty_infer(&self, span: Span) -> ty::t;
@@ -261,25 +262,16 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,
 }
 
 pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
-    this: &AC,
-    rscope: &RS,
-    trait_def_id: ast::DefId,
-    self_ty: Option<ty::t>,
-    path: &ast::Path) -> @ty::TraitRef
-{
-    let trait_def =
-        this.get_trait_def(trait_def_id);
-    let substs =
-        ast_path_substs(
-            this,
-            rscope,
-            &trait_def.generics,
-            self_ty,
-            path);
-    let trait_ref =
-        @ty::TraitRef {def_id: trait_def_id,
-                       substs: substs};
-    return trait_ref;
+        this: &AC,
+        rscope: &RS,
+        trait_def_id: ast::DefId,
+        self_ty: Option<ty::t>,
+        path: &ast::Path) -> Rc<ty::TraitRef> {
+    let trait_def = this.get_trait_def(trait_def_id);
+    Rc::new(ty::TraitRef {
+        def_id: trait_def_id,
+        substs: ast_path_substs(this, rscope, &trait_def.generics, self_ty, path)
+    })
 }
 
 pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 286c8d17751..9ceb3132509 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -40,7 +40,7 @@ pub fn check_match(fcx: &FnCtxt,
     for arm in arms.iter() {
         let mut pcx = pat_ctxt {
             fcx: fcx,
-            map: pat_id_map(tcx.def_map, *arm.pats.get(0)),
+            map: pat_id_map(&tcx.def_map, *arm.pats.get(0)),
         };
 
         for p in arm.pats.iter() { check_pat(&mut pcx, *p, discrim_ty);}
@@ -467,14 +467,14 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         fcx.write_ty(pat.id, b_ty);
       }
       ast::PatEnum(..) |
-      ast::PatIdent(..) if pat_is_const(tcx.def_map, pat) => {
+      ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
         let const_did = ast_util::def_id_of_def(tcx.def_map.borrow()
                                                    .get_copy(&pat.id));
         let const_tpt = ty::lookup_item_type(tcx, const_did);
         demand::suptype(fcx, pat.span, expected, const_tpt.ty);
         fcx.write_ty(pat.id, const_tpt.ty);
       }
-      ast::PatIdent(bm, ref name, sub) if pat_is_binding(tcx.def_map, pat) => {
+      ast::PatIdent(bm, ref name, sub) if pat_is_binding(&tcx.def_map, pat) => {
         let typ = fcx.local_ty(pat.span, pat.id);
 
         match bm {
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 178d3c8b544..3b33a17d582 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -30,7 +30,7 @@ itself (note that inherent impls can only be defined in the same
 module as the type itself).
 
 Inherent candidates are not always derived from impls.  If you have a
-trait instance, such as a value of type `@ToStr`, then the trait
+trait instance, such as a value of type `~ToStr`, then the trait
 methods (`to_str()`, in this case) are inherently associated with it.
 Another case is type parameters, in which case the methods of their
 bounds are inherent.
@@ -97,7 +97,7 @@ use util::ppaux;
 use util::ppaux::Repr;
 
 use collections::HashSet;
-use std::result;
+use std::rc::Rc;
 use syntax::ast::{DefId, SelfValue, SelfRegion};
 use syntax::ast::{SelfUniq, SelfStatic};
 use syntax::ast::{MutMutable, MutImmutable};
@@ -203,7 +203,7 @@ pub fn lookup_in_trait<'a>(
 // to a trait and its supertraits.
 fn get_method_index(tcx: &ty::ctxt,
                     trait_ref: &TraitRef,
-                    subtrait: @TraitRef,
+                    subtrait: Rc<TraitRef>,
                     n_method: uint) -> uint {
     // We need to figure the "real index" of the method in a
     // listing of all the methods of an object. We do this by
@@ -311,7 +311,7 @@ struct LookupContext<'a> {
 struct Candidate {
     rcvr_match_condition: RcvrMatchCondition,
     rcvr_substs: ty::substs,
-    method_ty: @ty::Method,
+    method_ty: Rc<ty::Method>,
     origin: MethodOrigin,
 }
 
@@ -412,7 +412,7 @@ impl<'a> LookupContext<'a> {
          * `self.inherent_candidates`.  See comment at the start of
          * the file.  To find the inherent candidates, we repeatedly
          * deref the self-ty to find the "base-type".  So, for
-         * example, if the receiver is @@C where `C` is a struct type,
+         * example, if the receiver is ~~C where `C` is a struct type,
          * we'll want to find the inherent impls for `C`.
          */
 
@@ -468,9 +468,11 @@ impl<'a> LookupContext<'a> {
         ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
 
         // Look for explicit implementations.
+        let impl_methods = self.tcx().impl_methods.borrow();
         for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
-            for impl_info in impl_infos.borrow().iter() {
-                self.push_candidates_from_impl(*impl_info, true);
+            for impl_did in impl_infos.borrow().iter() {
+                let methods = impl_methods.get(impl_did);
+                self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
             }
         }
     }
@@ -509,12 +511,15 @@ impl<'a> LookupContext<'a> {
             self_ty: Some(ty::mk_err()),
             ..(*substs).clone()
         };
-        let trait_ref = @TraitRef { def_id: did, substs: rcvr_substs.clone() };
+        let trait_ref = Rc::new(TraitRef {
+            def_id: did,
+            substs: rcvr_substs.clone()
+        });
 
-        self.push_inherent_candidates_from_bounds_inner(&[trait_ref],
+        self.push_inherent_candidates_from_bounds_inner(&[trait_ref.clone()],
             |new_trait_ref, m, method_num, _bound_num| {
-            let vtable_index = get_method_index(tcx, new_trait_ref,
-                                                trait_ref, method_num);
+            let vtable_index = get_method_index(tcx, &*new_trait_ref,
+                                                trait_ref.clone(), method_num);
             let mut m = (*m).clone();
             // We need to fix up the transformed self type.
             *m.fty.sig.inputs.get_mut(0) =
@@ -524,7 +529,7 @@ impl<'a> LookupContext<'a> {
             Some(Candidate {
                 rcvr_match_condition: RcvrMatchesIfObject(did),
                 rcvr_substs: new_trait_ref.substs.clone(),
-                method_ty: @m,
+                method_ty: Rc::new(m),
                 origin: MethodObject(MethodObject {
                         trait_id: new_trait_ref.def_id,
                         object_trait_id: did,
@@ -561,14 +566,14 @@ impl<'a> LookupContext<'a> {
         debug!("push_inherent_candidates_from_self()");
         self.push_inherent_candidates_from_bounds(
             rcvr_ty,
-            [self.fcx.inh.param_env.self_param_bound.unwrap()],
+            [self.fcx.inh.param_env.self_param_bound.clone().unwrap()],
             restrict_to,
             param_self)
     }
 
     fn push_inherent_candidates_from_bounds(&mut self,
                                             self_ty: ty::t,
-                                            bounds: &[@TraitRef],
+                                            bounds: &[Rc<TraitRef>],
                                             restrict_to: Option<DefId>,
                                             param: param_index) {
         self.push_inherent_candidates_from_bounds_inner(bounds,
@@ -598,9 +603,9 @@ impl<'a> LookupContext<'a> {
     // Do a search through a list of bounds, using a callback to actually
     // create the candidates.
     fn push_inherent_candidates_from_bounds_inner(&mut self,
-                                                  bounds: &[@TraitRef],
-                                                  mk_cand: |tr: @TraitRef,
-                                                            m: @ty::Method,
+                                                  bounds: &[Rc<TraitRef>],
+                                                  mk_cand: |tr: Rc<TraitRef>,
+                                                            m: Rc<ty::Method>,
                                                             method_num: uint,
                                                             bound_num: uint|
                                                             -> Option<Candidate>) {
@@ -616,7 +621,7 @@ impl<'a> LookupContext<'a> {
                 m.explicit_self != ast::SelfStatic &&
                 m.ident.name == self.m_name }) {
                 Some(pos) => {
-                    let method = *trait_methods.get(pos);
+                    let method = trait_methods.get(pos).clone();
 
                     match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
                         Some(cand) => {
@@ -643,40 +648,35 @@ impl<'a> LookupContext<'a> {
         // metadata if necessary.
         ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
 
+        let impl_methods = self.tcx().impl_methods.borrow();
         for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
-            for impl_info in impl_infos.borrow().iter() {
-                self.push_candidates_from_impl(*impl_info, false);
+            for impl_did in impl_infos.borrow().iter() {
+                let methods = impl_methods.get(impl_did);
+                self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
             }
         }
     }
 
     fn push_candidates_from_impl(&mut self,
-                                 impl_info: &ty::Impl,
+                                 impl_did: DefId,
+                                 impl_methods: &[DefId],
                                  is_extension: bool) {
-        if !self.impl_dups.insert(impl_info.did) {
+        if !self.impl_dups.insert(impl_did) {
             return; // already visited
         }
 
-        debug!("push_candidates_from_impl: {} {} {}",
+        debug!("push_candidates_from_impl: {} {}",
                token::get_name(self.m_name),
-               impl_info.ident.repr(self.tcx()),
-               impl_info.methods.iter()
-                                .map(|m| m.ident)
-                                .collect::<Vec<ast::Ident>>()
-                                .repr(self.tcx()));
-
-        let idx = {
-            match impl_info.methods
-                           .iter()
-                           .position(|m| m.ident.name == self.m_name) {
-                Some(idx) => idx,
-                None => { return; } // No method with the right name.
-            }
+               impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
+                                 .collect::<Vec<ast::Ident>>()
+                                 .repr(self.tcx()));
+
+        let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
+                                              .find(|m| m.ident.name == self.m_name) {
+            Some(method) => method,
+            None => { return; } // No method with the right name.
         };
 
-        let method = ty::method(self.tcx(),
-                                impl_info.methods.get(idx).def_id);
-
         // determine the `self` of the impl with fresh
         // variables for each parameter:
         let span = self.self_expr.map_or(self.span, |e| e.span);
@@ -684,7 +684,7 @@ impl<'a> LookupContext<'a> {
         let ty::ty_param_substs_and_ty {
             substs: impl_substs,
             ty: impl_ty
-        } = impl_self_ty(&vcx, span, impl_info.did);
+        } = impl_self_ty(&vcx, span, impl_did);
 
         let candidates = if is_extension {
             &mut self.extension_candidates
@@ -695,8 +695,8 @@ impl<'a> LookupContext<'a> {
         candidates.push(Candidate {
             rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
             rcvr_substs: impl_substs,
+            origin: MethodStatic(method.def_id),
             method_ty: method,
-            origin: MethodStatic(method.def_id)
         });
     }
 
@@ -715,7 +715,7 @@ impl<'a> LookupContext<'a> {
         // an explicit adjustment, but rather we hardwire the single deref
         // that occurs in trans and mem_categorization.
         let adjustment = match self.self_expr {
-            Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
+            Some(expr) => Some((expr.id, ty::AutoDerefRef(auto_deref_ref))),
             None => return None
         };
 
@@ -877,7 +877,7 @@ impl<'a> LookupContext<'a> {
             }
 
             ty_trait(~ty::TyTrait { def_id: trt_did, substs: trt_substs, bounds: b, .. }) => {
-                // Coerce ~/@/&Trait instances to &Trait.
+                // Coerce ~/&Trait instances to &Trait.
 
                 self.search_for_some_kind_of_autorefd_method(
                     AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
@@ -962,7 +962,7 @@ impl<'a> LookupContext<'a> {
                         Some(self_expr_id) => {
                             self.fcx.write_adjustment(
                                 self_expr_id,
-                                @ty::AutoDerefRef(ty::AutoDerefRef {
+                                ty::AutoDerefRef(ty::AutoDerefRef {
                                     autoderefs: autoderefs,
                                     autoref: Some(kind(region, *mutbl))
                                 }));
@@ -1187,8 +1187,8 @@ impl<'a> LookupContext<'a> {
         let span = self.self_expr.map_or(self.span, |e| e.span);
         match self.fcx.mk_subty(false, infer::Misc(span),
                                 rcvr_ty, transformed_self_ty) {
-            result::Ok(_) => {}
-            result::Err(_) => {
+            Ok(_) => {}
+            Err(_) => {
                 self.bug(format!("{} was a subtype of {} but now is not?",
                               self.ty_to_str(rcvr_ty),
                               self.ty_to_str(transformed_self_ty)));
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index bddd7f43d99..dc5b4f6d520 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -117,7 +117,7 @@ use util::nodemap::{FnvHashMap, NodeMap};
 use std::cell::{Cell, RefCell};
 use collections::HashMap;
 use std::mem::replace;
-use std::result;
+use std::rc::Rc;
 use std::vec::Vec;
 use syntax::abi;
 use syntax::ast::{Provided, Required};
@@ -155,13 +155,13 @@ pub mod method;
 /// share the inherited fields.
 pub struct Inherited<'a> {
     infcx: infer::InferCtxt<'a>,
-    locals: @RefCell<NodeMap<ty::t>>,
+    locals: RefCell<NodeMap<ty::t>>,
     param_env: ty::ParameterEnvironment,
 
     // Temporary tables:
     node_types: RefCell<NodeMap<ty::t>>,
     node_type_substs: RefCell<NodeMap<ty::substs>>,
-    adjustments: RefCell<NodeMap<@ty::AutoAdjustment>>,
+    adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
     method_map: MethodMap,
     vtable_map: vtable_map,
     upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
@@ -260,13 +260,13 @@ impl<'a> Inherited<'a> {
            -> Inherited<'a> {
         Inherited {
             infcx: infer::new_infer_ctxt(tcx),
-            locals: @RefCell::new(NodeMap::new()),
+            locals: RefCell::new(NodeMap::new()),
             param_env: param_env,
             node_types: RefCell::new(NodeMap::new()),
             node_type_substs: RefCell::new(NodeMap::new()),
             adjustments: RefCell::new(NodeMap::new()),
-            method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(FnvHashMap::new()),
+            method_map: RefCell::new(FnvHashMap::new()),
+            vtable_map: RefCell::new(FnvHashMap::new()),
             upvar_borrow_map: RefCell::new(HashMap::new()),
         }
     }
@@ -387,7 +387,7 @@ impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
     fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
             match p.node {
               ast::PatIdent(_, ref path, _)
-                  if pat_util::pat_is_binding(self.fcx.ccx.tcx.def_map, p) => {
+                  if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
                 self.assign(p.id, None);
                 debug!("Pattern binding {} is assigned to {}",
                        token::get_ident(path.segments.get(0).identifier),
@@ -469,7 +469,7 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
         // Add formal parameters.
         for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
             // Create type variables for each argument.
-            pat_util::pat_bindings(tcx.def_map,
+            pat_util::pat_bindings(&tcx.def_map,
                                    input.pat,
                                    |_bm, pat_id, _sp, _path| {
                                        visit.assign(pat_id, None);
@@ -478,7 +478,7 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
             // Check the pattern.
             let pcx = pat_ctxt {
                 fcx: &fcx,
-                map: pat_id_map(tcx.def_map, input.pat),
+                map: pat_id_map(&tcx.def_map, input.pat),
             };
             _match::check_pat(&pcx, input.pat, *arg_ty);
         }
@@ -622,9 +622,9 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
                                              it.span,
                                              &impl_tpt.generics,
                                              ast_trait_ref,
-                                             impl_trait_ref,
+                                             &*impl_trait_ref,
                                              ms.as_slice());
-                vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, impl_trait_ref);
+                vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, &*impl_trait_ref);
             }
             None => { }
         }
@@ -640,7 +640,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
                 }
                 Provided(m) => {
                     check_method_body(ccx, &trait_def.generics,
-                                      Some(trait_def.trait_ref), m);
+                                      Some(trait_def.trait_ref.clone()), m);
                 }
             }
         }
@@ -682,7 +682,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
 
 fn check_method_body(ccx: &CrateCtxt,
                      item_generics: &ty::Generics,
-                     self_bound: Option<@ty::TraitRef>,
+                     self_bound: Option<Rc<ty::TraitRef>>,
                      method: &ast::Method) {
     /*!
      * Type checks a method body.
@@ -744,10 +744,10 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
             Some(trait_method_ty) => {
                 compare_impl_method(ccx.tcx,
                                     impl_generics,
-                                    impl_method_ty,
+                                    &*impl_method_ty,
                                     impl_method.span,
                                     impl_method.body.id,
-                                    *trait_method_ty,
+                                    &**trait_method_ty,
                                     &impl_trait_ref.substs);
             }
             None => {
@@ -800,7 +800,7 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
  */
 fn compare_impl_method(tcx: &ty::ctxt,
                        impl_generics: &ty::Generics,
-                       impl_m: @ty::Method,
+                       impl_m: &ty::Method,
                        impl_m_span: Span,
                        impl_m_body_id: ast::NodeId,
                        trait_m: &ty::Method,
@@ -973,8 +973,8 @@ fn compare_impl_method(tcx: &ty::ctxt,
 
     match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
                           impl_fty, trait_fty) {
-        result::Ok(()) => {}
-        result::Err(ref terr) => {
+        Ok(()) => {}
+        Err(ref terr) => {
             tcx.sess.span_err(
                 impl_m_span,
                 format!("method `{}` has an incompatible type for trait: {}",
@@ -992,7 +992,7 @@ impl<'a> AstConv for FnCtxt<'a> {
         ty::lookup_item_type(self.tcx(), id)
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
         ty::lookup_trait_def(self.tcx(), id)
     }
 
@@ -1076,7 +1076,7 @@ impl<'a> FnCtxt<'a> {
         if derefs == 0 { return; }
         self.write_adjustment(
             node_id,
-            @ty::AutoDerefRef(ty::AutoDerefRef {
+            ty::AutoDerefRef(ty::AutoDerefRef {
                 autoderefs: derefs,
                 autoref: None })
         );
@@ -1084,7 +1084,7 @@ impl<'a> FnCtxt<'a> {
 
     pub fn write_adjustment(&self,
                             node_id: ast::NodeId,
-                            adj: @ty::AutoAdjustment) {
+                            adj: ty::AutoAdjustment) {
         debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
         self.inh.adjustments.borrow_mut().insert(node_id, adj);
     }
@@ -1175,8 +1175,8 @@ impl<'a> FnCtxt<'a> {
                                  infer::ExprAssignable(expr.span),
                                  sub,
                                  sup) {
-            Ok(None) => result::Ok(()),
-            Err(ref e) => result::Err((*e)),
+            Ok(None) => Ok(()),
+            Err(ref e) => Err((*e)),
             Ok(Some(adjustment)) => {
                 self.write_adjustment(expr.id, adjustment);
                 Ok(())
@@ -2100,7 +2100,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                         op: ast::BinOp,
                         rhs: @ast::Expr) -> ty::t {
         let tcx = fcx.ccx.tcx;
-        let lang = tcx.lang_items;
+        let lang = &tcx.lang_items;
         let (name, trait_did) = match op {
             ast::BiAdd => ("add", lang.add_trait()),
             ast::BiSub => ("sub", lang.sub_trait()),
@@ -2690,7 +2690,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         demand::suptype(fcx, expr.span, result_t, lhs_t);
 
         let tcx = fcx.tcx();
-        if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) {
+        if !ty::expr_is_lval(tcx, lhs) {
             tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
         }
 
@@ -2846,8 +2846,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         match expr_opt {
           None => match fcx.mk_eqty(false, infer::Misc(expr.span),
                                     ret_ty, ty::mk_nil()) {
-            result::Ok(_) => { /* fall through */ }
-            result::Err(_) => {
+            Ok(_) => { /* fall through */ }
+            Err(_) => {
                 tcx.sess.span_err(
                     expr.span,
                     "`return;` in function returning non-nil");
@@ -2867,7 +2867,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         check_expr_with_lvalue_pref(fcx, lhs, PreferMutLvalue);
 
         let tcx = fcx.tcx();
-        if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) {
+        if !ty::expr_is_lval(tcx, lhs) {
             tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
         }
 
@@ -3268,7 +3268,7 @@ pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
 
     let pcx = pat_ctxt {
         fcx: fcx,
-        map: pat_id_map(tcx.def_map, local.pat),
+        map: pat_id_map(&tcx.def_map, local.pat),
     };
     _match::check_pat(&pcx, local.pat, t);
     let pat_ty = fcx.node_ty(local.pat.id);
@@ -3543,10 +3543,10 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
                 vs: &[ast::P<ast::Variant>],
                 id: ast::NodeId,
                 hint: attr::ReprAttr)
-                -> Vec<@ty::VariantInfo> {
+                -> Vec<Rc<ty::VariantInfo>> {
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
-        let mut variants: Vec<@ty::VariantInfo> = Vec::new();
+        let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
         let mut disr_vals: Vec<ty::Disr> = Vec::new();
         let mut prev_disr_val: Option<ty::Disr> = None;
 
@@ -3602,7 +3602,8 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
             }
             disr_vals.push(current_disr_val);
 
-            let variant_info = @VariantInfo::from_ast_variant(ccx.tcx, v, current_disr_val);
+            let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, v,
+                                                                     current_disr_val));
             prev_disr_val = Some(current_disr_val);
 
             variants.push(variant_info);
@@ -3624,7 +3625,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
     let variants = do_check(ccx, vs, id, hint);
 
     // cache so that ty::enum_variants won't repeat this work
-    ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), @variants);
+    ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
 
     // Check that it is possible to represent this enum.
     check_representable(ccx.tcx, sp, id, "enum");
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index f6a4d972a07..94cbd3a3a75 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -131,6 +131,7 @@ use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
 use middle::typeck::MethodCall;
 use middle::pat_util;
+use util::nodemap::NodeMap;
 use util::ppaux::{ty_to_str, region_to_str, Repr};
 
 use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar};
@@ -140,6 +141,8 @@ use syntax::codemap::Span;
 use syntax::visit;
 use syntax::visit::Visitor;
 
+use std::cell::RefCell;
+
 // If mem categorization results in an error, it's because the type
 // check failed (or will fail, when the error is uncovered and
 // reported during writeback). In this case, we just ignore this part
@@ -155,7 +158,6 @@ macro_rules! ignore_err(
 
 pub struct Rcx<'a> {
     fcx: &'a FnCtxt<'a>,
-    errors_reported: uint,
 
     // id of innermost fn or loop
     repeating_scope: ast::NodeId,
@@ -234,7 +236,7 @@ impl<'a> Rcx<'a> {
     }
 
     /// Try to resolve the type for the given node.
-    fn resolve_node_type(&mut self, id: ast::NodeId) -> ty::t {
+    fn resolve_node_type(&self, id: ast::NodeId) -> ty::t {
         let t = self.fcx.node_ty(id);
         self.resolve_type(t)
     }
@@ -252,19 +254,19 @@ impl<'a> Rcx<'a> {
             ty_unadjusted
         } else {
             let tcx = self.fcx.tcx();
-            let adjustment = self.fcx.inh.adjustments.borrow().find_copy(&expr.id);
-            ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted, adjustment,
+            ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
+                          self.fcx.inh.adjustments.borrow().find(&expr.id),
                           |method_call| self.resolve_method_type(method_call))
         }
     }
 }
 
-impl<'a, 'b> mc::Typer for &'a mut Rcx<'b> {
+impl<'a, 'b> mc::Typer for &'a Rcx<'b> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
         self.fcx.tcx()
     }
 
-    fn node_ty(&mut self, id: ast::NodeId) -> mc::McResult<ty::t> {
+    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
         let t = self.resolve_node_type(id);
         if ty::type_is_error(t) {Err(())} else {Ok(t)}
     }
@@ -273,26 +275,25 @@ impl<'a, 'b> mc::Typer for &'a mut Rcx<'b> {
         self.resolve_method_type(method_call)
     }
 
-    fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
-        self.fcx.inh.adjustments.borrow().find_copy(&id)
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+        &self.fcx.inh.adjustments
     }
 
-    fn is_method_call(&mut self, id: ast::NodeId) -> bool {
+    fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
     }
 
-    fn temporary_scope(&mut self, id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
         self.tcx().region_maps.temporary_scope(id)
     }
 
-    fn upvar_borrow(&mut self, id: ty::UpvarId) -> ty::UpvarBorrow {
+    fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
         self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
     }
 }
 
 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
-    let mut rcx = Rcx { fcx: fcx, errors_reported: 0,
-                         repeating_scope: e.id };
+    let mut rcx = Rcx { fcx: fcx, repeating_scope: e.id };
     let rcx = &mut rcx;
     if fcx.err_count_since_creation() == 0 {
         // regionck assumes typeck succeeded
@@ -302,8 +303,7 @@ pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
 }
 
 pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
-    let mut rcx = Rcx { fcx: fcx, errors_reported: 0,
-                         repeating_scope: blk.id };
+    let mut rcx = Rcx { fcx: fcx, repeating_scope: blk.id };
     let rcx = &mut rcx;
     if fcx.err_count_since_creation() == 0 {
         // regionck assumes typeck succeeded
@@ -361,7 +361,7 @@ fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
     let tcx = rcx.fcx.tcx();
     debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
-    pat_util::pat_bindings(tcx.def_map, pat, |_, id, span, _| {
+    pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
         // If we have a variable that contains region'd data, that
         // data will be accessible from anywhere that the variable is
         // accessed. We must be wary of loops like this:
@@ -402,7 +402,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     // Check any autoderefs or autorefs that appear.
     for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
         debug!("adjustment={:?}", adjustment);
-        match **adjustment {
+        match *adjustment {
             ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: opt_autoref}) => {
                 let expr_ty = rcx.resolve_node_type(expr.id);
                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
@@ -611,20 +611,21 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     match ty::get(function_type).sty {
         ty::ty_closure(~ty::ClosureTy {
                 store: ty::RegionTraitStore(region, _), ..}) => {
-            let freevars = freevars::get_freevars(tcx, expr.id);
-            if freevars.is_empty() {
-                // No free variables means that the environment
-                // will be NULL at runtime and hence the closure
-                // has static lifetime.
-            } else {
-                // Closure must not outlive the variables it closes over.
-                constrain_free_variables(rcx, region, expr, freevars);
-
-                // Closure cannot outlive the appropriate temporary scope.
-                let s = rcx.repeating_scope;
-                rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
-                                region, ty::ReScope(s));
-            }
+            freevars::with_freevars(tcx, expr.id, |freevars| {
+                if freevars.is_empty() {
+                    // No free variables means that the environment
+                    // will be NULL at runtime and hence the closure
+                    // has static lifetime.
+                } else {
+                    // Closure must not outlive the variables it closes over.
+                    constrain_free_variables(rcx, region, expr, freevars);
+
+                    // Closure cannot outlive the appropriate temporary scope.
+                    let s = rcx.repeating_scope;
+                    rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
+                                    region, ty::ReScope(s));
+                }
+            });
         }
         _ => ()
     }
@@ -635,8 +636,9 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 
     match ty::get(function_type).sty {
         ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
-            let freevars = freevars::get_freevars(tcx, expr.id);
-            propagate_upupvar_borrow_kind(rcx, expr, freevars);
+            freevars::with_freevars(tcx, expr.id, |freevars| {
+                propagate_upupvar_borrow_kind(rcx, expr, freevars);
+            });
         }
         _ => ()
     }
@@ -644,7 +646,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     fn constrain_free_variables(rcx: &mut Rcx,
                                 region: ty::Region,
                                 expr: &ast::Expr,
-                                freevars: freevars::freevar_info) {
+                                freevars: &[freevars::freevar_entry]) {
         /*!
          * Make sure that all free variables referenced inside the closure
          * outlive the closure itself. Also, create an entry in the
@@ -690,7 +692,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 
     fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
                                      expr: &ast::Expr,
-                                     freevars: freevars::freevar_info) {
+                                     freevars: &[freevars::freevar_entry]) {
         let tcx = rcx.fcx.ccx.tcx;
         debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
         for freevar in freevars.iter() {
@@ -870,7 +872,7 @@ fn constrain_autoderefs(rcx: &mut Rcx,
                                 method.ty.repr(rcx.tcx())))
                 };
                 {
-                    let mut mc = mc::MemCategorizationContext { typer: &mut *rcx };
+                    let mc = mc::MemCategorizationContext { typer: &*rcx };
                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
                     link_region(mc.typer, deref_expr.span, r, m, self_cmt);
                 }
@@ -948,8 +950,7 @@ fn constrain_regions_in_type_of_node(
     rcx: &mut Rcx,
     id: ast::NodeId,
     minimum_lifetime: ty::Region,
-    origin: infer::SubregionOrigin) -> bool
-{
+    origin: infer::SubregionOrigin) {
     //! Guarantees that any lifetimes which appear in the type of
     //! the node `id` (after applying adjustments) are valid for at
     //! least `minimum_lifetime`
@@ -960,22 +961,21 @@ fn constrain_regions_in_type_of_node(
     // is going to fail anyway, so just stop here and let typeck
     // report errors later on in the writeback phase.
     let ty0 = rcx.resolve_node_type(id);
-    let adjustment = rcx.fcx.inh.adjustments.borrow().find_copy(&id);
-    let ty = ty::adjust_ty(tcx, origin.span(), id, ty0, adjustment,
+    let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
+                           rcx.fcx.inh.adjustments.borrow().find(&id),
                            |method_call| rcx.resolve_method_type(method_call));
     debug!("constrain_regions_in_type_of_node(\
-            ty={}, ty0={}, id={}, minimum_lifetime={:?}, adjustment={:?})",
+            ty={}, ty0={}, id={}, minimum_lifetime={:?})",
            ty_to_str(tcx, ty), ty_to_str(tcx, ty0),
-           id, minimum_lifetime, adjustment);
-    constrain_regions_in_type(rcx, minimum_lifetime, origin, ty)
+           id, minimum_lifetime);
+    constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
 }
 
 fn constrain_regions_in_type(
     rcx: &mut Rcx,
     minimum_lifetime: ty::Region,
     origin: infer::SubregionOrigin,
-    ty: ty::t) -> bool
-{
+    ty: ty::t) {
     /*!
      * Requires that any regions which appear in `ty` must be
      * superregions of `minimum_lifetime`.  Also enforces the constraint
@@ -990,7 +990,6 @@ fn constrain_regions_in_type(
      * code that R corresponds to."
      */
 
-    let e = rcx.errors_reported;
     let tcx = rcx.fcx.ccx.tcx;
 
     debug!("constrain_regions_in_type(minimum_lifetime={}, ty={})",
@@ -1009,7 +1008,7 @@ fn constrain_regions_in_type(
             // for regions that are as-yet-unknown.
         } else if r_sub == minimum_lifetime {
             rcx.fcx.mk_subr(
-                true, origin,
+                true, origin.clone(),
                 r_sub, r_sup);
         } else {
             rcx.fcx.mk_subr(
@@ -1017,8 +1016,6 @@ fn constrain_regions_in_type(
                 r_sub, r_sup);
         }
     });
-
-    return e == rcx.errors_reported;
 }
 
 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
@@ -1032,13 +1029,13 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
     debug!("link_addr_of(base=?)");
 
     let cmt = {
-        let mut mc = mc::MemCategorizationContext { typer: &mut *rcx };
+        let mc = mc::MemCategorizationContext { typer: &*rcx };
         ignore_err!(mc.cat_expr(base))
     };
     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
 }
 
-fn link_local(rcx: &mut Rcx, local: &ast::Local) {
+fn link_local(rcx: &Rcx, local: &ast::Local) {
     /*!
      * Computes the guarantors for any ref bindings in a `let` and
      * then ensures that the lifetime of the resulting pointer is
@@ -1050,12 +1047,12 @@ fn link_local(rcx: &mut Rcx, local: &ast::Local) {
         None => { return; }
         Some(expr) => expr,
     };
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
-    link_pattern(&mut mc, discr_cmt, local.pat);
+    link_pattern(mc, discr_cmt, local.pat);
 }
 
-fn link_match(rcx: &mut Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
+fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
     /*!
      * Computes the guarantors for any ref bindings in a match and
      * then ensures that the lifetime of the resulting pointer is
@@ -1063,19 +1060,19 @@ fn link_match(rcx: &mut Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
      */
 
     debug!("regionck::for_match()");
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let discr_cmt = ignore_err!(mc.cat_expr(discr));
     debug!("discr_cmt={}", discr_cmt.repr(mc.typer.tcx()));
     for arm in arms.iter() {
         for &root_pat in arm.pats.iter() {
-            link_pattern(&mut mc, discr_cmt, root_pat);
+            link_pattern(mc, discr_cmt.clone(), root_pat);
         }
     }
 }
 
-fn link_pattern(mc: &mut mc::MemCategorizationContext<&mut Rcx>,
+fn link_pattern(mc: mc::MemCategorizationContext<&Rcx>,
                 discr_cmt: mc::cmt,
-                root_pat: @ast::Pat) {
+                root_pat: &ast::Pat) {
     /*!
      * Link lifetimes of any ref bindings in `root_pat` to
      * the pointers found in the discriminant, if needed.
@@ -1105,7 +1102,7 @@ fn link_pattern(mc: &mut mc::MemCategorizationContext<&mut Rcx>,
         });
 }
 
-fn link_autoref(rcx: &mut Rcx,
+fn link_autoref(rcx: &Rcx,
                 expr: &ast::Expr,
                 autoderefs: uint,
                 autoref: &ty::AutoRef) {
@@ -1115,7 +1112,7 @@ fn link_autoref(rcx: &mut Rcx,
      */
 
     debug!("link_autoref(autoref={:?})", autoref);
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
     debug!("expr_cmt={}", expr_cmt.repr(mc.typer.tcx()));
 
@@ -1138,7 +1135,7 @@ fn link_autoref(rcx: &mut Rcx,
     }
 }
 
-fn link_by_ref(rcx: &mut Rcx,
+fn link_by_ref(rcx: &Rcx,
                expr: &ast::Expr,
                callee_scope: ast::NodeId) {
     /*!
@@ -1150,13 +1147,13 @@ fn link_by_ref(rcx: &mut Rcx,
     let tcx = rcx.tcx();
     debug!("link_by_ref(expr={}, callee_scope={})",
            expr.repr(tcx), callee_scope);
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let expr_cmt = ignore_err!(mc.cat_expr(expr));
     let region_min = ty::ReScope(callee_scope);
     link_region(mc.typer, expr.span, region_min, ast::MutImmutable, expr_cmt);
 }
 
-fn link_region_from_node_type(rcx: &mut Rcx,
+fn link_region_from_node_type(rcx: &Rcx,
                               span: Span,
                               id: ast::NodeId,
                               mutbl: ast::Mutability,
@@ -1176,7 +1173,7 @@ fn link_region_from_node_type(rcx: &mut Rcx,
     }
 }
 
-fn link_region(rcx: &mut Rcx,
+fn link_region(rcx: &Rcx,
                span: Span,
                region_min: ty::Region,
                mutbl: ast::Mutability,
@@ -1197,7 +1194,7 @@ fn link_region(rcx: &mut Rcx,
                region_min.repr(rcx.tcx()),
                mutbl.repr(rcx.tcx()),
                cmt_borrowed.repr(rcx.tcx()));
-        match cmt_borrowed.cat {
+        match cmt_borrowed.cat.clone() {
             mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
                 // References to an upvar `x` are translated to
                 // `*x`, since that is what happens in the
@@ -1287,7 +1284,7 @@ fn link_region(rcx: &mut Rcx,
     }
 }
 
-fn adjust_borrow_kind_for_assignment_lhs(rcx: &mut Rcx,
+fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
                                          lhs: &ast::Expr) {
     /*!
      * Adjusts the inferred borrow_kind as needed to account
@@ -1295,19 +1292,19 @@ fn adjust_borrow_kind_for_assignment_lhs(rcx: &mut Rcx,
      * expression.
      */
 
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let cmt = ignore_err!(mc.cat_expr(lhs));
     adjust_upvar_borrow_kind_for_mut(mc.typer, cmt);
 }
 
-fn adjust_upvar_borrow_kind_for_mut(rcx: &mut Rcx,
+fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
                                     cmt: mc::cmt) {
     let mut cmt = cmt;
     loop {
         debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
                cmt.repr(rcx.tcx()));
 
-        match cmt.cat {
+        match cmt.cat.clone() {
             mc::cat_deref(base, _, mc::OwnedPtr) |
             mc::cat_interior(base, _) |
             mc::cat_downcast(base) |
@@ -1331,14 +1328,14 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &mut Rcx,
                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
                     }
 
-                    _ => {
-                        // assignment to deref of an `&mut`
-                        // borrowed pointer implies that the
-                        // pointer itself must be unique, but not
-                        // necessarily *mutable*
-                        return adjust_upvar_borrow_kind_for_unique(rcx, base);
-                    }
+                    _ => {}
                 }
+
+                // assignment to deref of an `&mut`
+                // borrowed pointer implies that the
+                // pointer itself must be unique, but not
+                // necessarily *mutable*
+                return adjust_upvar_borrow_kind_for_unique(rcx, base);
             }
 
             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
@@ -1355,14 +1352,13 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &mut Rcx,
     }
 }
 
-fn adjust_upvar_borrow_kind_for_unique(rcx: &mut Rcx,
-                                       cmt: mc::cmt) {
+fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
     let mut cmt = cmt;
     loop {
         debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
                cmt.repr(rcx.tcx()));
 
-        match cmt.cat {
+        match cmt.cat.clone() {
             mc::cat_deref(base, _, mc::OwnedPtr) |
             mc::cat_interior(base, _) |
             mc::cat_downcast(base) |
@@ -1385,12 +1381,12 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &mut Rcx,
                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
                     }
 
-                    _ => {
-                        // for a borrowed pointer to be unique, its
-                        // base must be unique
-                        return adjust_upvar_borrow_kind_for_unique(rcx, base);
-                    }
+                    _ => {}
                 }
+
+                // for a borrowed pointer to be unique, its
+                // base must be unique
+                return adjust_upvar_borrow_kind_for_unique(rcx, base);
             }
 
             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 3f50a64e630..bb57fa2646b 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -27,9 +27,8 @@ use util::common::indenter;
 use util::ppaux;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
 use collections::HashSet;
-use std::cell::RefCell;
-use std::result;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
@@ -112,7 +111,7 @@ fn lookup_vtables(vcx: &VtableContext,
            type_param_defs.repr(vcx.tcx()),
            substs.repr(vcx.tcx()),
            result.repr(vcx.tcx()));
-    @result
+    result
 }
 
 fn lookup_vtables_for_param(vcx: &VtableContext,
@@ -139,7 +138,7 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
 
         // Substitute the values of the type parameters that may
         // appear in the bound.
-        let trait_ref = substs.as_ref().map_or(trait_ref, |substs| {
+        let trait_ref = substs.as_ref().map_or(trait_ref.clone(), |substs| {
             debug!("about to subst: {}, {}",
                    trait_ref.repr(tcx), substs.repr(tcx));
             trait_ref.subst(tcx, *substs)
@@ -147,13 +146,13 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
 
         debug!("after subst: {}", trait_ref.repr(tcx));
 
-        match lookup_vtable(vcx, span, ty, trait_ref, is_early) {
+        match lookup_vtable(vcx, span, ty, trait_ref.clone(), is_early) {
             Some(vtable) => param_result.push(vtable),
             None => {
                 vcx.tcx().sess.span_fatal(span,
                     format!("failed to find an implementation of \
                           trait {} for {}",
-                         vcx.infcx.trait_ref_to_str(trait_ref),
+                         vcx.infcx.trait_ref_to_str(&*trait_ref),
                          vcx.infcx.ty_to_str(ty)));
             }
         }
@@ -170,13 +169,13 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
            ty.repr(vcx.tcx()),
            param_result.repr(vcx.tcx()));
 
-    return @param_result;
+    param_result
 }
 
 fn relate_trait_refs(vcx: &VtableContext,
                      span: Span,
-                     act_trait_ref: @ty::TraitRef,
-                     exp_trait_ref: @ty::TraitRef) {
+                     act_trait_ref: Rc<ty::TraitRef>,
+                     exp_trait_ref: Rc<ty::TraitRef>) {
     /*!
      *
      * Checks that an implementation of `act_trait_ref` is suitable
@@ -187,17 +186,17 @@ fn relate_trait_refs(vcx: &VtableContext,
     match infer::mk_sub_trait_refs(vcx.infcx,
                                    false,
                                    infer::RelateTraitRefs(span),
-                                   act_trait_ref,
-                                   exp_trait_ref) {
-        result::Ok(()) => {} // Ok.
-        result::Err(ref err) => {
+                                   act_trait_ref.clone(),
+                                   exp_trait_ref.clone()) {
+        Ok(()) => {} // Ok.
+        Err(ref err) => {
             // There is an error, but we need to do some work to make
             // the message good.
             // Resolve any type vars in the trait refs
             let r_act_trait_ref =
-                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(act_trait_ref);
+                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(&*act_trait_ref);
             let r_exp_trait_ref =
-                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(exp_trait_ref);
+                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(&*exp_trait_ref);
             // Only print the message if there aren't any previous type errors
             // inside the types.
             if !ty::trait_ref_contains_error(&r_act_trait_ref) &&
@@ -218,12 +217,12 @@ fn relate_trait_refs(vcx: &VtableContext,
 fn lookup_vtable(vcx: &VtableContext,
                  span: Span,
                  ty: ty::t,
-                 trait_ref: @ty::TraitRef,
+                 trait_ref: Rc<ty::TraitRef>,
                  is_early: bool)
                  -> Option<vtable_origin> {
     debug!("lookup_vtable(ty={}, trait_ref={})",
            vcx.infcx.ty_to_str(ty),
-           vcx.infcx.trait_ref_to_str(trait_ref));
+           vcx.infcx.trait_ref_to_str(&*trait_ref));
     let _i = indenter();
 
     let ty = match fixup_ty(vcx, span, ty, is_early) {
@@ -244,23 +243,23 @@ fn lookup_vtable(vcx: &VtableContext,
         ty::ty_param(param_ty {idx: n, ..}) => {
             let env_bounds = &vcx.param_env.type_param_bounds;
             if env_bounds.len() > n {
-                let type_param_bounds: &[@ty::TraitRef] =
+                let type_param_bounds: &[Rc<ty::TraitRef>] =
                     env_bounds.get(n).trait_bounds.as_slice();
                 lookup_vtable_from_bounds(vcx, span,
                                           type_param_bounds,
                                           param_numbered(n),
-                                          trait_ref)
+                                          trait_ref.clone())
             } else {
                 None
             }
         }
 
         ty::ty_self(_) => {
-            let self_param_bound = vcx.param_env.self_param_bound.unwrap();
+            let self_param_bound = vcx.param_env.self_param_bound.clone().unwrap();
             lookup_vtable_from_bounds(vcx, span,
                                       [self_param_bound],
                                       param_self,
-                                      trait_ref)
+                                      trait_ref.clone())
         }
 
         // Default case just falls through
@@ -278,9 +277,9 @@ fn lookup_vtable(vcx: &VtableContext,
 // of them are the vtable we are looking for.
 fn lookup_vtable_from_bounds(vcx: &VtableContext,
                              span: Span,
-                             bounds: &[@ty::TraitRef],
+                             bounds: &[Rc<ty::TraitRef>],
                              param: param_index,
-                             trait_ref: @ty::TraitRef)
+                             trait_ref: Rc<ty::TraitRef>)
                              -> Option<vtable_origin> {
     let tcx = vcx.tcx();
 
@@ -291,7 +290,7 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext,
                bound_trait_ref.repr(vcx.tcx()));
 
         if bound_trait_ref.def_id == trait_ref.def_id {
-            relate_trait_refs(vcx, span, bound_trait_ref, trait_ref);
+            relate_trait_refs(vcx, span, bound_trait_ref, trait_ref.clone());
             let vtable = vtable_param(param, n_bound);
             debug!("found param vtable: {:?}",
                    vtable);
@@ -308,7 +307,7 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext,
 fn search_for_vtable(vcx: &VtableContext,
                      span: Span,
                      ty: ty::t,
-                     trait_ref: @ty::TraitRef,
+                     trait_ref: Rc<ty::TraitRef>,
                      is_early: bool)
                      -> Option<vtable_origin> {
     let tcx = vcx.tcx();
@@ -320,26 +319,28 @@ fn search_for_vtable(vcx: &VtableContext,
     ty::populate_implementations_for_trait_if_necessary(tcx,
                                                         trait_ref.def_id);
 
-    // FIXME: this is a bad way to do this, since we do
-    // pointless allocations.
-    let impls = tcx.trait_impls.borrow().find(&trait_ref.def_id)
-                               .map_or(@RefCell::new(Vec::new()), |x| *x);
+    let impls = match tcx.trait_impls.borrow().find_copy(&trait_ref.def_id) {
+        Some(impls) => impls,
+        None => {
+            return None;
+        }
+    };
     // impls is the list of all impls in scope for trait_ref.
-    for im in impls.borrow().iter() {
+    for &impl_did in impls.borrow().iter() {
         // im is one specific impl of trait_ref.
 
         // First, ensure we haven't processed this impl yet.
-        if impls_seen.contains(&im.did) {
+        if impls_seen.contains(&impl_did) {
             continue;
         }
-        impls_seen.insert(im.did);
+        impls_seen.insert(impl_did);
 
         // ty::impl_traits gives us the trait im implements.
         //
         // If foo implements a trait t, and if t is the same trait as
         // trait_ref, we need to unify it with trait_ref in order to
         // get all the ty vars sorted out.
-        let r = ty::impl_trait_ref(tcx, im.did);
+        let r = ty::impl_trait_ref(tcx, impl_did);
         let of_trait_ref = r.expect("trait_ref missing on trait impl");
         if of_trait_ref.def_id != trait_ref.def_id { continue; }
 
@@ -362,14 +363,14 @@ fn search_for_vtable(vcx: &VtableContext,
         let ty::ty_param_substs_and_ty {
             substs: substs,
             ty: for_ty
-        } = impl_self_ty(vcx, span, im.did);
+        } = impl_self_ty(vcx, span, impl_did);
         match infer::mk_subty(vcx.infcx,
                               false,
                               infer::RelateSelfType(span),
                               ty,
                               for_ty) {
-            result::Err(_) => continue,
-            result::Ok(()) => ()
+            Err(_) => continue,
+            Ok(()) => ()
         }
 
         // Now, in the previous example, for_ty is bound to
@@ -388,13 +389,13 @@ fn search_for_vtable(vcx: &VtableContext,
         // some value of U) with some_trait<T>. This would fail if T
         // and U weren't compatible.
 
-        debug!("(checking vtable) @2 relating trait \
+        debug!("(checking vtable) \\#2 relating trait \
                 ty {} to of_trait_ref {}",
-               vcx.infcx.trait_ref_to_str(trait_ref),
-               vcx.infcx.trait_ref_to_str(of_trait_ref));
+               vcx.infcx.trait_ref_to_str(&*trait_ref),
+               vcx.infcx.trait_ref_to_str(&*of_trait_ref));
 
         let of_trait_ref = of_trait_ref.subst(tcx, &substs);
-        relate_trait_refs(vcx, span, of_trait_ref, trait_ref);
+        relate_trait_refs(vcx, span, of_trait_ref, trait_ref.clone());
 
 
         // Recall that trait_ref -- the trait type we're casting to --
@@ -405,7 +406,7 @@ fn search_for_vtable(vcx: &VtableContext,
         // type variables in substs. This might still be OK: the
         // process of looking up bounds might constrain some of them.
         let im_generics =
-            ty::lookup_item_type(tcx, im.did).generics;
+            ty::lookup_item_type(tcx, impl_did).generics;
         let subres = lookup_vtables(vcx, span,
                                     im_generics.type_param_defs(), &substs,
                                     is_early);
@@ -429,7 +430,7 @@ fn search_for_vtable(vcx: &VtableContext,
                 they will be unified with the bounds for \
                 the target ty, {}",
                vcx.infcx.tys_to_str(substs_f.tps.as_slice()),
-               vcx.infcx.trait_ref_to_str(trait_ref));
+               vcx.infcx.trait_ref_to_str(&*trait_ref));
 
         // Next, we unify the fixed-up substitutions for the impl self
         // ty with the substitutions from the trait type that we're
@@ -438,12 +439,12 @@ fn search_for_vtable(vcx: &VtableContext,
         // I am a little confused about this, since it seems to be
         // very similar to the relate_trait_refs we already do,
         // but problems crop up if it is removed, so... -sully
-        connect_trait_tps(vcx, span, &substs_f, trait_ref, im.did);
+        connect_trait_tps(vcx, span, &substs_f, trait_ref.clone(), impl_did);
 
         // Finally, we register that we found a matching impl, and
         // record the def ID of the impl as well as the resolved list
         // of type substitutions for the target trait.
-        found.push(vtable_static(im.did, substs_f.tps.clone(), subres));
+        found.push(vtable_static(impl_did, substs_f.tps.clone(), subres));
     }
 
     match found.len() {
@@ -502,7 +503,7 @@ fn fixup_ty(vcx: &VtableContext,
 fn connect_trait_tps(vcx: &VtableContext,
                      span: Span,
                      impl_substs: &ty::substs,
-                     trait_ref: @ty::TraitRef,
+                     trait_ref: Rc<ty::TraitRef>,
                      impl_did: ast::DefId) {
     let tcx = vcx.tcx();
 
@@ -561,14 +562,14 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                     };
 
                       let vcx = fcx.vtable_context();
-                      let target_trait_ref = @ty::TraitRef {
+                      let target_trait_ref = Rc::new(ty::TraitRef {
                           def_id: target_def_id,
                           substs: ty::substs {
                               tps: target_substs.tps.clone(),
                               regions: target_substs.regions.clone(),
                               self_ty: Some(typ)
                           }
-                      };
+                      });
 
                       let param_bounds = ty::ParamBounds {
                           builtin_bounds: ty::EmptyBuiltinBounds(),
@@ -583,7 +584,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                                                      is_early);
 
                       if !is_early {
-                          insert_vtables(fcx, MethodCall::expr(ex.id), @vec!(vtables));
+                          insert_vtables(fcx, MethodCall::expr(ex.id), vec!(vtables));
                       }
 
                       // Now, if this is &trait, we need to link the
@@ -683,7 +684,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
     // Search for auto-adjustments to find trait coercions
     match fcx.inh.adjustments.borrow().find(&ex.id) {
         Some(adjustment) => {
-            match **adjustment {
+            match *adjustment {
                 AutoDerefRef(adj) => {
                     for autoderef in range(0, adj.autoderefs) {
                         let method_call = MethodCall::autoderef(ex.id, autoderef as u32);
@@ -743,7 +744,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
         [],
         impl_item.id);
 
-    let impl_trait_ref = @impl_trait_ref.subst(tcx, &param_env.free_substs);
+    let impl_trait_ref = impl_trait_ref.subst(tcx, &param_env.free_substs);
 
     let infcx = &infer::new_infer_ctxt(tcx);
     let vcx = VtableContext { infcx: infcx, param_env: &param_env };
@@ -761,7 +762,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
     // but that falls out of doing this.
     let param_bounds = ty::ParamBounds {
         builtin_bounds: ty::EmptyBuiltinBounds(),
-        trait_bounds: vec!(impl_trait_ref)
+        trait_bounds: vec!(Rc::new(impl_trait_ref))
     };
     let t = ty::node_id_to_type(tcx, impl_item.id);
     let t = t.subst(tcx, &param_env.free_substs);
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 6ad3d380b28..3843c38fd18 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -51,49 +51,36 @@ fn resolve_type_vars_in_type(fcx: &FnCtxt, sp: Span, typ: ty::t)
     }
 }
 
-fn resolve_type_vars_in_types(fcx: &FnCtxt, sp: Span, tys: &[ty::t])
-                          -> Vec<ty::t> {
-    tys.iter().map(|t| {
-        match resolve_type_vars_in_type(fcx, sp, *t) {
-            Some(t1) => t1,
-            None => ty::mk_err()
-        }
-    }).collect()
-}
-
 fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall) {
     let fcx = wbcx.fcx;
     let tcx = fcx.ccx.tcx;
 
     // Resolve any method map entry
-    match fcx.inh.method_map.borrow().find(&method_call) {
+    match fcx.inh.method_map.borrow_mut().pop(&method_call) {
         Some(method) => {
             debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})",
                    method_call, method.repr(tcx));
-            let method_ty = match resolve_type_vars_in_type(fcx, sp, method.ty) {
-                Some(t) => t,
-                None => {
-                    wbcx.success = false;
-                    return;
-                }
-            };
-            let mut new_tps = Vec::new();
-            for &subst in method.substs.tps.iter() {
-                match resolve_type_vars_in_type(fcx, sp, subst) {
-                    Some(t) => new_tps.push(t),
-                    None => { wbcx.success = false; return; }
-                }
-            }
             let new_method = MethodCallee {
                 origin: method.origin,
-                ty: method_ty,
+                ty: match resolve_type_vars_in_type(fcx, sp, method.ty) {
+                    Some(t) => t,
+                    None => {
+                        wbcx.success = false;
+                        return;
+                    }
+                },
                 substs: ty::substs {
-                    tps: new_tps,
+                    tps: method.substs.tps.move_iter().map(|subst| {
+                        match resolve_type_vars_in_type(fcx, sp, subst) {
+                            Some(t) => t,
+                            None => { wbcx.success = false; ty::mk_err() }
+                        }
+                    }).collect(),
                     regions: ty::ErasedRegions,
                     self_ty: None
                 }
             };
-            fcx.ccx.method_map.borrow_mut().insert(method_call, new_method);
+            tcx.method_map.borrow_mut().insert(method_call, new_method);
         }
         None => {}
     }
@@ -101,46 +88,46 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall
 
 fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) {
     // Resolve any vtable map entry
-    match fcx.inh.vtable_map.borrow().find_copy(&vtable_key) {
+    match fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
         Some(origins) => {
             let r_origins = resolve_origins(fcx, sp, origins);
-            fcx.ccx.vtable_map.borrow_mut().insert(vtable_key, r_origins);
             debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})",
                     vtable_key, r_origins.repr(fcx.tcx()));
+            fcx.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
         }
         None => {}
     }
 
     fn resolve_origins(fcx: &FnCtxt, sp: Span,
                        vtbls: vtable_res) -> vtable_res {
-        @vtbls.iter().map(|os| @os.iter().map(|origin| {
+        vtbls.move_iter().map(|os| os.move_iter().map(|origin| {
             match origin {
-                &vtable_static(def_id, ref tys, origins) => {
-                    let r_tys = resolve_type_vars_in_types(fcx,
-                                                           sp,
-                                                           tys.as_slice());
+                vtable_static(def_id, tys, origins) => {
+                    let r_tys = tys.move_iter().map(|t| {
+                        match resolve_type_vars_in_type(fcx, sp, t) {
+                            Some(t1) => t1,
+                            None => ty::mk_err()
+                        }
+                    }).collect();
                     let r_origins = resolve_origins(fcx, sp, origins);
                     vtable_static(def_id, r_tys, r_origins)
                 }
-                &vtable_param(n, b) => {
-                    vtable_param(n, b)
-                }
+                vtable_param(n, b) => vtable_param(n, b)
             }
         }).collect()).collect()
     }
 }
 
-fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
-                           -> Option<ty::t> {
+fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
     let fcx = wbcx.fcx;
     let tcx = fcx.ccx.tcx;
 
     // Resolve any borrowings for the node with id `id`
-    match fcx.inh.adjustments.borrow().find_copy(&id) {
-        None => (),
+    let resolved_adj = match fcx.inh.adjustments.borrow_mut().pop(&id) {
+        None => None,
 
         Some(adjustment) => {
-            match *adjustment {
+            Some(match adjustment {
                 ty::AutoAddEnv(store) => {
                     let r = match store {
                         ty::RegionTraitStore(r, _) => r,
@@ -156,6 +143,8 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                                 format!("cannot resolve bound for closure: \
                                          {}",
                                         infer::fixup_err_to_str(e)));
+                            wbcx.success = false;
+                            return;
                         }
                         Ok(r1) => {
                             // FIXME(eddyb) #2190 Allow only statically resolved
@@ -170,15 +159,12 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                                         "cannot coerce non-statically resolved bare fn")
                             }
 
-                            let resolved_adj = @ty::AutoAddEnv(match store {
+                            ty::AutoAddEnv(match store {
                                 ty::RegionTraitStore(..) => {
                                     ty::RegionTraitStore(r1, ast::MutMutable)
                                 }
                                 ty::UniqTraitStore => ty::UniqTraitStore
-                            });
-                            debug!("Adjustments for node {}: {:?}",
-                                   id, resolved_adj);
-                            tcx.adjustments.borrow_mut().insert(id, resolved_adj);
+                            })
                         }
                     }
                 }
@@ -190,42 +176,38 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                         resolve_vtable_map_entry(wbcx.fcx, sp, method_call);
                     }
 
-                    let fixup_region = |r| {
-                        match resolve_region(fcx.infcx(),
-                                             r,
-                                             resolve_all | force_all) {
-                            Ok(r1) => r1,
-                            Err(e) => {
-                                // This should not, I think, happen.
-                                tcx.sess.span_err(
-                                    sp,
-                                    format!("cannot resolve scope of borrow: \
-                                             {}",
-                                             infer::fixup_err_to_str(e)));
-                                r
-                            }
-                        }
-                    };
-
-                    let resolved_autoref = match adj.autoref {
-                        None => None,
-                        Some(ref r) => Some(r.map_region(fixup_region))
-                    };
-
-                    let resolved_adj = @ty::AutoDerefRef(ty::AutoDerefRef {
+                    ty::AutoDerefRef(ty::AutoDerefRef {
                         autoderefs: adj.autoderefs,
-                        autoref: resolved_autoref,
-                    });
-                    debug!("Adjustments for node {}: {:?}", id, resolved_adj);
-                    tcx.adjustments.borrow_mut().insert(id, resolved_adj);
+                        autoref: adj.autoref.map(|r| r.map_region(|r| {
+                            match resolve_region(fcx.infcx(), r,
+                                                resolve_all | force_all) {
+                                Ok(r1) => r1,
+                                Err(e) => {
+                                    // This should not, I think, happen.
+                                    tcx.sess.span_err(
+                                        sp,
+                                        format!("cannot resolve scope of borrow: \
+                                                {}",
+                                                infer::fixup_err_to_str(e)));
+                                    r
+                                }
+                            }
+                        })),
+                    })
                 }
 
-                ty::AutoObject(..) => {
-                    debug!("Adjustments for node {}: {:?}", id, adjustment);
-                    tcx.adjustments.borrow_mut().insert(id, adjustment);
-                }
-            }
+                adjustment => adjustment
+            })
         }
+    };
+
+    debug!("Adjustments for node {}: {:?}",
+           id, resolved_adj);
+    match resolved_adj {
+        Some(adj) => {
+            tcx.adjustments.borrow_mut().insert(id, adj);
+        }
+        None => {}
     }
 
     // Resolve the type of the node with id `id`
@@ -233,26 +215,23 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
     match resolve_type_vars_in_type(fcx, sp, n_ty) {
       None => {
         wbcx.success = false;
-        return None;
       }
 
       Some(t) => {
         debug!("resolve_type_vars_for_node(id={}, n_ty={}, t={})",
                id, ppaux::ty_to_str(tcx, n_ty), ppaux::ty_to_str(tcx, t));
         write_ty_to_tcx(tcx, id, t);
-        let mut ret = Some(t);
         fcx.opt_node_ty_substs(id, |substs| {
           let mut new_tps = Vec::new();
           for subst in substs.tps.iter() {
               match resolve_type_vars_in_type(fcx, sp, *subst) {
                 Some(t) => new_tps.push(t),
-                None => { wbcx.success = false; ret = None; break }
+                None => { wbcx.success = false; break }
               }
           }
           write_substs_to_tcx(tcx, id, new_tps);
-          ret.is_some()
+          wbcx.success
         });
-        ret
       }
     }
 }
@@ -401,7 +380,7 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, decl: &ast::FnDecl,
     for arg in decl.inputs.iter() {
         wbcx.visit_pat(arg.pat, ());
         // Privacy needs the type for the whole pattern, not just each binding
-        if !pat_util::pat_is_binding(fcx.tcx().def_map, arg.pat) {
+        if !pat_util::pat_is_binding(&fcx.tcx().def_map, arg.pat) {
             resolve_type_vars_for_node(wbcx, arg.pat.span, arg.pat.id);
         }
     }
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index c0fd73f4a36..3a50b0681e8 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -27,7 +27,6 @@ use middle::ty::{ty_uint, ty_uniq, ty_bare_fn, ty_closure};
 use middle::ty::type_is_ty_var;
 use middle::subst::Subst;
 use middle::ty;
-use middle::ty::{Impl, Method};
 use middle::typeck::CrateCtxt;
 use middle::typeck::infer::combine::Combine;
 use middle::typeck::infer::InferCtxt;
@@ -252,7 +251,8 @@ impl<'a> CoherenceChecker<'a> {
     fn check_implementation(&self, item: &Item,
                             associated_traits: &[TraitRef]) {
         let tcx = self.crate_context.tcx;
-        let self_type = ty::lookup_item_type(tcx, local_def(item.id));
+        let impl_did = local_def(item.id);
+        let self_type = ty::lookup_item_type(tcx, impl_did);
 
         // If there are no traits, then this implementation must have a
         // base type.
@@ -276,7 +276,7 @@ impl<'a> CoherenceChecker<'a> {
             }
         }
 
-        let implementation = self.create_impl_from_item(item);
+        let impl_methods = self.create_impl_from_item(item);
 
         for associated_trait in associated_traits.iter() {
             let trait_ref = ty::node_id_to_trait_ref(
@@ -285,7 +285,7 @@ impl<'a> CoherenceChecker<'a> {
                    trait_ref.repr(self.crate_context.tcx),
                    token::get_ident(item.ident));
 
-            self.add_trait_impl(trait_ref.def_id, implementation);
+            self.add_trait_impl(trait_ref.def_id, impl_did);
         }
 
         // Add the implementation to the mapping from implementation to base
@@ -300,20 +300,20 @@ impl<'a> CoherenceChecker<'a> {
             Some(base_type_def_id) => {
                 // FIXME: Gather up default methods?
                 if associated_traits.len() == 0 {
-                    self.add_inherent_impl(base_type_def_id, implementation);
+                    self.add_inherent_impl(base_type_def_id, impl_did);
                 }
             }
         }
 
-        tcx.impls.borrow_mut().insert(implementation.did, implementation);
+        tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
     }
 
     // Creates default method IDs and performs type substitutions for an impl
     // and trait pair. Then, for each provided method in the trait, inserts a
     // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
-    fn instantiate_default_methods(&self, impl_id: ast::DefId,
+    fn instantiate_default_methods(&self, impl_id: DefId,
                                    trait_ref: &ty::TraitRef,
-                                   all_methods: &mut Vec<@Method> ) {
+                                   all_methods: &mut Vec<DefId>) {
         let tcx = self.crate_context.tcx;
         debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
                impl_id, trait_ref.repr(tcx));
@@ -330,16 +330,16 @@ impl<'a> CoherenceChecker<'a> {
 
             // Create substitutions for the various trait parameters.
             let new_method_ty =
-                @subst_receiver_types_in_method_ty(
+                Rc::new(subst_receiver_types_in_method_ty(
                     tcx,
                     impl_id,
                     trait_ref,
                     new_did,
-                    *trait_method,
-                    Some(trait_method.def_id));
+                    &**trait_method,
+                    Some(trait_method.def_id)));
 
             debug!("new_method_ty={}", new_method_ty.repr(tcx));
-            all_methods.push(new_method_ty);
+            all_methods.push(new_did);
 
             // construct the polytype for the method based on the method_ty
             let new_generics = ty::Generics {
@@ -366,40 +366,24 @@ impl<'a> CoherenceChecker<'a> {
         }
     }
 
-    fn add_inherent_impl(&self, base_def_id: DefId,
-                         implementation: @Impl) {
+    fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
         let tcx = self.crate_context.tcx;
-        let implementation_list;
-        let mut inherent_impls = tcx.inherent_impls.borrow_mut();
-        match inherent_impls.find(&base_def_id) {
-            None => {
-                implementation_list = @RefCell::new(Vec::new());
-                inherent_impls.insert(base_def_id, implementation_list);
-            }
-            Some(&existing_implementation_list) => {
-                implementation_list = existing_implementation_list;
+        match tcx.inherent_impls.borrow().find(&base_def_id) {
+            Some(implementation_list) => {
+                implementation_list.borrow_mut().push(impl_def_id);
+                return;
             }
+            None => {}
         }
 
-        implementation_list.borrow_mut().push(implementation);
+        tcx.inherent_impls.borrow_mut().insert(base_def_id,
+                                               Rc::new(RefCell::new(vec!(impl_def_id))));
     }
 
-    fn add_trait_impl(&self, base_def_id: DefId,
-                      implementation: @Impl) {
-        let tcx = self.crate_context.tcx;
-        let implementation_list;
-        let mut trait_impls = tcx.trait_impls.borrow_mut();
-        match trait_impls.find(&base_def_id) {
-            None => {
-                implementation_list = @RefCell::new(Vec::new());
-                trait_impls.insert(base_def_id, implementation_list);
-            }
-            Some(&existing_implementation_list) => {
-                implementation_list = existing_implementation_list;
-            }
-        }
-
-        implementation_list.borrow_mut().push(implementation);
+    fn add_trait_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
+        ty::record_trait_implementation(self.crate_context.tcx,
+                                        base_def_id,
+                                        impl_def_id);
     }
 
     fn check_implementation_coherence(&self) {
@@ -410,34 +394,32 @@ impl<'a> CoherenceChecker<'a> {
 
     fn check_implementation_coherence_of(&self, trait_def_id: DefId) {
         // Unify pairs of polytypes.
-        self.iter_impls_of_trait_local(trait_def_id, |a| {
-            let implementation_a = a;
+        self.iter_impls_of_trait_local(trait_def_id, |impl_a| {
             let polytype_a =
-                self.get_self_type_for_implementation(implementation_a);
+                self.get_self_type_for_implementation(impl_a);
 
             // "We have an impl of trait <trait_def_id> for type <polytype_a>,
-            // and that impl is <implementation_a>"
-            self.iter_impls_of_trait(trait_def_id, |b| {
-                let implementation_b = b;
+            // and that impl is <impl_a>"
+            self.iter_impls_of_trait(trait_def_id, |impl_b| {
 
                 // An impl is coherent with itself
-                if a.did != b.did {
+                if impl_a != impl_b {
                     let polytype_b = self.get_self_type_for_implementation(
-                            implementation_b);
+                            impl_b);
 
                     if self.polytypes_unify(polytype_a.clone(), polytype_b) {
                         let session = &self.crate_context.tcx.sess;
                         session.span_err(
-                            self.span_of_impl(implementation_a),
+                            self.span_of_impl(impl_a),
                             format!("conflicting implementations for trait `{}`",
                                  ty::item_path_str(self.crate_context.tcx,
                                                    trait_def_id)));
-                        if implementation_b.did.krate == LOCAL_CRATE {
-                            session.span_note(self.span_of_impl(implementation_b),
+                        if impl_b.krate == LOCAL_CRATE {
+                            session.span_note(self.span_of_impl(impl_b),
                                               "note conflicting implementation here");
                         } else {
                             let crate_store = &self.crate_context.tcx.sess.cstore;
-                            let cdata = crate_store.get_crate_data(implementation_b.did.krate);
+                            let cdata = crate_store.get_crate_data(impl_b.krate);
                             session.note(
                                 "conflicting implementation in crate `" + cdata.name + "`");
                         }
@@ -447,7 +429,7 @@ impl<'a> CoherenceChecker<'a> {
         })
     }
 
-    fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) {
+    fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |DefId|) {
         self.iter_impls_of_trait_local(trait_def_id, |x| f(x));
 
         if trait_def_id.krate == LOCAL_CRATE {
@@ -456,17 +438,17 @@ impl<'a> CoherenceChecker<'a> {
 
         let crate_store = &self.crate_context.tcx.sess.cstore;
         csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| {
-            let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id);
-            let _ = lookup_item_type(self.crate_context.tcx, implementation.did);
-            f(implementation);
+            // Is this actually necessary?
+            let _ = lookup_item_type(self.crate_context.tcx, impl_def_id);
+            f(impl_def_id);
         });
     }
 
-    fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |@Impl|) {
+    fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |DefId|) {
         match self.crate_context.tcx.trait_impls.borrow().find(&trait_def_id) {
             Some(impls) => {
-                for &im in impls.borrow().iter() {
-                    f(im);
+                for &impl_did in impls.borrow().iter() {
+                    f(impl_did);
                 }
             }
             None => { /* no impls? */ }
@@ -526,9 +508,9 @@ impl<'a> CoherenceChecker<'a> {
                             b.monotype).is_ok()
     }
 
-    fn get_self_type_for_implementation(&self, implementation: @Impl)
+    fn get_self_type_for_implementation(&self, impl_did: DefId)
                                         -> ty_param_bounds_and_ty {
-        self.crate_context.tcx.tcache.borrow().get_copy(&implementation.did)
+        self.crate_context.tcx.tcache.borrow().get_copy(&impl_did)
     }
 
     // Privileged scope checking
@@ -538,7 +520,7 @@ impl<'a> CoherenceChecker<'a> {
     }
 
     fn trait_ref_to_trait_def_id(&self, trait_ref: &TraitRef) -> DefId {
-        let def_map = self.crate_context.tcx.def_map;
+        let def_map = &self.crate_context.tcx.def_map;
         let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
         let trait_id = def_id_of_def(trait_def);
         return trait_id;
@@ -580,15 +562,13 @@ impl<'a> CoherenceChecker<'a> {
         }
     }
 
-    // Converts an implementation in the AST to an Impl structure.
-    fn create_impl_from_item(&self, item: &Item) -> @Impl {
-        let tcx = self.crate_context.tcx;
+    // Converts an implementation in the AST to a vector of methods.
+    fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
         match item.node {
             ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
-                let mut methods = Vec::new();
-                for ast_method in ast_methods.iter() {
-                    methods.push(ty::method(tcx, local_def(ast_method.id)));
-                }
+                let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
+                    local_def(ast_method.id)
+                }).collect();
 
                 for trait_ref in trait_refs.iter() {
                     let ty_trait_ref = ty::node_id_to_trait_ref(
@@ -596,15 +576,11 @@ impl<'a> CoherenceChecker<'a> {
                         trait_ref.ref_id);
 
                     self.instantiate_default_methods(local_def(item.id),
-                                                     ty_trait_ref,
+                                                     &*ty_trait_ref,
                                                      &mut methods);
                 }
 
-                return @Impl {
-                    did: local_def(item.id),
-                    ident: item.ident,
-                    methods: methods
-                };
+                methods
             }
             _ => {
                 self.crate_context.tcx.sess.span_bug(item.span,
@@ -613,9 +589,9 @@ impl<'a> CoherenceChecker<'a> {
         }
     }
 
-    fn span_of_impl(&self, implementation: @Impl) -> Span {
-        assert_eq!(implementation.did.krate, LOCAL_CRATE);
-        self.crate_context.tcx.map.span(implementation.did.node)
+    fn span_of_impl(&self, impl_did: DefId) -> Span {
+        assert_eq!(impl_did.krate, LOCAL_CRATE);
+        self.crate_context.tcx.map.span(impl_did.node)
     }
 
     // External crate handling
@@ -624,36 +600,35 @@ impl<'a> CoherenceChecker<'a> {
                          impls_seen: &mut HashSet<DefId>,
                          impl_def_id: DefId) {
         let tcx = self.crate_context.tcx;
-        let implementation = @csearch::get_impl(tcx, impl_def_id);
+        let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
 
         // Make sure we don't visit the same implementation multiple times.
-        if !impls_seen.insert(implementation.did) {
+        if !impls_seen.insert(impl_def_id) {
             // Skip this one.
             return
         }
         // Good. Continue.
 
-        let _ = lookup_item_type(tcx, implementation.did);
-        let associated_traits = get_impl_trait(tcx, implementation.did);
+        let _ = lookup_item_type(tcx, impl_def_id);
+        let associated_traits = get_impl_trait(tcx, impl_def_id);
 
         // Do a sanity check.
         assert!(associated_traits.is_some());
 
         // Record all the trait methods.
         for trait_ref in associated_traits.iter() {
-              self.add_trait_impl(trait_ref.def_id, implementation);
+            self.add_trait_impl(trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for method in implementation.methods.iter() {
-            for source in method.provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut()
-                   .insert(method.def_id, *source);
+        for &method_def_id in methods.iter() {
+            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
+                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
             }
         }
 
-        tcx.impls.borrow_mut().insert(implementation.did, implementation);
+        tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
     }
 
     // Adds implementations and traits from external crates to the coherence
@@ -680,22 +655,21 @@ impl<'a> CoherenceChecker<'a> {
             Some(id) => id, None => { return }
         };
 
-        let trait_impls = tcx.trait_impls.borrow();
-        let impls_opt = trait_impls.find(&drop_trait);
-        let impls;
-        match impls_opt {
+        let impl_methods = tcx.impl_methods.borrow();
+        let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
             None => return, // No types with (new-style) dtors present.
-            Some(found_impls) => impls = found_impls
-        }
+            Some(found_impls) => found_impls
+        };
 
-        for impl_info in impls.borrow().iter() {
-            if impl_info.methods.len() < 1 {
+        for &impl_did in trait_impls.borrow().iter() {
+            let methods = impl_methods.get(&impl_did);
+            if methods.len() < 1 {
                 // We'll error out later. For now, just don't ICE.
                 continue;
             }
-            let method_def_id = impl_info.methods.get(0).def_id;
+            let method_def_id = *methods.get(0);
 
-            let self_type = self.get_self_type_for_implementation(*impl_info);
+            let self_type = self.get_self_type_for_implementation(impl_did);
             match ty::get(self_type.ty).sty {
                 ty::ty_enum(type_def_id, _) |
                 ty::ty_struct(type_def_id, _) => {
@@ -705,9 +679,9 @@ impl<'a> CoherenceChecker<'a> {
                 }
                 _ => {
                     // Destructors only work on nominal types.
-                    if impl_info.did.krate == ast::LOCAL_CRATE {
+                    if impl_did.krate == ast::LOCAL_CRATE {
                         {
-                            match tcx.map.find(impl_info.did.node) {
+                            match tcx.map.find(impl_did.node) {
                                 Some(ast_map::NodeItem(item)) => {
                                     tcx.sess.span_err((*item).span,
                                                       "the Drop trait may \
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 490a52df2ba..0102001aa3c 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -126,7 +126,7 @@ impl<'a> AstConv for CrateCtxt<'a> {
         }
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
         get_trait_def(self, id)
     }
 
@@ -195,7 +195,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                     // For each method, construct a suitable ty::Method and
                     // store it into the `tcx.methods` table:
                     for m in ms.iter() {
-                        let ty_method = @match m {
+                        let ty_method = Rc::new(match m {
                             &ast::Required(ref m) => {
                                 ty_method_of_trait_method(
                                     ccx, trait_id, &trait_ty_generics,
@@ -209,10 +209,10 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                                     &m.id, &m.ident, &m.explicit_self,
                                     &m.generics, &m.fn_style, m.decl)
                             }
-                        };
+                        });
 
                         if ty_method.explicit_self == ast::SelfStatic {
-                            make_static_method_ty(ccx, trait_id, ty_method,
+                            make_static_method_ty(ccx, trait_id, &*ty_method,
                                                   &trait_ty_generics);
                         }
 
@@ -221,7 +221,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                     }
 
                     // Add an entry mapping
-                    let method_def_ids = @ms.iter().map(|m| {
+                    let method_def_ids = Rc::new(ms.iter().map(|m| {
                         match m {
                             &ast::Required(ref ty_method) => {
                                 local_def(ty_method.id)
@@ -230,7 +230,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                                 local_def(method.id)
                             }
                         }
-                    }).collect();
+                    }).collect());
 
                     let trait_def_id = local_def(trait_id);
                     tcx.trait_method_def_ids.borrow_mut()
@@ -342,10 +342,10 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
         new_type_param_defs.push(ty::TypeParameterDef {
             ident: special_idents::self_,
             def_id: dummy_defid,
-            bounds: @ty::ParamBounds {
+            bounds: Rc::new(ty::ParamBounds {
                 builtin_bounds: ty::EmptyBuiltinBounds(),
                 trait_bounds: vec!(self_trait_ref)
-            },
+            }),
             default: None
         });
 
@@ -412,7 +412,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
     assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
 
     let self_ty = ty::mk_self(ccx.tcx, local_def(id));
-    let mut ty_trait_refs: Vec<@ty::TraitRef> = Vec::new();
+    let mut ty_trait_refs: Vec<Rc<ty::TraitRef>> = Vec::new();
     let mut bounds = ty::EmptyBuiltinBounds();
     for ast_trait_ref in ast_trait_refs.iter() {
         let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
@@ -434,7 +434,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
         }
     }
 
-    tcx.supertraits.borrow_mut().insert(local_def(id), @ty_trait_refs);
+    tcx.supertraits.borrow_mut().insert(local_def(id), Rc::new(ty_trait_refs));
     bounds
 }
 
@@ -489,12 +489,12 @@ fn convert_methods(ccx: &CrateCtxt,
         let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
         let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
                                                          num_rcvr_ty_params);
-        let mty = @ty_of_method(ccx,
-                                container,
-                                *m,
-                                untransformed_rcvr_ty,
-                                rcvr_ast_generics,
-                                rcvr_visibility);
+        let mty = Rc::new(ty_of_method(ccx,
+                                       container,
+                                       *m,
+                                       untransformed_rcvr_ty,
+                                       rcvr_ast_generics,
+                                       rcvr_visibility));
         let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
         debug!("method {} (id {}) has type {}",
                 m.ident.repr(ccx.tcx),
@@ -726,7 +726,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
         result
     }).collect();
 
-    tcx.struct_fields.borrow_mut().insert(local_def(id), @field_tys);
+    tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
 
     let super_struct = match struct_def.super_struct {
         Some(t) => match t.node {
@@ -813,8 +813,7 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
 
 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
                              ast_trait_ref: &ast::TraitRef,
-                             self_ty: ty::t) -> @ty::TraitRef
-{
+                             self_ty: ty::t) -> Rc<ty::TraitRef> {
     /*!
      * Instantiates the path for the given trait reference, assuming that
      * it's bound to a valid trait type. Returns the def_id for the defining
@@ -831,8 +830,8 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
                     ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
 
             ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
-                                                   trait_ref);
-            return trait_ref;
+                                                   trait_ref.clone());
+            trait_ref
         }
         _ => {
             ccx.tcx.sess.span_fatal(
@@ -843,7 +842,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
     }
 }
 
-fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
+fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
     if trait_id.krate != ast::LOCAL_CRATE {
         return ty::lookup_trait_def(ccx.tcx, trait_id)
     }
@@ -855,11 +854,11 @@ fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
     }
 }
 
-pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
+pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
     match tcx.trait_defs.borrow().find(&def_id) {
-        Some(&def) => return def,
+        Some(def) => return def.clone(),
         _ => {}
     }
 
@@ -872,13 +871,16 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
                                             it.id,
                                             it.span,
                                             supertraits.as_slice());
-            let trait_ref = @ty::TraitRef {def_id: def_id,
-                                           substs: substs};
-            let trait_def = @ty::TraitDef {generics: ty_generics,
-                                           bounds: bounds,
-                                           trait_ref: trait_ref};
-            tcx.trait_defs.borrow_mut().insert(def_id, trait_def);
-            return trait_def;
+            let trait_def = Rc::new(ty::TraitDef {
+                generics: ty_generics,
+                bounds: bounds,
+                trait_ref: Rc::new(ty::TraitRef {
+                    def_id: def_id,
+                    substs: substs
+                })
+            });
+            tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
+            trait_def
         }
         ref s => {
             tcx.sess.span_bug(
@@ -999,24 +1001,24 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
     }
 }
 
-pub fn ty_generics_for_type(ccx: &CrateCtxt,
-                            generics: &ast::Generics)
-                            -> ty::Generics {
+fn ty_generics_for_type(ccx: &CrateCtxt,
+                        generics: &ast::Generics)
+                        -> ty::Generics {
     ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
 }
 
-pub fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
-                                    generics: &ast::Generics,
-                                    base_index: uint)
-                                    -> ty::Generics {
+fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
+                                generics: &ast::Generics,
+                                base_index: uint)
+                                -> ty::Generics {
     let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
     ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
 }
 
-pub fn ty_generics(ccx: &CrateCtxt,
-                   lifetimes: &Vec<ast::Lifetime>,
-                   ty_params: &OwnedSlice<ast::TyParam>,
-                   base_index: uint) -> ty::Generics {
+fn ty_generics(ccx: &CrateCtxt,
+               lifetimes: &Vec<ast::Lifetime>,
+               ty_params: &OwnedSlice<ast::TyParam>,
+               base_index: uint) -> ty::Generics {
     return ty::Generics {
         region_param_defs: Rc::new(lifetimes.iter().map(|l| {
                 ty::RegionParameterDef { name: l.name,
@@ -1025,12 +1027,12 @@ pub fn ty_generics(ccx: &CrateCtxt,
         type_param_defs: Rc::new(ty_params.iter().enumerate().map(|(offset, param)| {
             let existing_def_opt = {
                 let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
-                ty_param_defs.find(&param.id).map(|&def| def)
+                ty_param_defs.find(&param.id).map(|def| def.clone())
             };
             existing_def_opt.unwrap_or_else(|| {
                 let param_ty = ty::param_ty {idx: base_index + offset,
                                              def_id: local_def(param.id)};
-                let bounds = @compute_bounds(ccx, param_ty, &param.bounds);
+                let bounds = Rc::new(compute_bounds(ccx, param_ty, &param.bounds));
                 let default = param.default.map(|path| {
                     let ty = ast_ty_to_ty(ccx, &ExplicitRscope, path);
                     let cur_idx = param_ty.idx;
@@ -1056,7 +1058,7 @@ pub fn ty_generics(ccx: &CrateCtxt,
                     default: default
                 };
                 debug!("def for param: {}", def.repr(ccx.tcx));
-                ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def);
+                ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
                 def
             })
         }).collect()),
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index ad0590318ea..e921674ad83 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -195,7 +195,7 @@ impl<'f> Coerce<'f> {
     }
 
     pub fn subtype(&self, a: ty::t, b: ty::t) -> CoerceResult {
-        match Sub(*self.get_ref()).tys(a, b) {
+        match Sub(self.get_ref().clone()).tys(a, b) {
             Ok(_) => Ok(None),         // No coercion required.
             Err(ref e) => Err(*e)
         }
@@ -232,8 +232,9 @@ impl<'f> Coerce<'f> {
         // to type check, we will construct the type that `&M*expr` would
         // yield.
 
-        let sub = Sub(*self.get_ref());
-        let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let sub = Sub(self.get_ref().clone());
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_borrow = self.get_ref().infcx.next_region_var(coercion);
 
         let inner_ty = match *sty_a {
             ty::ty_box(typ) | ty::ty_uniq(typ) => typ,
@@ -247,7 +248,7 @@ impl<'f> Coerce<'f> {
                                      r_borrow,
                                      mt {ty: inner_ty, mutbl: mt_b.mutbl});
         if_ok!(sub.tys(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
             autoref: Some(AutoPtr(r_borrow, mt_b.mutbl))
         })))
@@ -269,10 +270,11 @@ impl<'f> Coerce<'f> {
             }
         };
 
-        let r_a = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_a = self.get_ref().infcx.next_region_var(coercion);
         let a_borrowed = ty::mk_str(self.get_ref().infcx.tcx, VstoreSlice(r_a));
         if_ok!(self.subtype(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
             autoref: Some(AutoBorrowVec(r_a, MutImmutable))
         })))
@@ -288,8 +290,9 @@ impl<'f> Coerce<'f> {
                a.inf_str(self.get_ref().infcx), sty_a,
                b.inf_str(self.get_ref().infcx));
 
-        let sub = Sub(*self.get_ref());
-        let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let sub = Sub(self.get_ref().clone());
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_borrow = self.get_ref().infcx.next_region_var(coercion);
         let ty_inner = match *sty_a {
             ty::ty_uniq(t) | ty::ty_ptr(ty::mt{ty: t, ..}) |
             ty::ty_rptr(_, ty::mt{ty: t, ..}) => match ty::get(t).sty {
@@ -307,7 +310,7 @@ impl<'f> Coerce<'f> {
         let a_borrowed = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
                                       mt {ty: ty_inner, mutbl: mutbl_b});
         if_ok!(sub.tys(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
             autoref: Some(AutoBorrowVec(r_borrow, mutbl_b))
         })))
@@ -324,7 +327,8 @@ impl<'f> Coerce<'f> {
                b.inf_str(self.get_ref().infcx));
 
         let tcx = self.get_ref().infcx.tcx;
-        let r_a = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_a = self.get_ref().infcx.next_region_var(coercion);
 
         let a_borrowed = match *sty_a {
             ty::ty_trait(~ty::TyTrait { def_id, ref substs, bounds, .. }) => {
@@ -337,7 +341,7 @@ impl<'f> Coerce<'f> {
         };
 
         if_ok!(self.subtype(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
             autoref: Some(AutoBorrowObj(r_a, b_mutbl))
         })))
@@ -384,7 +388,7 @@ impl<'f> Coerce<'f> {
                 _ => return self.subtype(a, b)
             };
 
-            let adj = @ty::AutoAddEnv(fn_ty_b.store);
+            let adj = ty::AutoAddEnv(fn_ty_b.store);
             let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
                                            ty::ClosureTy {
                                                 sig: fn_ty_a.sig.clone(),
@@ -419,7 +423,7 @@ impl<'f> Coerce<'f> {
         // although references and unsafe ptrs have the same
         // representation, we still register an AutoDerefRef so that
         // regionck knows that the region for `a` must be valid here
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
             autoref: Some(ty::AutoUnsafe(mt_b.mutbl))
         })))
@@ -438,7 +442,7 @@ impl<'f> Coerce<'f> {
                a.inf_str(self.get_ref().infcx), sty_a,
                b.inf_str(self.get_ref().infcx));
 
-        Ok(Some(@ty::AutoObject(trait_store, bounds,
-                                trait_def_id, trait_substs.clone())))
+        Ok(Some(ty::AutoObject(trait_store, bounds,
+                               trait_def_id, trait_substs.clone())))
     }
 }
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index bd3bb18fa33..54cf6524664 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -235,19 +235,6 @@ pub trait Combine {
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
 
-    fn flds(&self, a: ty::field, b: ty::field) -> cres<ty::field> {
-        if a.ident == b.ident {
-            self.mts(&a.mt, &b.mt)
-                .and_then(|mt| Ok(ty::field {ident: a.ident, mt: mt}) )
-                .or_else(|e| Err(ty::terr_in_field(@e, a.ident)) )
-        } else {
-            Err(ty::terr_record_fields(
-                                       expected_found(self,
-                                                      a.ident,
-                                                      b.ident)))
-        }
-    }
-
     fn args(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         self.contratys(a, b).and_then(|t| Ok(t))
     }
@@ -337,6 +324,7 @@ pub trait Combine {
     }
 }
 
+#[deriving(Clone)]
 pub struct CombineFields<'a> {
     pub infcx: &'a InferCtxt<'a>,
     pub a_is_expected: bool,
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index 6ba727f9d4d..a5d41b15d5d 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -76,6 +76,7 @@ use middle::typeck::infer::region_inference::ProcessedErrors;
 use middle::typeck::infer::region_inference::SameRegions;
 use std::cell::{Cell, RefCell};
 use std::char::from_u32;
+use std::rc::Rc;
 use std::strbuf::StrBuf;
 use syntax::ast;
 use syntax::ast_map;
@@ -158,7 +159,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
         let p_errors = self.process_errors(errors);
         let errors = if p_errors.is_empty() { errors } else { &p_errors };
         for error in errors.iter() {
-            match *error {
+            match error.clone() {
                 ConcreteFailure(origin, sub, sup) => {
                     self.report_concrete_failure(origin, sub, sup);
                 }
@@ -206,7 +207,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
         let mut same_regions = Vec::new();
         let mut processed_errors = Vec::new();
         for error in errors.iter() {
-            match *error {
+            match error.clone() {
                 ConcreteFailure(origin, sub, sup) => {
                     debug!("processing ConcreteFailure")
                     let trace = match origin {
@@ -661,10 +662,10 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
                                same_regions: &[SameRegions]) {
         self.give_suggestion(same_regions);
         for vo in var_origins.iter() {
-            self.report_inference_failure(*vo);
+            self.report_inference_failure(vo.clone());
         }
-        for &(trace, terr) in trace_origins.iter() {
-            self.report_type_error(trace, &terr);
+        for &(ref trace, terr) in trace_origins.iter() {
+            self.report_type_error(trace.clone(), &terr);
         }
     }
 
@@ -1391,12 +1392,12 @@ impl Resolvable for ty::t {
     }
 }
 
-impl Resolvable for @ty::TraitRef {
-    fn resolve(&self, infcx: &InferCtxt) -> @ty::TraitRef {
-        @infcx.resolve_type_vars_in_trait_ref_if_possible(*self)
+impl Resolvable for Rc<ty::TraitRef> {
+    fn resolve(&self, infcx: &InferCtxt) -> Rc<ty::TraitRef> {
+        Rc::new(infcx.resolve_type_vars_in_trait_ref_if_possible(&**self))
     }
     fn contains_error(&self) -> bool {
-        ty::trait_ref_contains_error(*self)
+        ty::trait_ref_contains_error(&**self)
     }
 }
 
diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs
index 9f87993279c..32bc7eedf2f 100644
--- a/src/librustc/middle/typeck/infer/glb.rs
+++ b/src/librustc/middle/typeck/infer/glb.rs
@@ -38,11 +38,11 @@ impl<'f> Combine for Glb<'f> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { "glb".to_owned() }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace }
+    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(*self.get_ref()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(*self.get_ref()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(*self.get_ref()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
         let tcx = self.get_ref().infcx.tcx;
@@ -78,7 +78,7 @@ impl<'f> Combine for Glb<'f> {
     }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
-        Lub(*self.get_ref()).tys(a, b)
+        self.lub().tys(a, b)
     }
 
     fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
@@ -108,12 +108,12 @@ impl<'f> Combine for Glb<'f> {
                a.inf_str(self.get_ref().infcx),
                b.inf_str(self.get_ref().infcx));
 
-        Ok(self.get_ref().infcx.region_vars.glb_regions(Subtype(self.get_ref().trace), a, b))
+        Ok(self.get_ref().infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
     }
 
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
-        Lub(*self.get_ref()).regions(a, b)
+        self.lub().regions(a, b)
     }
 
     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
@@ -137,11 +137,11 @@ impl<'f> Combine for Glb<'f> {
         // Instantiate each bound region with a fresh region variable.
         let (a_with_fresh, a_map) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, a);
+                self.trace(), a);
         let a_vars = var_ids(self, &a_map);
         let (b_with_fresh, b_map) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, b);
+                self.trace(), b);
         let b_vars = var_ids(self, &b_map);
 
         // Collect constraints.
diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs
index 83cc9294244..ebfb17a8876 100644
--- a/src/librustc/middle/typeck/infer/lattice.rs
+++ b/src/librustc/middle/typeck/infer/lattice.rs
@@ -47,26 +47,26 @@ use util::common::indenter;
 
 use collections::HashMap;
 
-pub trait LatticeValue {
-    fn sub(cf: &CombineFields, a: &Self, b: &Self) -> ures;
-    fn lub(cf: &CombineFields, a: &Self, b: &Self) -> cres<Self>;
-    fn glb(cf: &CombineFields, a: &Self, b: &Self) -> cres<Self>;
+trait LatticeValue {
+    fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
+    fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
+    fn glb(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
 }
 
 pub type LatticeOp<'a, T> =
-    |cf: &CombineFields, a: &T, b: &T|: 'a -> cres<T>;
+    |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
 
 impl LatticeValue for ty::t {
-    fn sub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> ures {
-        Sub(*cf).tys(*a, *b).to_ures()
+    fn sub(cf: CombineFields, a: &ty::t, b: &ty::t) -> ures {
+        Sub(cf).tys(*a, *b).to_ures()
     }
 
-    fn lub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
-        Lub(*cf).tys(*a, *b)
+    fn lub(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
+        Lub(cf).tys(*a, *b)
     }
 
-    fn glb(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
-        Glb(*cf).tys(*a, *b)
+    fn glb(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
+        Glb(cf).tys(*a, *b)
     }
 }
 
@@ -142,7 +142,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
         match (&a_bounds.ub, &b_bounds.lb) {
             (&Some(ref a_ub), &Some(ref b_lb)) => {
                 let r = self.infcx.try(
-                    || LatticeValue::sub(self, a_ub, b_lb));
+                    || LatticeValue::sub(self.clone(), a_ub, b_lb));
                 match r {
                     Ok(()) => {
                         return Ok(());
@@ -232,7 +232,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
             (&Some(_),       &None) => Ok((*a).clone()),
             (&None,          &Some(_)) => Ok((*b).clone()),
             (&Some(ref v_a), &Some(ref v_b)) => {
-                lattice_op(self, v_a, v_b).and_then(|v| Ok(Some(v)))
+                lattice_op(self.clone(), v_a, v_b).and_then(|v| Ok(Some(v)))
             }
         }
     }
@@ -314,7 +314,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
                 uok()
             }
             (&Some(ref t_a), &Some(ref t_b)) => {
-                LatticeValue::sub(self, t_a, t_b)
+                LatticeValue::sub(self.clone(), t_a, t_b)
             }
         }
     }
@@ -337,7 +337,7 @@ pub trait TyLatticeDir {
 }
 
 impl<'f> LatticeDir for Lub<'f> {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { *self.get_ref() }
+    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
     fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.ub.clone() }
     fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
         Bounds { ub: Some(t), ..(*b).clone() }
@@ -351,7 +351,7 @@ impl<'f> TyLatticeDir for Lub<'f> {
 }
 
 impl<'f> LatticeDir for Glb<'f> {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { *self.get_ref() }
+    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
     fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.lb.clone() }
     fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
         Bounds { lb: Some(t), ..(*b).clone() }
diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs
index d42205f0035..d09bbc4253b 100644
--- a/src/librustc/middle/typeck/infer/lub.rs
+++ b/src/librustc/middle/typeck/infer/lub.rs
@@ -37,11 +37,11 @@ impl<'f> Combine for Lub<'f> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { "lub".to_owned() }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace }
+    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(*self.get_ref()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(*self.get_ref()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(*self.get_ref()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
         let tcx = self.get_ref().infcx.tcx;
@@ -72,7 +72,7 @@ impl<'f> Combine for Lub<'f> {
     }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
-        Glb(*self.get_ref()).tys(a, b)
+        self.glb().tys(a, b)
     }
 
     fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
@@ -98,7 +98,7 @@ impl<'f> Combine for Lub<'f> {
 
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
-        return Glb(*self.get_ref()).regions(a, b);
+        self.glb().regions(a, b)
     }
 
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
@@ -107,7 +107,7 @@ impl<'f> Combine for Lub<'f> {
                a.inf_str(self.get_ref().infcx),
                b.inf_str(self.get_ref().infcx));
 
-        Ok(self.get_ref().infcx.region_vars.lub_regions(Subtype(self.get_ref().trace), a, b))
+        Ok(self.get_ref().infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
     }
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
@@ -123,10 +123,10 @@ impl<'f> Combine for Lub<'f> {
         // Instantiate each bound region with a fresh region variable.
         let (a_with_fresh, a_map) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, a);
+                self.trace(), a);
         let (b_with_fresh, _) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, b);
+                self.trace(), b);
 
         // Collect constraints.
         let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index b2143b7d798..258f286d8f0 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -38,7 +38,7 @@ use middle::typeck::infer::to_str::InferStr;
 use middle::typeck::infer::unify::{ValsAndBindings, Root};
 use middle::typeck::infer::error_reporting::ErrorReporting;
 use std::cell::{Cell, RefCell};
-use std::result;
+use std::rc::Rc;
 use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
 use syntax::codemap;
@@ -72,7 +72,7 @@ pub struct Bounds<T> {
 pub type cres<T> = Result<T,ty::type_err>; // "combine result"
 pub type ures = cres<()>; // "unify result"
 pub type fres<T> = Result<T, fixup_err>; // "fixup result"
-pub type CoerceResult = cres<Option<@ty::AutoAdjustment>>;
+pub type CoerceResult = cres<Option<ty::AutoAdjustment>>;
 
 pub struct InferCtxt<'a> {
     pub tcx: &'a ty::ctxt,
@@ -129,7 +129,7 @@ pub enum TypeOrigin {
 #[deriving(Clone)]
 pub enum ValuePairs {
     Types(ty::expected_found<ty::t>),
-    TraitRefs(ty::expected_found<@ty::TraitRef>),
+    TraitRefs(ty::expected_found<Rc<ty::TraitRef>>),
 }
 
 /// The trace designates the path through inference that we took to
@@ -301,7 +301,7 @@ pub fn common_supertype(cx: &InferCtxt,
         values: Types(expected_found(a_is_expected, a, b))
     };
 
-    let result = cx.commit(|| cx.lub(a_is_expected, trace).tys(a, b));
+    let result = cx.commit(|| cx.lub(a_is_expected, trace.clone()).tys(a, b));
     match result {
         Ok(t) => t,
         Err(ref err) => {
@@ -375,8 +375,8 @@ pub fn mk_eqty(cx: &InferCtxt,
 pub fn mk_sub_trait_refs(cx: &InferCtxt,
                          a_is_expected: bool,
                          origin: TypeOrigin,
-                         a: @ty::TraitRef,
-                         b: @ty::TraitRef)
+                         a: Rc<ty::TraitRef>,
+                         b: Rc<ty::TraitRef>)
     -> ures
 {
     debug!("mk_sub_trait_refs({} <: {})",
@@ -385,10 +385,10 @@ pub fn mk_sub_trait_refs(cx: &InferCtxt,
         cx.commit(|| {
             let trace = TypeTrace {
                 origin: origin,
-                values: TraitRefs(expected_found(a_is_expected, a, b))
+                values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
             };
             let suber = cx.sub(a_is_expected, trace);
-            suber.trait_refs(a, b)
+            suber.trait_refs(&*a, &*b)
         })
     }).to_ures()
 }
@@ -666,8 +666,8 @@ impl<'a> InferCtxt<'a> {
 
     pub fn resolve_type_vars_if_possible(&self, typ: ty::t) -> ty::t {
         match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) {
-          result::Ok(new_type) => new_type,
-          result::Err(_) => typ
+            Ok(new_type) => new_type,
+            Err(_) => typ
         }
     }
 
@@ -854,7 +854,7 @@ impl Repr for TypeOrigin {
 impl SubregionOrigin {
     pub fn span(&self) -> Span {
         match *self {
-            Subtype(a) => a.span(),
+            Subtype(ref a) => a.span(),
             InfStackClosure(a) => a,
             InvokeClosure(a) => a,
             DerefPointer(a) => a,
@@ -877,7 +877,7 @@ impl SubregionOrigin {
 impl Repr for SubregionOrigin {
     fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
-            Subtype(a) => format!("Subtype({})", a.repr(tcx)),
+            Subtype(ref a) => format!("Subtype({})", a.repr(tcx)),
             InfStackClosure(a) => format!("InfStackClosure({})", a.repr(tcx)),
             InvokeClosure(a) => format!("InvokeClosure({})", a.repr(tcx)),
             DerefPointer(a) => format!("DerefPointer({})", a.repr(tcx)),
@@ -907,7 +907,7 @@ impl RegionVariableOrigin {
             AddrOfRegion(a) => a,
             AddrOfSlice(a) => a,
             Autoref(a) => a,
-            Coercion(a) => a.span(),
+            Coercion(ref a) => a.span(),
             EarlyBoundRegion(a, _) => a,
             LateBoundRegion(a, _) => a,
             BoundRegionInFnType(a, _) => a,
@@ -925,7 +925,7 @@ impl Repr for RegionVariableOrigin {
             AddrOfRegion(a) => format!("AddrOfRegion({})", a.repr(tcx)),
             AddrOfSlice(a) => format!("AddrOfSlice({})", a.repr(tcx)),
             Autoref(a) => format!("Autoref({})", a.repr(tcx)),
-            Coercion(a) => format!("Coercion({})", a.repr(tcx)),
+            Coercion(ref a) => format!("Coercion({})", a.repr(tcx)),
             EarlyBoundRegion(a, b) => format!("EarlyBoundRegion({},{})",
                                               a.repr(tcx), b.repr(tcx)),
             LateBoundRegion(a, b) => format!("LateBoundRegion({},{})",
diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs
index a446b94027b..bb6d479870b 100644
--- a/src/librustc/middle/typeck/infer/region_inference/mod.rs
+++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs
@@ -212,7 +212,7 @@ impl<'a> RegionVarBindings<'a> {
 
     pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
         let id = self.num_vars();
-        self.var_origins.borrow_mut().push(origin);
+        self.var_origins.borrow_mut().push(origin.clone());
         let vid = RegionVid { id: id };
         if self.in_snapshot() {
             self.undo_log.borrow_mut().push(AddVar(vid));
@@ -330,9 +330,9 @@ impl<'a> RegionVarBindings<'a> {
 
             _ => {
                 self.combine_vars(
-                    Lub, a, b, origin,
+                    Lub, a, b, origin.clone(),
                     |this, old_r, new_r|
-                    this.make_subregion(origin, old_r, new_r))
+                    this.make_subregion(origin.clone(), old_r, new_r))
             }
         }
     }
@@ -354,9 +354,9 @@ impl<'a> RegionVarBindings<'a> {
 
             _ => {
                 self.combine_vars(
-                    Glb, a, b, origin,
+                    Glb, a, b, origin.clone(),
                     |this, old_r, new_r|
-                    this.make_subregion(origin, new_r, old_r))
+                    this.make_subregion(origin.clone(), new_r, old_r))
             }
         }
     }
@@ -1150,10 +1150,10 @@ impl<'a> RegionVarBindings<'a> {
                 if !self.is_subregion_of(lower_bound.region,
                                          upper_bound.region) {
                     errors.push(SubSupConflict(
-                        *self.var_origins.borrow().get(node_idx.to_uint()),
-                        lower_bound.origin,
+                        self.var_origins.borrow().get(node_idx.to_uint()).clone(),
+                        lower_bound.origin.clone(),
                         lower_bound.region,
-                        upper_bound.origin,
+                        upper_bound.origin.clone(),
                         upper_bound.region));
                     return;
                 }
@@ -1200,10 +1200,10 @@ impl<'a> RegionVarBindings<'a> {
                   Ok(_) => {}
                   Err(_) => {
                     errors.push(SupSupConflict(
-                        *self.var_origins.borrow().get(node_idx.to_uint()),
-                        upper_bound_1.origin,
+                        self.var_origins.borrow().get(node_idx.to_uint()).clone(),
+                        upper_bound_1.origin.clone(),
                         upper_bound_1.region,
-                        upper_bound_2.origin,
+                        upper_bound_2.origin.clone(),
                         upper_bound_2.region));
                     return;
                   }
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 6d02094669c..2c8acd0573b 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -37,15 +37,16 @@ impl<'f> Combine for Sub<'f> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { "sub".to_owned() }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace }
+    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(*self.get_ref()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(*self.get_ref()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(*self.get_ref()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         let opp = CombineFields {
-            a_is_expected: !self.get_ref().a_is_expected,.. *self.get_ref()
+            a_is_expected: !self.get_ref().a_is_expected,
+            ..self.get_ref().clone()
         };
         Sub(opp).tys(b, a)
     }
@@ -53,7 +54,8 @@ impl<'f> Combine for Sub<'f> {
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
         let opp = CombineFields {
-            a_is_expected: !self.get_ref().a_is_expected,.. *self.get_ref()
+            a_is_expected: !self.get_ref().a_is_expected,
+            ..self.get_ref().clone()
         };
         Sub(opp).regions(b, a)
     }
@@ -63,7 +65,7 @@ impl<'f> Combine for Sub<'f> {
                self.tag(),
                a.inf_str(self.get_ref().infcx),
                b.inf_str(self.get_ref().infcx));
-        self.get_ref().infcx.region_vars.make_subregion(Subtype(self.get_ref().trace), a, b);
+        self.get_ref().infcx.region_vars.make_subregion(Subtype(self.trace()), a, b);
         Ok(a)
     }
 
@@ -167,7 +169,7 @@ impl<'f> Combine for Sub<'f> {
         // region variable.
         let (a_sig, _) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, a);
+                self.trace(), a);
 
         // Second, we instantiate each bound region in the supertype with a
         // fresh concrete region.
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index f78f0a8f273..26f0bc7ec72 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -171,11 +171,11 @@ impl MethodCall {
 
 // maps from an expression id that corresponds to a method call to the details
 // of the method to be invoked
-pub type MethodMap = @RefCell<FnvHashMap<MethodCall, MethodCallee>>;
+pub type MethodMap = RefCell<FnvHashMap<MethodCall, MethodCallee>>;
 
-pub type vtable_param_res = @Vec<vtable_origin> ;
+pub type vtable_param_res = Vec<vtable_origin>;
 // Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res = @Vec<vtable_param_res> ;
+pub type vtable_res = Vec<vtable_param_res>;
 
 #[deriving(Clone)]
 pub enum vtable_origin {
@@ -184,7 +184,7 @@ pub enum vtable_origin {
       from whence comes the vtable, and tys are the type substs.
       vtable_res is the vtable itself
      */
-    vtable_static(ast::DefId, Vec<ty::t> , vtable_res),
+    vtable_static(ast::DefId, Vec<ty::t>, vtable_res),
 
     /*
       Dynamic vtable, comes from a parameter that has a bound on it:
@@ -215,7 +215,7 @@ impl Repr for vtable_origin {
     }
 }
 
-pub type vtable_map = @RefCell<FnvHashMap<MethodCall, vtable_res>>;
+pub type vtable_map = RefCell<FnvHashMap<MethodCall, vtable_res>>;
 
 
 // Information about the vtable resolutions for a trait impl.
@@ -242,8 +242,6 @@ pub type impl_vtable_map = RefCell<DefIdMap<impl_res>>;
 pub struct CrateCtxt<'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: resolve::TraitMap,
-    method_map: MethodMap,
-    vtable_map: vtable_map,
     tcx: &'a ty::ctxt
 }
 
@@ -315,25 +313,6 @@ pub fn require_same_types(tcx: &ty::ctxt,
     }
 }
 
-// a list of mapping from in-scope-region-names ("isr") to the
-// corresponding ty::Region
-pub type isr_alist = @Vec<(ty::BoundRegion, ty::Region)>;
-
-trait get_region<'a, T:'static> {
-    fn get(&'a self, br: ty::BoundRegion) -> ty::Region;
-}
-
-impl<'a, T:'static> get_region <'a, T> for isr_alist {
-    fn get(&'a self, br: ty::BoundRegion) -> ty::Region {
-        let mut region = None;
-        for isr in self.iter() {
-            let (isr_br, isr_r) = *isr;
-            if isr_br == br { region = Some(isr_r); break; }
-        };
-        region.unwrap()
-    }
-}
-
 fn check_main_fn_ty(ccx: &CrateCtxt,
                     main_id: ast::NodeId,
                     main_span: Span) {
@@ -445,13 +424,10 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
 
 pub fn check_crate(tcx: &ty::ctxt,
                    trait_map: resolve::TraitMap,
-                   krate: &ast::Crate)
-                -> (MethodMap, vtable_map) {
+                   krate: &ast::Crate) {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         trait_map: trait_map,
-        method_map: @RefCell::new(FnvHashMap::new()),
-        vtable_map: @RefCell::new(FnvHashMap::new()),
         tcx: tcx
     };
 
@@ -473,5 +449,4 @@ pub fn check_crate(tcx: &ty::ctxt,
 
     check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
-    (ccx.method_map, ccx.vtable_map)
 }
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 907153d6cbe..9e7c221d3c5 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -197,6 +197,7 @@ use arena;
 use arena::Arena;
 use middle::ty;
 use std::fmt;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util;
@@ -254,7 +255,7 @@ struct TermsContext<'a> {
     tcx: &'a ty::ctxt,
     arena: &'a Arena,
 
-    empty_variances: @ty::ItemVariances,
+    empty_variances: Rc<ty::ItemVariances>,
 
     // Maps from the node id of a type/generic parameter to the
     // corresponding inferred index.
@@ -286,9 +287,11 @@ fn determine_parameters_to_be_inferred<'a>(tcx: &'a ty::ctxt,
 
         // cache and share the variance struct used for items with
         // no type/region parameters
-        empty_variances: @ty::ItemVariances { self_param: None,
-                                              type_params: OwnedSlice::empty(),
-                                              region_params: OwnedSlice::empty() }
+        empty_variances: Rc::new(ty::ItemVariances {
+            self_param: None,
+            type_params: OwnedSlice::empty(),
+            region_params: OwnedSlice::empty()
+        })
     };
 
     visit::walk_crate(&mut terms_cx, krate, ());
@@ -362,7 +365,7 @@ impl<'a> Visitor<()> for TermsContext<'a> {
                 if self.num_inferred() == inferreds_on_entry {
                     let newly_added = self.tcx.item_variance_map.borrow_mut().insert(
                         ast_util::local_def(item.id),
-                        self.empty_variances);
+                        self.empty_variances.clone());
                     assert!(newly_added);
                 }
 
@@ -1016,7 +1019,7 @@ impl<'a> SolveContext<'a> {
             }
 
             let newly_added = tcx.item_variance_map.borrow_mut()
-                                 .insert(item_def_id, @item_variances);
+                                 .insert(item_def_id, Rc::new(item_variances));
             assert!(newly_added);
         }
     }
diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs
index ac4db178a00..7d7d5d16d74 100644
--- a/src/librustc/util/nodemap.rs
+++ b/src/librustc/util/nodemap.rs
@@ -16,12 +16,13 @@ use std::io;
 use syntax::ast;
 
 pub type FnvHashMap<K, V> = HashMap<K, V, FnvHasher>;
+pub type FnvHashSet<V> = HashSet<V, FnvHasher>;
 
 pub type NodeMap<T> = FnvHashMap<ast::NodeId, T>;
 pub type DefIdMap<T> = FnvHashMap<ast::DefId, T>;
 
-pub type NodeSet = HashSet<ast::NodeId, FnvHasher>;
-pub type DefIdSet = HashSet<ast::DefId, FnvHasher>;
+pub type NodeSet = FnvHashSet<ast::NodeId>;
+pub type DefIdSet = FnvHashSet<ast::DefId>;
 
 // Hacks to get good names
 pub mod FnvHashMap {
@@ -31,6 +32,13 @@ pub mod FnvHashMap {
         HashMap::with_hasher(super::FnvHasher)
     }
 }
+pub mod FnvHashSet {
+    use std::hash::Hash;
+    use collections::HashSet;
+    pub fn new<V: Hash<super::FnvState> + TotalEq>() -> super::FnvHashSet<V> {
+        HashSet::with_hasher(super::FnvHasher)
+    }
+}
 pub mod NodeMap {
     pub fn new<T>() -> super::NodeMap<T> {
         super::FnvHashMap::new()
@@ -42,15 +50,13 @@ pub mod DefIdMap {
     }
 }
 pub mod NodeSet {
-    use collections::HashSet;
     pub fn new() -> super::NodeSet {
-        HashSet::with_hasher(super::FnvHasher)
+        super::FnvHashSet::new()
     }
 }
 pub mod DefIdSet {
-    use collections::HashSet;
     pub fn new() -> super::DefIdSet {
-        HashSet::with_hasher(super::FnvHasher)
+        super::FnvHashSet::new()
     }
 }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 1d98cc143de..316b5c6a45a 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 
-use metadata::encoder;
 use middle::ty::{ReSkolemized, ReVar};
 use middle::ty::{BoundRegion, BrAnon, BrNamed};
 use middle::ty::{BrFresh, ctxt};
@@ -23,6 +22,7 @@ use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
 use middle::typeck;
 
+use std::rc::Rc;
 use std::strbuf::StrBuf;
 use syntax::abi;
 use syntax::ast_map;
@@ -469,7 +469,7 @@ pub fn parameterized(cx: &ctxt,
 }
 
 pub fn ty_to_short_str(cx: &ctxt, typ: t) -> ~str {
-    let mut s = encoder::encoded_ty(cx, typ);
+    let mut s = typ.repr(cx);
     if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); }
     return s;
 }
@@ -498,6 +498,12 @@ impl Repr for () {
     }
 }
 
+impl<T:Repr> Repr for Rc<T> {
+    fn repr(&self, tcx: &ctxt) -> ~str {
+        (&**self).repr(tcx)
+    }
+}
+
 impl<T:Repr> Repr for @T {
     fn repr(&self, tcx: &ctxt) -> ~str {
         (&**self).repr(tcx)
@@ -888,7 +894,7 @@ impl Repr for Span {
     }
 }
 
-impl<A:UserString> UserString for @A {
+impl<A:UserString> UserString for Rc<A> {
     fn user_string(&self, tcx: &ctxt) -> ~str {
         let this: &A = &**self;
         this.user_string(tcx)
diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs
index 792673e3298..693407b854f 100644
--- a/src/libsyntax/util/small_vector.rs
+++ b/src/libsyntax/util/small_vector.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::mem;
+use std::slice;
 use std::vec;
 
 /// A vector type optimized for cases where the size is almost always 0 or 1
@@ -61,6 +62,14 @@ impl<T> SmallVector<T> {
         SmallVector { repr: Many(vs) }
     }
 
+    pub fn as_slice<'a>(&'a self) -> &'a [T] {
+        match self.repr {
+            Zero => &[],
+            One(ref v) => slice::ref_slice(v),
+            Many(ref vs) => vs.as_slice()
+        }
+    }
+
     pub fn push(&mut self, v: T) {
         match self.repr {
             Zero => self.repr = One(v),