about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2014-09-07 20:09:06 +0300
committerEduard Burtescu <edy.burt@gmail.com>2014-09-14 04:20:34 +0300
commitb06212864f77d87779656379b3773c1096dbf9e1 (patch)
treea740c647fa01982f84b982aaed82fe136982f41a
parentd379ad111ccef354730e51edea8119341a8e7871 (diff)
downloadrust-b06212864f77d87779656379b3773c1096dbf9e1.tar.gz
rust-b06212864f77d87779656379b3773c1096dbf9e1.zip
rustc: fix fallout from using ptr::P.
-rw-r--r--src/librustc/driver/driver.rs94
-rw-r--r--src/librustc/driver/pretty.rs132
-rw-r--r--src/librustc/driver/session.rs3
-rw-r--r--src/librustc/front/assign_node_ids_and_map.rs29
-rw-r--r--src/librustc/front/config.rs256
-rw-r--r--src/librustc/front/feature_gate.rs11
-rw-r--r--src/librustc/front/std_inject.rs52
-rw-r--r--src/librustc/front/test.rs103
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/builtin.rs81
-rw-r--r--src/librustc/lint/context.rs4
-rw-r--r--src/librustc/metadata/csearch.rs12
-rw-r--r--src/librustc/metadata/decoder.rs29
-rw-r--r--src/librustc/metadata/encoder.rs110
-rw-r--r--src/librustc/middle/astencode.rs550
-rw-r--r--src/librustc/middle/borrowck/graphviz.rs2
-rw-r--r--src/librustc/middle/borrowck/mod.rs59
-rw-r--r--src/librustc/middle/cfg/construct.rs165
-rw-r--r--src/librustc/middle/cfg/graphviz.rs8
-rw-r--r--src/librustc/middle/check_const.rs28
-rw-r--r--src/librustc/middle/check_match.rs337
-rw-r--r--src/librustc/middle/check_static.rs5
-rw-r--r--src/librustc/middle/const_eval.rs123
-rw-r--r--src/librustc/middle/dead.rs14
-rw-r--r--src/librustc/middle/effect.rs10
-rw-r--r--src/librustc/middle/entry.rs14
-rw-r--r--src/librustc/middle/expr_use_visitor.rs48
-rw-r--r--src/librustc/middle/intrinsicck.rs9
-rw-r--r--src/librustc/middle/kind.rs5
-rw-r--r--src/librustc/middle/liveness.rs85
-rw-r--r--src/librustc/middle/mem_categorization.rs4
-rw-r--r--src/librustc/middle/pat_util.rs12
-rw-r--r--src/librustc/middle/privacy.rs42
-rw-r--r--src/librustc/middle/reachable.rs8
-rw-r--r--src/librustc/middle/region.rs20
-rw-r--r--src/librustc/middle/resolve.rs89
-rw-r--r--src/librustc/middle/save/mod.rs68
-rw-r--r--src/librustc/middle/trans/_match.rs309
-rw-r--r--src/librustc/middle/trans/asm.rs8
-rw-r--r--src/librustc/middle/trans/base.rs43
-rw-r--r--src/librustc/middle/trans/callee.rs18
-rw-r--r--src/librustc/middle/trans/common.rs2
-rw-r--r--src/librustc/middle/trans/consts.rs12
-rw-r--r--src/librustc/middle/trans/controlflow.rs12
-rw-r--r--src/librustc/middle/trans/debuginfo.rs72
-rw-r--r--src/librustc/middle/trans/expr.rs69
-rw-r--r--src/librustc/middle/trans/inline.rs33
-rw-r--r--src/librustc/middle/trans/meth.rs12
-rw-r--r--src/librustc/middle/trans/monomorphize.rs10
-rw-r--r--src/librustc/middle/trans/tvec.rs6
-rw-r--r--src/librustc/middle/ty.rs36
-rw-r--r--src/librustc/middle/typeck/astconv.rs62
-rw-r--r--src/librustc/middle/typeck/check/_match.rs44
-rw-r--r--src/librustc/middle/typeck/check/mod.rs223
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs50
-rw-r--r--src/librustc/middle/typeck/coherence.rs6
-rw-r--r--src/librustc/middle/typeck/collect.rs88
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs210
-rw-r--r--src/librustc/middle/typeck/infer/test.rs32
-rw-r--r--src/librustc/middle/typeck/mod.rs14
-rw-r--r--src/librustc/middle/typeck/variance.rs4
-rw-r--r--src/librustc/util/common.rs2
-rw-r--r--src/librustc/util/ppaux.rs25
-rw-r--r--src/librustc_back/svh.rs2
64 files changed, 1956 insertions, 2070 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 018bfecd369..b80d53922f8 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -35,6 +35,7 @@ use std::io::fs;
 use std::os;
 use arena::TypedArena;
 use syntax::ast;
+use syntax::ast_map;
 use syntax::attr;
 use syntax::attr::{AttrMetaMethods};
 use syntax::diagnostics;
@@ -65,7 +66,7 @@ pub fn compile_input(sess: Session,
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
     let (outputs, trans, sess) = {
-        let (outputs, expanded_crate, ast_map, id) = {
+        let (outputs, expanded_crate, id) = {
             let krate = phase_1_parse_input(&sess, cfg, input);
             if stop_after_phase_1(&sess) { return; }
             let outputs = build_output_filenames(input,
@@ -75,25 +76,28 @@ pub fn compile_input(sess: Session,
                                                  &sess);
             let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(),
                                            input);
-            let (expanded_crate, ast_map)
+            let expanded_crate
                 = match phase_2_configure_and_expand(&sess, krate, id.as_slice(),
                                                      addl_plugins) {
                     None => return,
-                    Some(p) => p,
+                    Some(k) => k
                 };
 
-            (outputs, expanded_crate, ast_map, id)
+            (outputs, expanded_crate, id)
         };
+
+        let mut forest = ast_map::Forest::new(expanded_crate);
+        let ast_map = assign_node_ids_and_map(&sess, &mut forest);
+
         write_out_deps(&sess, input, &outputs, id.as_slice());
 
         if stop_after_phase_2(&sess) { return; }
 
         let type_arena = TypedArena::new();
-        let analysis = phase_3_run_analysis_passes(sess, &expanded_crate,
-                                                   ast_map, &type_arena, id);
-        phase_save_analysis(&analysis.ty_cx.sess, &expanded_crate, &analysis, outdir);
+        let analysis = phase_3_run_analysis_passes(sess, ast_map, &type_arena, id);
+        phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir);
         if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
-        let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate, analysis);
+        let (tcx, trans) = phase_4_translate_to_llvm(analysis);
 
         // Discard interned strings as they are no longer required.
         token::get_ident_interner().clear();
@@ -182,7 +186,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
                                     mut krate: ast::Crate,
                                     crate_name: &str,
                                     addl_plugins: Option<Plugins>)
-                                    -> Option<(ast::Crate, syntax::ast_map::Map)> {
+                                    -> Option<ast::Crate> {
     let time_passes = sess.time_passes();
 
     *sess.crate_types.borrow_mut() =
@@ -294,20 +298,37 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     krate = time(time_passes, "prelude injection", krate, |krate|
                  front::std_inject::maybe_inject_prelude(sess, krate));
 
-    let (krate, map) = time(time_passes, "assigning node ids and indexing ast", krate, |krate|
-         front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
+    time(time_passes, "checking that all macro invocations are gone", &krate, |krate|
+         syntax::ext::expand::check_for_macros(&sess.parse_sess, krate));
+
+    Some(krate)
+}
+
+pub fn assign_node_ids_and_map<'ast>(sess: &Session,
+                                     forest: &'ast mut ast_map::Forest)
+                                     -> ast_map::Map<'ast> {
+    struct NodeIdAssigner<'a> {
+        sess: &'a Session
+    }
+
+    impl<'a> ast_map::FoldOps for NodeIdAssigner<'a> {
+        fn new_id(&self, old_id: ast::NodeId) -> ast::NodeId {
+            assert_eq!(old_id, ast::DUMMY_NODE_ID);
+            self.sess.next_node_id()
+        }
+    }
+
+    let map = time(sess.time_passes(), "assigning node ids and indexing ast", forest, |forest|
+                   ast_map::map_crate(forest, NodeIdAssigner { sess: sess }));
 
     if sess.opts.debugging_opts & config::AST_JSON != 0 {
         let mut stdout = io::BufferedWriter::new(io::stdout());
         let mut json = json::PrettyEncoder::new(&mut stdout);
         // unwrapping so IoError isn't ignored
-        krate.encode(&mut json).unwrap();
+        map.krate().encode(&mut json).unwrap();
     }
 
-    time(time_passes, "checking that all macro invocations are gone", &krate, |krate|
-         syntax::ext::expand::check_for_macros(&sess.parse_sess, krate));
-
-    Some((krate, map))
+    map
 }
 
 pub struct CrateAnalysis<'tcx> {
@@ -324,11 +345,11 @@ pub struct CrateAnalysis<'tcx> {
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
 pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
-                                         krate: &ast::Crate,
-                                         ast_map: syntax::ast_map::Map,
+                                         ast_map: ast_map::Map<'tcx>,
                                          type_arena: &'tcx TypedArena<ty::t_box_>,
                                          name: String) -> CrateAnalysis<'tcx> {
     let time_passes = sess.time_passes();
+    let krate = ast_map.krate();
 
     time(time_passes, "external crate/lib resolution", (), |_|
          creader::read_crates(&sess, krate));
@@ -353,7 +374,7 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                                 |_| middle::resolve_lifetime::krate(&sess, krate));
 
     time(time_passes, "looking for entry point", (),
-         |_| middle::entry::find_entry_point(&sess, krate, &ast_map));
+         |_| middle::entry::find_entry_point(&sess, &ast_map));
 
     sess.plugin_registrar_fn.set(
         time(time_passes, "looking for plugin registrar", (), |_|
@@ -385,43 +406,43 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                             stability_index);
 
     // passes are timed inside typeck
-    typeck::check_crate(&ty_cx, trait_map, krate);
+    typeck::check_crate(&ty_cx, trait_map);
 
     time(time_passes, "check static items", (), |_|
-         middle::check_static::check_crate(&ty_cx, krate));
+         middle::check_static::check_crate(&ty_cx));
 
     // These next two const passes can probably be merged
     time(time_passes, "const marking", (), |_|
-         middle::const_eval::process_crate(krate, &ty_cx));
+         middle::const_eval::process_crate(&ty_cx));
 
     time(time_passes, "const checking", (), |_|
-         middle::check_const::check_crate(krate, &ty_cx));
+         middle::check_const::check_crate(&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, &exp_map2, a, b, krate));
+                 middle::privacy::check_crate(&ty_cx, &exp_map2, a, b));
 
     time(time_passes, "intrinsic checking", (), |_|
-         middle::intrinsicck::check_crate(&ty_cx, krate));
+         middle::intrinsicck::check_crate(&ty_cx));
 
     time(time_passes, "effect checking", (), |_|
-         middle::effect::check_crate(&ty_cx, krate));
+         middle::effect::check_crate(&ty_cx));
 
     time(time_passes, "match checking", (), |_|
-         middle::check_match::check_crate(&ty_cx, krate));
+         middle::check_match::check_crate(&ty_cx));
 
     time(time_passes, "liveness checking", (), |_|
-         middle::liveness::check_crate(&ty_cx, krate));
+         middle::liveness::check_crate(&ty_cx));
 
     time(time_passes, "borrow checking", (), |_|
-         middle::borrowck::check_crate(&ty_cx, krate));
+         middle::borrowck::check_crate(&ty_cx));
 
     time(time_passes, "rvalue checking", (), |_|
          middle::check_rvalues::check_crate(&ty_cx, krate));
 
     time(time_passes, "kind checking", (), |_|
-         kind::check_crate(&ty_cx, krate));
+         kind::check_crate(&ty_cx));
 
     let reachable_map =
         time(time_passes, "reachability checking", (), |_|
@@ -430,12 +451,11 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     time(time_passes, "death checking", (), |_| {
         middle::dead::check_crate(&ty_cx,
                                   &exported_items,
-                                  &reachable_map,
-                                  krate)
+                                  &reachable_map)
     });
 
     time(time_passes, "lint checking", (), |_|
-         lint::check_crate(&ty_cx, krate, &exported_items));
+         lint::check_crate(&ty_cx, &exported_items));
 
     CrateAnalysis {
         exp_map2: exp_map2,
@@ -475,16 +495,16 @@ pub struct CrateTranslation {
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
-pub fn phase_4_translate_to_llvm(krate: ast::Crate,
-                                 analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
+pub fn phase_4_translate_to_llvm<'tcx>(analysis: CrateAnalysis<'tcx>)
+                                       -> (ty::ctxt<'tcx>, CrateTranslation) {
     let time_passes = analysis.ty_cx.sess.time_passes();
 
     time(time_passes, "resolving dependency formats", (), |_|
          dependency_format::calculate(&analysis.ty_cx));
 
     // Option dance to work around the lack of stack once closures.
-    time(time_passes, "translation", (krate, analysis), |(krate, analysis)|
-         trans::base::trans_crate(krate, analysis))
+    time(time_passes, "translation", analysis, |analysis|
+         trans::base::trans_crate(analysis))
 }
 
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
diff --git a/src/librustc/driver/pretty.rs b/src/librustc/driver/pretty.rs
index a3227e4dbf1..7c27f23d485 100644
--- a/src/librustc/driver/pretty.rs
+++ b/src/librustc/driver/pretty.rs
@@ -91,13 +91,13 @@ pub fn parse_pretty(sess: &Session, name: &str) -> (PpMode, Option<UserIdentifie
 
 impl PpSourceMode {
     /// Constructs a `PrinterSupport` object and passes it to `f`.
-    fn call_with_pp_support<A,B>(&self,
-                                 sess: Session,
-                                 krate: &ast::Crate,
-                                 ast_map: Option<ast_map::Map>,
-                                 id: String,
-                                 payload: B,
-                                 f: |&PrinterSupport, B| -> A) -> A {
+    fn call_with_pp_support<'tcx, A, B>(&self,
+                                        sess: Session,
+                                        ast_map: Option<ast_map::Map<'tcx>>,
+                                        type_arena: &'tcx TypedArena<ty::t_box_>,
+                                        id: String,
+                                        payload: B,
+                                        f: |&PrinterSupport, B| -> A) -> A {
         match *self {
             PpmNormal | PpmExpanded => {
                 let annotation = NoAnn { sess: sess, ast_map: ast_map };
@@ -114,9 +114,8 @@ impl PpSourceMode {
             }
             PpmTyped => {
                 let ast_map = ast_map.expect("--pretty=typed missing ast_map");
-                let type_arena = TypedArena::new();
-                let analysis = driver::phase_3_run_analysis_passes(sess, krate, ast_map,
-                                                                   &type_arena, id);
+                let analysis = driver::phase_3_run_analysis_passes(sess, ast_map,
+                                                                   type_arena, id);
                 let annotation = TypedAnnotation { analysis: analysis };
                 f(&annotation, payload)
             }
@@ -124,69 +123,51 @@ impl PpSourceMode {
     }
 }
 
-trait SessionCarrier {
+trait PrinterSupport<'ast>: pprust::PpAnn {
     /// Provides a uniform interface for re-extracting a reference to a
     /// `Session` from a value that now owns it.
     fn sess<'a>(&'a self) -> &'a Session;
-}
 
-trait AstMapCarrier {
     /// Provides a uniform interface for re-extracting a reference to an
     /// `ast_map::Map` from a value that now owns it.
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map>;
-}
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>>;
 
-trait PrinterSupport : SessionCarrier + AstMapCarrier {
     /// Produces the pretty-print annotation object.
     ///
-    /// Usually implemented via `self as &pprust::PpAnn`.
-    ///
     /// (Rust does not yet support upcasting from a trait object to
     /// an object for one of its super-traits.)
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn;
+    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
 }
 
-struct NoAnn {
+struct NoAnn<'ast> {
     sess: Session,
-    ast_map: Option<ast_map::Map>,
-}
-
-impl PrinterSupport for NoAnn {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+    ast_map: Option<ast_map::Map<'ast>>
 }
 
-impl SessionCarrier for NoAnn {
+impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
     fn sess<'a>(&'a self) -> &'a Session { &self.sess }
-}
 
-impl AstMapCarrier for NoAnn {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
 }
 
-impl pprust::PpAnn for NoAnn {}
+impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
 
-struct IdentifiedAnnotation {
+struct IdentifiedAnnotation<'ast> {
     sess: Session,
-    ast_map: Option<ast_map::Map>,
-}
-
-impl PrinterSupport for IdentifiedAnnotation {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+    ast_map: Option<ast_map::Map<'ast>>,
 }
 
-impl SessionCarrier for IdentifiedAnnotation {
+impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
     fn sess<'a>(&'a self) -> &'a Session { &self.sess }
-}
 
-impl AstMapCarrier for IdentifiedAnnotation {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
 }
 
-impl pprust::PpAnn for IdentifiedAnnotation {
+impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> {
     fn pre(&self,
            s: &mut pprust::State,
            node: pprust::AnnNode) -> io::IoResult<()> {
@@ -222,26 +203,20 @@ impl pprust::PpAnn for IdentifiedAnnotation {
     }
 }
 
-struct HygieneAnnotation {
+struct HygieneAnnotation<'ast> {
     sess: Session,
-    ast_map: Option<ast_map::Map>,
-}
-
-impl PrinterSupport for HygieneAnnotation {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
+    ast_map: Option<ast_map::Map<'ast>>,
 }
 
-impl SessionCarrier for HygieneAnnotation {
+impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> {
     fn sess<'a>(&'a self) -> &'a Session { &self.sess }
-}
 
-impl AstMapCarrier for HygieneAnnotation {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'ast>> {
         self.ast_map.as_ref()
     }
 }
 
-impl pprust::PpAnn for HygieneAnnotation {
+impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> {
     fn post(&self,
             s: &mut pprust::State,
             node: pprust::AnnNode) -> io::IoResult<()> {
@@ -266,16 +241,10 @@ struct TypedAnnotation<'tcx> {
     analysis: CrateAnalysis<'tcx>,
 }
 
-impl<'tcx> PrinterSupport for TypedAnnotation<'tcx> {
-    fn pp_ann<'a>(&'a self) -> &'a pprust::PpAnn { self as &pprust::PpAnn }
-}
-
-impl<'tcx> SessionCarrier for TypedAnnotation<'tcx> {
+impl<'tcx> PrinterSupport<'tcx> for TypedAnnotation<'tcx> {
     fn sess<'a>(&'a self) -> &'a Session { &self.analysis.ty_cx.sess }
-}
 
-impl<'tcx> AstMapCarrier for TypedAnnotation<'tcx> {
-    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map> {
+    fn ast_map<'a>(&'a self) -> Option<&'a ast_map::Map<'tcx>> {
         Some(&self.analysis.ty_cx.map)
     }
 }
@@ -347,12 +316,12 @@ impl FromStr for UserIdentifiedItem {
     }
 }
 
-enum NodesMatchingUII<'a> {
+enum NodesMatchingUII<'a, 'ast: 'a> {
     NodesMatchingDirect(option::Item<ast::NodeId>),
-    NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, String>),
+    NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, 'ast, String>),
 }
 
-impl<'a> Iterator<ast::NodeId> for NodesMatchingUII<'a> {
+impl<'a, 'ast> Iterator<ast::NodeId> for NodesMatchingUII<'a, 'ast> {
     fn next(&mut self) -> Option<ast::NodeId> {
         match self {
             &NodesMatchingDirect(ref mut iter) => iter.next(),
@@ -369,7 +338,8 @@ impl UserIdentifiedItem {
         }
     }
 
-    fn all_matching_node_ids<'a>(&'a self, map: &'a ast_map::Map) -> NodesMatchingUII<'a> {
+    fn all_matching_node_ids<'a, 'ast>(&'a self, map: &'a ast_map::Map<'ast>)
+                                       -> NodesMatchingUII<'a, 'ast> {
         match *self {
             ItemViaNode(node_id) =>
                 NodesMatchingDirect(Some(node_id).move_iter()),
@@ -443,15 +413,24 @@ pub fn pretty_print_input(sess: Session,
     let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);
 
     let is_expanded = needs_expansion(&ppm);
-    let (krate, ast_map) = if needs_ast_map(&ppm, &opt_uii) {
-        let k = driver::phase_2_configure_and_expand(&sess, krate, id.as_slice(), None);
-        let (krate, ast_map) = match k {
+    let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
+    let krate = if compute_ast_map {
+        match driver::phase_2_configure_and_expand(&sess, krate, id.as_slice(), None) {
             None => return,
-            Some(p) => p,
-        };
-        (krate, Some(ast_map))
+            Some(k) => k
+        }
+    } else {
+        krate
+    };
+
+    let mut forest = ast_map::Forest::new(krate);
+    let type_arena = TypedArena::new();
+
+    let (krate, ast_map) = if compute_ast_map {
+        let map = driver::assign_node_ids_and_map(&sess, &mut forest);
+        (map.krate(), Some(map))
     } else {
-        (krate, None)
+        (forest.krate(), None)
     };
 
     let src_name = driver::source_name(input);
@@ -476,12 +455,12 @@ pub fn pretty_print_input(sess: Session,
     match (ppm, opt_uii) {
         (PpmSource(s), None) =>
             s.call_with_pp_support(
-                sess, &krate, ast_map, id, out, |annotation, out| {
+                sess, ast_map, &type_arena, id, out, |annotation, out| {
                     debug!("pretty printing source code {}", s);
                     let sess = annotation.sess();
                     pprust::print_crate(sess.codemap(),
                                         sess.diagnostic(),
-                                        &krate,
+                                        krate,
                                         src_name.to_string(),
                                         &mut rdr,
                                         out,
@@ -491,7 +470,7 @@ pub fn pretty_print_input(sess: Session,
 
         (PpmSource(s), Some(uii)) =>
             s.call_with_pp_support(
-                sess, &krate, ast_map, id, (out,uii), |annotation, (out,uii)| {
+                sess, ast_map, &type_arena, id, (out,uii), |annotation, (out,uii)| {
                     debug!("pretty printing source code {}", s);
                     let sess = annotation.sess();
                     let ast_map = annotation.ast_map()
@@ -533,9 +512,8 @@ pub fn pretty_print_input(sess: Session,
             match code {
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
-                    let type_arena = TypedArena::new();
-                    let analysis = driver::phase_3_run_analysis_passes(sess, &krate,
-                                                                       ast_map, &type_arena, id);
+                    let analysis = driver::phase_3_run_analysis_passes(sess, ast_map,
+                                                                       &type_arena, id);
                     print_flowgraph(variants, analysis, code, out)
                 }
                 None => {
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index 135e21e4e01..6f020184b33 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -263,7 +263,6 @@ pub fn build_session_(sopts: config::Options,
 }
 
 // Seems out of place, but it uses session, so I'm putting it here
-pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> String)
-              -> T {
+pub fn expect<T>(sess: &Session, opt: Option<T>, msg: || -> String) -> T {
     diagnostic::expect(sess.diagnostic(), opt, msg)
 }
diff --git a/src/librustc/front/assign_node_ids_and_map.rs b/src/librustc/front/assign_node_ids_and_map.rs
deleted file mode 100644
index f7c919131a8..00000000000
--- a/src/librustc/front/assign_node_ids_and_map.rs
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use driver::session::Session;
-
-use syntax::ast;
-use syntax::ast_map;
-
-struct NodeIdAssigner<'a> {
-    sess: &'a Session
-}
-
-impl<'a> ast_map::FoldOps for NodeIdAssigner<'a> {
-    fn new_id(&self, old_id: ast::NodeId) -> ast::NodeId {
-        assert_eq!(old_id, ast::DUMMY_NODE_ID);
-        self.sess.next_node_id()
-    }
-}
-
-pub fn assign_node_ids_and_map(sess: &Session, krate: ast::Crate) -> (ast::Crate, ast_map::Map) {
-    ast_map::map_crate(krate, NodeIdAssigner { sess: sess })
-}
diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs
index 93320caf5f2..f028f5c97b7 100644
--- a/src/librustc/front/config.rs
+++ b/src/librustc/front/config.rs
@@ -10,9 +10,8 @@
 
 use syntax::fold::Folder;
 use syntax::{ast, fold, attr};
-use syntax::codemap;
-
-use std::gc::{Gc, GC};
+use syntax::codemap::Spanned;
+use syntax::ptr::P;
 
 /// A folder that strips out items that do not belong in the current
 /// configuration.
@@ -28,22 +27,22 @@ pub fn strip_unconfigured_items(krate: ast::Crate) -> ast::Crate {
 }
 
 impl<'a> fold::Folder for Context<'a> {
-    fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
+    fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod {
         fold_mod(self, module)
     }
-    fn fold_block(&mut self, block: ast::P<ast::Block>) -> ast::P<ast::Block> {
+    fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
         fold_block(self, block)
     }
-    fn fold_foreign_mod(&mut self, foreign_mod: &ast::ForeignMod) -> ast::ForeignMod {
+    fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod {
         fold_foreign_mod(self, foreign_mod)
     }
-    fn fold_item_underscore(&mut self, item: &ast::Item_) -> ast::Item_ {
+    fn fold_item_underscore(&mut self, item: ast::Item_) -> ast::Item_ {
         fold_item_underscore(self, item)
     }
-    fn fold_expr(&mut self, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
+    fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
         fold_expr(self, expr)
     }
-    fn fold_mac(&mut self, mac: &ast::Mac) -> ast::Mac {
+    fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
         fold::noop_fold_mac(mac, self)
     }
 }
@@ -57,34 +56,32 @@ pub fn strip_items(krate: ast::Crate,
     ctxt.fold_crate(krate)
 }
 
-fn filter_view_item<'r>(cx: &mut Context, view_item: &'r ast::ViewItem)
-                        -> Option<&'r ast::ViewItem> {
-    if view_item_in_cfg(cx, view_item) {
+fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option<ast::ViewItem> {
+    if view_item_in_cfg(cx, &view_item) {
         Some(view_item)
     } else {
         None
     }
 }
 
-fn fold_mod(cx: &mut Context, m: &ast::Mod) -> ast::Mod {
-    let filtered_items: Vec<&Gc<ast::Item>> = m.items.iter()
-            .filter(|a| item_in_cfg(cx, &***a))
-            .collect();
-    let flattened_items = filtered_items.move_iter()
-            .flat_map(|&x| cx.fold_item(x).move_iter())
-            .collect();
-    let filtered_view_items = m.view_items.iter().filter_map(|a| {
-        filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
-    }).collect();
+fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod {
     ast::Mod {
-        inner: m.inner,
-        view_items: filtered_view_items,
-        items: flattened_items
+        inner: inner,
+        view_items: view_items.move_iter().filter_map(|a| {
+            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
+        }).collect(),
+        items: items.move_iter().filter_map(|a| {
+            if item_in_cfg(cx, &*a) {
+                Some(cx.fold_item(a))
+            } else {
+                None
+            }
+        }).flat_map(|x| x.move_iter()).collect()
     }
 }
 
-fn filter_foreign_item(cx: &mut Context, item: Gc<ast::ForeignItem>)
-                       -> Option<Gc<ast::ForeignItem>> {
+fn filter_foreign_item(cx: &mut Context, item: P<ast::ForeignItem>)
+                       -> Option<P<ast::ForeignItem>> {
     if foreign_item_in_cfg(cx, &*item) {
         Some(item)
     } else {
@@ -92,134 +89,135 @@ fn filter_foreign_item(cx: &mut Context, item: Gc<ast::ForeignItem>)
     }
 }
 
-fn fold_foreign_mod(cx: &mut Context, nm: &ast::ForeignMod) -> ast::ForeignMod {
-    let filtered_items = nm.items
-                           .iter()
-                           .filter_map(|a| filter_foreign_item(cx, *a))
-                           .collect();
-    let filtered_view_items = nm.view_items.iter().filter_map(|a| {
-        filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
-    }).collect();
+fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: ast::ForeignMod)
+                    -> ast::ForeignMod {
     ast::ForeignMod {
-        abi: nm.abi,
-        view_items: filtered_view_items,
-        items: filtered_items
+        abi: abi,
+        view_items: view_items.move_iter().filter_map(|a| {
+            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
+        }).collect(),
+        items: items.move_iter()
+                    .filter_map(|a| filter_foreign_item(cx, a))
+                    .collect()
     }
 }
 
-fn fold_item_underscore(cx: &mut Context, item: &ast::Item_) -> ast::Item_ {
-    let item = match *item {
-        ast::ItemImpl(ref a, ref b, c, ref impl_items) => {
-            let impl_items = impl_items.iter()
-                                       .filter(|ii| {
-                                           impl_item_in_cfg(cx, &**ii)
-                                       })
-                                       .map(|x| *x)
+fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ {
+    let item = match item {
+        ast::ItemImpl(a, b, c, impl_items) => {
+            let impl_items = impl_items.move_iter()
+                                       .filter(|ii| impl_item_in_cfg(cx, ii))
                                        .collect();
-            ast::ItemImpl((*a).clone(), (*b).clone(), c, impl_items)
+            ast::ItemImpl(a, b, c, impl_items)
         }
-        ast::ItemTrait(ref a, ref b, ref c, ref methods) => {
-            let methods = methods.iter()
-                                 .filter(|m| trait_method_in_cfg(cx, *m) )
-                                 .map(|x| (*x).clone())
+        ast::ItemTrait(a, b, c, methods) => {
+            let methods = methods.move_iter()
+                                 .filter(|m| trait_method_in_cfg(cx, m))
                                  .collect();
-            ast::ItemTrait((*a).clone(), (*b).clone(), (*c).clone(), methods)
+            ast::ItemTrait(a, b, c, methods)
         }
-        ast::ItemStruct(ref def, ref generics) => {
-            ast::ItemStruct(fold_struct(cx, &**def), generics.clone())
+        ast::ItemStruct(def, generics) => {
+            ast::ItemStruct(fold_struct(cx, def), generics)
         }
-        ast::ItemEnum(ref def, ref generics) => {
-            let mut variants = def.variants.iter().map(|c| c.clone()).
-            filter_map(|v| {
+        ast::ItemEnum(def, generics) => {
+            let mut variants = def.variants.move_iter().filter_map(|v| {
                 if !(cx.in_cfg)(v.node.attrs.as_slice()) {
                     None
                 } else {
-                    Some(match v.node.kind {
-                                ast::TupleVariantKind(..) => v,
-                                ast::StructVariantKind(ref def) => {
-                                    let def = fold_struct(cx, &**def);
-                                    box(GC) codemap::Spanned {
-                                        node: ast::Variant_ {
-                                            kind: ast::StructVariantKind(def.clone()),
-                                            ..v.node.clone()
-                                        },
-                                        ..*v
+                    Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind,
+                                                              disr_expr, vis}, span}| {
+                        Spanned {
+                            node: ast::Variant_ {
+                                id: id,
+                                name: name,
+                                attrs: attrs,
+                                kind: match kind {
+                                    ast::TupleVariantKind(..) => kind,
+                                    ast::StructVariantKind(def) => {
+                                        ast::StructVariantKind(fold_struct(cx, def))
                                     }
-                                }
-                            })
-                    }
-                });
+                                },
+                                disr_expr: disr_expr,
+                                vis: vis
+                            },
+                            span: span
+                        }
+                    }))
+                }
+            });
             ast::ItemEnum(ast::EnumDef {
                 variants: variants.collect(),
-            }, generics.clone())
+            }, generics)
         }
-        ref item => item.clone(),
+        item => item,
     };
 
-    fold::noop_fold_item_underscore(&item, cx)
+    fold::noop_fold_item_underscore(item, cx)
 }
 
-fn fold_struct(cx: &mut Context, def: &ast::StructDef) -> Gc<ast::StructDef> {
-    let mut fields = def.fields.iter().map(|c| c.clone()).filter(|m| {
-        (cx.in_cfg)(m.node.attrs.as_slice())
-    });
-    box(GC) ast::StructDef {
-        fields: fields.collect(),
-        ctor_id: def.ctor_id,
-        super_struct: def.super_struct.clone(),
-        is_virtual: def.is_virtual,
-    }
+fn fold_struct(cx: &mut Context, def: P<ast::StructDef>) -> P<ast::StructDef> {
+    def.map(|ast::StructDef {fields, ctor_id, super_struct, is_virtual}| {
+        ast::StructDef {
+            fields: fields.move_iter().filter(|m| {
+                (cx.in_cfg)(m.node.attrs.as_slice())
+            }).collect(),
+            ctor_id: ctor_id,
+            super_struct: super_struct,
+            is_virtual: is_virtual,
+        }
+    })
 }
 
-fn retain_stmt(cx: &mut Context, stmt: Gc<ast::Stmt>) -> bool {
+fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool {
     match stmt.node {
-      ast::StmtDecl(decl, _) => {
-        match decl.node {
-          ast::DeclItem(ref item) => {
-            item_in_cfg(cx, &**item)
-          }
-          _ => true
+        ast::StmtDecl(ref decl, _) => {
+            match decl.node {
+                ast::DeclItem(ref item) => {
+                    item_in_cfg(cx, &**item)
+                }
+                _ => true
+            }
         }
-      }
-      _ => true
+        _ => true
     }
 }
 
-fn fold_block(cx: &mut Context, b: ast::P<ast::Block>) -> ast::P<ast::Block> {
-    let resulting_stmts: Vec<&Gc<ast::Stmt>> =
-        b.stmts.iter().filter(|&a| retain_stmt(cx, *a)).collect();
-    let resulting_stmts = resulting_stmts.move_iter()
-        .flat_map(|stmt| cx.fold_stmt(&**stmt).move_iter())
-        .collect();
-    let filtered_view_items = b.view_items.iter().filter_map(|a| {
-        filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
-    }).collect();
-    ast::P(ast::Block {
-        view_items: filtered_view_items,
-        stmts: resulting_stmts,
-        expr: b.expr.map(|x| cx.fold_expr(x)),
-        id: b.id,
-        rules: b.rules,
-        span: b.span,
+fn fold_block(cx: &mut Context, b: P<ast::Block>) -> P<ast::Block> {
+    b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| {
+        let resulting_stmts: Vec<P<ast::Stmt>> =
+            stmts.move_iter().filter(|a| retain_stmt(cx, &**a)).collect();
+        let resulting_stmts = resulting_stmts.move_iter()
+            .flat_map(|stmt| cx.fold_stmt(stmt).move_iter())
+            .collect();
+        let filtered_view_items = view_items.move_iter().filter_map(|a| {
+            filter_view_item(cx, a).map(|x| cx.fold_view_item(x))
+        }).collect();
+        ast::Block {
+            id: id,
+            view_items: filtered_view_items,
+            stmts: resulting_stmts,
+            expr: expr.map(|x| cx.fold_expr(x)),
+            rules: rules,
+            span: span,
+        }
     })
 }
 
-fn fold_expr(cx: &mut Context, expr: Gc<ast::Expr>) -> Gc<ast::Expr> {
-    let expr = match expr.node {
-        ast::ExprMatch(ref m, ref arms) => {
-            let arms = arms.iter()
-                .filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
-                .map(|a| a.clone())
-                .collect();
-            box(GC) ast::Expr {
-                id: expr.id,
-                span: expr.span.clone(),
-                node: ast::ExprMatch(m.clone(), arms),
-            }
-        }
-        _ => expr.clone()
-    };
-    fold::noop_fold_expr(expr, cx)
+fn fold_expr(cx: &mut Context, expr: P<ast::Expr>) -> P<ast::Expr> {
+    expr.map(|ast::Expr {id, span, node}| {
+        fold::noop_fold_expr(ast::Expr {
+            id: id,
+            node: match node {
+                ast::ExprMatch(m, arms) => {
+                    ast::ExprMatch(m, arms.move_iter()
+                                        .filter(|a| (cx.in_cfg)(a.attrs.as_slice()))
+                                        .collect())
+                }
+                _ => node
+            },
+            span: span
+        }, cx)
+    })
 }
 
 fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool {
@@ -237,19 +235,19 @@ fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool {
 fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool {
     match *meth {
         ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
-        ast::ProvidedMethod(meth) => (cx.in_cfg)(meth.attrs.as_slice())
+        ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice())
     }
 }
 
 fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool {
     match *impl_item {
-        ast::MethodImplItem(meth) => (cx.in_cfg)(meth.attrs.as_slice()),
+        ast::MethodImplItem(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()),
     }
 }
 
 // Determine if an item should be translated in the current crate
 // configuration based on the item's attributes
-fn in_cfg(cfg: &[Gc<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
-    attr::test_cfg(cfg, attrs.iter().map(|x| *x))
+fn in_cfg(cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
+    attr::test_cfg(cfg, attrs.iter())
 }
 
diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 7750ddc91e1..13a40aba930 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -33,6 +33,7 @@ use syntax::parse::token;
 use driver::session::Session;
 
 use std::cell::Cell;
+use std::slice;
 
 /// This is a list of all known features since the beginning of time. This list
 /// can never shrink, it may only be expanded (in order to prevent old programs
@@ -220,7 +221,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
                 }
             }
 
-            ast::ItemStruct(struct_definition, _) => {
+            ast::ItemStruct(ref struct_definition, _) => {
                 if attr::contains_name(i.attrs.as_slice(), "simd") {
                     self.gate_feature("simd", i.span,
                                       "SIMD types are experimental and possibly buggy");
@@ -310,7 +311,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
 
     fn visit_ty(&mut self, t: &ast::Ty) {
         match t.node {
-            ast::TyClosure(closure) if closure.onceness == ast::Once => {
+            ast::TyClosure(ref closure) if closure.onceness == ast::Once => {
                 self.gate_feature("once_fns", t.span,
                                   "once functions are \
                                    experimental and likely to be removed");
@@ -352,7 +353,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
     fn visit_generics(&mut self, generics: &ast::Generics) {
         for type_parameter in generics.ty_params.iter() {
             match type_parameter.default {
-                Some(ty) => {
+                Some(ref ty) => {
                     self.gate_feature("default_type_params", ty.span,
                                       "default type parameters are \
                                        experimental and possibly buggy");
@@ -364,7 +365,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
     }
 
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
-        if attr::contains_name([*attr], "lang") {
+        if attr::contains_name(slice::ref_slice(attr), "lang") {
             self.gate_feature("lang_items",
                               attr.span,
                               "language items are subject to change");
@@ -420,7 +421,7 @@ pub fn check_crate(sess: &Session, krate: &ast::Crate) {
                                           expected #![feature(...)]");
             }
             Some(list) => {
-                for &mi in list.iter() {
+                for mi in list.iter() {
                     let name = match mi.node {
                         ast::MetaWord(ref word) => (*word).clone(),
                         _ => {
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index 32e0c323d1f..748641ba70c 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -21,10 +21,10 @@ use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::InternedString;
 use syntax::parse::token::special_idents;
 use syntax::parse::token;
+use syntax::ptr::P;
 use syntax::util::small_vector::SmallVector;
 
 use std::mem;
-use std::gc::{Gc, GC};
 
 pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
                                -> ast::Crate {
@@ -149,7 +149,6 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
         if !no_prelude(krate.attrs.as_slice()) {
             // only add `use std::prelude::*;` if there wasn't a
             // `#![no_implicit_prelude]` at the crate level.
-
             // fold_mod() will insert glob path.
             let globs_attr = attr::mk_attr_inner(attr::mk_attr_id(),
                                                  attr::mk_list_item(
@@ -161,23 +160,23 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
             attr::mark_used(&globs_attr);
             krate.attrs.push(globs_attr);
 
-            krate.module = self.fold_mod(&krate.module);
+            krate.module = self.fold_mod(krate.module);
         }
         krate
     }
 
-    fn fold_item(&mut self, item: Gc<ast::Item>) -> SmallVector<Gc<ast::Item>> {
+    fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         if !no_prelude(item.attrs.as_slice()) {
             // only recur if there wasn't `#![no_implicit_prelude]`
             // on this item, i.e. this means that the prelude is not
             // implicitly imported though the whole subtree
-            fold::noop_fold_item(&*item, self)
+            fold::noop_fold_item(item, self)
         } else {
             SmallVector::one(item)
         }
     }
 
-    fn fold_mod(&mut self, module: &ast::Mod) -> ast::Mod {
+    fn fold_mod(&mut self, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod {
         let prelude_path = ast::Path {
             span: DUMMY_SP,
             global: false,
@@ -194,44 +193,41 @@ impl<'a> fold::Folder for PreludeInjector<'a> {
                 }),
         };
 
-        let vp = box(GC) codemap::dummy_spanned(ast::ViewPathGlob(prelude_path,
-                                                                  ast::DUMMY_NODE_ID));
-        let vi2 = ast::ViewItem {
+        let (crates, uses) = view_items.partitioned(|x| {
+            match x.node {
+                ast::ViewItemExternCrate(..) => true,
+                _ => false,
+            }
+        });
+
+        // add prelude after any `extern crate` but before any `use`
+        let mut view_items = crates;
+        let vp = P(codemap::dummy_spanned(ast::ViewPathGlob(prelude_path, ast::DUMMY_NODE_ID)));
+        view_items.push(ast::ViewItem {
             node: ast::ViewItemUse(vp),
-            attrs: vec!(ast::Attribute {
+            attrs: vec![ast::Attribute {
                 span: DUMMY_SP,
                 node: ast::Attribute_ {
                     id: attr::mk_attr_id(),
                     style: ast::AttrOuter,
-                    value: box(GC) ast::MetaItem {
+                    value: P(ast::MetaItem {
                         span: DUMMY_SP,
                         node: ast::MetaWord(token::get_name(
                                 special_idents::prelude_import.name)),
-                    },
+                    }),
                     is_sugared_doc: false,
                 },
-            }),
+            }],
             vis: ast::Inherited,
             span: DUMMY_SP,
-        };
-
-        let (crates, uses) = module.view_items.partitioned(|x| {
-            match x.node {
-                ast::ViewItemExternCrate(..) => true,
-                _ => false,
-            }
         });
-
-        // add vi2 after any `extern crate` but before any `use`
-        let mut view_items = crates;
-        view_items.push(vi2);
         view_items.push_all_move(uses);
 
-        let new_module = ast::Mod {
+        fold::noop_fold_mod(ast::Mod {
+            inner: inner,
             view_items: view_items,
-            ..(*module).clone()
-        };
-        fold::noop_fold_mod(&new_module, self)
+            items: items
+        }, self)
     }
 }
 
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 63e93d266c7..a8c9c500095 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -16,10 +16,10 @@
 use driver::session::Session;
 use front::config;
 
-use std::gc::{Gc, GC};
 use std::slice;
 use std::mem;
 use std::vec;
+use syntax::{ast, ast_util};
 use syntax::ast_util::*;
 use syntax::attr::AttrMetaMethods;
 use syntax::attr;
@@ -28,13 +28,13 @@ use syntax::codemap;
 use syntax::ext::base::ExtCtxt;
 use syntax::ext::build::AstBuilder;
 use syntax::ext::expand::ExpansionConfig;
-use syntax::fold::Folder;
+use syntax::fold::{Folder, MoveMap};
 use syntax::fold;
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
 use syntax::print::pprust;
-use syntax::{ast, ast_util};
+use syntax::ptr::P;
 use syntax::util::small_vector::SmallVector;
 
 struct Test {
@@ -105,12 +105,12 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
         folded
     }
 
-    fn fold_item(&mut self, i: Gc<ast::Item>) -> SmallVector<Gc<ast::Item>> {
+    fn fold_item(&mut self, i: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         self.cx.path.push(i.ident);
         debug!("current path: {}",
                ast_util::path_name_i(self.cx.path.as_slice()));
 
-        if is_test_fn(&self.cx, i) || is_bench_fn(&self.cx, i) {
+        if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) {
             match i.node {
                 ast::ItemFn(_, ast::UnsafeFn, _, _, _) => {
                     let sess = self.cx.sess;
@@ -123,9 +123,9 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
                     let test = Test {
                         span: i.span,
                         path: self.cx.path.clone(),
-                        bench: is_bench_fn(&self.cx, i),
-                        ignore: is_ignored(&self.cx, i),
-                        should_fail: should_fail(i)
+                        bench: is_bench_fn(&self.cx, &*i),
+                        ignore: is_ignored(&self.cx, &*i),
+                        should_fail: should_fail(&*i)
                     };
                     self.cx.testfns.push(test);
                     self.tests.push(i.ident);
@@ -138,14 +138,14 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
         // We don't want to recurse into anything other than mods, since
         // mods or tests inside of functions will break things
         let res = match i.node {
-            ast::ItemMod(..) => fold::noop_fold_item(&*i, self),
+            ast::ItemMod(..) => fold::noop_fold_item(i, self),
             _ => SmallVector::one(i),
         };
         self.cx.path.pop();
         res
     }
 
-    fn fold_mod(&mut self, m: &ast::Mod) -> ast::Mod {
+    fn fold_mod(&mut self, m: ast::Mod) -> ast::Mod {
         let tests = mem::replace(&mut self.tests, Vec::new());
         let tested_submods = mem::replace(&mut self.tested_submods, Vec::new());
         let mut mod_folded = fold::noop_fold_mod(m, self);
@@ -155,22 +155,25 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
         // Remove any #[main] from the AST so it doesn't clash with
         // the one we're going to add. Only if compiling an executable.
 
-        fn nomain(item: Gc<ast::Item>) -> Gc<ast::Item> {
-            box(GC) ast::Item {
-                attrs: item.attrs.iter().filter_map(|attr| {
-                    if !attr.check_name("main") {
-                        Some(*attr)
-                    } else {
-                        None
-                    }
-                }).collect(),
-                .. (*item).clone()
-            }
-        }
+        mod_folded.items = mem::replace(&mut mod_folded.items, vec![]).move_map(|item| {
+            item.map(|ast::Item {id, ident, attrs, node, vis, span}| {
+                ast::Item {
+                    id: id,
+                    ident: ident,
+                    attrs: attrs.move_iter().filter_map(|attr| {
+                        if !attr.check_name("main") {
+                            Some(attr)
+                        } else {
+                            None
+                        }
+                    }).collect(),
+                    node: node,
+                    vis: vis,
+                    span: span
+                }
+            })
+        });
 
-        for i in mod_folded.items.mut_iter() {
-            *i = nomain(*i);
-        }
         if !tests.is_empty() || !tested_submods.is_empty() {
             let (it, sym) = mk_reexport_mod(&mut self.cx, tests, tested_submods);
             mod_folded.items.push(it);
@@ -188,7 +191,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
 }
 
 fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>,
-                   tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (Gc<ast::Item>, ast::Ident) {
+                   tested_submods: Vec<(ast::Ident, ast::Ident)>) -> (P<ast::Item>, ast::Ident) {
     let mut view_items = Vec::new();
     let super_ = token::str_to_ident("super");
 
@@ -208,14 +211,14 @@ fn mk_reexport_mod(cx: &mut TestCtxt, tests: Vec<ast::Ident>,
     };
 
     let sym = token::gensym_ident("__test_reexports");
-    let it = box(GC) ast::Item {
+    let it = P(ast::Item {
         ident: sym.clone(),
         attrs: Vec::new(),
         id: ast::DUMMY_NODE_ID,
         node: ast::ItemMod(reexport_mod),
         vis: ast::Public,
         span: DUMMY_SP,
-    };
+    });
 
     (it, sym)
 }
@@ -266,10 +269,10 @@ fn strip_test_functions(krate: ast::Crate) -> ast::Crate {
     })
 }
 
-fn is_test_fn(cx: &TestCtxt, i: Gc<ast::Item>) -> bool {
+fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_test_attr = attr::contains_name(i.attrs.as_slice(), "test");
 
-    fn has_test_signature(i: Gc<ast::Item>) -> bool {
+    fn has_test_signature(i: &ast::Item) -> bool {
         match &i.node {
           &ast::ItemFn(ref decl, _, _, ref generics, _) => {
             let no_output = match decl.output.node {
@@ -295,10 +298,10 @@ fn is_test_fn(cx: &TestCtxt, i: Gc<ast::Item>) -> bool {
     return has_test_attr && has_test_signature(i);
 }
 
-fn is_bench_fn(cx: &TestCtxt, i: Gc<ast::Item>) -> bool {
+fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_bench_attr = attr::contains_name(i.attrs.as_slice(), "bench");
 
-    fn has_test_signature(i: Gc<ast::Item>) -> bool {
+    fn has_test_signature(i: &ast::Item) -> bool {
         match i.node {
             ast::ItemFn(ref decl, _, _, ref generics, _) => {
                 let input_cnt = decl.inputs.len();
@@ -325,19 +328,19 @@ fn is_bench_fn(cx: &TestCtxt, i: Gc<ast::Item>) -> bool {
     return has_bench_attr && has_test_signature(i);
 }
 
-fn is_ignored(cx: &TestCtxt, i: Gc<ast::Item>) -> bool {
+fn is_ignored(cx: &TestCtxt, i: &ast::Item) -> bool {
     i.attrs.iter().any(|attr| {
         // check ignore(cfg(foo, bar))
         attr.check_name("ignore") && match attr.meta_item_list() {
             Some(ref cfgs) => {
-                attr::test_cfg(cx.config.as_slice(), cfgs.iter().map(|x| *x))
+                attr::test_cfg(cx.config.as_slice(), cfgs.iter())
             }
             None => true
         }
     })
 }
 
-fn should_fail(i: Gc<ast::Item>) -> bool {
+fn should_fail(i: &ast::Item) -> bool {
     attr::contains_name(i.attrs.as_slice(), "should_fail")
 }
 
@@ -362,9 +365,9 @@ fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
     let id_test = token::str_to_ident("test");
     let (vi, vis) = if cx.is_test_crate {
         (ast::ViewItemUse(
-            box(GC) nospan(ast::ViewPathSimple(id_test,
-                                        path_node(vec!(id_test)),
-                                        ast::DUMMY_NODE_ID))),
+            P(nospan(ast::ViewPathSimple(id_test,
+                                         path_node(vec!(id_test)),
+                                         ast::DUMMY_NODE_ID)))),
          ast::Public)
     } else {
         (ast::ViewItemExternCrate(id_test, None, ast::DUMMY_NODE_ID),
@@ -378,7 +381,7 @@ fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
     }
 }
 
-fn mk_test_module(cx: &mut TestCtxt) -> (Gc<ast::Item>, Option<ast::ViewItem>) {
+fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<ast::ViewItem>) {
     // Link to test crate
     let view_items = vec!(mk_std(cx));
 
@@ -421,7 +424,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (Gc<ast::Item>, Option<ast::ViewItem>) {
                                        ast::DUMMY_NODE_ID));
 
         ast::ViewItem {
-            node: ast::ViewItemUse(box(GC) use_path),
+            node: ast::ViewItemUse(P(use_path)),
             attrs: vec![],
             vis: ast::Inherited,
             span: DUMMY_SP
@@ -430,7 +433,7 @@ fn mk_test_module(cx: &mut TestCtxt) -> (Gc<ast::Item>, Option<ast::ViewItem>) {
 
     debug!("Synthetic test module:\n{}\n", pprust::item_to_string(&item));
 
-    (box(GC) item, reexport)
+    (P(item), reexport)
 }
 
 fn nospan<T>(t: T) -> codemap::Spanned<T> {
@@ -449,7 +452,7 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path {
     }
 }
 
-fn mk_tests(cx: &TestCtxt) -> Gc<ast::Item> {
+fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
     // The vector of test_descs for this crate
     let test_descs = mk_test_descs(cx);
 
@@ -483,24 +486,24 @@ fn is_test_crate(krate: &ast::Crate) -> bool {
     }
 }
 
-fn mk_test_descs(cx: &TestCtxt) -> Gc<ast::Expr> {
+fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
     debug!("building test vector from {} tests", cx.testfns.len());
 
-    box(GC) ast::Expr {
+    P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
         node: ast::ExprAddrOf(ast::MutImmutable,
-            box(GC) ast::Expr {
+            P(ast::Expr {
                 id: ast::DUMMY_NODE_ID,
                 node: ast::ExprVec(cx.testfns.iter().map(|test| {
                     mk_test_desc_and_fn_rec(cx, test)
-            }).collect()),
-            span: DUMMY_SP,
-        }),
+                }).collect()),
+                span: DUMMY_SP,
+            })),
         span: DUMMY_SP,
-    }
+    })
 }
 
-fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> Gc<ast::Expr> {
+fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
     // FIXME #15962: should be using quote_expr, but that stringifies
     // __test_reexports, causing it to be reinterned, losing the
     // gensym information.
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index ce262bf449a..fd643a70c7b 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -119,7 +119,6 @@ pub mod front {
     pub mod config;
     pub mod test;
     pub mod std_inject;
-    pub mod assign_node_ids_and_map;
     pub mod feature_gate;
     pub mod show_span;
 }
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 616219a3cb9..58c05bee443 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -36,8 +36,8 @@ use lint::{Context, LintPass, LintArray};
 
 use std::cmp;
 use std::collections::HashMap;
+use std::slice;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
-use std::gc::Gc;
 use syntax::abi;
 use syntax::ast_map;
 use syntax::attr::AttrMetaMethods;
@@ -45,6 +45,7 @@ use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token;
 use syntax::{ast, ast_util, visit};
+use syntax::ptr::P;
 use syntax::visit::Visitor;
 
 declare_lint!(WHILE_TRUE, Warn,
@@ -59,9 +60,9 @@ impl LintPass for WhileTrue {
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         match e.node {
-            ast::ExprWhile(cond, _, _) => {
+            ast::ExprWhile(ref cond, _, _) => {
                 match cond.node {
-                    ast::ExprLit(lit) => {
+                    ast::ExprLit(ref lit) => {
                         match lit.node {
                             ast::LitBool(true) => {
                                 cx.span_lint(WHILE_TRUE, e.span,
@@ -91,9 +92,9 @@ impl LintPass for UnusedCasts {
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         match e.node {
-            ast::ExprCast(expr, ty) => {
-                let t_t = ast_ty_to_ty(cx, &infer::new_infer_ctxt(cx.tcx), &*ty);
-                if ty::get(ty::expr_ty(cx.tcx, &*expr)).sty == ty::get(t_t).sty {
+            ast::ExprCast(ref expr, ref ty) => {
+                let t_t = ast_ty_to_ty(cx, &infer::new_infer_ctxt(cx.tcx), &**ty);
+                if ty::get(ty::expr_ty(cx.tcx, &**expr)).sty == ty::get(t_t).sty {
                     cx.span_lint(UNNECESSARY_TYPECAST, ty.span, "unnecessary type cast");
                 }
             }
@@ -131,9 +132,9 @@ impl LintPass for TypeLimits {
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         match e.node {
-            ast::ExprUnary(ast::UnNeg, expr) => {
+            ast::ExprUnary(ast::UnNeg, ref expr) => {
                 match expr.node  {
-                    ast::ExprLit(lit) => {
+                    ast::ExprLit(ref lit) => {
                         match lit.node {
                             ast::LitInt(_, ast::UnsignedIntLit(_)) => {
                                 cx.span_lint(UNSIGNED_NEGATE, e.span,
@@ -144,7 +145,7 @@ impl LintPass for TypeLimits {
                         }
                     },
                     _ => {
-                        let t = ty::expr_ty(cx.tcx, &*expr);
+                        let t = ty::expr_ty(cx.tcx, &**expr);
                         match ty::get(t).sty {
                             ty::ty_uint(_) => {
                                 cx.span_lint(UNSIGNED_NEGATE, e.span,
@@ -160,16 +161,16 @@ impl LintPass for TypeLimits {
                     self.negated_expr_id = expr.id;
                 }
             },
-            ast::ExprParen(expr) if self.negated_expr_id == e.id => {
+            ast::ExprParen(ref expr) if self.negated_expr_id == e.id => {
                 self.negated_expr_id = expr.id;
             },
-            ast::ExprBinary(binop, l, r) => {
-                if is_comparison(binop) && !check_limits(cx.tcx, binop, &*l, &*r) {
+            ast::ExprBinary(binop, ref l, ref r) => {
+                if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) {
                     cx.span_lint(TYPE_LIMITS, e.span,
                                  "comparison is useless due to type limits");
                 }
             },
-            ast::ExprLit(lit) => {
+            ast::ExprLit(ref lit) => {
                 match ty::get(ty::expr_ty(cx.tcx, e)).sty {
                     ty::ty_int(t) => {
                         match lit.node {
@@ -292,7 +293,7 @@ impl LintPass for TypeLimits {
                 ty::ty_int(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i64 = match lit.node {
-                        ast::ExprLit(li) => match li.node {
+                        ast::ExprLit(ref li) => match li.node {
                             ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
                             ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64,
                             ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
@@ -306,7 +307,7 @@ impl LintPass for TypeLimits {
                 ty::ty_uint(uint_ty) => {
                     let (min, max): (u64, u64) = uint_ty_range(uint_ty);
                     let lit_val: u64 = match lit.node {
-                        ast::ExprLit(li) => match li.node {
+                        ast::ExprLit(ref li) => match li.node {
                             ast::LitInt(v, _) => v,
                             _ => return true
                         },
@@ -400,8 +401,8 @@ impl LintPass for CTypes {
             ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
                 for ni in nmod.items.iter() {
                     match ni.node {
-                        ast::ForeignItemFn(decl, _) => check_foreign_fn(cx, &*decl),
-                        ast::ForeignItemStatic(t, _) => check_ty(cx, &*t)
+                        ast::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl),
+                        ast::ForeignItemStatic(ref t, _) => check_ty(cx, &**t)
                     }
                 }
             }
@@ -477,7 +478,7 @@ impl LintPass for HeapMemory {
 
         // If it's a struct, we also have to check the fields' types
         match it.node {
-            ast::ItemStruct(struct_def, _) => {
+            ast::ItemStruct(ref struct_def, _) => {
                 for struct_field in struct_def.fields.iter() {
                     self.check_heap_type(cx, struct_field.span,
                                          ty::node_id_to_type(cx.tcx, struct_field.node.id));
@@ -658,7 +659,7 @@ impl LintPass for PathStatement {
 
     fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
         match s.node {
-            ast::StmtSemi(expr, _) => {
+            ast::StmtSemi(ref expr, _) => {
                 match expr.node {
                     ast::ExprPath(_) => cx.span_lint(PATH_STATEMENT, s.span,
                                                      "path statement with no effect"),
@@ -685,10 +686,10 @@ impl LintPass for UnusedResult {
 
     fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
         let expr = match s.node {
-            ast::StmtSemi(expr, _) => expr,
+            ast::StmtSemi(ref expr, _) => &**expr,
             _ => return
         };
-        let t = ty::expr_ty(cx.tcx, &*expr);
+        let t = ty::expr_ty(cx.tcx, expr);
         match ty::get(t).sty {
             ty::ty_nil | ty::ty_bot | ty::ty_bool => return,
             _ => {}
@@ -698,7 +699,7 @@ impl LintPass for UnusedResult {
             _ => {}
         }
 
-        let t = ty::expr_ty(cx.tcx, &*expr);
+        let t = ty::expr_ty(cx.tcx, expr);
         let mut warned = false;
         match ty::get(t).sty {
             ty::ty_struct(did, _) |
@@ -1080,29 +1081,29 @@ impl LintPass for UnnecessaryParens {
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         let (value, msg, struct_lit_needs_parens) = match e.node {
-            ast::ExprIf(cond, _, _) => (cond, "`if` condition", true),
-            ast::ExprWhile(cond, _, _) => (cond, "`while` condition", true),
-            ast::ExprMatch(head, _) => (head, "`match` head expression", true),
-            ast::ExprRet(Some(value)) => (value, "`return` value", false),
-            ast::ExprAssign(_, value) => (value, "assigned value", false),
-            ast::ExprAssignOp(_, _, value) => (value, "assigned value", false),
+            ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
+            ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
+            ast::ExprMatch(ref head, _) => (head, "`match` head expression", true),
+            ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
+            ast::ExprAssign(_, ref value) => (value, "assigned value", false),
+            ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
             _ => return
         };
-        self.check_unnecessary_parens_core(cx, &*value, msg, struct_lit_needs_parens);
+        self.check_unnecessary_parens_core(cx, &**value, msg, struct_lit_needs_parens);
     }
 
     fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
         let (value, msg) = match s.node {
-            ast::StmtDecl(decl, _) => match decl.node {
-                ast::DeclLocal(local) => match local.init {
-                    Some(value) => (value, "assigned value"),
+            ast::StmtDecl(ref decl, _) => match decl.node {
+                ast::DeclLocal(ref local) => match local.init {
+                    Some(ref value) => (value, "assigned value"),
                     None => return
                 },
                 _ => return
             },
             _ => return
         };
-        self.check_unnecessary_parens_core(cx, &*value, msg, false);
+        self.check_unnecessary_parens_core(cx, &**value, msg, false);
     }
 }
 
@@ -1157,12 +1158,12 @@ declare_lint!(pub UNUSED_MUT, Warn,
 pub struct UnusedMut;
 
 impl UnusedMut {
-    fn check_unused_mut_pat(&self, cx: &Context, pats: &[Gc<ast::Pat>]) {
+    fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
         // collect all mutable pattern and group their NodeIDs by their Identifier to
         // avoid false warnings in match arms with multiple patterns
         let mut mutables = HashMap::new();
-        for &p in pats.iter() {
-            pat_util::pat_bindings(&cx.tcx.def_map, &*p, |mode, id, _, path1| {
+        for p in pats.iter() {
+            pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| {
                 let ident = path1.node;
                 match mode {
                     ast::BindByValue(ast::MutMutable) => {
@@ -1205,10 +1206,10 @@ impl LintPass for UnusedMut {
 
     fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
         match s.node {
-            ast::StmtDecl(d, _) => {
+            ast::StmtDecl(ref d, _) => {
                 match d.node {
-                    ast::DeclLocal(l) => {
-                        self.check_unused_mut_pat(cx, &[l.pat]);
+                    ast::DeclLocal(ref l) => {
+                        self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
                     },
                     _ => {}
                 }
@@ -1221,7 +1222,7 @@ impl LintPass for UnusedMut {
                 _: visit::FnKind, decl: &ast::FnDecl,
                 _: &ast::Block, _: Span, _: ast::NodeId) {
         for a in decl.inputs.iter() {
-            self.check_unused_mut_pat(cx, &[a.pat]);
+            self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
         }
     }
 }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index b1975ab913f..4dd94441512 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -278,7 +278,7 @@ pub fn gather_attrs(attrs: &[ast::Attribute])
 
         attr::mark_used(attr);
 
-        let meta = attr.node.value;
+        let meta = &attr.node.value;
         let metas = match meta.node {
             ast::MetaList(_, ref metas) => metas,
             _ => {
@@ -709,8 +709,8 @@ impl LintPass for GatherNodeLevels {
 ///
 /// Consumes the `lint_store` field of the `Session`.
 pub fn check_crate(tcx: &ty::ctxt,
-                   krate: &ast::Crate,
                    exported_items: &ExportedItems) {
+    let krate = tcx.map.krate();
     let mut cx = Context::new(tcx, krate, exported_items);
 
     // Visit the whole crate.
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index ac161ef8bde..c27f1d9ed1f 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -97,18 +97,18 @@ pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem>
         path.as_slice())
 }
 
-pub enum found_ast {
-    found(ast::InlinedItem),
-    found_parent(ast::DefId, ast::InlinedItem),
+pub enum found_ast<'ast> {
+    found(&'ast ast::InlinedItem),
+    found_parent(ast::DefId, &'ast ast::InlinedItem),
     not_found,
 }
 
 // Finds the AST for this item in the crate metadata, if any.  If the item was
 // not marked for inlining, then the AST will not be present and hence none
 // will be returned.
-pub fn maybe_get_item_ast(tcx: &ty::ctxt, def: ast::DefId,
-                          decode_inlined_item: decoder::DecodeInlinedItem)
-                       -> found_ast {
+pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId,
+                                decode_inlined_item: decoder::DecodeInlinedItem)
+                                -> found_ast<'tcx> {
     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)
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 904ca2416e0..bcf9a4f678d 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -30,7 +30,6 @@ use middle::ty;
 use middle::typeck;
 use middle::astencode::vtable_decoder_helpers;
 
-use std::gc::Gc;
 use std::hash::Hash;
 use std::hash;
 use std::io::extensions::u64_from_be_bytes;
@@ -48,6 +47,7 @@ use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::ast;
 use syntax::codemap;
+use syntax::ptr::P;
 
 pub type Cmd<'a> = &'a crate_metadata;
 
@@ -612,27 +612,28 @@ 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: Cmd,
-                                  tcx: &ty::ctxt,
-                                  path: Vec<ast_map::PathElem>,
-                                  par_doc: rbml::Doc|: 'a
-                                  -> Result<ast::InlinedItem, Vec<ast_map::PathElem> >;
+pub type DecodeInlinedItem<'a> = <'tcx> |cdata: Cmd,
+                                         tcx: &ty::ctxt<'tcx>,
+                                         path: Vec<ast_map::PathElem>,
+                                         par_doc: rbml::Doc|: 'a
+                                         -> Result<&'tcx ast::InlinedItem,
+                                                   Vec<ast_map::PathElem>>;
 
-pub fn maybe_get_item_ast(cdata: Cmd, tcx: &ty::ctxt, id: ast::NodeId,
-                          decode_inlined_item: DecodeInlinedItem)
-                          -> csearch::found_ast {
+pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeId,
+                                decode_inlined_item: DecodeInlinedItem)
+                                -> csearch::found_ast<'tcx> {
     debug!("Looking up item: {}", id);
     let item_doc = lookup_item(id, cdata.data());
     let path = Vec::from_slice(item_path(item_doc).init());
     match decode_inlined_item(cdata, tcx, path, item_doc) {
-        Ok(ref ii) => csearch::found(*ii),
+        Ok(ii) => csearch::found(ii),
         Err(path) => {
             match item_parent_item(item_doc) {
                 Some(did) => {
                     let did = translate_def_id(cdata, did);
                     let parent_item = lookup_item(did.node, cdata.data());
                     match decode_inlined_item(cdata, tcx, path, parent_item) {
-                        Ok(ref ii) => csearch::found_parent(did, *ii),
+                        Ok(ii) => csearch::found_parent(did, ii),
                         Err(_) => csearch::not_found
                     }
                 }
@@ -1003,8 +1004,8 @@ pub fn get_struct_fields(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId)
     result
 }
 
-fn get_meta_items(md: rbml::Doc) -> Vec<Gc<ast::MetaItem>> {
-    let mut items: Vec<Gc<ast::MetaItem>> = Vec::new();
+fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
+    let mut items: Vec<P<ast::MetaItem>> = Vec::new();
     reader::tagged_docs(md, tag_meta_item_word, |meta_item_doc| {
         let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
         let n = token::intern_and_get_ident(nd.as_str_slice());
@@ -1043,7 +1044,7 @@ fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
             // Currently it's only possible to have a single meta item on
             // an attribute
             assert_eq!(meta_items.len(), 1u);
-            let meta_item = *meta_items.get(0);
+            let meta_item = meta_items.move_iter().nth(0).unwrap();
             attrs.push(
                 codemap::Spanned {
                     node: ast::Attribute_ {
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 209a09dbfaf..376cccc3f10 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -29,7 +29,6 @@ use util::nodemap::{NodeMap, NodeSet};
 
 use serialize::Encodable;
 use std::cell::RefCell;
-use std::gc::Gc;
 use std::hash::Hash;
 use std::hash;
 use std::mem;
@@ -46,6 +45,7 @@ use syntax::attr::AttrMetaMethods;
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token::special_idents;
 use syntax::parse::token;
+use syntax::ptr::P;
 use syntax::visit::Visitor;
 use syntax::visit;
 use syntax;
@@ -55,16 +55,11 @@ use rbml::io::SeekableMemWriter;
 /// A borrowed version of `ast::InlinedItem`.
 pub enum InlinedItemRef<'a> {
     IIItemRef(&'a ast::Item),
-    IITraitItemRef(ast::DefId, InlinedTraitItemRef<'a>),
+    IITraitItemRef(ast::DefId, &'a ast::TraitItem),
+    IIImplItemRef(ast::DefId, &'a ast::ImplItem),
     IIForeignRef(&'a ast::ForeignItem)
 }
 
-/// A borrowed version of `ast::InlinedTraitItem`.
-pub enum InlinedTraitItemRef<'a> {
-    ProvidedInlinedTraitItemRef(&'a Method),
-    RequiredInlinedTraitItemRef(&'a Method),
-}
-
 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
 
 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
@@ -507,7 +502,7 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
 /// * For enums, iterates through the node IDs of the variants.
 ///
 /// * For newtype structs, iterates through the node ID of the constructor.
-fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
+fn each_auxiliary_node_id(item: &Item, callback: |NodeId| -> bool) -> bool {
     let mut continue_ = true;
     match item.node {
         ItemEnum(ref enum_def, _) => {
@@ -518,7 +513,7 @@ fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
                 }
             }
         }
-        ItemStruct(struct_def, _) => {
+        ItemStruct(ref struct_def, _) => {
             // If this is a newtype struct, return the constructor.
             match struct_def.ctor_id {
                 Some(ctor_id) if struct_def.fields.len() > 0 &&
@@ -587,7 +582,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
         rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
         rbml_w.end_tag();
 
-        each_auxiliary_node_id(*item, |auxiliary_node_id| {
+        each_auxiliary_node_id(&**item, |auxiliary_node_id| {
             rbml_w.start_tag(tag_mod_child);
             rbml_w.wr_str(def_to_string(local_def(
                         auxiliary_node_id)).as_slice());
@@ -858,7 +853,7 @@ fn encode_info_for_method(ecx: &EncodeContext,
                           impl_path: PathElems,
                           is_default_impl: bool,
                           parent_id: NodeId,
-                          ast_method_opt: Option<Gc<Method>>) {
+                          ast_item_opt: Option<&ImplItem>) {
 
     debug!("encode_info_for_method: {:?} {}", m.def_id,
            token::get_ident(m.ident));
@@ -877,26 +872,20 @@ fn encode_info_for_method(ecx: &EncodeContext,
 
     let elem = ast_map::PathName(m.ident.name);
     encode_path(rbml_w, impl_path.chain(Some(elem).move_iter()));
-    match ast_method_opt {
-        Some(ast_method) => {
-            encode_attributes(rbml_w, ast_method.attrs.as_slice())
-        }
-        None => ()
-    }
-
-    for &ast_method in ast_method_opt.iter() {
-        let any_types = !pty.generics.types.is_empty();
-        if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
-            encode_inlined_item(ecx,
-                                rbml_w,
-                                IITraitItemRef(local_def(parent_id),
-                                               RequiredInlinedTraitItemRef(
-                                                   &*ast_method)));
-        }
-        if !any_types {
-            encode_symbol(ecx, rbml_w, m.def_id.node);
+    match ast_item_opt {
+        Some(&ast::MethodImplItem(ref ast_method)) => {
+            encode_attributes(rbml_w, ast_method.attrs.as_slice());
+            let any_types = !pty.generics.types.is_empty();
+            if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
+                encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
+                                                               ast_item_opt.unwrap()));
+            }
+            if !any_types {
+                encode_symbol(ecx, rbml_w, m.def_id.node);
+            }
+            encode_method_argument_names(rbml_w, ast_method.pe_fn_decl());
         }
-        encode_method_argument_names(rbml_w, &*ast_method.pe_fn_decl());
+        None => {}
     }
 
     rbml_w.end_tag();
@@ -1127,7 +1116,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                  (*enum_definition).variants.as_slice(),
                                  index);
       }
-      ItemStruct(struct_def, _) => {
+      ItemStruct(ref struct_def, _) => {
         let fields = ty::lookup_struct_fields(tcx, def_id);
 
         /* First, encode the fields
@@ -1178,7 +1167,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             None => {}
         }
       }
-      ItemImpl(_, ref opt_trait, ty, ref ast_items) => {
+      ItemImpl(_, ref opt_trait, ref ty, ref ast_items) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
         let impl_items = tcx.impl_items.borrow();
@@ -1228,7 +1217,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         let num_implemented_methods = ast_items.len();
         for (i, &trait_item_def_id) in items.iter().enumerate() {
             let ast_item = if i < num_implemented_methods {
-                Some(*ast_items.get(i))
+                Some(ast_items.get(i))
             } else {
                 None
             };
@@ -1238,29 +1227,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 pos: rbml_w.writer.tell().unwrap(),
             });
 
-            let trait_item_type =
+            let ty::MethodTraitItem(method_type) =
                 ty::impl_or_trait_item(tcx, trait_item_def_id.def_id());
-            match (trait_item_type, ast_item) {
-                (ty::MethodTraitItem(method_type),
-                 Some(ast::MethodImplItem(ast_method))) => {
-                    encode_info_for_method(ecx,
-                                           rbml_w,
-                                           &*method_type,
-                                           path.clone(),
-                                           false,
-                                           item.id,
-                                           Some(ast_method))
-                }
-                (ty::MethodTraitItem(method_type), None) => {
-                    encode_info_for_method(ecx,
-                                           rbml_w,
-                                           &*method_type,
-                                           path.clone(),
-                                           false,
-                                           item.id,
-                                           None)
-                }
-            }
+            encode_info_for_method(ecx, rbml_w, &*method_type, path.clone(),
+                                   false, item.id, ast_item)
         }
       }
       ItemTrait(_, _, _, ref ms) => {
@@ -1345,15 +1315,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
                         }
                     }
 
-                    match ms.get(i) {
-                        &RequiredMethod(ref tm) => {
+                    let trait_item = ms.get(i);
+                    match *trait_item {
+                        RequiredMethod(ref tm) => {
                             encode_attributes(rbml_w, tm.attrs.as_slice());
                             encode_item_sort(rbml_w, 'r');
                             encode_parent_sort(rbml_w, 't');
                             encode_method_argument_names(rbml_w, &*tm.decl);
                         }
 
-                        &ProvidedMethod(m) => {
+                        ProvidedMethod(ref m) => {
                             encode_attributes(rbml_w, m.attrs.as_slice());
                             // If this is a static method, we've already
                             // encoded this.
@@ -1366,14 +1337,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
                             }
                             encode_item_sort(rbml_w, 'p');
                             encode_parent_sort(rbml_w, 't');
-                            encode_inlined_item(
-                                ecx,
-                                rbml_w,
-                                IITraitItemRef(
-                                    def_id,
-                                    ProvidedInlinedTraitItemRef(&*m)));
-                            encode_method_argument_names(rbml_w,
-                                                         &*m.pe_fn_decl());
+                            encode_inlined_item(ecx, rbml_w,
+                                                IITraitItemRef(def_id, trait_item));
+                            encode_method_argument_names(rbml_w, &*m.pe_fn_decl());
                         }
                     }
                 }
@@ -1571,7 +1537,7 @@ fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
     wr.write_be_u32(n as u32);
 }
 
-fn encode_meta_item(rbml_w: &mut Encoder, mi: Gc<MetaItem>) {
+fn encode_meta_item(rbml_w: &mut Encoder, mi: &MetaItem) {
     match mi.node {
       MetaWord(ref name) => {
         rbml_w.start_tag(tag_meta_item_word);
@@ -1601,7 +1567,7 @@ fn encode_meta_item(rbml_w: &mut Encoder, mi: Gc<MetaItem>) {
         rbml_w.writer.write(name.get().as_bytes());
         rbml_w.end_tag();
         for inner_item in items.iter() {
-            encode_meta_item(rbml_w, *inner_item);
+            encode_meta_item(rbml_w, &**inner_item);
         }
         rbml_w.end_tag();
       }
@@ -1613,7 +1579,7 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[Attribute]) {
     for attr in attrs.iter() {
         rbml_w.start_tag(tag_attribute);
         rbml_w.wr_tagged_u8(tag_attribute_is_sugared_doc, attr.node.is_sugared_doc as u8);
-        encode_meta_item(rbml_w, attr.node.value);
+        encode_meta_item(rbml_w, &*attr.node.value);
         rbml_w.end_tag();
     }
     rbml_w.end_tag();
@@ -1852,12 +1818,12 @@ fn encode_misc_info(ecx: &EncodeContext,
                     rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_misc_info);
     rbml_w.start_tag(tag_misc_info_crate_items);
-    for &item in krate.module.items.iter() {
+    for item in krate.module.items.iter() {
         rbml_w.start_tag(tag_mod_child);
         rbml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
         rbml_w.end_tag();
 
-        each_auxiliary_node_id(item, |auxiliary_node_id| {
+        each_auxiliary_node_id(&**item, |auxiliary_node_id| {
             rbml_w.start_tag(tag_mod_child);
             rbml_w.wr_str(def_to_string(local_def(
                         auxiliary_node_id)).as_slice());
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index b7597b50b49..2dab3c2b1da 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -36,6 +36,7 @@ use syntax::ast_util::PostExpansionMethod;
 use syntax::codemap::Span;
 use syntax::fold::Folder;
 use syntax::parse::token;
+use syntax::ptr::P;
 use syntax;
 
 use libc;
@@ -52,25 +53,20 @@ use serialize::{EncoderHelpers};
 
 #[cfg(test)] use syntax::parse;
 #[cfg(test)] use syntax::print::pprust;
-#[cfg(test)] use std::gc::Gc;
 
-struct DecodeContext<'a, 'tcx: 'a> {
-    cdata: &'a cstore::crate_metadata,
+struct DecodeContext<'a, 'b, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-}
-
-struct ExtendedDecodeContext<'a, 'tcx: 'a> {
-    dcx: &'a DecodeContext<'a, 'tcx>,
+    cdata: &'b cstore::crate_metadata,
     from_id_range: ast_util::IdRange,
     to_id_range: ast_util::IdRange
 }
 
 trait tr {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> Self;
+    fn tr(&self, dcx: &DecodeContext) -> Self;
 }
 
 trait tr_intern {
-    fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
+    fn tr_intern(&self, dcx: &DecodeContext) -> ast::DefId;
 }
 
 pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
@@ -84,19 +80,21 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
     let id = match ii {
         e::IIItemRef(i) => i.id,
         e::IIForeignRef(i) => i.id,
-        e::IITraitItemRef(_, e::ProvidedInlinedTraitItemRef(m)) => m.id,
-        e::IITraitItemRef(_, e::RequiredInlinedTraitItemRef(m)) => m.id,
+        e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
+        e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
+        e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id
     };
     debug!("> Encoding inlined item: {} ({})",
            ecx.tcx.map.path_to_string(id),
            rbml_w.writer.tell());
 
+    // Folding could be avoided with a smarter encoder.
     let ii = simplify_ast(ii);
     let id_range = ast_util::compute_id_range_for_inlined_item(&ii);
 
     rbml_w.start_tag(c::tag_ast as uint);
     id_range.encode(rbml_w);
-    encode_ast(rbml_w, ii);
+    encode_ast(rbml_w, &ii);
     encode_side_tables_for_ii(ecx, rbml_w, &ii);
     rbml_w.end_tag();
 
@@ -105,15 +103,28 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
            rbml_w.writer.tell());
 }
 
-pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
-                           tcx: &ty::ctxt,
-                           path: Vec<ast_map::PathElem>,
-                           par_doc: rbml::Doc)
-                           -> Result<ast::InlinedItem, Vec<ast_map::PathElem>> {
-    let dcx = &DecodeContext {
-        cdata: cdata,
-        tcx: tcx,
-    };
+impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
+    fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
+        if id == ast::DUMMY_NODE_ID {
+            // Used by ast_map to map the NodeInlinedParent.
+            self.tcx.sess.next_node_id()
+        } else {
+            self.tr_id(id)
+        }
+    }
+    fn new_def_id(&self, def_id: ast::DefId) -> ast::DefId {
+        self.tr_def_id(def_id)
+    }
+    fn new_span(&self, span: Span) -> Span {
+        self.tr_span(span)
+    }
+}
+
+pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
+                                 tcx: &ty::ctxt<'tcx>,
+                                 path: Vec<ast_map::PathElem>,
+                                 par_doc: rbml::Doc)
+                                 -> Result<&'tcx ast::InlinedItem, Vec<ast_map::PathElem>> {
     match par_doc.opt_child(c::tag_ast) {
       None => Err(path),
       Some(ast_doc) => {
@@ -127,21 +138,28 @@ pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
         });
         let mut ast_dsr = reader::Decoder::new(ast_doc);
         let from_id_range = Decodable::decode(&mut ast_dsr).unwrap();
-        let to_id_range = reserve_id_range(&dcx.tcx.sess, from_id_range);
-        let xcx = &ExtendedDecodeContext {
-            dcx: dcx,
+        let to_id_range = reserve_id_range(&tcx.sess, from_id_range);
+        let dcx = &DecodeContext {
+            cdata: cdata,
+            tcx: tcx,
             from_id_range: from_id_range,
             to_id_range: to_id_range
         };
         let raw_ii = decode_ast(ast_doc);
-        let ii = renumber_and_map_ast(xcx, &dcx.tcx.map, path, raw_ii);
-        let ident = match ii {
-            ast::IIItem(i) => i.ident,
-            ast::IIForeign(i) => i.ident,
-            ast::IITraitItem(_, iti) => {
-                match iti {
-                    ast::ProvidedInlinedTraitItem(m) => m.pe_ident(),
-                    ast::RequiredInlinedTraitItem(m) => m.pe_ident(),
+        let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, raw_ii, dcx);
+
+        let ident = match *ii {
+            ast::IIItem(ref i) => i.ident,
+            ast::IIForeign(ref i) => i.ident,
+            ast::IITraitItem(_, ref ti) => {
+                match *ti {
+                    ast::ProvidedMethod(ref m) => m.pe_ident(),
+                    ast::RequiredMethod(ref ty_m) => ty_m.ident
+                }
+            },
+            ast::IIImplItem(_, ref m) => {
+                match *m {
+                    ast::MethodImplItem(ref m) => m.pe_ident()
                 }
             }
         };
@@ -149,12 +167,12 @@ pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
         debug!("< Decoded inlined fn: {}::{}",
                path_as_str.unwrap(),
                token::get_ident(ident));
-        region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, &ii);
-        decode_side_tables(xcx, ast_doc);
-        match ii {
-          ast::IIItem(i) => {
+        region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii);
+        decode_side_tables(dcx, ast_doc);
+        match *ii {
+          ast::IIItem(ref i) => {
             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
-                   syntax::print::pprust::item_to_string(&*i));
+                   syntax::print::pprust::item_to_string(&**i));
           }
           _ => { }
         }
@@ -176,7 +194,7 @@ fn reserve_id_range(sess: &Session,
     ast_util::IdRange { min: to_id_min, max: to_id_max }
 }
 
-impl<'a, 'tcx> ExtendedDecodeContext<'a, 'tcx> {
+impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
         /*!
          * Translates an internal id, meaning a node id that is known
@@ -214,7 +232,7 @@ impl<'a, 'tcx> ExtendedDecodeContext<'a, 'tcx> {
          * `tr_intern_def_id()` below.
          */
 
-        decoder::translate_def_id(self.dcx.cdata, did)
+        decoder::translate_def_id(self.cdata, did)
     }
     pub fn tr_intern_def_id(&self, did: ast::DefId) -> ast::DefId {
         /*!
@@ -233,26 +251,26 @@ impl<'a, 'tcx> ExtendedDecodeContext<'a, 'tcx> {
 }
 
 impl tr_intern for ast::DefId {
-    fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId {
-        xcx.tr_intern_def_id(*self)
+    fn tr_intern(&self, dcx: &DecodeContext) -> ast::DefId {
+        dcx.tr_intern_def_id(*self)
     }
 }
 
 impl tr for ast::DefId {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ast::DefId {
-        xcx.tr_def_id(*self)
+    fn tr(&self, dcx: &DecodeContext) -> ast::DefId {
+        dcx.tr_def_id(*self)
     }
 }
 
 impl tr for Option<ast::DefId> {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> Option<ast::DefId> {
-        self.map(|d| xcx.tr_def_id(d))
+    fn tr(&self, dcx: &DecodeContext) -> Option<ast::DefId> {
+        self.map(|d| dcx.tr_def_id(d))
     }
 }
 
 impl tr for Span {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> Span {
-        xcx.tr_span(*self)
+    fn tr(&self, dcx: &DecodeContext) -> Span {
+        dcx.tr_span(*self)
     }
 }
 
@@ -267,18 +285,18 @@ 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,
+    fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId;
+    fn read_def_id_nodcx(&mut self,
                          cdata: &cstore::crate_metadata) -> ast::DefId;
 }
 
 impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
-    fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
+    fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId {
         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
-        did.tr(xcx)
+        did.tr(dcx)
     }
 
-    fn read_def_id_noxcx(&mut self,
+    fn read_def_id_nodcx(&mut self,
                          cdata: &cstore::crate_metadata) -> ast::DefId {
         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
         decoder::translate_def_id(cdata, did)
@@ -300,7 +318,7 @@ impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
 // We also have to adjust the spans: for now we just insert a dummy span,
 // but eventually we should add entries to the local codemap as required.
 
-fn encode_ast(rbml_w: &mut Encoder, item: ast::InlinedItem) {
+fn encode_ast(rbml_w: &mut Encoder, item: &ast::InlinedItem) {
     rbml_w.start_tag(c::tag_tree as uint);
     item.encode(rbml_w);
     rbml_w.end_tag();
@@ -309,29 +327,36 @@ fn encode_ast(rbml_w: &mut Encoder, item: ast::InlinedItem) {
 struct NestedItemsDropper;
 
 impl Folder for NestedItemsDropper {
-    fn fold_block(&mut self, blk: ast::P<ast::Block>) -> ast::P<ast::Block> {
-        let stmts_sans_items = blk.stmts.iter().filter_map(|stmt| {
-            match stmt.node {
-                ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => Some(*stmt),
-                ast::StmtDecl(decl, _) => {
-                    match decl.node {
-                        ast::DeclLocal(_) => Some(*stmt),
-                        ast::DeclItem(_) => None,
+    fn fold_block(&mut self, blk: P<ast::Block>) -> P<ast::Block> {
+        blk.and_then(|ast::Block {id, stmts, expr, rules, span, ..}| {
+            let stmts_sans_items = stmts.move_iter().filter_map(|stmt| {
+                let use_stmt = match stmt.node {
+                    ast::StmtExpr(_, _) | ast::StmtSemi(_, _) => true,
+                    ast::StmtDecl(ref decl, _) => {
+                        match decl.node {
+                            ast::DeclLocal(_) => true,
+                            ast::DeclItem(_) => false,
+                        }
                     }
+                    ast::StmtMac(..) => fail!("unexpanded macro in astencode")
+                };
+                if use_stmt {
+                    Some(stmt)
+                } else {
+                    None
                 }
-                ast::StmtMac(..) => fail!("unexpanded macro in astencode")
-            }
-        }).collect();
-        let blk_sans_items = ast::P(ast::Block {
-            view_items: Vec::new(), // I don't know if we need the view_items
-                                    // here, but it doesn't break tests!
-            stmts: stmts_sans_items,
-            expr: blk.expr,
-            id: blk.id,
-            rules: blk.rules,
-            span: blk.span,
-        });
-        fold::noop_fold_block(blk_sans_items, self)
+            }).collect();
+            let blk_sans_items = P(ast::Block {
+                view_items: Vec::new(), // I don't know if we need the view_items
+                                        // here, but it doesn't break tests!
+                stmts: stmts_sans_items,
+                expr: expr,
+                id: id,
+                rules: rules,
+                span: span,
+            });
+            fold::noop_fold_block(blk_sans_items, self)
+        })
     }
 }
 
@@ -351,27 +376,35 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
     match ii {
         // HACK we're not dropping items.
         e::IIItemRef(i) => {
-            ast::IIItem(fold::noop_fold_item(i, &mut fld)
+            ast::IIItem(fold::noop_fold_item(P(i.clone()), &mut fld)
                             .expect_one("expected one item"))
         }
-        e::IITraitItemRef(d, iti) => {
-            ast::IITraitItem(d, match iti {
-                e::ProvidedInlinedTraitItemRef(m) => {
-                    ast::ProvidedInlinedTraitItem(
-                        fold::noop_fold_method(m, &mut fld)
+        e::IITraitItemRef(d, ti) => {
+            ast::IITraitItem(d, match *ti {
+                ast::ProvidedMethod(ref m) => {
+                    ast::ProvidedMethod(
+                        fold::noop_fold_method(m.clone(), &mut fld)
                             .expect_one("noop_fold_method must produce \
                                          exactly one method"))
                 }
-                e::RequiredInlinedTraitItemRef(m) => {
-                    ast::RequiredInlinedTraitItem(
-                        fold::noop_fold_method(m, &mut fld)
+                ast::RequiredMethod(ref ty_m) => {
+                    ast::RequiredMethod(
+                        fold::noop_fold_type_method(ty_m.clone(), &mut fld))
+                }
+            })
+        }
+        e::IIImplItemRef(d, m) => {
+            ast::IIImplItem(d, match *m {
+                ast::MethodImplItem(ref m) => {
+                    ast::MethodImplItem(
+                        fold::noop_fold_method(m.clone(), &mut fld)
                             .expect_one("noop_fold_method must produce \
                                          exactly one method"))
                 }
             })
         }
         e::IIForeignRef(i) => {
-            ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
+            ast::IIForeign(fold::noop_fold_foreign_item(P(i.clone()), &mut fld))
         }
     }
 }
@@ -382,114 +415,61 @@ fn decode_ast(par_doc: rbml::Doc) -> ast::InlinedItem {
     Decodable::decode(&mut d).unwrap()
 }
 
-struct AstRenumberer<'a, 'tcx: 'a> {
-    xcx: &'a ExtendedDecodeContext<'a, 'tcx>,
-}
-
-impl<'a, 'tcx> ast_map::FoldOps for AstRenumberer<'a, 'tcx> {
-    fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
-        if id == ast::DUMMY_NODE_ID {
-            // Used by ast_map to map the NodeInlinedParent.
-            self.xcx.dcx.tcx.sess.next_node_id()
-        } else {
-            self.xcx.tr_id(id)
-        }
-    }
-    fn new_span(&self, span: Span) -> Span {
-        self.xcx.tr_span(span)
-    }
-}
-
-fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
-                        map: &ast_map::Map,
-                        path: Vec<ast_map::PathElem> ,
-                        ii: ast::InlinedItem) -> ast::InlinedItem {
-    ast_map::map_decoded_item(map,
-                              path.move_iter().collect(),
-                              AstRenumberer { xcx: xcx },
-                              |fld| {
-        match ii {
-            ast::IIItem(i) => {
-                ast::IIItem(fld.fold_item(i).expect_one("expected one item"))
-            }
-            ast::IITraitItem(d, iti) => {
-                match iti {
-                    ast::ProvidedInlinedTraitItem(m) => {
-                        ast::IITraitItem(
-                            xcx.tr_def_id(d),
-                            ast::ProvidedInlinedTraitItem(
-                                fld.fold_method(m)
-                                   .expect_one("expected one method")))
-                    }
-                    ast::RequiredInlinedTraitItem(m) => {
-                        ast::IITraitItem(
-                            xcx.tr_def_id(d),
-                            ast::RequiredInlinedTraitItem(
-                                fld.fold_method(m)
-                                   .expect_one("expected one method")))
-                    }
-                }
-            }
-            ast::IIForeign(i) => ast::IIForeign(fld.fold_foreign_item(i))
-        }
-    })
-}
-
 // ______________________________________________________________________
 // Encoding and decoding of ast::def
 
-fn decode_def(xcx: &ExtendedDecodeContext, doc: rbml::Doc) -> def::Def {
+fn decode_def(dcx: &DecodeContext, doc: rbml::Doc) -> def::Def {
     let mut dsr = reader::Decoder::new(doc);
     let def: def::Def = Decodable::decode(&mut dsr).unwrap();
-    def.tr(xcx)
+    def.tr(dcx)
 }
 
 impl tr for def::Def {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> def::Def {
+    fn tr(&self, dcx: &DecodeContext) -> def::Def {
         match *self {
-          def::DefFn(did, p) => def::DefFn(did.tr(xcx), p),
+          def::DefFn(did, p) => def::DefFn(did.tr(dcx), p),
           def::DefStaticMethod(did, wrapped_did2, p) => {
-            def::DefStaticMethod(did.tr(xcx),
+            def::DefStaticMethod(did.tr(dcx),
                                    match wrapped_did2 {
                                     def::FromTrait(did2) => {
-                                        def::FromTrait(did2.tr(xcx))
+                                        def::FromTrait(did2.tr(dcx))
                                     }
                                     def::FromImpl(did2) => {
-                                        def::FromImpl(did2.tr(xcx))
+                                        def::FromImpl(did2.tr(dcx))
                                     }
                                    },
                                    p)
           }
           def::DefMethod(did0, did1) => {
-            def::DefMethod(did0.tr(xcx), did1.map(|did1| did1.tr(xcx)))
+            def::DefMethod(did0.tr(dcx), did1.map(|did1| did1.tr(dcx)))
           }
-          def::DefSelfTy(nid) => { def::DefSelfTy(xcx.tr_id(nid)) }
-          def::DefMod(did) => { def::DefMod(did.tr(xcx)) }
-          def::DefForeignMod(did) => { def::DefForeignMod(did.tr(xcx)) }
-          def::DefStatic(did, m) => { def::DefStatic(did.tr(xcx), m) }
-          def::DefArg(nid, b) => { def::DefArg(xcx.tr_id(nid), b) }
-          def::DefLocal(nid, b) => { def::DefLocal(xcx.tr_id(nid), b) }
+          def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
+          def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
+          def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
+          def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
+          def::DefArg(nid, b) => { def::DefArg(dcx.tr_id(nid), b) }
+          def::DefLocal(nid, b) => { def::DefLocal(dcx.tr_id(nid), b) }
           def::DefVariant(e_did, v_did, is_s) => {
-            def::DefVariant(e_did.tr(xcx), v_did.tr(xcx), is_s)
+            def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
           },
-          def::DefTrait(did) => def::DefTrait(did.tr(xcx)),
-          def::DefTy(did) => def::DefTy(did.tr(xcx)),
+          def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
+          def::DefTy(did) => def::DefTy(did.tr(dcx)),
           def::DefPrimTy(p) => def::DefPrimTy(p),
-          def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(xcx), v),
-          def::DefBinding(nid, bm) => def::DefBinding(xcx.tr_id(nid), bm),
-          def::DefUse(did) => def::DefUse(did.tr(xcx)),
+          def::DefTyParam(s, did, v) => def::DefTyParam(s, did.tr(dcx), v),
+          def::DefBinding(nid, bm) => def::DefBinding(dcx.tr_id(nid), bm),
+          def::DefUse(did) => def::DefUse(did.tr(dcx)),
           def::DefUpvar(nid1, def, nid2, nid3) => {
-            def::DefUpvar(xcx.tr_id(nid1),
-                           box(GC) (*def).tr(xcx),
-                           xcx.tr_id(nid2),
-                           xcx.tr_id(nid3))
+            def::DefUpvar(dcx.tr_id(nid1),
+                           box(GC) (*def).tr(dcx),
+                           dcx.tr_id(nid2),
+                           dcx.tr_id(nid3))
           }
-          def::DefStruct(did) => def::DefStruct(did.tr(xcx)),
-          def::DefRegion(nid) => def::DefRegion(xcx.tr_id(nid)),
+          def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
+          def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
           def::DefTyParamBinder(nid) => {
-            def::DefTyParamBinder(xcx.tr_id(nid))
+            def::DefTyParamBinder(dcx.tr_id(nid))
           }
-          def::DefLabel(nid) => def::DefLabel(xcx.tr_id(nid))
+          def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
         }
     }
 }
@@ -498,44 +478,44 @@ impl tr for def::Def {
 // Encoding and decoding of ancillary information
 
 impl tr for ty::Region {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::Region {
+    fn tr(&self, dcx: &DecodeContext) -> ty::Region {
         match *self {
             ty::ReLateBound(id, br) => {
-                ty::ReLateBound(xcx.tr_id(id), br.tr(xcx))
+                ty::ReLateBound(dcx.tr_id(id), br.tr(dcx))
             }
             ty::ReEarlyBound(id, space, index, ident) => {
-                ty::ReEarlyBound(xcx.tr_id(id), space, index, ident)
+                ty::ReEarlyBound(dcx.tr_id(id), space, index, ident)
             }
             ty::ReScope(id) => {
-                ty::ReScope(xcx.tr_id(id))
+                ty::ReScope(dcx.tr_id(id))
             }
             ty::ReEmpty | ty::ReStatic | ty::ReInfer(..) => {
                 *self
             }
             ty::ReFree(ref fr) => {
-                ty::ReFree(ty::FreeRegion {scope_id: xcx.tr_id(fr.scope_id),
-                                            bound_region: fr.bound_region.tr(xcx)})
+                ty::ReFree(ty::FreeRegion {scope_id: dcx.tr_id(fr.scope_id),
+                                            bound_region: fr.bound_region.tr(dcx)})
             }
         }
     }
 }
 
 impl tr for ty::BoundRegion {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::BoundRegion {
+    fn tr(&self, dcx: &DecodeContext) -> ty::BoundRegion {
         match *self {
             ty::BrAnon(_) |
             ty::BrFresh(_) => *self,
-            ty::BrNamed(id, ident) => ty::BrNamed(xcx.tr_def_id(id),
+            ty::BrNamed(id, ident) => ty::BrNamed(dcx.tr_def_id(id),
                                                     ident),
         }
     }
 }
 
 impl tr for ty::TraitStore {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::TraitStore {
+    fn tr(&self, dcx: &DecodeContext) -> ty::TraitStore {
         match *self {
             ty::RegionTraitStore(r, m) => {
-                ty::RegionTraitStore(r.tr(xcx), m)
+                ty::RegionTraitStore(r.tr(dcx), m)
             }
             ty::UniqTraitStore => ty::UniqTraitStore
         }
@@ -554,16 +534,16 @@ fn encode_capture_mode(rbml_w: &mut Encoder, cm: CaptureMode) {
 }
 
 trait rbml_decoder_helper {
-    fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_freevar_entry(&mut self, dcx: &DecodeContext)
                           -> freevar_entry;
     fn read_capture_mode(&mut self) -> CaptureMode;
 }
 
 impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
-    fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_freevar_entry(&mut self, dcx: &DecodeContext)
                           -> freevar_entry {
         let fv: freevar_entry = Decodable::decode(self).unwrap();
-        fv.tr(xcx)
+        fv.tr(dcx)
     }
 
     fn read_capture_mode(&mut self) -> CaptureMode {
@@ -573,19 +553,19 @@ impl<'a> rbml_decoder_helper for reader::Decoder<'a> {
 }
 
 impl tr for freevar_entry {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> freevar_entry {
+    fn tr(&self, dcx: &DecodeContext) -> freevar_entry {
         freevar_entry {
-            def: self.def.tr(xcx),
-            span: self.span.tr(xcx),
+            def: self.def.tr(dcx),
+            span: self.span.tr(dcx),
         }
     }
 }
 
 impl tr for ty::UpvarBorrow {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::UpvarBorrow {
+    fn tr(&self, dcx: &DecodeContext) -> ty::UpvarBorrow {
         ty::UpvarBorrow {
             kind: self.kind,
-            region: self.region.tr(xcx)
+            region: self.region.tr(dcx)
         }
     }
 }
@@ -594,7 +574,7 @@ impl tr for ty::UpvarBorrow {
 // Encoding and decoding of MethodCallee
 
 trait read_method_callee_helper {
-    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_method_callee(&mut self, dcx: &DecodeContext)
         -> (typeck::ExprAdjustment, MethodCallee);
 }
 
@@ -621,7 +601,7 @@ fn encode_method_callee(ecx: &e::EncodeContext,
 }
 
 impl<'a> read_method_callee_helper for reader::Decoder<'a> {
-    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_method_callee(&mut self, dcx: &DecodeContext)
         -> (typeck::ExprAdjustment, MethodCallee) {
 
         self.read_struct("MethodCallee", 4, |this| {
@@ -632,13 +612,13 @@ impl<'a> read_method_callee_helper for reader::Decoder<'a> {
                 origin: this.read_struct_field("origin", 1, |this| {
                     let method_origin: MethodOrigin =
                         Decodable::decode(this).unwrap();
-                    Ok(method_origin.tr(xcx))
+                    Ok(method_origin.tr(dcx))
                 }).unwrap(),
                 ty: this.read_struct_field("ty", 2, |this| {
-                    Ok(this.read_ty(xcx))
+                    Ok(this.read_ty(dcx))
                 }).unwrap(),
                 substs: this.read_struct_field("substs", 3, |this| {
-                    Ok(this.read_substs(xcx))
+                    Ok(this.read_substs(dcx))
                 }).unwrap()
             }))
         }).unwrap()
@@ -646,16 +626,16 @@ impl<'a> read_method_callee_helper for reader::Decoder<'a> {
 }
 
 impl tr for MethodOrigin {
-    fn tr(&self, xcx: &ExtendedDecodeContext) -> MethodOrigin {
+    fn tr(&self, dcx: &DecodeContext) -> MethodOrigin {
         match *self {
-            typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(xcx)),
+            typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(dcx)),
             typeck::MethodStaticUnboxedClosure(did) => {
-                typeck::MethodStaticUnboxedClosure(did.tr(xcx))
+                typeck::MethodStaticUnboxedClosure(did.tr(dcx))
             }
             typeck::MethodParam(ref mp) => {
                 typeck::MethodParam(
                     typeck::MethodParam {
-                        trait_id: mp.trait_id.tr(xcx),
+                        trait_id: mp.trait_id.tr(dcx),
                         .. *mp
                     }
                 )
@@ -663,7 +643,7 @@ impl tr for MethodOrigin {
             typeck::MethodObject(ref mo) => {
                 typeck::MethodObject(
                     typeck::MethodObject {
-                        trait_id: mo.trait_id.tr(xcx),
+                        trait_id: mo.trait_id.tr(dcx),
                         .. *mo
                     }
                 )
@@ -862,10 +842,10 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
                   0 => {
                     typeck::vtable_static(
                         this.read_enum_variant_arg(0u, |this| {
-                            Ok(this.read_def_id_noxcx(cdata))
+                            Ok(this.read_def_id_nodcx(cdata))
                         }).unwrap(),
                         this.read_enum_variant_arg(1u, |this| {
-                            Ok(this.read_substs_noxcx(tcx, cdata))
+                            Ok(this.read_substs_nodcx(tcx, cdata))
                         }).unwrap(),
                         this.read_enum_variant_arg(2u, |this| {
                             Ok(this.read_vtable_res(tcx, cdata))
@@ -885,7 +865,7 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
                   2 => {
                     typeck::vtable_unboxed_closure(
                         this.read_enum_variant_arg(0u, |this| {
-                            Ok(this.read_def_id_noxcx(cdata))
+                            Ok(this.read_def_id_nodcx(cdata))
                         }).unwrap()
                     )
                   }
@@ -1398,40 +1378,40 @@ impl<'a> doc_decoder_helpers for rbml::Doc<'a> {
 }
 
 trait rbml_decoder_decoder_helpers {
-    fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t;
-    fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t>;
-    fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_ty(&mut self, dcx: &DecodeContext) -> ty::t;
+    fn read_tys(&mut self, dcx: &DecodeContext) -> Vec<ty::t>;
+    fn read_type_param_def(&mut self, dcx: &DecodeContext)
                            -> ty::TypeParameterDef;
-    fn read_polytype(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_polytype(&mut self, dcx: &DecodeContext)
                      -> ty::Polytype;
-    fn read_existential_bounds(&mut self, xcx: &ExtendedDecodeContext) -> ty::ExistentialBounds;
-    fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> subst::Substs;
-    fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
-    fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_existential_bounds(&mut self, dcx: &DecodeContext) -> ty::ExistentialBounds;
+    fn read_substs(&mut self, dcx: &DecodeContext) -> subst::Substs;
+    fn read_auto_adjustment(&mut self, dcx: &DecodeContext) -> ty::AutoAdjustment;
+    fn read_unboxed_closure(&mut self, dcx: &DecodeContext)
                             -> ty::UnboxedClosure;
-    fn read_auto_deref_ref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef;
-    fn read_autoref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoRef;
-    fn read_unsize_kind(&mut self, xcx: &ExtendedDecodeContext) -> ty::UnsizeKind;
+    fn read_auto_deref_ref(&mut self, dcx: &DecodeContext) -> ty::AutoDerefRef;
+    fn read_autoref(&mut self, dcx: &DecodeContext) -> ty::AutoRef;
+    fn read_unsize_kind(&mut self, dcx: &DecodeContext) -> ty::UnsizeKind;
     fn convert_def_id(&mut self,
-                      xcx: &ExtendedDecodeContext,
+                      dcx: &DecodeContext,
                       source: DefIdSource,
                       did: ast::DefId)
                       -> ast::DefId;
 
     // Versions of the type reading functions that don't need the full
-    // ExtendedDecodeContext.
-    fn read_ty_noxcx(&mut self,
+    // DecodeContext.
+    fn read_ty_nodcx(&mut self,
                      tcx: &ty::ctxt, cdata: &cstore::crate_metadata) -> ty::t;
-    fn read_tys_noxcx(&mut self,
+    fn read_tys_nodcx(&mut self,
                       tcx: &ty::ctxt,
                       cdata: &cstore::crate_metadata) -> Vec<ty::t>;
-    fn read_substs_noxcx(&mut self, tcx: &ty::ctxt,
+    fn read_substs_nodcx(&mut self, tcx: &ty::ctxt,
                          cdata: &cstore::crate_metadata)
                          -> subst::Substs;
 }
 
 impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
-    fn read_ty_noxcx(&mut self,
+    fn read_ty_nodcx(&mut self,
                      tcx: &ty::ctxt, cdata: &cstore::crate_metadata) -> ty::t {
         self.read_opaque(|_, doc| {
             Ok(tydecode::parse_ty_data(
@@ -1443,16 +1423,16 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_tys_noxcx(&mut self,
+    fn read_tys_nodcx(&mut self,
                       tcx: &ty::ctxt,
                       cdata: &cstore::crate_metadata) -> Vec<ty::t> {
-        self.read_to_vec(|this| Ok(this.read_ty_noxcx(tcx, cdata)) )
+        self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
             .unwrap()
             .move_iter()
             .collect()
     }
 
-    fn read_substs_noxcx(&mut self,
+    fn read_substs_nodcx(&mut self,
                          tcx: &ty::ctxt,
                          cdata: &cstore::crate_metadata)
                          -> subst::Substs
@@ -1467,7 +1447,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t {
+    fn read_ty(&mut self, dcx: &DecodeContext) -> ty::t {
         // Note: regions types embed local node ids.  In principle, we
         // should translate these node ids into the new decode
         // context.  However, we do not bother, because region types
@@ -1478,10 +1458,10 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
 
             let ty = tydecode::parse_ty_data(
                 doc.data,
-                xcx.dcx.cdata.cnum,
+                dcx.cdata.cnum,
                 doc.start,
-                xcx.dcx.tcx,
-                |s, a| this.convert_def_id(xcx, s, a));
+                dcx.tcx,
+                |s, a| this.convert_def_id(dcx, s, a));
 
             Ok(ty)
         }).unwrap();
@@ -1495,23 +1475,23 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }
     }
 
-    fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t> {
-        self.read_to_vec(|this| Ok(this.read_ty(xcx))).unwrap().move_iter().collect()
+    fn read_tys(&mut self, dcx: &DecodeContext) -> Vec<ty::t> {
+        self.read_to_vec(|this| Ok(this.read_ty(dcx))).unwrap().move_iter().collect()
     }
 
-    fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_type_param_def(&mut self, dcx: &DecodeContext)
                            -> ty::TypeParameterDef {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_type_param_def_data(
                 doc.data,
                 doc.start,
-                xcx.dcx.cdata.cnum,
-                xcx.dcx.tcx,
-                |s, a| this.convert_def_id(xcx, s, a)))
+                dcx.cdata.cnum,
+                dcx.tcx,
+                |s, a| this.convert_def_id(dcx, s, a)))
         }).unwrap()
     }
 
-    fn read_polytype(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_polytype(&mut self, dcx: &DecodeContext)
                                    -> ty::Polytype {
         self.read_struct("Polytype", 2, |this| {
             Ok(ty::Polytype {
@@ -1521,7 +1501,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                             types:
                             this.read_struct_field("types", 0, |this| {
                                 Ok(this.read_vec_per_param_space(
-                                    |this| this.read_type_param_def(xcx)))
+                                    |this| this.read_type_param_def(dcx)))
                             }).unwrap(),
 
                             regions:
@@ -1533,34 +1513,34 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                     })
                 }).unwrap(),
                 ty: this.read_struct_field("ty", 1, |this| {
-                    Ok(this.read_ty(xcx))
+                    Ok(this.read_ty(dcx))
                 }).unwrap()
             })
         }).unwrap()
     }
 
-    fn read_existential_bounds(&mut self, xcx: &ExtendedDecodeContext) -> ty::ExistentialBounds
+    fn read_existential_bounds(&mut self, dcx: &DecodeContext) -> ty::ExistentialBounds
     {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_existential_bounds_data(doc.data,
-                                                       xcx.dcx.cdata.cnum,
+                                                       dcx.cdata.cnum,
                                                        doc.start,
-                                                       xcx.dcx.tcx,
-                                                       |s, a| this.convert_def_id(xcx, s, a)))
+                                                       dcx.tcx,
+                                                       |s, a| this.convert_def_id(dcx, s, a)))
         }).unwrap()
     }
 
-    fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> subst::Substs {
+    fn read_substs(&mut self, dcx: &DecodeContext) -> subst::Substs {
         self.read_opaque(|this, doc| {
             Ok(tydecode::parse_substs_data(doc.data,
-                                        xcx.dcx.cdata.cnum,
+                                        dcx.cdata.cnum,
                                         doc.start,
-                                        xcx.dcx.tcx,
-                                        |s, a| this.convert_def_id(xcx, s, a)))
+                                        dcx.tcx,
+                                        |s, a| this.convert_def_id(dcx, s, a)))
         }).unwrap()
     }
 
-    fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment {
+    fn read_auto_adjustment(&mut self, dcx: &DecodeContext) -> ty::AutoAdjustment {
         self.read_enum("AutoAdjustment", |this| {
             let variants = ["AutoAddEnv", "AutoDerefRef"];
             this.read_enum_variant(variants, |this, i| {
@@ -1569,12 +1549,12 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                         let store: ty::TraitStore =
                             this.read_enum_variant_arg(0, |this| Decodable::decode(this)).unwrap();
 
-                        ty::AutoAddEnv(store.tr(xcx))
+                        ty::AutoAddEnv(store.tr(dcx))
                     }
                     1 => {
                         let auto_deref_ref: ty::AutoDerefRef =
                             this.read_enum_variant_arg(0,
-                                |this| Ok(this.read_auto_deref_ref(xcx))).unwrap();
+                                |this| Ok(this.read_auto_deref_ref(dcx))).unwrap();
 
                         ty::AutoDerefRef(auto_deref_ref)
                     }
@@ -1584,7 +1564,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_auto_deref_ref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef {
+    fn read_auto_deref_ref(&mut self, dcx: &DecodeContext) -> ty::AutoDerefRef {
         self.read_struct("AutoDerefRef", 2, |this| {
             Ok(ty::AutoDerefRef {
                 autoderefs: this.read_struct_field("autoderefs", 0, |this| {
@@ -1593,7 +1573,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                 autoref: this.read_struct_field("autoref", 1, |this| {
                     this.read_option(|this, b| {
                         if b {
-                            Ok(Some(this.read_autoref(xcx)))
+                            Ok(Some(this.read_autoref(dcx)))
                         } else {
                             Ok(None)
                         }
@@ -1603,7 +1583,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_autoref(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoRef {
+    fn read_autoref(&mut self, dcx: &DecodeContext) -> ty::AutoRef {
         self.read_enum("AutoRef", |this| {
             let variants = ["AutoPtr",
                             "AutoUnsize",
@@ -1619,25 +1599,25 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                         let a: Option<Box<ty::AutoRef>> =
                             this.read_enum_variant_arg(2, |this| this.read_option(|this, b| {
                                 if b {
-                                    Ok(Some(box this.read_autoref(xcx)))
+                                    Ok(Some(box this.read_autoref(dcx)))
                                 } else {
                                     Ok(None)
                                 }
                             })).unwrap();
 
-                        ty::AutoPtr(r.tr(xcx), m, a)
+                        ty::AutoPtr(r.tr(dcx), m, a)
                     }
                     1 => {
                         let uk: ty::UnsizeKind =
                             this.read_enum_variant_arg(0,
-                                |this| Ok(this.read_unsize_kind(xcx))).unwrap();
+                                |this| Ok(this.read_unsize_kind(dcx))).unwrap();
 
                         ty::AutoUnsize(uk)
                     }
                     2 => {
                         let uk: ty::UnsizeKind =
                             this.read_enum_variant_arg(0,
-                                |this| Ok(this.read_unsize_kind(xcx))).unwrap();
+                                |this| Ok(this.read_unsize_kind(dcx))).unwrap();
 
                         ty::AutoUnsizeUniq(uk)
                     }
@@ -1647,7 +1627,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                         let a: Option<Box<ty::AutoRef>> =
                             this.read_enum_variant_arg(1, |this| this.read_option(|this, b| {
                                 if b {
-                                    Ok(Some(box this.read_autoref(xcx)))
+                                    Ok(Some(box this.read_autoref(dcx)))
                                 } else {
                                     Ok(None)
                                 }
@@ -1661,7 +1641,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_unsize_kind(&mut self, xcx: &ExtendedDecodeContext) -> ty::UnsizeKind {
+    fn read_unsize_kind(&mut self, dcx: &DecodeContext) -> ty::UnsizeKind {
         self.read_enum("UnsizeKind", |this| {
             let variants = ["UnsizeLength", "UnsizeStruct", "UnsizeVtable"];
             this.read_enum_variant(variants, |this, i| {
@@ -1675,7 +1655,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                     1 => {
                         let uk: ty::UnsizeKind =
                             this.read_enum_variant_arg(0,
-                                |this| Ok(this.read_unsize_kind(xcx))).unwrap();
+                                |this| Ok(this.read_unsize_kind(dcx))).unwrap();
                         let idx: uint =
                             this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
 
@@ -1684,13 +1664,13 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
                     2 => {
                         let b =
                             this.read_enum_variant_arg(
-                                0, |this| Ok(this.read_existential_bounds(xcx))).unwrap();
+                                0, |this| Ok(this.read_existential_bounds(dcx))).unwrap();
                         let def_id: ast::DefId =
                             this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap();
                         let substs = this.read_enum_variant_arg(2,
-                            |this| Ok(this.read_substs(xcx))).unwrap();
+                            |this| Ok(this.read_substs(dcx))).unwrap();
 
-                        ty::UnsizeVtable(b, def_id.tr(xcx), substs)
+                        ty::UnsizeVtable(b, def_id.tr(dcx), substs)
                     }
                     _ => fail!("bad enum variant for ty::UnsizeKind")
                 })
@@ -1698,15 +1678,15 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_unboxed_closure(&mut self, xcx: &ExtendedDecodeContext)
+    fn read_unboxed_closure(&mut self, dcx: &DecodeContext)
                             -> ty::UnboxedClosure {
         let closure_type = self.read_opaque(|this, doc| {
             Ok(tydecode::parse_ty_closure_data(
                 doc.data,
-                xcx.dcx.cdata.cnum,
+                dcx.cdata.cnum,
                 doc.start,
-                xcx.dcx.tcx,
-                |s, a| this.convert_def_id(xcx, s, a)))
+                dcx.tcx,
+                |s, a| this.convert_def_id(dcx, s, a)))
         }).unwrap();
         let variants = [
             "FnUnboxedClosureKind",
@@ -1728,7 +1708,7 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn convert_def_id(&mut self,
-                      xcx: &ExtendedDecodeContext,
+                      dcx: &DecodeContext,
                       source: tydecode::DefIdSource,
                       did: ast::DefId)
                       -> ast::DefId {
@@ -1761,21 +1741,20 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> {
          */
 
         let r = match source {
-            NominalType | TypeWithId | RegionParameter => xcx.tr_def_id(did),
-            TypeParameter => xcx.tr_intern_def_id(did)
+            NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
+            TypeParameter => dcx.tr_intern_def_id(did)
         };
         debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
         return r;
     }
 }
 
-fn decode_side_tables(xcx: &ExtendedDecodeContext,
+fn decode_side_tables(dcx: &DecodeContext,
                       ast_doc: rbml::Doc) {
-    let dcx = xcx.dcx;
     let tbl_doc = ast_doc.get(c::tag_table as uint);
     reader::docs(tbl_doc, |tag, entry_doc| {
         let id0 = entry_doc.get(c::tag_table_id as uint).as_int();
-        let id = xcx.tr_id(id0 as ast::NodeId);
+        let id = dcx.tr_id(id0 as ast::NodeId);
 
         debug!(">> Side table document with tag 0x{:x} \
                 found for id {} (orig {})",
@@ -1783,7 +1762,7 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
 
         match c::astencode_tag::from_uint(tag) {
             None => {
-                xcx.dcx.tcx.sess.bug(
+                dcx.tcx.sess.bug(
                     format!("unknown tag found in side tables: {:x}",
                             tag).as_slice());
             }
@@ -1794,36 +1773,36 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
 
                 match value {
                     c::tag_table_def => {
-                        let def = decode_def(xcx, val_doc);
+                        let def = decode_def(dcx, val_doc);
                         dcx.tcx.def_map.borrow_mut().insert(id, def);
                     }
                     c::tag_table_node_type => {
-                        let ty = val_dsr.read_ty(xcx);
+                        let ty = val_dsr.read_ty(dcx);
                         debug!("inserting ty for node {:?}: {}",
                                id, ty_to_string(dcx.tcx, ty));
                         dcx.tcx.node_types.borrow_mut().insert(id as uint, ty);
                     }
                     c::tag_table_item_subst => {
                         let item_substs = ty::ItemSubsts {
-                            substs: val_dsr.read_substs(xcx)
+                            substs: val_dsr.read_substs(dcx)
                         };
                         dcx.tcx.item_substs.borrow_mut().insert(
                             id, item_substs);
                     }
                     c::tag_table_freevars => {
                         let fv_info = val_dsr.read_to_vec(|val_dsr| {
-                            Ok(val_dsr.read_freevar_entry(xcx))
+                            Ok(val_dsr.read_freevar_entry(dcx))
                         }).unwrap().move_iter().collect();
                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
                     }
                     c::tag_table_upvar_borrow_map => {
                         let var_id: ast::NodeId = Decodable::decode(val_dsr).unwrap();
                         let upvar_id = ty::UpvarId {
-                            var_id: xcx.tr_id(var_id),
+                            var_id: dcx.tr_id(var_id),
                             closure_expr_id: id
                         };
                         let ub: ty::UpvarBorrow = Decodable::decode(val_dsr).unwrap();
-                        dcx.tcx.upvar_borrow_map.borrow_mut().insert(upvar_id, ub.tr(xcx));
+                        dcx.tcx.upvar_borrow_map.borrow_mut().insert(upvar_id, ub.tr(dcx));
                     }
                     c::tag_table_capture_modes => {
                         let capture_mode = val_dsr.read_capture_mode();
@@ -1833,16 +1812,16 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                            .insert(id, capture_mode);
                     }
                     c::tag_table_tcache => {
-                        let pty = val_dsr.read_polytype(xcx);
+                        let pty = val_dsr.read_polytype(dcx);
                         let lid = ast::DefId { krate: ast::LOCAL_CRATE, node: id };
                         dcx.tcx.tcache.borrow_mut().insert(lid, pty);
                     }
                     c::tag_table_param_defs => {
-                        let bounds = val_dsr.read_type_param_def(xcx);
+                        let bounds = val_dsr.read_type_param_def(dcx);
                         dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
                     }
                     c::tag_table_method_map => {
-                        let (adjustment, method) = val_dsr.read_method_callee(xcx);
+                        let (adjustment, method) = val_dsr.read_method_callee(dcx);
                         let method_call = MethodCall {
                             expr_id: id,
                             adjustment: adjustment
@@ -1851,8 +1830,8 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                     }
                     c::tag_table_vtable_map => {
                         let (adjustment, vtable_res) =
-                            val_dsr.read_vtable_res_with_key(xcx.dcx.tcx,
-                                                             xcx.dcx.cdata);
+                            val_dsr.read_vtable_res_with_key(dcx.tcx,
+                                                             dcx.cdata);
                         let vtable_key = MethodCall {
                             expr_id: id,
                             adjustment: adjustment
@@ -1860,12 +1839,12 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         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(dcx);
                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
                     }
                     c::tag_table_unboxed_closures => {
                         let unboxed_closure =
-                            val_dsr.read_unboxed_closure(xcx);
+                            val_dsr.read_unboxed_closure(dcx);
                         dcx.tcx
                            .unboxed_closures
                            .borrow_mut()
@@ -1873,7 +1852,7 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                                    unboxed_closure);
                     }
                     _ => {
-                        xcx.dcx.tcx.sess.bug(
+                        dcx.tcx.sess.bug(
                             format!("unknown tag found in side tables: {:x}",
                                     tag).as_slice());
                     }
@@ -1890,17 +1869,17 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
 // Testing of astencode_gen
 
 #[cfg(test)]
-fn encode_item_ast(rbml_w: &mut Encoder, item: Gc<ast::Item>) {
+fn encode_item_ast(rbml_w: &mut Encoder, item: &ast::Item) {
     rbml_w.start_tag(c::tag_tree as uint);
     (*item).encode(rbml_w);
     rbml_w.end_tag();
 }
 
 #[cfg(test)]
-fn decode_item_ast(par_doc: rbml::Doc) -> Gc<ast::Item> {
+fn decode_item_ast(par_doc: rbml::Doc) -> ast::Item {
     let chi_doc = par_doc.get(c::tag_tree as uint);
     let mut d = reader::Decoder::new(chi_doc);
-    box(GC) Decodable::decode(&mut d).unwrap()
+    Decodable::decode(&mut d).unwrap()
 }
 
 #[cfg(test)]
@@ -1935,17 +1914,14 @@ fn mk_ctxt() -> parse::ParseSess {
 }
 
 #[cfg(test)]
-fn roundtrip(in_item: Option<Gc<ast::Item>>) {
+fn roundtrip(in_item: Option<P<ast::Item>>) {
     let in_item = in_item.unwrap();
     let mut wr = SeekableMemWriter::new();
-    {
-        let mut rbml_w = writer::Encoder::new(&mut wr);
-        encode_item_ast(&mut rbml_w, in_item);
-    }
+    encode_item_ast(&mut writer::Encoder::new(&mut wr), &*in_item);
     let rbml_doc = rbml::Doc::new(wr.get_ref());
     let out_item = decode_item_ast(rbml_doc);
 
-    assert!(in_item == out_item);
+    assert!(*in_item == out_item);
 }
 
 #[test]
diff --git a/src/librustc/middle/borrowck/graphviz.rs b/src/librustc/middle/borrowck/graphviz.rs
index e75378de5a5..c789db5be0c 100644
--- a/src/librustc/middle/borrowck/graphviz.rs
+++ b/src/librustc/middle/borrowck/graphviz.rs
@@ -44,7 +44,7 @@ impl Variant {
 }
 
 pub struct DataflowLabeller<'a, 'tcx: 'a> {
-    pub inner: cfg_dot::LabelledCFG<'a>,
+    pub inner: cfg_dot::LabelledCFG<'a, 'tcx>,
     pub variants: Vec<Variant>,
     pub borrowck_ctxt: &'a BorrowckCtxt<'a, 'tcx>,
     pub analysis_data: &'a borrowck::AnalysisData<'a, 'tcx>,
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index acc2f47a0fe..0d584a7664f 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -22,9 +22,7 @@ use middle::mem_categorization as mc;
 use middle::ty;
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
-use std::cell::{Cell};
 use std::rc::Rc;
-use std::gc::{Gc, GC};
 use std::string::String;
 use syntax::ast;
 use syntax::ast_map;
@@ -71,34 +69,33 @@ impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt,
-                   krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt) {
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
-        stats: box(GC) BorrowStats {
-            loaned_paths_same: Cell::new(0),
-            loaned_paths_imm: Cell::new(0),
-            stable_paths: Cell::new(0),
-            guaranteed_paths: Cell::new(0),
+        stats: BorrowStats {
+            loaned_paths_same: 0,
+            loaned_paths_imm: 0,
+            stable_paths: 0,
+            guaranteed_paths: 0
         }
     };
 
-    visit::walk_crate(&mut bccx, krate);
+    visit::walk_crate(&mut bccx, tcx.map.krate());
 
     if tcx.sess.borrowck_stats() {
         println!("--- borrowck stats ---");
         println!("paths requiring guarantees: {}",
-                 bccx.stats.guaranteed_paths.get());
+                 bccx.stats.guaranteed_paths);
         println!("paths requiring loans     : {}",
-                 make_stat(&bccx, bccx.stats.loaned_paths_same.get()));
+                 make_stat(&bccx, bccx.stats.loaned_paths_same));
         println!("paths requiring imm loans : {}",
-                 make_stat(&bccx, bccx.stats.loaned_paths_imm.get()));
+                 make_stat(&bccx, bccx.stats.loaned_paths_imm));
         println!("stable paths              : {}",
-                 make_stat(&bccx, bccx.stats.stable_paths.get()));
+                 make_stat(&bccx, bccx.stats.stable_paths));
     }
 
     fn make_stat(bccx: &BorrowckCtxt, stat: uint) -> String {
-        let total = bccx.stats.guaranteed_paths.get() as f64;
+        let total = bccx.stats.guaranteed_paths as f64;
         let perc = if total == 0.0 { 0.0 } else { stat as f64 * 100.0 / total };
         format!("{} ({:.0f}%)", stat, perc)
     }
@@ -110,8 +107,8 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
     // loan step is intended for things that have a data
     // flow dependent conditions.
     match item.node {
-        ast::ItemStatic(_, _, ex) => {
-            gather_loans::gather_loans_in_static_initializer(this, &*ex);
+        ast::ItemStatic(_, _, ref ex) => {
+            gather_loans::gather_loans_in_static_initializer(this, &**ex);
         }
         _ => {
             visit::walk_item(this, item);
@@ -206,11 +203,11 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
 
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
-        stats: box(GC) BorrowStats {
-            loaned_paths_same: Cell::new(0),
-            loaned_paths_imm: Cell::new(0),
-            stable_paths: Cell::new(0),
-            guaranteed_paths: Cell::new(0),
+        stats: BorrowStats {
+            loaned_paths_same: 0,
+            loaned_paths_imm: 0,
+            stable_paths: 0,
+            guaranteed_paths: 0
         }
     };
 
@@ -234,14 +231,14 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
 
     // Statistics:
-    stats: Gc<BorrowStats>,
+    stats: BorrowStats
 }
 
-pub struct BorrowStats {
-    loaned_paths_same: Cell<uint>,
-    loaned_paths_imm: Cell<uint>,
-    stable_paths: Cell<uint>,
-    guaranteed_paths: Cell<uint>,
+struct BorrowStats {
+    loaned_paths_same: uint,
+    loaned_paths_imm: uint,
+    stable_paths: uint,
+    guaranteed_paths: uint
 }
 
 pub type BckResult<T> = Result<T, BckError>;
@@ -290,9 +287,9 @@ pub fn closure_to_block(closure_id: ast::NodeId,
                     tcx: &ty::ctxt) -> ast::NodeId {
     match tcx.map.get(closure_id) {
         ast_map::NodeExpr(expr) => match expr.node {
-            ast::ExprProc(_, block) |
-            ast::ExprFnBlock(_, _, block) |
-            ast::ExprUnboxedFn(_, _, _, block) => { block.id }
+            ast::ExprProc(_, ref block) |
+            ast::ExprFnBlock(_, _, ref block) |
+            ast::ExprUnboxedFn(_, _, _, ref block) => { block.id }
             _ => fail!("encountered non-closure id: {}", closure_id)
         },
         _ => fail!("encountered non-expr id: {}", closure_id)
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 6e9b27655af..05cc61a7547 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -15,10 +15,9 @@ use middle::typeck;
 use middle::ty;
 use syntax::ast;
 use syntax::ast_util;
+use syntax::ptr::P;
 use util::nodemap::NodeMap;
 
-use std::gc::Gc;
-
 struct CFGBuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     exit_map: NodeMap<CFGIndex>,
@@ -69,15 +68,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
         let mut stmts_exit = pred;
         for stmt in blk.stmts.iter() {
-            stmts_exit = self.stmt(stmt.clone(), stmts_exit);
+            stmts_exit = self.stmt(&**stmt, stmts_exit);
         }
 
-        let expr_exit = self.opt_expr(blk.expr.clone(), stmts_exit);
+        let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
 
         self.add_node(blk.id, [expr_exit])
     }
 
-    fn stmt(&mut self, stmt: Gc<ast::Stmt>, pred: CFGIndex) -> CFGIndex {
+    fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex {
         match stmt.node {
             ast::StmtDecl(ref decl, id) => {
                 let exit = self.decl(&**decl, pred);
@@ -85,7 +84,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             }
 
             ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => {
-                let exit = self.expr(expr.clone(), pred);
+                let exit = self.expr(&**expr, pred);
                 self.add_node(id, [exit])
             }
 
@@ -98,7 +97,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     fn decl(&mut self, decl: &ast::Decl, pred: CFGIndex) -> CFGIndex {
         match decl.node {
             ast::DeclLocal(ref local) => {
-                let init_exit = self.opt_expr(local.init.clone(), pred);
+                let init_exit = self.opt_expr(&local.init, pred);
                 self.pat(&*local.pat, init_exit)
             }
 
@@ -127,24 +126,20 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
 
             ast::PatEnum(_, Some(ref subpats)) |
             ast::PatTup(ref subpats) => {
-                let pats_exit =
-                    self.pats_all(subpats.iter().map(|p| p.clone()), pred);
+                let pats_exit = self.pats_all(subpats.iter(), pred);
                 self.add_node(pat.id, [pats_exit])
             }
 
             ast::PatStruct(_, ref subpats, _) => {
                 let pats_exit =
-                    self.pats_all(subpats.iter().map(|f| f.pat.clone()), pred);
+                    self.pats_all(subpats.iter().map(|f| &f.pat), pred);
                 self.add_node(pat.id, [pats_exit])
             }
 
             ast::PatVec(ref pre, ref vec, ref post) => {
-                let pre_exit =
-                    self.pats_all(pre.iter().map(|p| *p), pred);
-                let vec_exit =
-                    self.pats_all(vec.iter().map(|p| *p), pre_exit);
-                let post_exit =
-                    self.pats_all(post.iter().map(|p| *p), vec_exit);
+                let pre_exit = self.pats_all(pre.iter(), pred);
+                let vec_exit = self.pats_all(vec.iter(), pre_exit);
+                let post_exit = self.pats_all(post.iter(), vec_exit);
                 self.add_node(pat.id, [post_exit])
             }
 
@@ -154,16 +149,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
         }
     }
 
-    fn pats_all<I: Iterator<Gc<ast::Pat>>>(&mut self,
-                                        pats: I,
-                                        pred: CFGIndex) -> CFGIndex {
+    fn pats_all<'a, I: Iterator<&'a P<ast::Pat>>>(&mut self,
+                                          pats: I,
+                                          pred: CFGIndex) -> CFGIndex {
         //! Handles case where all of the patterns must match.
         let mut pats = pats;
-        pats.fold(pred, |pred, pat| self.pat(&*pat, pred))
+        pats.fold(pred, |pred, pat| self.pat(&**pat, pred))
     }
 
     fn pats_any(&mut self,
-                pats: &[Gc<ast::Pat>],
+                pats: &[P<ast::Pat>],
                 pred: CFGIndex) -> CFGIndex {
         //! Handles case where just one of the patterns must match.
 
@@ -171,15 +166,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             self.pat(&*pats[0], pred)
         } else {
             let collect = self.add_dummy_node([]);
-            for &pat in pats.iter() {
-                let pat_exit = self.pat(&*pat, pred);
+            for pat in pats.iter() {
+                let pat_exit = self.pat(&**pat, pred);
                 self.add_contained_edge(pat_exit, collect);
             }
             collect
         }
     }
 
-    fn expr(&mut self, expr: Gc<ast::Expr>, pred: CFGIndex) -> CFGIndex {
+    fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
         match expr.node {
             ast::ExprBlock(ref blk) => {
                 let blk_exit = self.block(&**blk, pred);
@@ -201,7 +196,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 //    v 3   v 4
                 //   [..expr..]
                 //
-                let cond_exit = self.expr(cond.clone(), pred);           // 1
+                let cond_exit = self.expr(&**cond, pred);                // 1
                 let then_exit = self.block(&**then, cond_exit);          // 2
                 self.add_node(expr.id, [cond_exit, then_exit])           // 3,4
             }
@@ -221,9 +216,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 //    v 4   v 5
                 //   [..expr..]
                 //
-                let cond_exit = self.expr(cond.clone(), pred);           // 1
+                let cond_exit = self.expr(&**cond, pred);                // 1
                 let then_exit = self.block(&**then, cond_exit);          // 2
-                let else_exit = self.expr(otherwise.clone(), cond_exit); // 3
+                let else_exit = self.expr(&**otherwise, cond_exit);      // 3
                 self.add_node(expr.id, [then_exit, else_exit])           // 4, 5
             }
 
@@ -247,7 +242,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
 
                 // Is the condition considered part of the loop?
                 let loopback = self.add_dummy_node([pred]);              // 1
-                let cond_exit = self.expr(cond.clone(), loopback);       // 2
+                let cond_exit = self.expr(&**cond, loopback);            // 2
                 let expr_exit = self.add_node(expr.id, [cond_exit]);     // 3
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.id,
@@ -283,7 +278,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 // Note that `break` and `continue` statements
                 // may cause additional edges.
 
-                let head = self.expr(head.clone(), pred);       // 1
+                let head = self.expr(&**head, pred);            // 1
                 let loopback = self.add_dummy_node([head]);     // 2
                 let cond = self.add_dummy_node([loopback]);     // 3
                 let expr_exit = self.add_node(expr.id, [cond]); // 4
@@ -353,7 +348,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 //     v 6   v    v
                 //  [.....expr.....]
                 //
-                let discr_exit = self.expr(discr.clone(), pred);         // 1
+                let discr_exit = self.expr(&**discr, pred);              // 1
 
                 let expr_exit = self.add_node(expr.id, []);
                 let mut cond_exit = discr_exit;
@@ -361,10 +356,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                     cond_exit = self.add_dummy_node([cond_exit]);        // 2
                     let pats_exit = self.pats_any(arm.pats.as_slice(),
                                                   cond_exit);            // 3
-                    let guard_exit = self.opt_expr(arm.guard,
+                    let guard_exit = self.opt_expr(&arm.guard,
                                                    pats_exit);           // 4
-                    let body_exit = self.expr(arm.body.clone(),
-                                              guard_exit);               // 5
+                    let body_exit = self.expr(&*arm.body, guard_exit);   // 5
                     self.add_contained_edge(body_exit, expr_exit);       // 6
                 }
                 expr_exit
@@ -385,13 +379,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 //    v 3  v 4
                 //   [..exit..]
                 //
-                let l_exit = self.expr(l.clone(), pred);                  // 1
-                let r_exit = self.expr(r.clone(), l_exit);               // 2
+                let l_exit = self.expr(&**l, pred);                      // 1
+                let r_exit = self.expr(&**r, l_exit);                    // 2
                 self.add_node(expr.id, [l_exit, r_exit])                 // 3,4
             }
 
             ast::ExprRet(ref v) => {
-                let v_exit = self.opt_expr(v.clone(), pred);
+                let v_exit = self.opt_expr(v, pred);
                 let b = self.add_node(expr.id, [v_exit]);
                 self.add_returning_edge(expr, b);
                 self.add_node(ast::DUMMY_NODE_ID, [])
@@ -414,62 +408,60 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             }
 
             ast::ExprVec(ref elems) => {
-                self.straightline(expr, pred, elems.as_slice())
+                self.straightline(expr, pred, elems.iter().map(|e| &**e))
             }
 
             ast::ExprCall(ref func, ref args) => {
-                self.call(expr, pred, func.clone(), args.as_slice())
+                self.call(expr, pred, &**func, args.iter().map(|e| &**e))
             }
 
             ast::ExprMethodCall(_, _, ref args) => {
-                self.call(expr, pred, *args.get(0), args.slice_from(1))
+                self.call(expr, pred, &**args.get(0), args.slice_from(1).iter().map(|e| &**e))
             }
 
             ast::ExprIndex(ref l, ref r) |
-            ast::ExprBinary(_, ref l, ref r) if self.is_method_call(&*expr) => {
-                self.call(expr, pred, l.clone(), [r.clone()])
+            ast::ExprBinary(_, ref l, ref r) if self.is_method_call(expr) => {
+                self.call(expr, pred, &**l, Some(&**r).move_iter())
             }
 
-            ast::ExprUnary(_, ref e) if self.is_method_call(&*expr) => {
-                self.call(expr, pred, e.clone(), [])
+            ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {
+                self.call(expr, pred, &**e, None::<ast::Expr>.iter())
             }
 
             ast::ExprTup(ref exprs) => {
-                self.straightline(expr, pred, exprs.as_slice())
+                self.straightline(expr, pred, exprs.iter().map(|e| &**e))
             }
 
-            ast::ExprStruct(_, ref fields, base) => {
+            ast::ExprStruct(_, ref fields, ref base) => {
                 let base_exit = self.opt_expr(base, pred);
-                let field_exprs: Vec<Gc<ast::Expr>> =
-                    fields.iter().map(|f| f.expr).collect();
-                self.straightline(expr, base_exit, field_exprs.as_slice())
+                self.straightline(expr, base_exit, fields.iter().map(|f| &*f.expr))
             }
 
-            ast::ExprRepeat(elem, count) => {
-                self.straightline(expr, pred, [elem, count])
+            ast::ExprRepeat(ref elem, ref count) => {
+                self.straightline(expr, pred, [elem, count].iter().map(|&e| &**e))
             }
 
-            ast::ExprAssign(l, r) |
-            ast::ExprAssignOp(_, l, r) => {
-                self.straightline(expr, pred, [r, l])
+            ast::ExprAssign(ref l, ref r) |
+            ast::ExprAssignOp(_, ref l, ref r) => {
+                self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
             }
 
-            ast::ExprIndex(l, r) |
-            ast::ExprBinary(_, l, r) => { // NB: && and || handled earlier
-                self.straightline(expr, pred, [l, r])
+            ast::ExprIndex(ref l, ref r) |
+            ast::ExprBinary(_, ref l, ref r) => { // NB: && and || handled earlier
+                self.straightline(expr, pred, [l, r].iter().map(|&e| &**e))
             }
 
-            ast::ExprBox(p, e) => {
-                self.straightline(expr, pred, [p, e])
+            ast::ExprBox(ref p, ref e) => {
+                self.straightline(expr, pred, [p, e].iter().map(|&e| &**e))
             }
 
-            ast::ExprAddrOf(_, e) |
-            ast::ExprCast(e, _) |
-            ast::ExprUnary(_, e) |
-            ast::ExprParen(e) |
-            ast::ExprField(e, _, _) |
-            ast::ExprTupField(e, _, _) => {
-                self.straightline(expr, pred, [e])
+            ast::ExprAddrOf(_, ref e) |
+            ast::ExprCast(ref e, _) |
+            ast::ExprUnary(_, ref e) |
+            ast::ExprParen(ref e) |
+            ast::ExprField(ref e, _, _) |
+            ast::ExprTupField(ref e, _, _) => {
+                self.straightline(expr, pred, Some(&**e).move_iter())
             }
 
             ast::ExprInlineAsm(ref inline_asm) => {
@@ -477,13 +469,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 let outputs = inline_asm.outputs.iter();
                 let post_inputs = self.exprs(inputs.map(|a| {
                     debug!("cfg::construct InlineAsm id:{} input:{:?}", expr.id, a);
-                    let &(_, expr) = a;
-                    expr
+                    let &(_, ref expr) = a;
+                    &**expr
                 }), pred);
                 let post_outputs = self.exprs(outputs.map(|a| {
                     debug!("cfg::construct InlineAsm id:{} output:{:?}", expr.id, a);
-                    let &(_, expr, _) = a;
-                    expr
+                    let &(_, ref expr, _) = a;
+                    &**expr
                 }), post_inputs);
                 self.add_node(expr.id, [post_outputs])
             }
@@ -494,16 +486,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             ast::ExprUnboxedFn(..) |
             ast::ExprLit(..) |
             ast::ExprPath(..) => {
-                self.straightline(expr, pred, [])
+                self.straightline(expr, pred, None::<ast::Expr>.iter())
             }
         }
     }
 
-    fn call(&mut self,
-            call_expr: Gc<ast::Expr>,
+    fn call<'a, I: Iterator<&'a ast::Expr>>(&mut self,
+            call_expr: &ast::Expr,
             pred: CFGIndex,
-            func_or_rcvr: Gc<ast::Expr>,
-            args: &[Gc<ast::Expr>]) -> CFGIndex {
+            func_or_rcvr: &ast::Expr,
+            args: I) -> CFGIndex {
         let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
         let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
 
@@ -516,28 +508,27 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
         }
     }
 
-    fn exprs<I:Iterator<Gc<ast::Expr>>>(&mut self,
-                                        mut exprs: I,
-                                        pred: CFGIndex) -> CFGIndex {
+    fn exprs<'a, I: Iterator<&'a ast::Expr>>(&mut self,
+                                             mut exprs: I,
+                                             pred: CFGIndex) -> CFGIndex {
         //! Constructs graph for `exprs` evaluated in order
         exprs.fold(pred, |p, e| self.expr(e, p))
     }
 
     fn opt_expr(&mut self,
-                opt_expr: Option<Gc<ast::Expr>>,
+                opt_expr: &Option<P<ast::Expr>>,
                 pred: CFGIndex) -> CFGIndex {
         //! Constructs graph for `opt_expr` evaluated, if Some
-
-        opt_expr.iter().fold(pred, |p, &e| self.expr(e, p))
+        opt_expr.iter().fold(pred, |p, e| self.expr(&**e, p))
     }
 
-    fn straightline(&mut self,
-                    expr: Gc<ast::Expr>,
+    fn straightline<'a, I: Iterator<&'a ast::Expr>>(&mut self,
+                    expr: &ast::Expr,
                     pred: CFGIndex,
-                    subexprs: &[Gc<ast::Expr>]) -> CFGIndex {
+                    subexprs: I) -> CFGIndex {
         //! Handles case of an expression that evaluates `subexprs` in order
 
-        let subexprs_exit = self.exprs(subexprs.iter().map(|&e|e), pred);
+        let subexprs_exit = self.exprs(subexprs, pred);
         self.add_node(expr.id, [subexprs_exit])
     }
 
@@ -566,7 +557,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn add_exiting_edge(&mut self,
-                        from_expr: Gc<ast::Expr>,
+                        from_expr: &ast::Expr,
                         from_index: CFGIndex,
                         to_loop: LoopScope,
                         to_index: CFGIndex) {
@@ -581,7 +572,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn add_returning_edge(&mut self,
-                          _from_expr: Gc<ast::Expr>,
+                          _from_expr: &ast::Expr,
                           from_index: CFGIndex) {
         let mut data = CFGEdgeData {
             exiting_scopes: vec!(),
@@ -593,7 +584,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     }
 
     fn find_scope(&self,
-                  expr: Gc<ast::Expr>,
+                  expr: &ast::Expr,
                   label: Option<ast::Ident>) -> LoopScope {
         match label {
             None => {
diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs
index 0cccae8b8c9..84b96edc126 100644
--- a/src/librustc/middle/cfg/graphviz.rs
+++ b/src/librustc/middle/cfg/graphviz.rs
@@ -22,8 +22,8 @@ use middle::cfg;
 pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode);
 pub type Edge<'a> = &'a cfg::CFGEdge;
 
-pub struct LabelledCFG<'a>{
-    pub ast_map: &'a ast_map::Map,
+pub struct LabelledCFG<'a, 'ast: 'a> {
+    pub ast_map: &'a ast_map::Map<'ast>,
     pub cfg: &'a cfg::CFG,
     pub name: String,
 }
@@ -49,7 +49,7 @@ fn replace_newline_with_backslash_l(s: String) -> String {
     }
 }
 
-impl<'a> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a> {
+impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
     fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()) }
 
     fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
@@ -110,7 +110,7 @@ impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
     }
 }
 
-impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a>
+impl<'a, 'ast> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast>
 {
     fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
     fn edges(&self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index c0160b72784..303961105b5 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -53,15 +53,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(krate: &Crate, tcx: &ty::ctxt) {
-    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false }, krate);
+pub fn check_crate(tcx: &ty::ctxt) {
+    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false },
+                      tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
 
 fn check_item(v: &mut CheckCrateVisitor, it: &Item) {
     match it.node {
-        ItemStatic(_, _, ex) => {
-            v.inside_const(|v| v.visit_expr(&*ex));
+        ItemStatic(_, _, ref ex) => {
+            v.inside_const(|v| v.visit_expr(&**ex));
             check_item_recursion(&v.tcx.sess, &v.tcx.map, &v.tcx.def_map, it);
         }
         ItemEnum(ref enum_definition, _) => {
@@ -78,9 +79,9 @@ fn check_item(v: &mut CheckCrateVisitor, it: &Item) {
 fn check_pat(v: &mut CheckCrateVisitor, p: &Pat) {
     fn is_str(e: &Expr) -> bool {
         match e.node {
-            ExprBox(_, expr) => {
+            ExprBox(_, ref expr) => {
                 match expr.node {
-                    ExprLit(lit) => ast_util::lit_is_str(lit),
+                    ExprLit(ref lit) => ast_util::lit_is_str(&**lit),
                     _ => false,
                 }
             }
@@ -106,7 +107,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
             span_err!(v.tcx.sess, e.span, E0010, "cannot do allocations in constant expressions");
             return;
           }
-          ExprLit(lit) if ast_util::lit_is_str(lit) => {}
+          ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {}
           ExprBinary(..) | ExprUnary(..) => {
             let method_call = typeck::MethodCall::expr(e.id);
             if v.tcx.method_map.borrow().contains_key(&method_call) {
@@ -149,7 +150,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
               }
             }
           }
-          ExprCall(callee, _) => {
+          ExprCall(ref callee, _) => {
             match v.tcx.def_map.borrow().find(&callee.id) {
                 Some(&DefStruct(..)) => {}    // OK.
                 Some(&DefVariant(..)) => {}    // OK.
@@ -194,7 +195,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
           ExprTup(..) |
           ExprRepeat(..) |
           ExprStruct(..) => { }
-          ExprAddrOf(_, inner) => {
+          ExprAddrOf(_, ref inner) => {
                 match inner.node {
                     // Mutable slices are allowed.
                     ExprVec(_) => {}
@@ -214,12 +215,13 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr) {
     visit::walk_expr(v, e);
 }
 
-struct CheckItemRecursionVisitor<'a> {
+struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
     root_it: &'a Item,
     sess: &'a Session,
-    ast_map: &'a ast_map::Map,
+    ast_map: &'a ast_map::Map<'ast>,
     def_map: &'a resolve::DefMap,
-    idstack: Vec<NodeId> }
+    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)
@@ -238,7 +240,7 @@ pub fn check_item_recursion<'a>(sess: &'a Session,
     visitor.visit_item(it);
 }
 
-impl<'a, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a> {
+impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
     fn visit_item(&mut self, it: &Item) {
         if self.idstack.iter().any(|x| x == &(it.id)) {
             self.sess.span_fatal(self.root_it.span, "recursive constant");
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 6e8f6530075..eb308f903d3 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -19,19 +19,26 @@ use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
 use std::fmt;
-use std::gc::{Gc, GC};
 use std::iter::AdditiveIterator;
 use std::iter::range_inclusive;
+use std::slice;
 use syntax::ast::*;
 use syntax::ast_util::walk_pat;
 use syntax::codemap::{Span, Spanned, DUMMY_SP};
 use syntax::fold::{Folder, noop_fold_pat};
 use syntax::print::pprust::pat_to_string;
 use syntax::parse::token;
+use syntax::ptr::P;
 use syntax::visit::{mod, Visitor, FnKind};
 use util::ppaux::ty_to_string;
 
-struct Matrix(Vec<Vec<Gc<Pat>>>);
+static DUMMY_WILD_PAT: Pat = Pat {
+    id: DUMMY_NODE_ID,
+    node: PatWild(PatWildSingle),
+    span: DUMMY_SP
+};
+
+struct Matrix<'a>(Vec<Vec<&'a Pat>>);
 
 /// Pretty-printer for matrices of patterns, example:
 /// ++++++++++++++++++++++++++
@@ -45,7 +52,7 @@ struct Matrix(Vec<Vec<Gc<Pat>>>);
 /// ++++++++++++++++++++++++++
 /// + _     + [_, _, ..tail] +
 /// ++++++++++++++++++++++++++
-impl fmt::Show for Matrix {
+impl<'a> fmt::Show for Matrix<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "\n"));
 
@@ -80,8 +87,8 @@ impl fmt::Show for Matrix {
     }
 }
 
-impl FromIterator<Vec<Gc<Pat>>> for Matrix {
-    fn from_iter<T: Iterator<Vec<Gc<Pat>>>>(mut iterator: T) -> Matrix {
+impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
+    fn from_iter<T: Iterator<Vec<&'a Pat>>>(mut iterator: T) -> Matrix<'a> {
         Matrix(iterator.collect())
     }
 }
@@ -110,7 +117,7 @@ pub enum Constructor {
 #[deriving(Clone, PartialEq)]
 enum Usefulness {
     Useful,
-    UsefulWithWitness(Vec<Gc<Pat>>),
+    UsefulWithWitness(Vec<P<Pat>>),
     NotUseful
 }
 
@@ -132,16 +139,15 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt, krate: &Crate) {
-    let mut cx = MatchCheckCtxt { tcx: tcx };
-    visit::walk_crate(&mut cx, krate);
+pub fn check_crate(tcx: &ty::ctxt) {
+    visit::walk_crate(&mut MatchCheckCtxt { tcx: tcx }, tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
 
 fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
     visit::walk_expr(cx, ex);
     match ex.node {
-        ExprMatch(scrut, ref arms) => {
+        ExprMatch(ref scrut, ref arms) => {
             // First, check legality of move bindings.
             for arm in arms.iter() {
                 check_legality_of_move_bindings(cx,
@@ -156,28 +162,26 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
             // assigning or borrowing anything mutably.
             for arm in arms.iter() {
                 match arm.guard {
-                    Some(guard) => check_for_mutation_in_guard(cx, &*guard),
+                    Some(ref guard) => check_for_mutation_in_guard(cx, &**guard),
                     None => {}
                 }
             }
 
             let mut static_inliner = StaticInliner::new(cx.tcx);
-            let inlined_arms = arms
-                .iter()
-                .map(|arm| Arm {
-                    pats: arm.pats.iter().map(|pat| {
-                        static_inliner.fold_pat(*pat)
-                    }).collect(),
-                    ..arm.clone()
-                })
-                .collect::<Vec<Arm>>();
+            let inlined_arms = arms.iter().map(|arm| {
+                (arm.pats.iter().map(|pat| {
+                    static_inliner.fold_pat((*pat).clone())
+                }).collect(), arm.guard.as_ref().map(|e| &**e))
+            }).collect::<Vec<(Vec<P<Pat>>, Option<&Expr>)>>();
 
             if static_inliner.failed {
                 return;
             }
 
             // Third, check if there are any references to NaN that we should warn about.
-            check_for_static_nan(cx, inlined_arms.as_slice());
+            for &(ref pats, _) in inlined_arms.iter() {
+                check_for_static_nan(cx, pats.as_slice());
+            }
 
             // Fourth, check for unreachable arms.
             check_arms(cx, inlined_arms.as_slice());
@@ -198,28 +202,25 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
             }
 
             let matrix: Matrix = inlined_arms
-                .move_iter()
-                .filter(|arm| arm.guard.is_none())
-                .flat_map(|arm| arm.pats.move_iter())
-                .map(|pat| vec![pat])
+                .iter()
+                .filter(|&&(_, guard)| guard.is_none())
+                .flat_map(|arm| arm.ref0().iter())
+                .map(|pat| vec![&**pat])
                 .collect();
             check_exhaustive(cx, ex.span, &matrix);
         },
         ExprForLoop(ref pat, _, _, _) => {
             let mut static_inliner = StaticInliner::new(cx.tcx);
-            match is_refutable(cx, static_inliner.fold_pat(*pat)) {
-                Some(uncovered_pat) => {
-                    cx.tcx.sess.span_err(
-                        pat.span,
-                        format!("refutable pattern in `for` loop binding: \
-                                 `{}` not covered",
-                                pat_to_string(&*uncovered_pat)).as_slice());
-                },
-                None => {}
-            }
+            is_refutable(cx, &*static_inliner.fold_pat((*pat).clone()), |uncovered_pat| {
+                cx.tcx.sess.span_err(
+                    pat.span,
+                    format!("refutable pattern in `for` loop binding: \
+                            `{}` not covered",
+                            pat_to_string(uncovered_pat)).as_slice());
+            });
 
             // Check legality of move bindings.
-            check_legality_of_move_bindings(cx, false, [ *pat ]);
+            check_legality_of_move_bindings(cx, false, slice::ref_slice(pat));
             check_legality_of_bindings_in_at_patterns(cx, &**pat);
         }
         _ => ()
@@ -234,36 +235,34 @@ fn is_expr_const_nan(tcx: &ty::ctxt, expr: &Expr) -> bool {
 }
 
 // Check that we do not match against a static NaN (#6804)
-fn check_for_static_nan(cx: &MatchCheckCtxt, arms: &[Arm]) {
-    for arm in arms.iter() {
-        for &pat in arm.pats.iter() {
-            walk_pat(&*pat, |p| {
-                match p.node {
-                    PatLit(expr) if is_expr_const_nan(cx.tcx, &*expr) => {
-                        span_warn!(cx.tcx.sess, p.span, E0003,
-                            "unmatchable NaN in pattern, \
-                             use the is_nan method in a guard instead");
-                    }
-                    _ => ()
+fn check_for_static_nan(cx: &MatchCheckCtxt, pats: &[P<Pat>]) {
+    for pat in pats.iter() {
+        walk_pat(&**pat, |p| {
+            match p.node {
+                PatLit(ref expr) if is_expr_const_nan(cx.tcx, &**expr) => {
+                    span_warn!(cx.tcx.sess, p.span, E0003,
+                        "unmatchable NaN in pattern, \
+                            use the is_nan method in a guard instead");
                 }
-                true
-            });
-        }
+                _ => ()
+            }
+            true
+        });
     }
 }
 
 // Check for unreachable patterns
-fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
-    let mut seen = Matrix(vec!());
-    for arm in arms.iter() {
-        for &pat in arm.pats.iter() {
-            let v = vec![pat];
+fn check_arms(cx: &MatchCheckCtxt, arms: &[(Vec<P<Pat>>, Option<&Expr>)]) {
+    let mut seen = Matrix(vec![]);
+    for &(ref pats, guard) in arms.iter() {
+        for pat in pats.iter() {
+            let v = vec![&**pat];
             match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
                 NotUseful => span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"),
                 Useful => (),
                 UsefulWithWitness(_) => unreachable!()
             }
-            if arm.guard.is_none() {
+            if guard.is_none() {
                 let Matrix(mut rows) = seen;
                 rows.push(v);
                 seen = Matrix(rows);
@@ -272,17 +271,24 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
     }
 }
 
+fn raw_pat<'a>(p: &'a Pat) -> &'a Pat {
+    match p.node {
+        PatIdent(_, _, Some(ref s)) => raw_pat(&**s),
+        _ => p
+    }
+}
+
 fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
-    match is_useful(cx, matrix, [wild()], ConstructWitness) {
+    match is_useful(cx, matrix, &[&DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
             let witness = match pats.as_slice() {
-                [witness] => witness,
-                [] => wild(),
+                [ref witness] => &**witness,
+                [] => &DUMMY_WILD_PAT,
                 _ => unreachable!()
             };
             span_err!(cx.tcx.sess, sp, E0004,
                 "non-exhaustive patterns: `{}` not covered",
-                pat_to_string(&*witness)
+                pat_to_string(witness)
             );
         }
         NotUseful => {
@@ -292,17 +298,17 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
     }
 }
 
-fn const_val_to_expr(value: &const_val) -> Gc<Expr> {
+fn const_val_to_expr(value: &const_val) -> P<Expr> {
     let node = match value {
         &const_bool(b) => LitBool(b),
         &const_nil => LitNil,
         _ => unreachable!()
     };
-    box (GC) Expr {
+    P(Expr {
         id: 0,
-        node: ExprLit(box(GC) Spanned { node: node, span: DUMMY_SP }),
+        node: ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
         span: DUMMY_SP
-    }
+    })
 }
 
 pub struct StaticInliner<'a, 'tcx: 'a> {
@@ -320,16 +326,18 @@ impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
-    fn fold_pat(&mut self, pat: Gc<Pat>) -> Gc<Pat> {
+    fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         match pat.node {
             PatIdent(..) | PatEnum(..) => {
                 let def = self.tcx.def_map.borrow().find_copy(&pat.id);
                 match def {
                     Some(DefStatic(did, _)) => match lookup_const_by_id(self.tcx, did) {
-                        Some(const_expr) => box (GC) Pat {
-                            span: pat.span,
-                            ..(*const_expr_to_pat(self.tcx, const_expr)).clone()
-                        },
+                        Some(const_expr) => {
+                            const_expr_to_pat(self.tcx, const_expr).map(|mut new_pat| {
+                                new_pat.span = pat.span;
+                                new_pat
+                            })
+                        }
                         None => {
                             self.failed = true;
                             span_err!(self.tcx.sess, pat.span, E0158,
@@ -359,9 +367,11 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
 /// left_ty: struct X { a: (bool, &'static str), b: uint}
 /// pats: [(false, "foo"), 42]  => X { a: (false, "foo"), b: 42 }
 fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
-                     pats: Vec<Gc<Pat>>, left_ty: ty::t) -> Gc<Pat> {
+                     pats: Vec<&Pat>, left_ty: ty::t) -> P<Pat> {
+    let pats_len = pats.len();
+    let mut pats = pats.move_iter().map(|p| P((*p).clone()));
     let pat = match ty::get(left_ty).sty {
-        ty::ty_tup(_) => PatTup(pats),
+        ty::ty_tup(_) => PatTup(pats.collect()),
 
         ty::ty_enum(cid, _) | ty::ty_struct(cid, _)  => {
             let (vid, is_structure) = match ctor {
@@ -374,16 +384,16 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
             if is_structure {
                 let fields = ty::lookup_struct_fields(cx.tcx, vid);
                 let field_pats: Vec<FieldPat> = fields.move_iter()
-                    .zip(pats.iter())
-                    .filter(|&(_, pat)| pat.node != PatWild(PatWildSingle))
+                    .zip(pats)
+                    .filter(|&(_, ref pat)| pat.node != PatWild(PatWildSingle))
                     .map(|(field, pat)| FieldPat {
                         ident: Ident::new(field.name),
-                        pat: pat.clone()
+                        pat: pat
                     }).collect();
-                let has_more_fields = field_pats.len() < pats.len();
+                let has_more_fields = field_pats.len() < pats_len;
                 PatStruct(def_to_path(cx.tcx, vid), field_pats, has_more_fields)
             } else {
-                PatEnum(def_to_path(cx.tcx, vid), Some(pats))
+                PatEnum(def_to_path(cx.tcx, vid), Some(pats.collect()))
             }
         }
 
@@ -391,35 +401,35 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
             match ty::get(ty).sty {
                ty::ty_vec(_, Some(n)) => match ctor {
                     &Single => {
-                        assert_eq!(pats.len(), n);
-                        PatVec(pats, None, vec!())
+                        assert_eq!(pats_len, n);
+                        PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
                 ty::ty_vec(_, None) => match ctor {
                     &Slice(n) => {
-                        assert_eq!(pats.len(), n);
-                        PatVec(pats, None, vec!())
+                        assert_eq!(pats_len, n);
+                        PatVec(pats.collect(), None, vec!())
                     },
                     _ => unreachable!()
                 },
                 ty::ty_str => PatWild(PatWildSingle),
 
                 _ => {
-                    assert_eq!(pats.len(), 1);
-                    PatRegion(pats.get(0).clone())
+                    assert_eq!(pats_len, 1);
+                    PatRegion(pats.nth(0).unwrap())
                 }
             }
         }
 
         ty::ty_box(_) => {
-            assert_eq!(pats.len(), 1);
-            PatBox(pats.get(0).clone())
+            assert_eq!(pats_len, 1);
+            PatBox(pats.nth(0).unwrap())
         }
 
         ty::ty_vec(_, Some(len)) => {
-            assert_eq!(pats.len(), len);
-            PatVec(pats, None, vec!())
+            assert_eq!(pats_len, len);
+            PatVec(pats.collect(), None, vec![])
         }
 
         _ => {
@@ -430,11 +440,11 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
         }
     };
 
-    box (GC) Pat {
+    P(Pat {
         id: 0,
         node: pat,
         span: DUMMY_SP
-    }
+    })
 }
 
 fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
@@ -492,7 +502,7 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: ty::t,
 // So it assumes that v is non-empty.
 fn is_useful(cx: &MatchCheckCtxt,
              matrix: &Matrix,
-             v: &[Gc<Pat>],
+             v: &[&Pat],
              witness: WitnessPreference)
              -> Usefulness {
     let &Matrix(ref rows) = matrix;
@@ -506,12 +516,12 @@ fn is_useful(cx: &MatchCheckCtxt,
     if rows.get(0).len() == 0u {
         return NotUseful;
     }
-    let real_pat = match rows.iter().find(|r| r.get(0).id != 0) {
+    let real_pat = match rows.iter().find(|r| r.get(0).id != DUMMY_NODE_ID) {
         Some(r) => raw_pat(*r.get(0)),
         None if v.len() == 0 => return NotUseful,
         None => v[0]
     };
-    let left_ty = if real_pat.id == 0 {
+    let left_ty = if real_pat.id == DUMMY_NODE_ID {
         ty::mk_nil()
     } else {
         ty::pat_ty(cx.tcx, &*real_pat)
@@ -530,14 +540,13 @@ fn is_useful(cx: &MatchCheckCtxt,
                     match is_useful_specialized(cx, matrix, v, c.clone(), left_ty, witness) {
                         UsefulWithWitness(pats) => UsefulWithWitness({
                             let arity = constructor_arity(cx, &c, left_ty);
-                            let subpats = {
+                            let mut result = {
                                 let pat_slice = pats.as_slice();
-                                Vec::from_fn(arity, |i| {
-                                    pat_slice.get(i).map(|p| p.clone())
-                                        .unwrap_or_else(|| wild())
-                                })
+                                let subpats = Vec::from_fn(arity, |i| {
+                                    pat_slice.get(i).map_or(&DUMMY_WILD_PAT, |p| &**p)
+                                });
+                                vec![construct_witness(cx, &c, subpats, left_ty)]
                             };
-                            let mut result = vec!(construct_witness(cx, &c, subpats, left_ty));
                             result.extend(pats.move_iter().skip(arity));
                             result
                         }),
@@ -547,13 +556,21 @@ fn is_useful(cx: &MatchCheckCtxt,
             },
 
             Some(constructor) => {
-                let matrix = rows.iter().filter_map(|r| default(cx, r.as_slice())).collect();
+                let matrix = rows.iter().filter_map(|r| {
+                    if pat_is_binding_or_wild(&cx.tcx.def_map, raw_pat(r[0])) {
+                        Some(Vec::from_slice(r.tail()))
+                    } else {
+                        None
+                    }
+                }).collect();
                 match is_useful(cx, &matrix, v.tail(), witness) {
                     UsefulWithWitness(pats) => {
                         let arity = constructor_arity(cx, &constructor, left_ty);
-                        let wild_pats = Vec::from_elem(arity, wild());
+                        let wild_pats = Vec::from_elem(arity, &DUMMY_WILD_PAT);
                         let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
-                        UsefulWithWitness(vec!(enum_pat).append(pats.as_slice()))
+                        let mut new_pats = vec![enum_pat];
+                        new_pats.extend(pats.move_iter());
+                        UsefulWithWitness(new_pats)
                     },
                     result => result
                 }
@@ -566,8 +583,9 @@ fn is_useful(cx: &MatchCheckCtxt,
     }
 }
 
-fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, v: &[Gc<Pat>],
-                         ctor: Constructor, lty: ty::t, witness: WitnessPreference) -> Usefulness {
+fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix,
+                         v: &[&Pat], ctor: Constructor, lty: ty::t,
+                         witness: WitnessPreference) -> Usefulness {
     let arity = constructor_arity(cx, &ctor, lty);
     let matrix = Matrix(m.iter().filter_map(|r| {
         specialize(cx, r.as_slice(), &ctor, 0u, arity)
@@ -587,7 +605,7 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, v: &[Gc<P
 ///
 /// On the other hand, a wild pattern and an identifier pattern cannot be
 /// specialized in any way.
-fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
+fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
                     left_ty: ty::t, max_slice_length: uint) -> Vec<Constructor> {
     let pat = raw_pat(p);
     match pat.node {
@@ -613,10 +631,10 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
                 Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
-        PatLit(expr) =>
-            vec!(ConstantValue(eval_const_expr(cx.tcx, &*expr))),
-        PatRange(lo, hi) =>
-            vec!(ConstantRange(eval_const_expr(cx.tcx, &*lo), eval_const_expr(cx.tcx, &*hi))),
+        PatLit(ref expr) =>
+            vec!(ConstantValue(eval_const_expr(cx.tcx, &**expr))),
+        PatRange(ref lo, ref hi) =>
+            vec!(ConstantRange(eval_const_expr(cx.tcx, &**lo), eval_const_expr(cx.tcx, &**hi))),
         PatVec(ref before, ref slice, ref after) =>
             match ty::get(left_ty).sty {
                 ty::ty_vec(_, Some(_)) => vec!(Single),
@@ -691,14 +709,15 @@ fn range_covered_by_constructor(ctor: &Constructor,
 /// different patterns.
 /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
 /// fields filled with wild patterns.
-pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
-                  constructor: &Constructor, col: uint, arity: uint) -> Option<Vec<Gc<Pat>>> {
+pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
+                      constructor: &Constructor, col: uint, arity: uint) -> Option<Vec<&'a Pat>> {
     let &Pat {
         id: pat_id, node: ref node, span: pat_span
-    } = &(*raw_pat(r[col]));
-    let head: Option<Vec<Gc<Pat>>> = match node {
+    } = raw_pat(r[col]);
+    let head: Option<Vec<&Pat>> = match node {
+
         &PatWild(_) =>
-            Some(Vec::from_elem(arity, wild())),
+            Some(Vec::from_elem(arity, &DUMMY_WILD_PAT)),
 
         &PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().find_copy(&pat_id);
@@ -710,7 +729,7 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
                 } else {
                     None
                 },
-                _ => Some(Vec::from_elem(arity, wild()))
+                _ => Some(Vec::from_elem(arity, &DUMMY_WILD_PAT))
             }
         }
 
@@ -722,8 +741,8 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
                 DefVariant(_, id, _) if *constructor != Variant(id) => None,
                 DefVariant(..) | DefFn(..) | DefStruct(..) => {
                     Some(match args {
-                        &Some(ref args) => args.clone(),
-                        &None => Vec::from_elem(arity, wild())
+                        &Some(ref args) => args.iter().map(|p| &**p).collect(),
+                        &None => Vec::from_elem(arity, &DUMMY_WILD_PAT)
                     })
                 }
                 _ => None
@@ -757,8 +776,8 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
                 let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id);
                 let args = struct_fields.iter().map(|sf| {
                     match pattern_fields.iter().find(|f| f.ident.name == sf.name) {
-                        Some(f) => f.pat,
-                        _ => wild()
+                        Some(ref f) => &*f.pat,
+                        _ => &DUMMY_WILD_PAT
                     }
                 }).collect();
                 args
@@ -766,15 +785,15 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
         }
 
         &PatTup(ref args) =>
-            Some(args.clone()),
+            Some(args.iter().map(|p| &**p).collect()),
 
         &PatBox(ref inner) | &PatRegion(ref inner) =>
-            Some(vec!(inner.clone())),
+            Some(vec![&**inner]),
 
         &PatLit(ref expr) => {
             let expr_value = eval_const_expr(cx.tcx, &**expr);
             match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
-                Some(true) => Some(vec!()),
+                Some(true) => Some(vec![]),
                 Some(false) => None,
                 None => {
                     cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
@@ -787,7 +806,7 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
             let from_value = eval_const_expr(cx.tcx, &**from);
             let to_value = eval_const_expr(cx.tcx, &**to);
             match range_covered_by_constructor(constructor, &from_value, &to_value) {
-                Some(true) => Some(vec!()),
+                Some(true) => Some(vec![]),
                 Some(false) => None,
                 None => {
                     cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
@@ -800,28 +819,28 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
             match *constructor {
                 // Fixed-length vectors.
                 Single => {
-                    let mut pats = before.clone();
-                    pats.grow_fn(arity - before.len() - after.len(), |_| wild());
-                    pats.push_all(after.as_slice());
+                    let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect();
+                    pats.grow_fn(arity - before.len() - after.len(), |_| &DUMMY_WILD_PAT);
+                    pats.extend(after.iter().map(|p| &**p));
                     Some(pats)
                 },
                 Slice(length) if before.len() + after.len() <= length && slice.is_some() => {
-                    let mut pats = before.clone();
-                    pats.grow_fn(arity - before.len() - after.len(), |_| wild());
-                    pats.push_all(after.as_slice());
+                    let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect();
+                    pats.grow_fn(arity - before.len() - after.len(), |_| &DUMMY_WILD_PAT);
+                    pats.extend(after.iter().map(|p| &**p));
                     Some(pats)
                 },
                 Slice(length) if before.len() + after.len() == length => {
-                    let mut pats = before.clone();
-                    pats.push_all(after.as_slice());
+                    let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect();
+                    pats.extend(after.iter().map(|p| &**p));
                     Some(pats)
                 },
                 SliceWithSubslice(prefix, suffix)
                     if before.len() == prefix
                         && after.len() == suffix
                         && slice.is_some() => {
-                    let mut pats = before.clone();
-                    pats.push_all(after.as_slice());
+                    let mut pats: Vec<&Pat> = before.iter().map(|p| &**p).collect();
+                    pats.extend(after.iter().map(|p| &**p));
                     Some(pats)
                 }
                 _ => None
@@ -836,14 +855,6 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
     head.map(|head| head.append(r.slice_to(col)).append(r.slice_from(col + 1)))
 }
 
-fn default(cx: &MatchCheckCtxt, r: &[Gc<Pat>]) -> Option<Vec<Gc<Pat>>> {
-    if pat_is_binding_or_wild(&cx.tcx.def_map, &*raw_pat(r[0])) {
-        Some(Vec::from_slice(r.tail()))
-    } else {
-        None
-    }
-}
-
 fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
     visit::walk_local(cx, loc);
 
@@ -853,18 +864,15 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
     };
 
     let mut static_inliner = StaticInliner::new(cx.tcx);
-    match is_refutable(cx, static_inliner.fold_pat(loc.pat)) {
-        Some(pat) => {
-            span_err!(cx.tcx.sess, loc.pat.span, E0005,
-                "refutable pattern in {} binding: `{}` not covered",
-                name, pat_to_string(&*pat)
-            );
-        },
-        None => ()
-    }
+    is_refutable(cx, &*static_inliner.fold_pat(loc.pat.clone()), |pat| {
+        span_err!(cx.tcx.sess, loc.pat.span, E0005,
+            "refutable pattern in {} binding: `{}` not covered",
+            name, pat_to_string(pat)
+        );
+    });
 
     // Check legality of move bindings and `@` patterns.
-    check_legality_of_move_bindings(cx, false, [ loc.pat ]);
+    check_legality_of_move_bindings(cx, false, slice::ref_slice(&loc.pat));
     check_legality_of_bindings_in_at_patterns(cx, &*loc.pat);
 }
 
@@ -875,26 +883,23 @@ fn check_fn(cx: &mut MatchCheckCtxt,
             sp: Span) {
     visit::walk_fn(cx, kind, decl, body, sp);
     for input in decl.inputs.iter() {
-        match is_refutable(cx, input.pat) {
-            Some(pat) => {
-                span_err!(cx.tcx.sess, input.pat.span, E0006,
-                    "refutable pattern in function argument: `{}` not covered",
-                    pat_to_string(&*pat)
-                );
-            },
-            None => ()
-        }
-        check_legality_of_move_bindings(cx, false, [input.pat]);
+        is_refutable(cx, &*input.pat, |pat| {
+            span_err!(cx.tcx.sess, input.pat.span, E0006,
+                "refutable pattern in function argument: `{}` not covered",
+                pat_to_string(pat)
+            );
+        });
+        check_legality_of_move_bindings(cx, false, slice::ref_slice(&input.pat));
         check_legality_of_bindings_in_at_patterns(cx, &*input.pat);
     }
 }
 
-fn is_refutable(cx: &MatchCheckCtxt, pat: Gc<Pat>) -> Option<Gc<Pat>> {
+fn is_refutable<A>(cx: &MatchCheckCtxt, pat: &Pat, refutable: |&Pat| -> A) -> Option<A> {
     let pats = Matrix(vec!(vec!(pat)));
-    match is_useful(cx, &pats, [wild()], ConstructWitness) {
+    match is_useful(cx, &pats, [&DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => {
             assert_eq!(pats.len(), 1);
-            Some(pats.get(0).clone())
+            Some(refutable(&*pats[0]))
         },
         NotUseful => None,
         Useful => unreachable!()
@@ -904,7 +909,7 @@ fn is_refutable(cx: &MatchCheckCtxt, pat: Gc<Pat>) -> Option<Gc<Pat>> {
 // Legality of move bindings checking
 fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                                    has_guard: bool,
-                                   pats: &[Gc<Pat>]) {
+                                   pats: &[P<Pat>]) {
     let tcx = cx.tcx;
     let def_map = &tcx.def_map;
     let mut by_ref_span = None;
@@ -920,7 +925,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
         })
     }
 
-    let check_move: |&Pat, Option<Gc<Pat>>| = |p, sub| {
+    let check_move: |&Pat, Option<&Pat>| = |p, sub| {
         // check legality of moving out of the enum
 
         // x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -939,10 +944,10 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
         walk_pat(&**pat, |p| {
             if pat_is_binding(def_map, &*p) {
                 match p.node {
-                    PatIdent(BindByValue(_), _, sub) => {
+                    PatIdent(BindByValue(_), _, ref sub) => {
                         let pat_ty = ty::node_id_to_type(tcx, p.id);
                         if ty::type_moves_by_default(tcx, pat_ty) {
-                            check_move(p, sub);
+                            check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
                     PatIdent(BindByRef(_), _, _) => {
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index 46896b8811f..7a11090a8ee 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -56,8 +56,9 @@ struct CheckStaticVisitor<'a, 'tcx: 'a> {
     in_const: bool
 }
 
-pub fn check_crate(tcx: &ty::ctxt, krate: &ast::Crate) {
-    visit::walk_crate(&mut CheckStaticVisitor { tcx: tcx, in_const: false }, krate)
+pub fn check_crate(tcx: &ty::ctxt) {
+    visit::walk_crate(&mut CheckStaticVisitor { tcx: tcx, in_const: false },
+                      tcx.map.krate())
 }
 
 impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 23ab6f4585b..8c7c8eda2d2 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -22,12 +22,12 @@ use util::nodemap::{DefIdMap};
 
 use syntax::ast::*;
 use syntax::parse::token::InternedString;
+use syntax::ptr::P;
 use syntax::visit::Visitor;
 use syntax::visit;
 use syntax::{ast, ast_map, ast_util};
 
 use std::rc::Rc;
-use std::gc::{Gc, GC};
 
 //
 // This pass classifies expressions by their constant-ness.
@@ -83,7 +83,7 @@ pub fn join_all<It: Iterator<constness>>(mut cs: It) -> constness {
     cs.fold(integral_const, |a, b| join(a, b))
 }
 
-pub fn lookup_const(tcx: &ty::ctxt, e: &Expr) -> Option<Gc<Expr>> {
+fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
     let opt_def = tcx.def_map.borrow().find_copy(&e.id);
     match opt_def {
         Some(def::DefStatic(def_id, false)) => {
@@ -96,83 +96,90 @@ pub fn lookup_const(tcx: &ty::ctxt, e: &Expr) -> Option<Gc<Expr>> {
     }
 }
 
-pub fn lookup_variant_by_id(tcx: &ty::ctxt,
+fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
                             enum_def: ast::DefId,
                             variant_def: ast::DefId)
-                       -> Option<Gc<Expr>> {
-    fn variant_expr(variants: &[ast::P<ast::Variant>],
-                    id: ast::NodeId) -> Option<Gc<Expr>> {
+                            -> Option<&'a Expr> {
+    fn variant_expr<'a>(variants: &'a [P<ast::Variant>], id: ast::NodeId)
+                        -> Option<&'a Expr> {
         for variant in variants.iter() {
             if variant.node.id == id {
-                return variant.node.disr_expr;
+                return variant.node.disr_expr.as_ref().map(|e| &**e);
             }
         }
         None
     }
 
     if ast_util::is_local(enum_def) {
-        {
-            match tcx.map.find(enum_def.node) {
-                None => None,
-                Some(ast_map::NodeItem(it)) => match it.node {
-                    ItemEnum(ast::EnumDef { variants: ref variants }, _) => {
-                        variant_expr(variants.as_slice(), variant_def.node)
-                    }
-                    _ => None
-                },
-                Some(_) => None
-            }
+        match tcx.map.find(enum_def.node) {
+            None => None,
+            Some(ast_map::NodeItem(it)) => match it.node {
+                ItemEnum(ast::EnumDef { variants: ref variants }, _) => {
+                    variant_expr(variants.as_slice(), variant_def.node)
+                }
+                _ => None
+            },
+            Some(_) => None
         }
     } else {
         match tcx.extern_const_variants.borrow().find(&variant_def) {
-            Some(&e) => return e,
+            Some(&ast::DUMMY_NODE_ID) => return None,
+            Some(&expr_id) => {
+                return Some(tcx.map.expect_expr(expr_id));
+            }
             None => {}
         }
-        let e = match csearch::maybe_get_item_ast(tcx, enum_def,
+        let expr_id = match csearch::maybe_get_item_ast(tcx, enum_def,
             |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
-            csearch::found(ast::IIItem(item)) => match item.node {
+            csearch::found(&ast::IIItem(ref item)) => match item.node {
                 ItemEnum(ast::EnumDef { variants: ref variants }, _) => {
-                    variant_expr(variants.as_slice(), variant_def.node)
+                    // NOTE this doesn't do the right thing, it compares inlined
+                    // NodeId's to the original variant_def's NodeId, but they
+                    // come from different crates, so they will likely never match.
+                    variant_expr(variants.as_slice(), variant_def.node).map(|e| e.id)
                 }
                 _ => None
             },
             _ => None
         };
-        tcx.extern_const_variants.borrow_mut().insert(variant_def, e);
-        return e;
+        tcx.extern_const_variants.borrow_mut().insert(variant_def,
+                                                      expr_id.unwrap_or(ast::DUMMY_NODE_ID));
+        expr_id.map(|id| tcx.map.expect_expr(id))
     }
 }
 
-pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId)
-                          -> Option<Gc<Expr>> {
+pub fn lookup_const_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
+                          -> Option<&'a Expr> {
     if ast_util::is_local(def_id) {
-        {
-            match tcx.map.find(def_id.node) {
-                None => None,
-                Some(ast_map::NodeItem(it)) => match it.node {
-                    ItemStatic(_, ast::MutImmutable, const_expr) => {
-                        Some(const_expr)
-                    }
-                    _ => None
-                },
-                Some(_) => None
-            }
+        match tcx.map.find(def_id.node) {
+            None => None,
+            Some(ast_map::NodeItem(it)) => match it.node {
+                ItemStatic(_, ast::MutImmutable, ref const_expr) => {
+                    Some(&**const_expr)
+                }
+                _ => None
+            },
+            Some(_) => None
         }
     } else {
         match tcx.extern_const_statics.borrow().find(&def_id) {
-            Some(&e) => return e,
+            Some(&ast::DUMMY_NODE_ID) => return None,
+            Some(&expr_id) => {
+                return Some(tcx.map.expect_expr(expr_id));
+            }
             None => {}
         }
-        let e = match csearch::maybe_get_item_ast(tcx, def_id,
+        let expr_id = match csearch::maybe_get_item_ast(tcx, def_id,
             |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
-            csearch::found(ast::IIItem(item)) => match item.node {
-                ItemStatic(_, ast::MutImmutable, const_expr) => Some(const_expr),
+            csearch::found(&ast::IIItem(ref item)) => match item.node {
+                ItemStatic(_, ast::MutImmutable, ref const_expr) => Some(const_expr.id),
                 _ => None
             },
             _ => None
         };
-        tcx.extern_const_statics.borrow_mut().insert(def_id, e);
-        return e;
+        tcx.extern_const_statics.borrow_mut().insert(def_id,
+                                                     expr_id.unwrap_or(ast::DUMMY_NODE_ID));
+        expr_id.map(|id| tcx.map.expect_expr(id))
     }
 }
 
@@ -271,8 +278,8 @@ impl<'a, 'tcx> ConstEvalVisitor<'a, 'tcx> {
 impl<'a, 'tcx, 'v> Visitor<'v> for ConstEvalVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, t: &Ty) {
         match t.node {
-            TyFixedLengthVec(_, expr) => {
-                check::check_const_in_type(self.tcx, &*expr, ty::mk_uint());
+            TyFixedLengthVec(_, ref expr) => {
+                check::check_const_in_type(self.tcx, &**expr, ty::mk_uint());
             }
             _ => {}
         }
@@ -285,13 +292,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstEvalVisitor<'a, 'tcx> {
     }
 }
 
-pub fn process_crate(krate: &ast::Crate,
-                     tcx: &ty::ctxt) {
-    let mut v = ConstEvalVisitor {
+pub fn process_crate(tcx: &ty::ctxt) {
+    visit::walk_crate(&mut ConstEvalVisitor {
         tcx: tcx,
         ccache: DefIdMap::new(),
-    };
-    visit::walk_crate(&mut v, krate);
+    }, tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
 
@@ -309,12 +314,12 @@ pub enum const_val {
     const_nil
 }
 
-pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: Gc<Expr>) -> Gc<Pat> {
+pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<Pat> {
     let pat = match expr.node {
         ExprTup(ref exprs) =>
-            PatTup(exprs.iter().map(|&expr| const_expr_to_pat(tcx, expr)).collect()),
+            PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect()),
 
-        ExprCall(callee, ref args) => {
+        ExprCall(ref callee, ref args) => {
             let def = tcx.def_map.borrow().get_copy(&callee.id);
             tcx.def_map.borrow_mut().find_or_insert(expr.id, def);
             let path = match def {
@@ -322,20 +327,20 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: Gc<Expr>) -> Gc<Pat> {
                 def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
                 _ => unreachable!()
             };
-            let pats = args.iter().map(|&expr| const_expr_to_pat(tcx, expr)).collect();
+            let pats = args.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect();
             PatEnum(path, Some(pats))
         }
 
         ExprStruct(ref path, ref fields, None) => {
             let field_pats = fields.iter().map(|field| FieldPat {
                 ident: field.ident.node,
-                pat: const_expr_to_pat(tcx, field.expr)
+                pat: const_expr_to_pat(tcx, &*field.expr)
             }).collect();
             PatStruct(path.clone(), field_pats, false)
         }
 
         ExprVec(ref exprs) => {
-            let pats = exprs.iter().map(|&expr| const_expr_to_pat(tcx, expr)).collect();
+            let pats = exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr)).collect();
             PatVec(pats, None, vec![])
         }
 
@@ -347,7 +352,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: Gc<Expr>) -> Gc<Pat> {
                 Some(def::DefVariant(..)) =>
                     PatEnum(path.clone(), None),
                 _ => {
-                    match lookup_const(tcx, &*expr) {
+                    match lookup_const(tcx, expr) {
                         Some(actual) => return const_expr_to_pat(tcx, actual),
                         _ => unreachable!()
                     }
@@ -355,9 +360,9 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: Gc<Expr>) -> Gc<Pat> {
             }
         }
 
-        _ => PatLit(expr)
+        _ => PatLit(P(expr.clone()))
     };
-    box (GC) Pat { id: expr.id, node: pat, span: expr.span }
+    P(Pat { id: expr.id, node: pat, span: expr.span })
 }
 
 pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 68bcd950f9c..46e3585912a 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -219,12 +219,12 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                 }
             }
             ast_map::NodeTraitItem(trait_method) => {
-                visit::walk_trait_item(self, &*trait_method);
+                visit::walk_trait_item(self, trait_method);
             }
             ast_map::NodeImplItem(impl_item) => {
                 match *impl_item {
-                    ast::MethodImplItem(method) => {
-                        visit::walk_block(self, &*method.pe_body());
+                    ast::MethodImplItem(ref method) => {
+                        visit::walk_block(self, method.pe_body());
                     }
                 }
             }
@@ -338,7 +338,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
             ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
-                        ast::MethodImplItem(method) => {
+                        ast::MethodImplItem(ref method) => {
                             self.worklist.push(method.id);
                         }
                     }
@@ -422,7 +422,7 @@ fn should_warn(item: &ast::Item) -> bool {
 
 fn get_struct_ctor_id(item: &ast::Item) -> Option<ast::NodeId> {
     match item.node {
-        ast::ItemStruct(struct_def, _) => struct_def.ctor_id,
+        ast::ItemStruct(ref struct_def, _) => struct_def.ctor_id,
         _ => None
     }
 }
@@ -551,8 +551,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
 
 pub fn check_crate(tcx: &ty::ctxt,
                    exported_items: &privacy::ExportedItems,
-                   reachable_symbols: &NodeSet,
-                   krate: &ast::Crate) {
+                   reachable_symbols: &NodeSet) {
+    let krate = tcx.map.krate();
     let live_symbols = find_live(tcx, exported_items,
                                  reachable_symbols, krate);
     let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index db9eb90b6ec..b492203b352 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -64,7 +64,7 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
 
     fn check_str_index(&mut self, e: &ast::Expr) {
         let base_type = match e.node {
-            ast::ExprIndex(base, _) => ty::node_id_to_type(self.tcx, base.id),
+            ast::ExprIndex(ref base, _) => ty::node_id_to_type(self.tcx, base.id),
             _ => return
         };
         debug!("effect: checking index with base type {}",
@@ -153,7 +153,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                                         "invocation of unsafe method")
                 }
             }
-            ast::ExprCall(base, _) => {
+            ast::ExprCall(ref base, _) => {
                 let base_type = ty::node_id_to_type(self.tcx, base.id);
                 debug!("effect: call case, base type is {}",
                        ppaux::ty_to_string(self.tcx, base_type));
@@ -161,7 +161,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                     self.require_unsafe(expr.span, "call to unsafe function")
                 }
             }
-            ast::ExprUnary(ast::UnDeref, base) => {
+            ast::ExprUnary(ast::UnDeref, ref base) => {
                 let base_type = ty::node_id_to_type(self.tcx, base.id);
                 debug!("effect: unary case, base type is {}",
                         ppaux::ty_to_string(self.tcx, base_type));
@@ -197,11 +197,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt, krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt) {
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
         unsafe_context: SafeContext,
     };
 
-    visit::walk_crate(&mut visitor, krate);
+    visit::walk_crate(&mut visitor, tcx.map.krate());
 }
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 2b96eb717ea..01854564c05 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -11,7 +11,7 @@
 
 use driver::config;
 use driver::session::Session;
-use syntax::ast::{Crate, Name, NodeId, Item, ItemFn};
+use syntax::ast::{Name, NodeId, Item, ItemFn};
 use syntax::ast_map;
 use syntax::attr;
 use syntax::codemap::Span;
@@ -19,10 +19,10 @@ use syntax::parse::token;
 use syntax::visit;
 use syntax::visit::Visitor;
 
-struct EntryContext<'a> {
+struct EntryContext<'a, 'ast: 'a> {
     session: &'a Session,
 
-    ast_map: &'a ast_map::Map,
+    ast_map: &'a ast_map::Map<'ast>,
 
     // The interned Name for "main".
     main_name: Name,
@@ -41,13 +41,13 @@ struct EntryContext<'a> {
     non_main_fns: Vec<(NodeId, Span)> ,
 }
 
-impl<'a, 'v> Visitor<'v> for EntryContext<'a> {
+impl<'a, 'ast, 'v> Visitor<'v> for EntryContext<'a, 'ast> {
     fn visit_item(&mut self, item: &Item) {
         find_item(item, self);
     }
 }
 
-pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map) {
+pub fn find_entry_point(session: &Session, ast_map: &ast_map::Map) {
     let any_exe = session.crate_types.borrow().iter().any(|ty| {
         *ty == config::CrateTypeExecutable
     });
@@ -57,7 +57,7 @@ pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map
     }
 
     // If the user wants no main function at all, then stop here.
-    if attr::contains_name(krate.attrs.as_slice(), "no_main") {
+    if attr::contains_name(ast_map.krate().attrs.as_slice(), "no_main") {
         session.entry_type.set(Some(config::EntryNone));
         return
     }
@@ -72,7 +72,7 @@ pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map
         non_main_fns: Vec::new(),
     };
 
-    visit::walk_crate(&mut ctxt, krate);
+    visit::walk_crate(&mut ctxt, ast_map.krate());
 
     configure_main(&mut ctxt);
 }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index d2362b7e942..1e79ea68eeb 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -24,8 +24,8 @@ use middle::typeck::{MethodStatic, MethodStaticUnboxedClosure};
 use middle::typeck;
 use util::ppaux::Repr;
 
-use std::gc::Gc;
 use syntax::ast;
+use syntax::ptr::P;
 use syntax::codemap::Span;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -242,7 +242,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
                 ty::ReScope(body.id), // Args live only as long as the fn body.
                 arg_ty);
 
-            self.walk_pat(arg_cmt, arg.pat.clone());
+            self.walk_pat(arg_cmt, &*arg.pat);
         }
     }
 
@@ -258,7 +258,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
         self.delegate.consume(consume_id, consume_span, cmt, mode);
     }
 
-    fn consume_exprs(&mut self, exprs: &Vec<Gc<ast::Expr>>) {
+    fn consume_exprs(&mut self, exprs: &Vec<P<ast::Expr>>) {
         for expr in exprs.iter() {
             self.consume_expr(&**expr);
         }
@@ -315,7 +315,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
             ast::ExprPath(..) => { }
 
             ast::ExprUnary(ast::UnDeref, ref base) => {      // *base
-                if !self.walk_overloaded_operator(expr, &**base, []) {
+                if !self.walk_overloaded_operator(expr, &**base, None) {
                     self.select_from_expr(&**base);
                 }
             }
@@ -328,8 +328,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
                 self.select_from_expr(&**base);
             }
 
-            ast::ExprIndex(ref lhs, ref rhs) => {           // lhs[rhs]
-                if !self.walk_overloaded_operator(expr, &**lhs, [rhs.clone()]) {
+            ast::ExprIndex(ref lhs, ref rhs) => {       // lhs[rhs]
+                if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
                     self.select_from_expr(&**lhs);
                     self.consume_expr(&**rhs);
                 }
@@ -345,7 +345,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
             }
 
             ast::ExprStruct(_, ref fields, ref opt_with) => {
-                self.walk_struct_expr(expr, fields, opt_with.clone());
+                self.walk_struct_expr(expr, fields, opt_with);
             }
 
             ast::ExprTup(ref exprs) => {
@@ -423,19 +423,19 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
                                                  pat.span,
                                                  ty::ReScope(blk.id),
                                                  pattern_type);
-                self.walk_pat(pat_cmt, pat.clone());
+                self.walk_pat(pat_cmt, &**pat);
 
                 self.walk_block(&**blk);
             }
 
             ast::ExprUnary(_, ref lhs) => {
-                if !self.walk_overloaded_operator(expr, &**lhs, []) {
+                if !self.walk_overloaded_operator(expr, &**lhs, None) {
                     self.consume_expr(&**lhs);
                 }
             }
 
             ast::ExprBinary(_, ref lhs, ref rhs) => {
-                if !self.walk_overloaded_operator(expr, &**lhs, [rhs.clone()]) {
+                if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
                     self.consume_expr(&**lhs);
                     self.consume_expr(&**rhs);
                 }
@@ -554,7 +554,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
             ast::StmtDecl(ref decl, _) => {
                 match decl.node {
                     ast::DeclLocal(ref local) => {
-                        self.walk_local(local.clone());
+                        self.walk_local(&**local);
                     }
 
                     ast::DeclItem(_) => {
@@ -575,7 +575,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
         }
     }
 
-    fn walk_local(&mut self, local: Gc<ast::Local>) {
+    fn walk_local(&mut self, local: &ast::Local) {
         match local.init {
             None => {
                 let delegate = &mut self.delegate;
@@ -592,7 +592,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
                 // `walk_pat`:
                 self.walk_expr(&**expr);
                 let init_cmt = return_if_err!(self.mc.cat_expr(&**expr));
-                self.walk_pat(init_cmt, local.pat);
+                self.walk_pat(init_cmt, &*local.pat);
             }
         }
     }
@@ -617,14 +617,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
     fn walk_struct_expr(&mut self,
                         _expr: &ast::Expr,
                         fields: &Vec<ast::Field>,
-                        opt_with: Option<Gc<ast::Expr>>) {
+                        opt_with: &Option<P<ast::Expr>>) {
         // Consume the expressions supplying values for each field.
         for field in fields.iter() {
             self.consume_expr(&*field.expr);
         }
 
-        let with_expr = match opt_with {
-            Some(ref w) => { w.clone() }
+        let with_expr = match *opt_with {
+            Some(ref w) => &**w,
             None => { return; }
         };
 
@@ -773,7 +773,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
     fn walk_overloaded_operator(&mut self,
                                 expr: &ast::Expr,
                                 receiver: &ast::Expr,
-                                args: &[Gc<ast::Expr>])
+                                rhs: Option<&ast::Expr>)
                                 -> bool
     {
         if !self.typer.is_method_call(expr.id) {
@@ -789,15 +789,15 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
         let r = ty::ReScope(expr.id);
         let bk = ty::ImmBorrow;
 
-        for arg in args.iter() {
-            self.borrow_expr(&**arg, r, bk, OverloadedOperator);
+        for &arg in rhs.iter() {
+            self.borrow_expr(arg, r, bk, OverloadedOperator);
         }
         return true;
     }
 
     fn walk_arm(&mut self, discr_cmt: mc::cmt, arm: &ast::Arm) {
-        for &pat in arm.pats.iter() {
-            self.walk_pat(discr_cmt.clone(), pat);
+        for pat in arm.pats.iter() {
+            self.walk_pat(discr_cmt.clone(), &**pat);
         }
 
         for guard in arm.guard.iter() {
@@ -807,7 +807,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
         self.consume_expr(&*arm.body);
     }
 
-    fn walk_pat(&mut self, cmt_discr: mc::cmt, pat: Gc<ast::Pat>) {
+    fn walk_pat(&mut self, cmt_discr: mc::cmt, pat: &ast::Pat) {
         debug!("walk_pat cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
                pat.repr(self.tcx()));
         let mc = &self.mc;
@@ -859,14 +859,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
                 }
             } else {
                 match pat.node {
-                    ast::PatVec(_, Some(slice_pat), _) => {
+                    ast::PatVec(_, Some(ref slice_pat), _) => {
                         // The `slice_pat` here creates a slice into
                         // the original vector.  This is effectively a
                         // borrow of the elements of the vector being
                         // matched.
 
                         let (slice_cmt, slice_mutbl, slice_r) = {
-                            match mc.cat_slice_pattern(cmt_pat, &*slice_pat) {
+                            match mc.cat_slice_pattern(cmt_pat, &**slice_pat) {
                                 Ok(v) => v,
                                 Err(()) => {
                                     tcx.sess.span_bug(slice_pat.span,
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 76ade1a7504..9d0d21d6d2a 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -148,11 +148,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: &ctxt, krate: &ast::Crate) {
-    let mut visitor = IntrinsicCheckingVisitor {
-        tcx: tcx,
-    };
-
-    visit::walk_crate(&mut visitor, krate);
+pub fn check_crate(tcx: &ctxt) {
+    visit::walk_crate(&mut IntrinsicCheckingVisitor { tcx: tcx },
+                      tcx.map.krate());
 }
 
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 1e398ce210b..33f7680d873 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -83,14 +83,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt,
-                   krate: &Crate) {
+pub fn check_crate(tcx: &ty::ctxt) {
     let mut ctx = Context {
         tcx: tcx,
         struct_and_enum_bounds_checked: HashSet::new(),
         parameter_environments: Vec::new(),
     };
-    visit::walk_crate(&mut ctx, krate);
+    visit::walk_crate(&mut ctx, tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
 
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 18f3de82280..aecfa36c108 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -111,7 +111,6 @@ use lint;
 use util::nodemap::NodeMap;
 
 use std::fmt;
-use std::gc::Gc;
 use std::io;
 use std::mem::transmute;
 use std::rc::Rc;
@@ -122,16 +121,16 @@ use syntax::codemap::{BytePos, original_sp, Span};
 use syntax::parse::token::special_idents;
 use syntax::parse::token;
 use syntax::print::pprust::{expr_to_string, block_to_string};
+use syntax::ptr::P;
 use syntax::{visit, ast_util};
 use syntax::visit::{Visitor, FnKind};
 
 /// For use with `propagate_through_loop`.
-#[deriving(PartialEq, Eq)]
-enum LoopKind {
+enum LoopKind<'a> {
     /// An endless `loop` loop.
     LoopLoop,
     /// A `while` loop, with the given expression as condition.
-    WhileLoop(Gc<Expr>),
+    WhileLoop(&'a Expr),
     /// A `for` loop.
     ForLoop,
 }
@@ -189,9 +188,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> {
     fn visit_arm(&mut self, a: &Arm) { visit_arm(self, a); }
 }
 
-pub fn check_crate(tcx: &ty::ctxt,
-                   krate: &Crate) {
-    visit::walk_crate(&mut IrMaps::new(tcx), krate);
+pub fn check_crate(tcx: &ty::ctxt) {
+    visit::walk_crate(&mut IrMaps::new(tcx), tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
 
@@ -617,25 +615,25 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn arm_pats_bindings(&mut self,
-                         pats: &[Gc<Pat>],
+                         pat: Option<&Pat>,
                          f: |&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId|) {
-        // only consider the first pattern; any later patterns must have
-        // the same bindings, and we also consider the first pattern to be
-        // the "authoritative" set of ids
-        if !pats.is_empty() {
-            self.pat_bindings(&*pats[0], f)
+        match pat {
+            Some(pat) => {
+                self.pat_bindings(pat, f);
+            }
+            None => {}
         }
     }
 
-    fn define_bindings_in_pat(&mut self, pat: Gc<Pat>, succ: LiveNode)
+    fn define_bindings_in_pat(&mut self, pat: &Pat, succ: LiveNode)
                               -> LiveNode {
-        self.define_bindings_in_arm_pats([pat], succ)
+        self.define_bindings_in_arm_pats(Some(pat), succ)
     }
 
-    fn define_bindings_in_arm_pats(&mut self, pats: &[Gc<Pat>], succ: LiveNode)
+    fn define_bindings_in_arm_pats(&mut self, pat: Option<&Pat>, succ: LiveNode)
                                    -> LiveNode {
         let mut succ = succ;
-        self.arm_pats_bindings(pats, |this, ln, var, _sp, _id| {
+        self.arm_pats_bindings(pat, |this, ln, var, _sp, _id| {
             this.init_from_succ(ln, succ);
             this.define(ln, var);
             succ = ln;
@@ -882,7 +880,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn propagate_through_block(&mut self, blk: &Block, succ: LiveNode)
                                -> LiveNode {
-        let succ = self.propagate_through_opt_expr(blk.expr, succ);
+        let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
         blk.stmts.iter().rev().fold(succ, |succ, stmt| {
             self.propagate_through_stmt(&**stmt, succ)
         })
@@ -931,11 +929,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         // initialization, which is mildly more complex than checking
         // once at the func header but otherwise equivalent.
 
-        let succ = self.propagate_through_opt_expr(local.init, succ);
-        self.define_bindings_in_pat(local.pat, succ)
+        let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
+        self.define_bindings_in_pat(&*local.pat, succ)
     }
 
-    fn propagate_through_exprs(&mut self, exprs: &[Gc<Expr>], succ: LiveNode)
+    fn propagate_through_exprs(&mut self, exprs: &[P<Expr>], succ: LiveNode)
                                -> LiveNode {
         exprs.iter().rev().fold(succ, |succ, expr| {
             self.propagate_through_expr(&**expr, succ)
@@ -943,7 +941,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn propagate_through_opt_expr(&mut self,
-                                  opt_expr: Option<Gc<Expr>>,
+                                  opt_expr: Option<&Expr>,
                                   succ: LiveNode)
                                   -> LiveNode {
         opt_expr.iter().fold(succ, |succ, expr| {
@@ -1014,7 +1012,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             //    v     v
             //   (  succ  )
             //
-            let else_ln = self.propagate_through_opt_expr(els.clone(), succ);
+            let else_ln = self.propagate_through_opt_expr(els.as_ref().map(|e| &**e), succ);
             let then_ln = self.propagate_through_block(&**then, succ);
             let ln = self.live_node(expr.id, expr.span);
             self.init_from_succ(ln, else_ln);
@@ -1023,10 +1021,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           }
 
           ExprWhile(ref cond, ref blk, _) => {
-            self.propagate_through_loop(expr,
-                                        WhileLoop(cond.clone()),
-                                        &**blk,
-                                        succ)
+            self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
           }
 
           ExprForLoop(_, ref head, ref blk, _) => {
@@ -1062,9 +1057,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 let body_succ =
                     self.propagate_through_expr(&*arm.body, succ);
                 let guard_succ =
-                    self.propagate_through_opt_expr(arm.guard, body_succ);
+                    self.propagate_through_opt_expr(arm.guard.as_ref().map(|e| &**e), body_succ);
+                // only consider the first pattern; any later patterns must have
+                // the same bindings, and we also consider the first pattern to be
+                // the "authoritative" set of ids
                 let arm_succ =
-                    self.define_bindings_in_arm_pats(arm.pats.as_slice(),
+                    self.define_bindings_in_arm_pats(arm.pats.as_slice().head().map(|p| &**p),
                                                      guard_succ);
                 self.merge_from_succ(ln, arm_succ, first_merge);
                 first_merge = false;
@@ -1072,10 +1070,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             self.propagate_through_expr(&**e, ln)
           }
 
-          ExprRet(o_e) => {
+          ExprRet(ref o_e) => {
             // ignore succ and subst exit_ln:
             let exit_ln = self.s.exit_ln;
-            self.propagate_through_opt_expr(o_e, exit_ln)
+            self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
           }
 
           ExprBreak(opt_label) => {
@@ -1134,7 +1132,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           }
 
           ExprStruct(_, ref fields, ref with_expr) => {
-            let succ = self.propagate_through_opt_expr(with_expr.clone(), succ);
+            let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
             fields.iter().rev().fold(succ, |succ, field| {
                 self.propagate_through_expr(&*field.expr, succ)
             })
@@ -1182,7 +1180,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           ExprIndex(ref l, ref r) |
           ExprBinary(_, ref l, ref r) |
           ExprBox(ref l, ref r) => {
-            self.propagate_through_exprs([l.clone(), r.clone()], succ)
+            let r_succ = self.propagate_through_expr(&**r, succ);
+            self.propagate_through_expr(&**l, r_succ)
           }
 
           ExprAddrOf(_, ref e) |
@@ -1342,12 +1341,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         let mut first_merge = true;
         let ln = self.live_node(expr.id, expr.span);
         self.init_empty(ln, succ);
-        if kind != LoopLoop {
-            // If this is not a `loop` loop, then it's possible we bypass
-            // the body altogether. Otherwise, the only way is via a `break`
-            // in the loop body.
-            self.merge_from_succ(ln, succ, first_merge);
-            first_merge = false;
+        match kind {
+            LoopLoop => {}
+            _ => {
+                // If this is not a `loop` loop, then it's possible we bypass
+                // the body altogether. Otherwise, the only way is via a `break`
+                // in the loop body.
+                self.merge_from_succ(ln, succ, first_merge);
+                first_merge = false;
+            }
         }
         debug!("propagate_through_loop: using id for loop body {} {}",
                expr.id, block_to_string(body));
@@ -1413,7 +1415,10 @@ fn check_local(this: &mut Liveness, local: &Local) {
 }
 
 fn check_arm(this: &mut Liveness, arm: &Arm) {
-    this.arm_pats_bindings(arm.pats.as_slice(), |this, ln, var, sp, id| {
+    // only consider the first pattern; any later patterns must have
+    // the same bindings, and we also consider the first pattern to be
+    // the "authoritative" set of ids
+    this.arm_pats_bindings(arm.pats.as_slice().head().map(|p| &**p), |this, ln, var, sp, id| {
         this.warn_about_unused(sp, id, ln, var);
     });
     visit::walk_arm(this, arm);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 0d3dd8f91d9..3e42ee9187c 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -490,7 +490,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           }
 
           ast::ExprPath(_) => {
-            let def = self.tcx().def_map.borrow().get_copy(&expr.id);
+            let def = *self.tcx().def_map.borrow().get(&expr.id);
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
 
@@ -1154,7 +1154,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
             if_ok!(self.cat_pattern(subcmt, &**subpat, op));
           }
 
-          ast::PatVec(ref before, slice, ref after) => {
+          ast::PatVec(ref before, ref slice, ref after) => {
               let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt));
               for before_pat in before.iter() {
                   if_ok!(self.cat_pattern(elt_cmt.clone(), &**before_pat,
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 727f5ad9385..ac1a62b1852 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -13,7 +13,6 @@ use middle::resolve;
 use middle::ty;
 
 use std::collections::HashMap;
-use std::gc::{Gc, GC};
 use syntax::ast::*;
 use syntax::ast_util::{walk_pat};
 use syntax::codemap::{Span, DUMMY_SP};
@@ -115,17 +114,6 @@ pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Ident> {
     }
 }
 
-pub fn wild() -> Gc<Pat> {
-    box (GC) Pat { id: 0, node: PatWild(PatWildSingle), span: DUMMY_SP }
-}
-
-pub fn raw_pat(p: Gc<Pat>) -> Gc<Pat> {
-    match p.node {
-        PatIdent(_, _, Some(s)) => { raw_pat(s) }
-        _ => { p }
-    }
-}
-
 pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
     ty::with_path(tcx, id, |mut path| Path {
         global: false,
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index da957024b9a..feacbf84f67 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -12,7 +12,6 @@
 //! outside their scopes. This pass will also generate a set of exported items
 //! which are available for use externally when compiled as a library.
 
-use std::gc::Gc;
 use std::mem::replace;
 
 use metadata::csearch;
@@ -263,7 +262,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                 if public_ty || public_trait {
                     for impl_item in impl_items.iter() {
                         match *impl_item {
-                            ast::MethodImplItem(method) => {
+                            ast::MethodImplItem(ref method) => {
                                 let meth_public =
                                     match method.pe_explicit_self().node {
                                         ast::SelfStatic => public_ty,
@@ -457,11 +456,10 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                 // invocation.
                 // FIXME(#10573) is this the right behavior? Why not consider
                 //               where the method was defined?
-                Some(ast_map::NodeImplItem(ref ii)) => {
-                    match **ii {
-                        ast::MethodImplItem(m) => {
-                            let imp = self.tcx
-                                          .map
+                Some(ast_map::NodeImplItem(ii)) => {
+                    match *ii {
+                        ast::MethodImplItem(ref m) => {
+                            let imp = self.tcx.map
                                           .get_parent_did(closest_private_id);
                             match ty::impl_trait_ref(self.tcx, imp) {
                                 Some(..) => return Allowable,
@@ -1108,7 +1106,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                                  impls");
                 for impl_item in impl_items.iter() {
                     match *impl_item {
-                        ast::MethodImplItem(m) => {
+                        ast::MethodImplItem(ref m) => {
                             check_inherited(m.span, m.pe_vis(), "");
                         }
                     }
@@ -1169,7 +1167,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                 tcx.sess.span_err(sp, "visibility has no effect inside functions");
             }
         }
-        let check_struct = |def: &Gc<ast::StructDef>| {
+        let check_struct = |def: &ast::StructDef| {
             for f in def.fields.iter() {
                match f.node.kind {
                     ast::NamedField(_, p) => check_inherited(tcx, f.span, p),
@@ -1182,7 +1180,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
             ast::ItemImpl(_, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
-                        ast::MethodImplItem(m) => {
+                        ast::MethodImplItem(ref m) => {
                             check_inherited(tcx, m.span, m.pe_vis());
                         }
                     }
@@ -1198,13 +1196,13 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                     check_inherited(tcx, v.span, v.node.vis);
 
                     match v.node.kind {
-                        ast::StructVariantKind(ref s) => check_struct(s),
+                        ast::StructVariantKind(ref s) => check_struct(&**s),
                         ast::TupleVariantKind(..) => {}
                     }
                 }
             }
 
-            ast::ItemStruct(ref def, _) => check_struct(def),
+            ast::ItemStruct(ref def, _) => check_struct(&**def),
 
             ast::ItemTrait(_, _, _, ref methods) => {
                 for m in methods.iter() {
@@ -1305,7 +1303,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
             // (i.e. we could just return here to not check them at
             // all, or some worse estimation of whether an impl is
             // publicly visible.
-            ast::ItemImpl(ref g, ref trait_ref, self_, ref impl_items) => {
+            ast::ItemImpl(ref g, ref trait_ref, ref self_, ref impl_items) => {
                 // `impl [... for] Private` is never visible.
                 let self_contains_private;
                 // impl [... for] Public<...>, but not `impl [... for]
@@ -1320,7 +1318,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                         at_outer_type: true,
                         outer_type_is_public_path: false,
                     };
-                    visitor.visit_ty(&*self_);
+                    visitor.visit_ty(&**self_);
                     self_contains_private = visitor.contains_private;
                     self_is_public_path = visitor.outer_type_is_public_path;
                 }
@@ -1349,7 +1347,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     impl_items.iter()
                               .any(|impl_item| {
                                   match *impl_item {
-                                      ast::MethodImplItem(m) => {
+                                      ast::MethodImplItem(ref m) => {
                                           self.exported_items.contains(&m.id)
                                       }
                                   }
@@ -1365,8 +1363,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                         None => {
                             for impl_item in impl_items.iter() {
                                 match *impl_item {
-                                    ast::MethodImplItem(method) => {
-                                        visit::walk_method_helper(self, &*method)
+                                    ast::MethodImplItem(ref method) => {
+                                        visit::walk_method_helper(self, &**method)
                                     }
                                 }
                             }
@@ -1393,13 +1391,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                     let mut found_pub_static = false;
                     for impl_item in impl_items.iter() {
                         match *impl_item {
-                            ast::MethodImplItem(method) => {
+                            ast::MethodImplItem(ref method) => {
                                 if method.pe_explicit_self().node ==
                                         ast::SelfStatic &&
                                         self.exported_items
                                             .contains(&method.id) {
                                     found_pub_static = true;
-                                    visit::walk_method_helper(self, &*method);
+                                    visit::walk_method_helper(self, &**method);
                                 }
                             }
                         }
@@ -1487,8 +1485,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
 pub fn check_crate(tcx: &ty::ctxt,
                    exp_map2: &resolve::ExportMap2,
                    external_exports: resolve::ExternalExports,
-                   last_private_map: resolve::LastPrivateMap,
-                   krate: &ast::Crate) -> (ExportedItems, PublicItems) {
+                   last_private_map: resolve::LastPrivateMap)
+                   -> (ExportedItems, PublicItems) {
+    let krate = tcx.map.krate();
+
     // Figure out who everyone's parent is
     let mut visitor = ParentVisitor {
         parents: NodeMap::new(),
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index d7cf25e7410..630b65f5278 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -201,7 +201,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
                 match *impl_item {
-                    ast::MethodImplItem(method) => {
+                    ast::MethodImplItem(ref method) => {
                         if generics_require_inlining(method.pe_generics()) ||
                                 attributes_specify_inlining(
                                     method.attrs.as_slice()) {
@@ -333,10 +333,10 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             }
             ast_map::NodeImplItem(impl_item) => {
                 match *impl_item {
-                    ast::MethodImplItem(method) => {
+                    ast::MethodImplItem(ref method) => {
                         let did = self.tcx.map.get_parent_did(search_item);
-                        if method_might_be_inlined(self.tcx, &*method, did) {
-                            visit::walk_block(self, &*method.pe_body())
+                        if method_might_be_inlined(self.tcx, &**method, did) {
+                            visit::walk_block(self, method.pe_body())
                         }
                     }
                 }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 45107d26f2f..4f81aac5eb0 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -29,12 +29,12 @@ use util::common::can_reach;
 
 use std::cell::RefCell;
 use std::collections::{HashMap, HashSet};
-use std::gc::Gc;
 use syntax::codemap::Span;
 use syntax::{ast, visit};
-use syntax::visit::{Visitor, FnKind};
 use syntax::ast::{Block, Item, FnDecl, NodeId, Arm, Pat, Stmt, Expr, Local};
 use syntax::ast_util::{stmt_id};
+use syntax::ptr::P;
+use syntax::visit::{Visitor, FnKind};
 
 /**
 The region maps encode information about region relationships.
@@ -422,7 +422,7 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &ast::Arm) {
     visitor.region_maps.mark_as_terminating_scope(arm.body.id);
 
     match arm.guard {
-        Some(expr) => {
+        Some(ref expr) => {
             visitor.region_maps.mark_as_terminating_scope(expr.id);
         }
         None => { }
@@ -471,28 +471,28 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
         // scopes, meaning that temporaries cannot outlive them.
         // This ensures fixed size stacks.
 
-        ast::ExprBinary(ast::BiAnd, _, r) |
-        ast::ExprBinary(ast::BiOr, _, r) => {
+        ast::ExprBinary(ast::BiAnd, _, ref r) |
+        ast::ExprBinary(ast::BiOr, _, ref r) => {
             // For shortcircuiting operators, mark the RHS as a terminating
             // scope since it only executes conditionally.
             visitor.region_maps.mark_as_terminating_scope(r.id);
         }
 
-        ast::ExprIf(_, then, Some(otherwise)) => {
+        ast::ExprIf(_, ref then, Some(ref otherwise)) => {
             visitor.region_maps.mark_as_terminating_scope(then.id);
             visitor.region_maps.mark_as_terminating_scope(otherwise.id);
         }
 
-        ast::ExprIf(expr, then, None) => {
+        ast::ExprIf(ref expr, ref then, None) => {
             visitor.region_maps.mark_as_terminating_scope(expr.id);
             visitor.region_maps.mark_as_terminating_scope(then.id);
         }
 
-        ast::ExprLoop(body, _) => {
+        ast::ExprLoop(ref body, _) => {
             visitor.region_maps.mark_as_terminating_scope(body.id);
         }
 
-        ast::ExprWhile(expr, body, _) => {
+        ast::ExprWhile(ref expr, ref body, _) => {
             visitor.region_maps.mark_as_terminating_scope(expr.id);
             visitor.region_maps.mark_as_terminating_scope(body.id);
         }
@@ -776,7 +776,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &ast::Local) {
                 ast::ExprTupField(ref subexpr, _, _) |
                 ast::ExprIndex(ref subexpr, _) |
                 ast::ExprParen(ref subexpr) => {
-                    let subexpr: &'a Gc<Expr> = subexpr; // FIXME(#11586)
+                    let subexpr: &'a P<Expr> = subexpr; // FIXME(#11586)
                     expr = &**subexpr;
                 }
                 _ => {
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index ed795ff0aac..64ae2776ccc 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -30,7 +30,7 @@ use syntax::ast::{Ident, ImplItem, Item, ItemEnum, ItemFn, ItemForeignMod};
 use syntax::ast::{ItemImpl, ItemMac, ItemMod, ItemStatic, ItemStruct};
 use syntax::ast::{ItemTrait, ItemTy, LOCAL_CRATE, Local, Method};
 use syntax::ast::{MethodImplItem, Mod, Name, NamedField, NodeId};
-use syntax::ast::{P, Pat, PatEnum, PatIdent, PatLit};
+use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
 use syntax::ast::{PatRange, PatStruct, Path, PathListIdent, PathListMod};
 use syntax::ast::{PrimTy, Public, SelfExplicit, SelfStatic};
 use syntax::ast::{RegionTyParamBound, StmtDecl, StructField};
@@ -43,8 +43,7 @@ use syntax::ast::{UnboxedFnTyParamBound, UnnamedField, UnsafeFn, Variant};
 use syntax::ast::{ViewItem, ViewItemExternCrate, ViewItemUse, ViewPathGlob};
 use syntax::ast::{ViewPathList, ViewPathSimple, Visibility};
 use syntax::ast;
-use syntax::ast_util::{PostExpansionMethod, local_def};
-use syntax::ast_util::{trait_item_to_ty_method, walk_pat};
+use syntax::ast_util::{PostExpansionMethod, local_def, walk_pat};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
 use syntax::parse::token::special_names;
@@ -52,6 +51,7 @@ use syntax::parse::token::special_idents;
 use syntax::parse::token;
 use syntax::codemap::{Span, DUMMY_SP, Pos};
 use syntax::owned_slice::OwnedSlice;
+use syntax::ptr::P;
 use syntax::visit;
 use syntax::visit::Visitor;
 
@@ -1164,7 +1164,7 @@ impl<'a> Resolver<'a> {
         // Check each statement.
         for statement in block.stmts.iter() {
             match statement.node {
-                StmtDecl(declaration, _) => {
+                StmtDecl(ref declaration, _) => {
                     match declaration.node {
                         DeclItem(_) => {
                             return true;
@@ -1277,7 +1277,7 @@ impl<'a> Resolver<'a> {
             }
 
             // These items live in both the type and value namespaces.
-            ItemStruct(struct_def, _) => {
+            ItemStruct(ref struct_def, _) => {
                 // Adding to both Type and Value namespaces or just Type?
                 let (forbid, ctor_id) = match struct_def.ctor_id {
                     Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
@@ -1309,7 +1309,7 @@ impl<'a> Resolver<'a> {
                 parent
             }
 
-            ItemImpl(_, None, ty, ref impl_items) => {
+            ItemImpl(_, None, ref ty, ref impl_items) => {
                 // If this implements an anonymous trait, then add all the
                 // methods within to a new module, if the type was defined
                 // within this module.
@@ -1364,7 +1364,7 @@ impl<'a> Resolver<'a> {
                         // For each implementation item...
                         for impl_item in impl_items.iter() {
                             match *impl_item {
-                                MethodImplItem(method) => {
+                                MethodImplItem(ref method) => {
                                     // Add the method to the module.
                                     let ident = method.pe_ident();
                                     let method_name_bindings =
@@ -1430,37 +1430,42 @@ impl<'a> Resolver<'a> {
 
                 // Add the names of all the methods to the trait info.
                 for method in methods.iter() {
-                    let ty_m = trait_item_to_ty_method(method);
-
-                    let ident = ty_m.ident;
+                    let (m_id, m_ident, m_fn_style, m_self, m_span) = match *method {
+                        ast::RequiredMethod(ref m) => {
+                            (m.id, m.ident, m.fn_style, &m.explicit_self, m.span)
+                        }
+                        ast::ProvidedMethod(ref m) => {
+                            (m.id, m.pe_ident(), m.pe_fn_style(), m.pe_explicit_self(), m.span)
+                        }
+                    };
 
                     // Add it as a name in the trait module.
-                    let (def, static_flag) = match ty_m.explicit_self.node {
+                    let (def, static_flag) = match m_self.node {
                         SelfStatic => {
                             // Static methods become `def_static_method`s.
-                            (DefStaticMethod(local_def(ty_m.id),
+                            (DefStaticMethod(local_def(m_id),
                                               FromTrait(local_def(item.id)),
-                                              ty_m.fn_style),
+                                              m_fn_style),
                              StaticMethodTraitItemKind)
                         }
                         _ => {
                             // Non-static methods become `def_method`s.
-                            (DefMethod(local_def(ty_m.id),
+                            (DefMethod(local_def(m_id),
                                        Some(local_def(item.id))),
                              NonstaticMethodTraitItemKind)
                         }
                     };
 
                     let method_name_bindings =
-                        self.add_child(ident,
+                        self.add_child(m_ident,
                                        module_parent.clone(),
                                        ForbidDuplicateValues,
-                                       ty_m.span);
-                    method_name_bindings.define_value(def, ty_m.span, true);
+                                       m_span);
+                    method_name_bindings.define_value(def, m_span, true);
 
                     self.trait_item_map
                         .borrow_mut()
-                        .insert((ident.name, def_id), static_flag);
+                        .insert((m_ident.name, def_id), static_flag);
                 }
 
                 name_bindings.define_type(DefTrait(def_id), sp, is_public);
@@ -4068,7 +4073,7 @@ impl<'a> Resolver<'a> {
             ItemStruct(ref struct_def, ref generics) => {
                 self.resolve_struct(item.id,
                                     generics,
-                                    struct_def.super_struct,
+                                    &struct_def.super_struct,
                                     struct_def.fields.as_slice());
             }
 
@@ -4100,15 +4105,15 @@ impl<'a> Resolver<'a> {
                 });
             }
 
-            ItemFn(fn_decl, _, _, ref generics, block) => {
+            ItemFn(ref fn_decl, _, _, ref generics, ref block) => {
                 self.resolve_function(ItemRibKind,
-                                      Some(fn_decl),
+                                      Some(&**fn_decl),
                                       HasTypeParameters
                                         (generics,
                                          FnSpace,
                                          item.id,
                                          ItemRibKind),
-                                      block);
+                                      &**block);
             }
 
             ItemStatic(..) => {
@@ -4179,9 +4184,9 @@ impl<'a> Resolver<'a> {
 
     fn resolve_function(&mut self,
                         rib_kind: RibKind,
-                        optional_declaration: Option<P<FnDecl>>,
+                        optional_declaration: Option<&FnDecl>,
                         type_parameters: TypeParameters,
-                        block: P<Block>) {
+                        block: &Block) {
         // Create a value rib for the function.
         let function_value_rib = Rib::new(rib_kind);
         self.value_ribs.borrow_mut().push(function_value_rib);
@@ -4357,7 +4362,7 @@ impl<'a> Resolver<'a> {
     fn resolve_struct(&mut self,
                       id: NodeId,
                       generics: &Generics,
-                      super_struct: Option<P<Ty>>,
+                      super_struct: &Option<P<Ty>>,
                       fields: &[StructField]) {
         // If applicable, create a rib for the type parameters.
         self.with_type_parameter_rib(HasTypeParameters(generics,
@@ -4370,8 +4375,8 @@ impl<'a> Resolver<'a> {
             this.resolve_where_clause(&generics.where_clause);
 
             // Resolve the super struct.
-            match super_struct {
-                Some(t) => match t.node {
+            match *super_struct {
+                Some(ref t) => match t.node {
                     TyPath(ref path, None, path_id) => {
                         match this.resolve_path(id, path, TypeNS, true) {
                             Some((DefTy(def_id), lp)) if this.structs.contains_key(&def_id) => {
@@ -4489,7 +4494,7 @@ impl<'a> Resolver<'a> {
                 this.with_current_self_type(self_type, |this| {
                     for impl_item in impl_items.iter() {
                         match *impl_item {
-                            MethodImplItem(method) => {
+                            MethodImplItem(ref method) => {
                                 // If this is a trait impl, ensure the method
                                 // exists in trait
                                 this.check_trait_item(method.pe_ident(),
@@ -4500,7 +4505,7 @@ impl<'a> Resolver<'a> {
                                 this.resolve_method(
                                     MethodRibKind(id,
                                                   ProvidedMethod(method.id)),
-                                    &*method);
+                                    &**method);
                             }
                         }
                     }
@@ -4738,7 +4743,7 @@ impl<'a> Resolver<'a> {
                 });
             }
 
-            TyClosure(c) | TyProc(c) => {
+            TyClosure(ref c) | TyProc(ref c) => {
                 self.resolve_type_parameter_bounds(ty.id, &c.bounds,
                                                    TraitBoundingTypeParameter);
                 visit::walk_ty(self, ty);
@@ -4775,7 +4780,7 @@ impl<'a> Resolver<'a> {
                     let renamed = mtwt::resolve(ident);
 
                     match self.resolve_bare_identifier_pattern(ident, pattern.span) {
-                        FoundStructOrEnumVariant(def, lp)
+                        FoundStructOrEnumVariant(ref def, lp)
                                 if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
                                     struct or enum variant",
@@ -4785,7 +4790,7 @@ impl<'a> Resolver<'a> {
                                 pattern,
                                 binding_mode,
                                 "an enum variant");
-                            self.record_def(pattern.id, (def, lp));
+                            self.record_def(pattern.id, (def.clone(), lp));
                         }
                         FoundStructOrEnumVariant(..) => {
                             self.resolve_error(
@@ -4795,7 +4800,7 @@ impl<'a> Resolver<'a> {
                                          scope",
                                         token::get_name(renamed)).as_slice());
                         }
-                        FoundConst(def, lp) if mode == RefutableMode => {
+                        FoundConst(ref def, lp) if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
                                     constant",
                                    token::get_name(renamed));
@@ -4804,7 +4809,7 @@ impl<'a> Resolver<'a> {
                                 pattern,
                                 binding_mode,
                                 "a constant");
-                            self.record_def(pattern.id, (def, lp));
+                            self.record_def(pattern.id, (def.clone(), lp));
                         }
                         FoundConst(..) => {
                             self.resolve_error(pattern.span,
@@ -5024,7 +5029,7 @@ impl<'a> Resolver<'a> {
         if path.segments.len() > 1 {
             let def = self.resolve_module_relative_path(path, namespace);
             match (def, unqualified_def) {
-                (Some((d, _)), Some((ud, _))) if d == ud => {
+                (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
                     self.session
                         .add_lint(lint::builtin::UNNECESSARY_QUALIFICATION,
                                   id,
@@ -5386,8 +5391,8 @@ impl<'a> Resolver<'a> {
                                                     -> Option<(Path, NodeId, FallbackChecks)> {
             match t.node {
                 TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)),
-                TyPtr(mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
-                TyRptr(_, mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
+                TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
+                TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
                 // This doesn't handle the remaining `Ty` variants as they are not
                 // that commonly the self_type, it might be interesting to provide
                 // support for those in future.
@@ -5647,12 +5652,12 @@ impl<'a> Resolver<'a> {
                 visit::walk_expr(self, expr);
             }
 
-            ExprFnBlock(_, fn_decl, block) |
-            ExprProc(fn_decl, block) |
-            ExprUnboxedFn(_, _, fn_decl, block) => {
+            ExprFnBlock(_, ref fn_decl, ref block) |
+            ExprProc(ref fn_decl, ref block) |
+            ExprUnboxedFn(_, _, ref fn_decl, ref block) => {
                 self.resolve_function(FunctionRibKind(expr.id, block.id),
-                                      Some(fn_decl), NoTypeParameters,
-                                      block);
+                                      Some(&**fn_decl), NoTypeParameters,
+                                      &**block);
             }
 
             ExprStruct(ref path, _, _) => {
diff --git a/src/librustc/middle/save/mod.rs b/src/librustc/middle/save/mod.rs
index 1d4050c71b1..04e04efd93c 100644
--- a/src/librustc/middle/save/mod.rs
+++ b/src/librustc/middle/save/mod.rs
@@ -35,7 +35,6 @@ use middle::ty;
 use middle::typeck;
 
 use std::cell::Cell;
-use std::gc::Gc;
 use std::io;
 use std::io::File;
 use std::io::fs;
@@ -54,6 +53,7 @@ use syntax::owned_slice::OwnedSlice;
 use syntax::visit;
 use syntax::visit::Visitor;
 use syntax::print::pprust::{path_to_string,ty_to_string};
+use syntax::ptr::P;
 
 use middle::save::span_utils::SpanUtils;
 use middle::save::recorder::Recorder;
@@ -289,9 +289,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                 NodeItem(item) => {
                     scope_id = item.id;
                     match item.node {
-                        ast::ItemImpl(_, _, ty, _) => {
+                        ast::ItemImpl(_, _, ref ty, _) => {
                             let mut result = String::from_str("<");
-                            result.push_str(ty_to_string(&*ty).as_slice());
+                            result.push_str(ty_to_string(&**ty).as_slice());
 
                             match ty::trait_of_item(&self.analysis.ty_cx,
                                                     ast_util::local_def(method.id)) {
@@ -466,9 +466,9 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
 
     fn process_fn(&mut self,
                   item: &ast::Item,
-                  decl: ast::P<ast::FnDecl>,
+                  decl: &ast::FnDecl,
                   ty_params: &ast::Generics,
-                  body: ast::P<ast::Block>) {
+                  body: &ast::Block) {
         let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
 
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Fn);
@@ -494,7 +494,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
 
     fn process_static(&mut self,
                       item: &ast::Item,
-                      typ: ast::P<ast::Ty>,
+                      typ: &ast::Ty,
                       mt: ast::Mutability,
                       expr: &ast::Expr)
     {
@@ -611,7 +611,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                     item: &ast::Item,
                     type_parameters: &ast::Generics,
                     trait_ref: &Option<ast::TraitRef>,
-                    typ: ast::P<ast::Ty>,
+                    typ: &ast::Ty,
                     impl_items: &Vec<ast::ImplItem>) {
         match typ.node {
             ast::TyPath(ref path, _, id) => {
@@ -643,8 +643,8 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
         self.process_generic_params(type_parameters, item.span, "", item.id);
         for impl_item in impl_items.iter() {
             match *impl_item {
-                ast::MethodImplItem(method) => {
-                    visit::walk_method_helper(self, &*method)
+                ast::MethodImplItem(ref method) => {
+                    visit::walk_method_helper(self, &**method)
                 }
             }
         }
@@ -833,7 +833,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                           ex: &ast::Expr,
                           path: &ast::Path,
                           fields: &Vec<ast::Field>,
-                          base: &Option<Gc<ast::Expr>>) {
+                          base: &Option<P<ast::Expr>>) {
         if generated_code(path.span) {
             return
         }
@@ -883,7 +883,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
 
     fn process_method_call(&mut self,
                            ex: &ast::Expr,
-                           args: &Vec<Gc<ast::Expr>>) {
+                           args: &Vec<P<ast::Expr>>) {
         let method_map = self.analysis.ty_cx.method_map.borrow();
         let method_callee = method_map.get(&typeck::MethodCall::expr(ex.id));
         let (def_id, decl_id) = match method_callee.origin {
@@ -1010,7 +1010,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
                 self.collected_paths.push((p.id, path, immut, recorder::VarRef));
                 match *optional_subpattern {
                     None => {}
-                    Some(subpattern) => self.visit_pat(&*subpattern),
+                    Some(ref subpattern) => self.visit_pat(&**subpattern)
                 }
             }
             _ => visit::walk_pat(self, p)
@@ -1025,28 +1025,28 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
         }
 
         match item.node {
-            ast::ItemFn(decl, _, _, ref ty_params, body) =>
-                self.process_fn(item, decl, ty_params, body),
-            ast::ItemStatic(typ, mt, expr) =>
-                self.process_static(item, typ, mt, &*expr),
-            ast::ItemStruct(def, ref ty_params) => self.process_struct(item, &*def, ty_params),
+            ast::ItemFn(ref decl, _, _, ref ty_params, ref body) =>
+                self.process_fn(item, &**decl, ty_params, &**body),
+            ast::ItemStatic(ref typ, mt, ref expr) =>
+                self.process_static(item, &**typ, mt, &**expr),
+            ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
             ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
             ast::ItemImpl(ref ty_params,
                           ref trait_ref,
-                          typ,
+                          ref typ,
                           ref impl_items) => {
                 self.process_impl(item,
                                   ty_params,
                                   trait_ref,
-                                  typ,
+                                  &**typ,
                                   impl_items)
             }
             ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) =>
                 self.process_trait(item, generics, trait_refs, methods),
             ast::ItemMod(ref m) => self.process_mod(item, m),
-            ast::ItemTy(ty, ref ty_params) => {
+            ast::ItemTy(ref ty, ref ty_params) => {
                 let qualname = self.analysis.ty_cx.map.path_to_string(item.id);
-                let value = ty_to_string(&*ty);
+                let value = ty_to_string(&**ty);
                 let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
                 self.fmt.typedef_str(item.span,
                                      sub_span,
@@ -1054,7 +1054,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                      qualname.as_slice(),
                                      value.as_slice());
 
-                self.visit_ty(&*ty);
+                self.visit_ty(&**ty);
                 self.process_generic_params(ty_params, item.span, qualname.as_slice(), item.id);
             },
             ast::ItemMac(_) => (),
@@ -1073,8 +1073,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 }
             }
             match param.default {
-                Some(ty) => self.visit_ty(&*ty),
-                None => (),
+                Some(ref ty) => self.visit_ty(&**ty),
+                None => {}
             }
         }
     }
@@ -1139,7 +1139,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                             qualname,
                                             method_type.id);
             }
-            ast::ProvidedMethod(method) => self.process_method(&*method),
+            ast::ProvidedMethod(ref method) => self.process_method(&**method)
         }
     }
 
@@ -1269,7 +1269,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
         }
 
         match ex.node {
-            ast::ExprCall(_f, ref _args) => {
+            ast::ExprCall(ref _f, ref _args) => {
                 // Don't need to do anything for function calls,
                 // because just walking the callee path does what we want.
                 visit::walk_expr(self, ex);
@@ -1278,14 +1278,14 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
             ast::ExprStruct(ref path, ref fields, ref base) =>
                 self.process_struct_lit(ex, path, fields, base),
             ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
-            ast::ExprField(sub_ex, ident, _) => {
+            ast::ExprField(ref sub_ex, ident, _) => {
                 if generated_code(sub_ex.span) {
                     return
                 }
 
-                self.visit_expr(&*sub_ex);
+                self.visit_expr(&**sub_ex);
 
-                let t = ty::expr_ty_adjusted(&self.analysis.ty_cx, &*sub_ex);
+                let t = ty::expr_ty_adjusted(&self.analysis.ty_cx, &**sub_ex);
                 let t_box = ty::get(t);
                 match t_box.sty {
                     ty::ty_struct(def_id, _) => {
@@ -1306,14 +1306,14 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                             "Expected struct type, but not ty_struct"),
                 }
             },
-            ast::ExprTupField(sub_ex, idx, _) => {
+            ast::ExprTupField(ref sub_ex, idx, _) => {
                 if generated_code(sub_ex.span) {
                     return
                 }
 
-                self.visit_expr(&*sub_ex);
+                self.visit_expr(&**sub_ex);
 
-                let t = ty::expr_ty_adjusted(&self.analysis.ty_cx, &*sub_ex);
+                let t = ty::expr_ty_adjusted(&self.analysis.ty_cx, &**sub_ex);
                 let t_box = ty::get(t);
                 match t_box.sty {
                     ty::ty_struct(def_id, _) => {
@@ -1334,7 +1334,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                                             "Expected struct type, but not ty_struct"),
                 }
             },
-            ast::ExprFnBlock(_, decl, body) => {
+            ast::ExprFnBlock(_, ref decl, ref body) => {
                 if generated_code(body.span) {
                     return
                 }
@@ -1349,7 +1349,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
                 self.visit_ty(&*decl.output);
 
                 // walk the body
-                self.nest(ex.id, |v| v.visit_block(&*body));
+                self.nest(ex.id, |v| v.visit_block(&**body));
             },
             _ => {
                 visit::walk_expr(self, ex)
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index dd0668b8fa0..755ff991fb6 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -218,24 +218,20 @@ use util::ppaux::{Repr, vec_map_to_string};
 
 use std;
 use std::collections::HashMap;
-use std::gc::{Gc};
 use std::rc::Rc;
 use syntax::ast;
-use syntax::ast::Ident;
+use syntax::ast::{DUMMY_NODE_ID, Ident};
 use syntax::codemap::Span;
 use syntax::fold::Folder;
+use syntax::ptr::P;
 
-struct ConstantExpr<'a, 'tcx: 'a>(&'a ty::ctxt<'tcx>, Gc<ast::Expr>);
+struct ConstantExpr<'a>(&'a ast::Expr);
 
-impl<'a, 'tcx> Eq for ConstantExpr<'a, 'tcx> {
-    fn assert_receiver_is_total_eq(&self) {}
-}
-
-impl<'a, 'tcx> PartialEq for ConstantExpr<'a, 'tcx> {
-    fn eq(&self, other: &ConstantExpr<'a, 'tcx>) -> bool {
-        let &ConstantExpr(tcx, expr) = self;
-        let &ConstantExpr(_, other_expr) = other;
-        match const_eval::compare_lit_exprs(tcx, &*expr, &*other_expr) {
+impl<'a> ConstantExpr<'a> {
+    fn eq(self, other: ConstantExpr<'a>, tcx: &ty::ctxt) -> bool {
+        let ConstantExpr(expr) = self;
+        let ConstantExpr(other_expr) = other;
+        match const_eval::compare_lit_exprs(tcx, expr, other_expr) {
             Some(val1) => val1 == 0,
             None => fail!("compare_list_exprs: type mismatch"),
         }
@@ -243,30 +239,44 @@ impl<'a, 'tcx> PartialEq for ConstantExpr<'a, 'tcx> {
 }
 
 // An option identifying a branch (either a literal, an enum variant or a range)
-#[deriving(Eq, PartialEq)]
-enum Opt<'blk, 'tcx: 'blk> {
-    ConstantValue(ConstantExpr<'blk, 'tcx>),
-    ConstantRange(ConstantExpr<'blk, 'tcx>, ConstantExpr<'blk, 'tcx>),
+enum Opt<'a> {
+    ConstantValue(ConstantExpr<'a>),
+    ConstantRange(ConstantExpr<'a>, ConstantExpr<'a>),
     Variant(ty::Disr, Rc<adt::Repr>, ast::DefId),
     SliceLengthEqual(uint),
     SliceLengthGreaterOrEqual(/* prefix length */ uint, /* suffix length */ uint),
 }
 
-impl<'blk, 'tcx> Opt<'blk, 'tcx> {
-    fn trans(&self, mut bcx: Block<'blk, 'tcx>) -> OptResult<'blk, 'tcx> {
+impl<'a> Opt<'a> {
+    fn eq(&self, other: &Opt<'a>, tcx: &ty::ctxt) -> bool {
+        match (self, other) {
+            (&ConstantValue(a), &ConstantValue(b)) => a.eq(b, tcx),
+            (&ConstantRange(a1, a2), &ConstantRange(b1, b2)) => {
+                a1.eq(b1, tcx) && a2.eq(b2, tcx)
+            }
+            (&Variant(a_disr, ref a_repr, a_def), &Variant(b_disr, ref b_repr, b_def)) => {
+                a_disr == b_disr && *a_repr == *b_repr && a_def == b_def
+            }
+            (&SliceLengthEqual(a), &SliceLengthEqual(b)) => a == b,
+            (&SliceLengthGreaterOrEqual(a1, a2), &SliceLengthGreaterOrEqual(b1, b2)) => {
+                a1 == b1 && a2 == b2
+            }
+            _ => false
+        }
+    }
+
+    fn trans<'blk, 'tcx>(&self, mut bcx: Block<'blk, 'tcx>) -> OptResult<'blk, 'tcx> {
         let _icx = push_ctxt("match::trans_opt");
         let ccx = bcx.ccx();
         match *self {
-            ConstantValue(ConstantExpr(_, lit_expr)) => {
+            ConstantValue(ConstantExpr(lit_expr)) => {
                 let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id);
                 let (llval, _, _) = consts::const_expr(ccx, &*lit_expr, true);
                 let lit_datum = immediate_rvalue(llval, lit_ty);
                 let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
                 SingleResult(Result::new(bcx, lit_datum.val))
             }
-            ConstantRange(
-                ConstantExpr(_, ref l1),
-                ConstantExpr(_, ref l2)) => {
+            ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2)) => {
                 let (l1, _, _) = consts::const_expr(ccx, &**l1, true);
                 let (l2, _, _) = consts::const_expr(ccx, &**l2, true);
                 RangeResult(Result::new(bcx, l1), Result::new(bcx, l2))
@@ -325,9 +335,9 @@ pub struct BindingInfo {
 
 type BindingsMap = HashMap<Ident, BindingInfo>;
 
-struct ArmData<'a, 'blk, 'tcx: 'blk> {
+struct ArmData<'p, 'blk, 'tcx: 'blk> {
     bodycx: Block<'blk, 'tcx>,
-    arm: &'a ast::Arm,
+    arm: &'p ast::Arm,
     bindings_map: BindingsMap
 }
 
@@ -337,13 +347,13 @@ struct ArmData<'a, 'blk, 'tcx: 'blk> {
  * 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.
  */
-struct Match<'a, 'blk: 'a, 'tcx: 'blk> {
-    pats: Vec<Gc<ast::Pat>>,
-    data: &'a ArmData<'a, 'blk, 'tcx>,
+struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
+    pats: Vec<&'p ast::Pat>,
+    data: &'a ArmData<'p, 'blk, 'tcx>,
     bound_ptrs: Vec<(Ident, ValueRef)>
 }
 
-impl<'a, 'blk, 'tcx> Repr for Match<'a, 'blk, 'tcx> {
+impl<'a, 'p, 'blk, 'tcx> Repr for Match<'a, 'p, 'blk, 'tcx> {
     fn repr(&self, tcx: &ty::ctxt) -> String {
         if tcx.sess.verbose() {
             // for many programs, this just take too long to serialize
@@ -364,11 +374,11 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool {
     return false;
 }
 
-fn expand_nested_bindings<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                          m: &'a [Match<'a, 'blk, 'tcx>],
-                                          col: uint,
-                                          val: ValueRef)
-                                          -> Vec<Match<'a, 'blk, 'tcx>> {
+fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                              m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                              col: uint,
+                                              val: ValueRef)
+                                              -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
     debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -381,9 +391,9 @@ fn expand_nested_bindings<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let mut pat = *br.pats.get(col);
         loop {
             pat = match pat.node {
-                ast::PatIdent(_, ref path, Some(inner)) => {
+                ast::PatIdent(_, ref path, Some(ref inner)) => {
                     bound_ptrs.push((path.node, val));
-                    inner.clone()
+                    &**inner
                 },
                 _ => break
             }
@@ -399,15 +409,15 @@ fn expand_nested_bindings<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }).collect()
 }
 
-type EnterPatterns<'a> = |&[Gc<ast::Pat>]|: 'a -> Option<Vec<Gc<ast::Pat>>>;
+type EnterPatterns<'a> = <'p> |&[&'p ast::Pat]|: 'a -> Option<Vec<&'p ast::Pat>>;
 
-fn enter_match<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                               dm: &DefMap,
-                               m: &'a [Match<'a, 'blk, 'tcx>],
-                               col: uint,
-                               val: ValueRef,
-                               e: EnterPatterns)
-                               -> Vec<Match<'a, 'blk, 'tcx>> {
+fn enter_match<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                   dm: &DefMap,
+                                   m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                   col: uint,
+                                   val: ValueRef,
+                                   e: EnterPatterns)
+                                   -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
     debug!("enter_match(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -425,7 +435,7 @@ fn enter_match<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         bound_ptrs.push((path.node, val));
                     }
                 }
-                ast::PatVec(ref before, Some(slice), ref after) => {
+                ast::PatVec(ref before, Some(ref slice), ref after) => {
                     match slice.node {
                         ast::PatIdent(_, ref path, None) => {
                             let subslice_val = bind_subslice_pat(
@@ -438,7 +448,6 @@ fn enter_match<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
                 _ => {}
             }
-
             Match {
                 pats: pats,
                 data: br.data,
@@ -448,12 +457,12 @@ fn enter_match<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }).collect()
 }
 
-fn enter_default<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 dm: &DefMap,
-                                 m: &'a [Match<'a, 'blk, 'tcx>],
-                                 col: uint,
-                                 val: ValueRef)
-                                 -> Vec<Match<'a, 'blk, 'tcx>> {
+fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                     dm: &DefMap,
+                                     m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                     col: uint,
+                                     val: ValueRef)
+                                     -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
     debug!("enter_default(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -499,16 +508,16 @@ fn enter_default<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// takes the complete row of patterns rather than just the first one.
 /// Also, most of the enter_() family functions have been unified with
 /// the check_match specialization step.
-fn enter_opt<'a, 'blk, 'tcx>(
+fn enter_opt<'a, 'p, 'blk, 'tcx>(
              bcx: Block<'blk, 'tcx>,
              _: ast::NodeId,
              dm: &DefMap,
-             m: &'a [Match<'a, 'blk, 'tcx>],
+             m: &[Match<'a, 'p, 'blk, 'tcx>],
              opt: &Opt,
              col: uint,
              variant_size: uint,
              val: ValueRef)
-             -> Vec<Match<'a, 'blk, 'tcx>> {
+             -> Vec<Match<'a, 'p, 'blk, 'tcx>> {
     debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -518,10 +527,10 @@ fn enter_opt<'a, 'blk, 'tcx>(
     let _indenter = indenter();
 
     let ctor = match opt {
-        &ConstantValue(ConstantExpr(_, expr)) => check_match::ConstantValue(
+        &ConstantValue(ConstantExpr(expr)) => check_match::ConstantValue(
             const_eval::eval_const_expr(bcx.tcx(), &*expr)
         ),
-        &ConstantRange(ConstantExpr(_, lo), ConstantExpr(_, hi)) => check_match::ConstantRange(
+        &ConstantRange(ConstantExpr(lo), ConstantExpr(hi)) => check_match::ConstantRange(
             const_eval::eval_const_expr(bcx.tcx(), &*lo),
             const_eval::eval_const_expr(bcx.tcx(), &*hi)
         ),
@@ -542,51 +551,41 @@ fn enter_opt<'a, 'blk, 'tcx>(
 // Returns the options in one column of matches. An option is something that
 // needs to be conditionally matched at runtime; for example, the discriminant
 // on a set of enum variants or a literal.
-fn get_branches<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                            m: &[Match], col: uint)
-                            -> Vec<Opt<'blk, 'tcx>> {
-    let ccx = bcx.ccx();
-
-    fn add_to_set<'blk, 'tcx>(set: &mut Vec<Opt<'blk, 'tcx>>, opt: Opt<'blk, 'tcx>) {
-        if !set.contains(&opt) {
-            set.push(opt);
-        }
-    }
+fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                    m: &[Match<'a, 'p, 'blk, 'tcx>], col: uint)
+                                    -> Vec<Opt<'p>> {
+    let tcx = bcx.tcx();
 
-    let mut found = Vec::new();
+    let mut found: Vec<Opt> = vec![];
     for (i, br) in m.iter().enumerate() {
         let cur = *br.pats.get(col);
-        match cur.node {
-            ast::PatLit(l) => {
-                add_to_set(&mut found, ConstantValue(ConstantExpr(ccx.tcx(), l)));
-            }
+        let opt = match cur.node {
+            ast::PatLit(ref l) => ConstantValue(ConstantExpr(&**l)),
             ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
                 // This is either an enum variant or a variable binding.
-                let opt_def = ccx.tcx().def_map.borrow().find_copy(&cur.id);
+                let opt_def = tcx.def_map.borrow().find_copy(&cur.id);
                 match opt_def {
                     Some(def::DefVariant(enum_id, var_id, _)) => {
-                        let variant = ty::enum_variant_with_id(ccx.tcx(), enum_id, var_id);
-                        add_to_set(&mut found, Variant(
-                            variant.disr_val,
-                            adt::represent_node(bcx, cur.id), var_id
-                        ));
+                        let variant = ty::enum_variant_with_id(tcx, enum_id, var_id);
+                        Variant(variant.disr_val, adt::represent_node(bcx, cur.id), var_id)
                     }
-                    _ => {}
+                    _ => continue
                 }
             }
-            ast::PatRange(l1, l2) => {
-                add_to_set(&mut found, ConstantRange(
-                    ConstantExpr(ccx.tcx(), l1),
-                    ConstantExpr(ccx.tcx(), l2)
-                ));
+            ast::PatRange(ref l1, ref l2) => {
+                ConstantRange(ConstantExpr(&**l1), ConstantExpr(&**l2))
             }
             ast::PatVec(ref before, None, ref after) => {
-                add_to_set(&mut found, SliceLengthEqual(before.len() + after.len()));
+                SliceLengthEqual(before.len() + after.len())
             }
             ast::PatVec(ref before, Some(_), ref after) => {
-                add_to_set(&mut found, SliceLengthGreaterOrEqual(before.len(), after.len()));
+                SliceLengthGreaterOrEqual(before.len(), after.len())
             }
-            _ => {}
+            _ => continue
+        };
+
+        if !found.iter().any(|x| x.eq(&opt, tcx)) {
+            found.push(opt);
         }
     }
     found
@@ -870,14 +869,14 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     bcx
 }
 
-fn compile_guard<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 guard_expr: &ast::Expr,
-                                 data: &ArmData,
-                                 m: &'a [Match<'a, 'blk, 'tcx>],
-                                 vals: &[ValueRef],
-                                 chk: &FailureHandler,
-                                 has_genuine_default: bool)
-                                 -> Block<'blk, 'tcx> {
+fn compile_guard<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                     guard_expr: &ast::Expr,
+                                     data: &ArmData,
+                                     m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                     vals: &[ValueRef],
+                                     chk: &FailureHandler,
+                                     has_genuine_default: bool)
+                                     -> Block<'blk, 'tcx> {
     debug!("compile_guard(bcx={}, guard_expr={}, m={}, vals={})",
            bcx.to_str(),
            bcx.expr_to_string(guard_expr),
@@ -918,11 +917,11 @@ fn compile_guard<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     })
 }
 
-fn compile_submatch<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    m: &'a [Match<'a, 'blk, 'tcx>],
-                                    vals: &[ValueRef],
-                                    chk: &FailureHandler,
-                                    has_genuine_default: bool) {
+fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                        m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                        vals: &[ValueRef],
+                                        chk: &FailureHandler,
+                                        has_genuine_default: bool) {
     debug!("compile_submatch(bcx={}, m={}, vals={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -978,13 +977,13 @@ fn compile_submatch<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-fn compile_submatch_continue<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                                             m: &'a [Match<'a, 'blk, 'tcx>],
-                                             vals: &[ValueRef],
-                                             chk: &FailureHandler,
-                                             col: uint,
-                                             val: ValueRef,
-                                             has_genuine_default: bool) {
+fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
+                                                 m: &[Match<'a, 'p, 'blk, 'tcx>],
+                                                 vals: &[ValueRef],
+                                                 chk: &FailureHandler,
+                                                 col: uint,
+                                                 val: ValueRef,
+                                                 has_genuine_default: bool) {
     let fcx = bcx.fcx;
     let tcx = bcx.tcx();
     let dm = &tcx.def_map;
@@ -994,9 +993,11 @@ fn compile_submatch_continue<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
     // Find a real id (we're adding placeholder wildcard patterns, but
     // each column is guaranteed to have at least one real pattern)
-    let pat_id = m.iter().map(|br| br.pats.get(col).id).find(|&id| id != 0).unwrap_or(0);
+    let pat_id = m.iter().map(|br| br.pats.get(col).id)
+                         .find(|&id| id != DUMMY_NODE_ID)
+                         .unwrap_or(DUMMY_NODE_ID);
 
-    let left_ty = if pat_id == 0 {
+    let left_ty = if pat_id == DUMMY_NODE_ID {
         ty::mk_nil()
     } else {
         node_id_type(bcx, pat_id)
@@ -1264,7 +1265,7 @@ impl euv::Delegate for ReassignmentChecker {
     }
 }
 
-fn create_bindings_map(bcx: Block, pat: Gc<ast::Pat>,
+fn create_bindings_map(bcx: Block, pat: &ast::Pat,
                       discr: &ast::Expr, body: &ast::Expr) -> BindingsMap {
     // Create the bindings map, which is a mapping from each binding name
     // to an alloca() that will be the value for that local variable.
@@ -1345,14 +1346,17 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
     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), discr_expr, &*arm.body)
+        bindings_map: create_bindings_map(bcx, &**arm.pats.get(0), discr_expr, &*arm.body)
     }).collect();
 
     let mut static_inliner = StaticInliner::new(scope_cx.tcx());
+    let arm_pats: Vec<Vec<P<ast::Pat>>> = arm_datas.iter().map(|arm_data| {
+        arm_data.arm.pats.iter().map(|p| static_inliner.fold_pat((*p).clone())).collect()
+    }).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![static_inliner.fold_pat(p)],
+    for (arm_data, pats) in arm_datas.iter().zip(arm_pats.iter()) {
+        matches.extend(pats.iter().map(|p| Match {
+            pats: vec![&**p],
             data: arm_data,
             bound_ptrs: Vec::new(),
         }));
@@ -1404,11 +1408,25 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("match::store_local");
     let mut bcx = bcx;
     let tcx = bcx.tcx();
-    let pat = local.pat;
-    let opt_init_expr = local.init;
+    let pat = &*local.pat;
+
+    fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
+                                       pat: &ast::Pat)
+                                       -> Block<'blk, 'tcx> {
+        // 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, _, path1| {
+            let scope = cleanup::var_scope(tcx, p_id);
+            bcx = mk_binding_alloca(
+                bcx, p_id, &path1.node, BindLocal, scope, (),
+                |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
+        });
+        bcx
+    }
 
-    return match opt_init_expr {
-        Some(init_expr) => {
+    match local.init {
+        Some(ref init_expr) => {
             // Optimize the "let x = expr" case. This just writes
             // the result of evaluating `expr` directly into the alloca
             // for `x`. Often the general path results in similar or the
@@ -1424,7 +1442,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     let var_scope = cleanup::var_scope(tcx, local.id);
                     return mk_binding_alloca(
                         bcx, pat.id, ident, BindLocal, var_scope, (),
-                        |(), bcx, v, _| expr::trans_into(bcx, &*init_expr,
+                        |(), bcx, v, _| expr::trans_into(bcx, &**init_expr,
                                                          expr::SaveIn(v)));
                 }
 
@@ -1433,8 +1451,8 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
             // General path.
             let init_datum =
-                unpack_datum!(bcx, expr::trans_to_lvalue(bcx, &*init_expr, "let"));
-            if ty::type_is_bot(expr_ty(bcx, &*init_expr)) {
+                unpack_datum!(bcx, expr::trans_to_lvalue(bcx, &**init_expr, "let"));
+            if ty::type_is_bot(expr_ty(bcx, &**init_expr)) {
                 create_dummy_locals(bcx, pat)
             } else {
                 if bcx.sess().asm_comments() {
@@ -1447,26 +1465,11 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         None => {
             create_dummy_locals(bcx, pat)
         }
-    };
-
-    fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                                       pat: Gc<ast::Pat>)
-                                       -> Block<'blk, 'tcx> {
-        // 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, _, path1| {
-                let scope = cleanup::var_scope(tcx, p_id);
-                bcx = mk_binding_alloca(
-                    bcx, p_id, &path1.node, BindLocal, scope, (),
-                    |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx });
-            });
-        bcx
     }
 }
 
 pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                             pat: Gc<ast::Pat>,
+                             pat: &ast::Pat,
                              arg: Datum<Rvalue>,
                              arg_scope: cleanup::ScopeId)
                              -> Block<'blk, 'tcx> {
@@ -1520,7 +1523,7 @@ pub fn store_arg<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 /// Generates code for the pattern binding in a `for` loop like
 /// `for <pat> in <expr> { ... }`.
 pub fn store_for_loop_binding<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                          pat: Gc<ast::Pat>,
+                                          pat: &ast::Pat,
                                           llvalue: ValueRef,
                                           body_scope: cleanup::ScopeId)
                                           -> Block<'blk, 'tcx> {
@@ -1573,7 +1576,7 @@ fn mk_binding_alloca<'blk, 'tcx, A>(bcx: Block<'blk, 'tcx>,
 }
 
 fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    pat: Gc<ast::Pat>,
+                                    pat: &ast::Pat,
                                     val: ValueRef,
                                     binding_mode: IrrefutablePatternBindingMode,
                                     cleanup_scope: cleanup::ScopeId)
@@ -1611,7 +1614,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let tcx = bcx.tcx();
     let ccx = bcx.ccx();
     match pat.node {
-        ast::PatIdent(pat_binding_mode, ref path1, inner) => {
+        ast::PatIdent(pat_binding_mode, ref path1, ref inner) => {
             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
@@ -1637,8 +1640,8 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     });
             }
 
-            for &inner_pat in inner.iter() {
-                bcx = bind_irrefutable_pat(bcx, inner_pat, val,
+            for inner_pat in inner.iter() {
+                bcx = bind_irrefutable_pat(bcx, &**inner_pat, val,
                                            binding_mode, cleanup_scope);
             }
         }
@@ -1655,9 +1658,9 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                     vinfo.disr_val,
                                                     val);
                     for sub_pat in sub_pats.iter() {
-                        for (i, argval) in args.vals.iter().enumerate() {
-                            bcx = bind_irrefutable_pat(bcx, *sub_pat.get(i),
-                                                       *argval, binding_mode,
+                        for (i, &argval) in args.vals.iter().enumerate() {
+                            bcx = bind_irrefutable_pat(bcx, &**sub_pat.get(i),
+                                                       argval, binding_mode,
                                                        cleanup_scope);
                         }
                     }
@@ -1674,7 +1677,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             for (i, elem) in elems.iter().enumerate() {
                                 let fldptr = adt::trans_field_ptr(bcx, &*repr,
                                                                   val, 0, i);
-                                bcx = bind_irrefutable_pat(bcx, *elem,
+                                bcx = bind_irrefutable_pat(bcx, &**elem,
                                                            fldptr, binding_mode,
                                                            cleanup_scope);
                             }
@@ -1695,7 +1698,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
                     let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val,
                                                       discr, ix);
-                    bcx = bind_irrefutable_pat(bcx, f.pat, fldptr,
+                    bcx = bind_irrefutable_pat(bcx, &*f.pat, fldptr,
                                                binding_mode, cleanup_scope);
                 }
             })
@@ -1704,17 +1707,17 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             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);
-                bcx = bind_irrefutable_pat(bcx, *elem, fldptr,
+                bcx = bind_irrefutable_pat(bcx, &**elem, fldptr,
                                            binding_mode, cleanup_scope);
             }
         }
-        ast::PatBox(inner) => {
+        ast::PatBox(ref inner) => {
             let llbox = Load(bcx, val);
-            bcx = bind_irrefutable_pat(bcx, inner, llbox, binding_mode, cleanup_scope);
+            bcx = bind_irrefutable_pat(bcx, &**inner, llbox, binding_mode, cleanup_scope);
         }
-        ast::PatRegion(inner) => {
+        ast::PatRegion(ref inner) => {
             let loaded_val = Load(bcx, val);
-            bcx = bind_irrefutable_pat(bcx, inner, loaded_val, binding_mode, cleanup_scope);
+            bcx = bind_irrefutable_pat(bcx, &**inner, loaded_val, binding_mode, cleanup_scope);
         }
         ast::PatVec(ref before, ref slice, ref after) => {
             let pat_ty = node_id_type(bcx, pat.id);
@@ -1733,8 +1736,8 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 .chain(slice.iter())
                 .chain(after.iter())
                 .zip(extracted.vals.move_iter())
-                .fold(bcx, |bcx, (&inner, elem)|
-                    bind_irrefutable_pat(bcx, inner, elem, binding_mode, cleanup_scope)
+                .fold(bcx, |bcx, (inner, elem)|
+                    bind_irrefutable_pat(bcx, &**inner, elem, binding_mode, cleanup_scope)
                 );
         }
         ast::PatMac(..) => {
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 7fb692c270e..c474aab9b26 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -67,10 +67,10 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
         let in_datum = unpack_datum!(bcx, expr::trans(bcx, &**input));
         unpack_result!(bcx, {
             callee::trans_arg_datum(bcx,
-                                   expr_ty(bcx, &**input),
-                                   in_datum,
-                                   cleanup::CustomScope(temp_scope),
-                                   callee::DontAutorefArg)
+                                    expr_ty(bcx, &**input),
+                                    in_datum,
+                                    cleanup::CustomScope(temp_scope),
+                                    callee::DontAutorefArg)
         })
     }).collect::<Vec<_>>().append(ext_inputs.as_slice());
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index c023b7a9534..e86df865118 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1356,7 +1356,7 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
     match tcx.map.find(id) {
         Some(ast_map::NodeItem(i)) => {
             match i.node {
-                ast::ItemFn(_, _, _, _, blk) => {
+                ast::ItemFn(_, _, _, _, ref blk) => {
                     let mut explicit = CheckForNestedReturnsVisitor::explicit();
                     let mut implicit = CheckForNestedReturnsVisitor::implicit();
                     visit::walk_item(&mut explicit, &*i);
@@ -1368,12 +1368,12 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
         }
         Some(ast_map::NodeTraitItem(trait_method)) => {
             match *trait_method {
-                ast::ProvidedMethod(m) => {
+                ast::ProvidedMethod(ref m) => {
                     match m.node {
-                        ast::MethDecl(_, _, _, _, _, _, blk, _) => {
+                        ast::MethDecl(_, _, _, _, _, _, ref blk, _) => {
                             let mut explicit = CheckForNestedReturnsVisitor::explicit();
                             let mut implicit = CheckForNestedReturnsVisitor::implicit();
-                            visit::walk_method_helper(&mut explicit, &*m);
+                            visit::walk_method_helper(&mut explicit, &**m);
                             visit::walk_expr_opt(&mut implicit, &blk.expr);
                             explicit.found || implicit.found
                         }
@@ -1386,11 +1386,11 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
                 }
             }
         }
-        Some(ast_map::NodeImplItem(ref ii)) => {
-            match **ii {
+        Some(ast_map::NodeImplItem(ii)) => {
+            match *ii {
                 ast::MethodImplItem(ref m) => {
                     match m.node {
-                        ast::MethDecl(_, _, _, _, _, _, blk, _) => {
+                        ast::MethDecl(_, _, _, _, _, _, ref blk, _) => {
                             let mut explicit = CheckForNestedReturnsVisitor::explicit();
                             let mut implicit = CheckForNestedReturnsVisitor::implicit();
                             visit::walk_method_helper(&mut explicit, &**m);
@@ -1404,12 +1404,12 @@ fn has_nested_returns(tcx: &ty::ctxt, id: ast::NodeId) -> bool {
         }
         Some(ast_map::NodeExpr(e)) => {
             match e.node {
-                ast::ExprFnBlock(_, _, blk) |
-                ast::ExprProc(_, blk) |
-                ast::ExprUnboxedFn(_, _, _, blk) => {
+                ast::ExprFnBlock(_, _, ref blk) |
+                ast::ExprProc(_, ref blk) |
+                ast::ExprUnboxedFn(_, _, _, ref blk) => {
                     let mut explicit = CheckForNestedReturnsVisitor::explicit();
                     let mut implicit = CheckForNestedReturnsVisitor::implicit();
-                    visit::walk_expr(&mut explicit, &*e);
+                    visit::walk_expr(&mut explicit, e);
                     visit::walk_expr_opt(&mut implicit, &blk.expr);
                     explicit.found || implicit.found
                 }
@@ -1649,7 +1649,7 @@ fn copy_args_to_allocas<'blk, 'tcx>(fcx: &FunctionContext<'blk, 'tcx>,
         // This alloca should be optimized away by LLVM's mem-to-reg pass in
         // the event it's not truly needed.
 
-        bcx = _match::store_arg(bcx, args[i].pat, arg_datum, arg_scope_id);
+        bcx = _match::store_arg(bcx, &*args[i].pat, arg_datum, arg_scope_id);
 
         if fcx.ccx.sess().opts.debuginfo == FullDebugInfo {
             debuginfo::create_argument_metadata(bcx, &args[i]);
@@ -1701,7 +1701,7 @@ fn copy_unboxed_closure_args_to_allocas<'blk, 'tcx>(
                           tuple_element_datum.to_rvalue_datum(bcx,
                                                               "arg"));
         bcx = _match::store_arg(bcx,
-                                args[j].pat,
+                                &*args[j].pat,
                                 tuple_element_datum,
                                 arg_scope_id);
 
@@ -2008,7 +2008,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     if !type_is_zero_size(ccx, result_ty) {
         match args {
             callee::ArgExprs(exprs) => {
-                let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
+                let fields = exprs.iter().map(|x| &**x).enumerate().collect::<Vec<_>>();
                 bcx = expr::trans_adt(bcx, result_ty, disr, fields.as_slice(),
                                       None, expr::SaveIn(llresult));
             }
@@ -2792,15 +2792,15 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     ccx.sess().bug("unexpected variant: required trait method in \
                                    get_item_val()");
                 }
-                ast::ProvidedMethod(m) => {
-                    register_method(ccx, id, &*m)
+                ast::ProvidedMethod(ref m) => {
+                    register_method(ccx, id, &**m)
                 }
             }
         }
 
         ast_map::NodeImplItem(ii) => {
             match *ii {
-                ast::MethodImplItem(m) => register_method(ccx, id, &*m),
+                ast::MethodImplItem(ref m) => register_method(ccx, id, &**m),
             }
         }
 
@@ -3042,9 +3042,10 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
     }
 }
 
-pub fn trans_crate(krate: ast::Crate,
-                   analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
+pub fn trans_crate<'tcx>(analysis: CrateAnalysis<'tcx>)
+                         -> (ty::ctxt<'tcx>, CrateTranslation) {
     let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, name, .. } = analysis;
+    let krate = tcx.map.krate();
 
     // Before we touch LLVM, make sure that multithreading is enabled.
     unsafe {
@@ -3064,7 +3065,7 @@ pub fn trans_crate(krate: ast::Crate,
         }
     }
 
-    let link_meta = link::build_link_meta(&tcx.sess, &krate, name);
+    let link_meta = link::build_link_meta(&tcx.sess, krate, name);
 
     let codegen_units = tcx.sess.opts.cg.codegen_units;
     let shared_ccx = SharedCrateContext::new(link_meta.crate_name.as_slice(),
@@ -3096,7 +3097,7 @@ pub fn trans_crate(krate: ast::Crate,
     }
 
     // Translate the metadata.
-    let metadata = write_metadata(&shared_ccx, &krate);
+    let metadata = write_metadata(&shared_ccx, krate);
 
     if shared_ccx.sess().trans_stats() {
         let stats = shared_ccx.stats();
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 5d66ec0a4b9..878d95773ad 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -53,10 +53,10 @@ use middle::typeck::MethodCall;
 use util::ppaux::Repr;
 use util::ppaux::ty_to_string;
 
-use std::gc::Gc;
 use syntax::abi as synabi;
 use syntax::ast;
 use syntax::ast_map;
+use syntax::ptr::P;
 
 pub struct MethodData {
     pub llfn: ValueRef,
@@ -902,7 +902,7 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub enum CallArgs<'a> {
     // Supply value of arguments as a list of expressions that must be
     // translated. This is used in the common case of `foo(bar, qux)`.
-    ArgExprs(&'a [Gc<ast::Expr>]),
+    ArgExprs(&'a [P<ast::Expr>]),
 
     // Supply value of arguments as a list of LLVM value refs; frequently
     // used with lang items and so forth, when the argument is an internal
@@ -916,12 +916,12 @@ pub enum CallArgs<'a> {
 
     // Supply value of arguments as a list of expressions that must be
     // translated, for overloaded call operators.
-    ArgOverloadedCall(&'a [Gc<ast::Expr>]),
+    ArgOverloadedCall(Vec<&'a ast::Expr>),
 }
 
 fn trans_args_under_call_abi<'blk, 'tcx>(
                              mut bcx: Block<'blk, 'tcx>,
-                             arg_exprs: &[Gc<ast::Expr>],
+                             arg_exprs: &[P<ast::Expr>],
                              fn_ty: ty::t,
                              llargs: &mut Vec<ValueRef>,
                              arg_cleanup_scope: cleanup::ScopeId,
@@ -941,13 +941,13 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
     }
 
     // Now untuple the rest of the arguments.
-    let tuple_expr = arg_exprs[1];
+    let tuple_expr = &arg_exprs[1];
     let tuple_type = node_id_type(bcx, tuple_expr.id);
 
     match ty::get(tuple_type).sty {
         ty::ty_tup(ref field_types) => {
             let tuple_datum = unpack_datum!(bcx,
-                                            expr::trans(bcx, &*tuple_expr));
+                                            expr::trans(bcx, &**tuple_expr));
             let tuple_lvalue_datum =
                 unpack_datum!(bcx,
                               tuple_datum.to_lvalue_datum(bcx,
@@ -982,7 +982,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
 
 fn trans_overloaded_call_args<'blk, 'tcx>(
                               mut bcx: Block<'blk, 'tcx>,
-                              arg_exprs: &[Gc<ast::Expr>],
+                              arg_exprs: Vec<&ast::Expr>,
                               fn_ty: ty::t,
                               llargs: &mut Vec<ValueRef>,
                               arg_cleanup_scope: cleanup::ScopeId,
@@ -991,7 +991,7 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
     // Translate the `self` argument first.
     let arg_tys = ty::ty_fn_args(fn_ty);
     if !ignore_self {
-        let arg_datum = unpack_datum!(bcx, expr::trans(bcx, &*arg_exprs[0]));
+        let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0]));
         llargs.push(unpack_result!(bcx, {
             trans_arg_datum(bcx,
                             *arg_tys.get(0),
@@ -1007,7 +1007,7 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
         ty::ty_tup(ref field_types) => {
             for (i, &field_type) in field_types.iter().enumerate() {
                 let arg_datum =
-                    unpack_datum!(bcx, expr::trans(bcx, &*arg_exprs[i + 1]));
+                    unpack_datum!(bcx, expr::trans(bcx, arg_exprs[i + 1]));
                 llargs.push(unpack_result!(bcx, {
                     trans_arg_datum(bcx,
                                     field_type,
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 4ac9ae64d5a..bbb9ba4bbb6 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -472,7 +472,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
 
     pub fn def(&self, nid: ast::NodeId) -> def::Def {
         match self.tcx().def_map.borrow().find(&nid) {
-            Some(&v) => v,
+            Some(v) => v.clone(),
             None => {
                 self.tcx().sess.bug(format!(
                     "no def associated with node id {:?}", nid).as_slice());
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 8f6a3864b37..576031500b9 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -33,12 +33,12 @@ use middle::ty;
 use util::ppaux::{Repr, ty_to_string};
 
 use std::c_str::ToCStr;
-use std::gc::Gc;
 use std::vec;
 use libc::c_uint;
 use syntax::{ast, ast_util};
+use syntax::ptr::P;
 
-pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: ast::Lit)
+pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
     -> ValueRef {
     let _icx = push_ctxt("trans_lit");
     debug!("const_lit: {}", lit);
@@ -102,7 +102,7 @@ fn first_two<R, S, T>((a, b, _): (R, S, T)) -> (R, S) {
 }
 
 fn const_vec(cx: &CrateContext, e: &ast::Expr,
-             es: &[Gc<ast::Expr>], is_local: bool) -> (ValueRef, Type, bool) {
+             es: &[P<ast::Expr>], is_local: bool) -> (ValueRef, Type, bool) {
     let vec_ty = ty::expr_ty(cx.tcx(), e);
     let unit_ty = ty::sequence_element_type(cx.tcx(), vec_ty);
     let llunitty = type_of::type_of(cx, unit_ty);
@@ -321,7 +321,7 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
 // if it's assigned to a static.
 fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                          is_local: bool) -> (ValueRef, bool) {
-    let map_list = |exprs: &[Gc<ast::Expr>]| {
+    let map_list = |exprs: &[P<ast::Expr>]| {
         exprs.iter().map(|e| first_two(const_expr(cx, &**e, is_local)))
              .fold((Vec::new(), true),
                    |(l, all_inlineable), (val, inlineable)| {
@@ -332,7 +332,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
         let _icx = push_ctxt("const_expr");
         return match e.node {
           ast::ExprLit(ref lit) => {
-              (consts::const_lit(cx, e, (**lit).clone()), true)
+              (consts::const_lit(cx, e, &**lit), true)
           }
           ast::ExprBinary(b, ref e1, ref e2) => {
             let (te1, _, _) = const_expr(cx, &**e1, is_local);
@@ -653,7 +653,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                 }
             }
           }
-          ast::ExprCall(callee, ref args) => {
+          ast::ExprCall(ref callee, ref args) => {
               let opt_def = cx.tcx().def_map.borrow().find_copy(&callee.id);
               match opt_def {
                   Some(def::DefStruct(_)) => {
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 164ddd65f35..fb12520741b 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -39,8 +39,6 @@ use syntax::parse::token::InternedString;
 use syntax::parse::token;
 use syntax::visit::Visitor;
 
-use std::gc::Gc;
-
 pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                               s: &ast::Stmt)
                               -> Block<'blk, 'tcx> {
@@ -61,7 +59,7 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         ast::StmtExpr(ref e, _) | ast::StmtSemi(ref e, _) => {
             bcx = trans_stmt_semi(bcx, &**e);
         }
-        ast::StmtDecl(d, _) => {
+        ast::StmtDecl(ref d, _) => {
             match d.node {
                 ast::DeclLocal(ref local) => {
                     bcx = init_local(bcx, &**local);
@@ -132,8 +130,8 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             if_id: ast::NodeId,
                             cond: &ast::Expr,
-                            thn: ast::P<ast::Block>,
-                            els: Option<Gc<ast::Expr>>,
+                            thn: &ast::Block,
+                            els: Option<&ast::Expr>,
                             dest: expr::Dest)
                             -> Block<'blk, 'tcx> {
     debug!("trans_if(bcx={}, if_id={}, cond={}, thn={:?}, dest={})",
@@ -251,7 +249,7 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// Translates a `for` loop.
 pub fn trans_for<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                              loop_info: NodeInfo,
-                             pat: Gc<ast::Pat>,
+                             pat: &ast::Pat,
                              head: &ast::Expr,
                              body: &ast::Block)
                              -> Block<'blk, 'tcx> {
@@ -453,7 +451,7 @@ pub fn trans_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             e: Option<Gc<ast::Expr>>)
+                             e: Option<&ast::Expr>)
                              -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_ret");
     let fcx = bcx.fcx;
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index f0b0507afbb..21ba2189414 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -207,7 +207,6 @@ use std::c_str::{CString, ToCStr};
 use std::cell::{Cell, RefCell};
 use std::collections::HashMap;
 use std::collections::HashSet;
-use std::gc::Gc;
 use std::ptr;
 use std::rc::{Rc, Weak};
 use syntax::util::interner::Interner;
@@ -1129,8 +1128,8 @@ pub fn create_function_debug_context(cx: &CrateContext,
             }
 
             match item.node {
-                ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
-                    (item.ident, fn_decl, generics, top_level_block, item.span, true)
+                ast::ItemFn(ref fn_decl, _, _, ref generics, ref top_level_block) => {
+                    (item.ident, &**fn_decl, generics, &**top_level_block, item.span, true)
                 }
                 _ => {
                     cx.sess().span_bug(item.span,
@@ -1158,16 +1157,16 @@ pub fn create_function_debug_context(cx: &CrateContext,
         }
         ast_map::NodeExpr(ref expr) => {
             match expr.node {
-                ast::ExprFnBlock(_, fn_decl, top_level_block) |
-                ast::ExprProc(fn_decl, top_level_block) |
-                ast::ExprUnboxedFn(_, _, fn_decl, top_level_block) => {
+                ast::ExprFnBlock(_, ref fn_decl, ref top_level_block) |
+                ast::ExprProc(ref fn_decl, ref top_level_block) |
+                ast::ExprUnboxedFn(_, _, ref fn_decl, ref top_level_block) => {
                     let name = format!("fn{}", token::gensym("fn"));
                     let name = token::str_to_ident(name.as_slice());
-                    (name, fn_decl,
+                    (name, &**fn_decl,
                         // This is not quite right. It should actually inherit
                         // the generics of the enclosing function.
                         &empty_generics,
-                        top_level_block,
+                        &**top_level_block,
                         expr.span,
                         // Don't try to lookup the item path:
                         false)
@@ -1287,9 +1286,8 @@ pub fn create_function_debug_context(cx: &CrateContext,
         source_locations_enabled: Cell::new(false),
     };
 
-    let arg_pats = fn_decl.inputs.iter().map(|arg_ref| arg_ref.pat).collect::<Vec<_>>();
     populate_scope_map(cx,
-                       arg_pats.as_slice(),
+                       fn_decl.inputs.as_slice(),
                        &*top_level_block,
                        fn_metadata,
                        &mut *fn_debug_context.scope_map.borrow_mut());
@@ -3169,7 +3167,7 @@ fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
 // introducing *artificial* lexical scope descriptors where necessary. These
 // artificial scopes allow GDB to correctly handle name shadowing.
 fn populate_scope_map(cx: &CrateContext,
-                      arg_pats: &[Gc<ast::Pat>],
+                      args: &[ast::Arg],
                       fn_entry_block: &ast::Block,
                       fn_metadata: DISubprogram,
                       scope_map: &mut HashMap<ast::NodeId, DIScope>) {
@@ -3185,8 +3183,8 @@ fn populate_scope_map(cx: &CrateContext,
 
     // Push argument identifiers onto the stack so arguments integrate nicely
     // with variable shadowing.
-    for &arg_pat in arg_pats.iter() {
-        pat_util::pat_bindings(def_map, &*arg_pat, |_, _, _, path1| {
+    for arg in args.iter() {
+        pat_util::pat_bindings(def_map, &*arg.pat, |_, _, _, path1| {
             scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
                                                ident: Some(path1.node) });
         })
@@ -3272,10 +3270,10 @@ fn populate_scope_map(cx: &CrateContext,
                  scope_stack: &mut Vec<ScopeStackEntry> ,
                  scope_map: &mut HashMap<ast::NodeId, DIScope>) {
         match *decl {
-            codemap::Spanned { node: ast::DeclLocal(local), .. } => {
+            codemap::Spanned { node: ast::DeclLocal(ref local), .. } => {
                 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
 
-                walk_pattern(cx, local.pat, scope_stack, scope_map);
+                walk_pattern(cx, &*local.pat, scope_stack, scope_map);
 
                 for exp in local.init.iter() {
                     walk_expr(cx, &**exp, scope_stack, scope_map);
@@ -3286,7 +3284,7 @@ fn populate_scope_map(cx: &CrateContext,
     }
 
     fn walk_pattern(cx: &CrateContext,
-                    pat: Gc<ast::Pat>,
+                    pat: &ast::Pat,
                     scope_stack: &mut Vec<ScopeStackEntry> ,
                     scope_map: &mut HashMap<ast::NodeId, DIScope>) {
 
@@ -3367,8 +3365,8 @@ fn populate_scope_map(cx: &CrateContext,
 
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
-                for &sub_pat in sub_pat_opt.iter() {
-                    walk_pattern(cx, sub_pat, scope_stack, scope_map);
+                for sub_pat in sub_pat_opt.iter() {
+                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
                 }
             }
 
@@ -3379,9 +3377,9 @@ fn populate_scope_map(cx: &CrateContext,
             ast::PatEnum(_, ref sub_pats_opt) => {
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
-                for ref sub_pats in sub_pats_opt.iter() {
-                    for &p in sub_pats.iter() {
-                        walk_pattern(cx, p, scope_stack, scope_map);
+                for sub_pats in sub_pats_opt.iter() {
+                    for p in sub_pats.iter() {
+                        walk_pattern(cx, &**p, scope_stack, scope_map);
                     }
                 }
             }
@@ -3389,8 +3387,8 @@ fn populate_scope_map(cx: &CrateContext,
             ast::PatStruct(_, ref field_pats, _) => {
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
-                for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
-                    walk_pattern(cx, sub_pat, scope_stack, scope_map);
+                for &ast::FieldPat { pat: ref sub_pat, .. } in field_pats.iter() {
+                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
                 }
             }
 
@@ -3398,13 +3396,13 @@ fn populate_scope_map(cx: &CrateContext,
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
                 for sub_pat in sub_pats.iter() {
-                    walk_pattern(cx, sub_pat.clone(), scope_stack, scope_map);
+                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
                 }
             }
 
             ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat) => {
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-                walk_pattern(cx, sub_pat.clone(), scope_stack, scope_map);
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
             }
 
             ast::PatLit(ref exp) => {
@@ -3421,16 +3419,16 @@ fn populate_scope_map(cx: &CrateContext,
             ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
 
-                for &sub_pat in front_sub_pats.iter() {
-                    walk_pattern(cx, sub_pat, scope_stack, scope_map);
+                for sub_pat in front_sub_pats.iter() {
+                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
                 }
 
-                for &sub_pat in middle_sub_pats.iter() {
-                    walk_pattern(cx, sub_pat, scope_stack, scope_map);
+                for sub_pat in middle_sub_pats.iter() {
+                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
                 }
 
-                for &sub_pat in back_sub_pats.iter() {
-                    walk_pattern(cx, sub_pat, scope_stack, scope_map);
+                for sub_pat in back_sub_pats.iter() {
+                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
                 }
             }
 
@@ -3466,8 +3464,8 @@ fn populate_scope_map(cx: &CrateContext,
                 walk_expr(cx, &**sub_expr, scope_stack, scope_map);
             }
 
-            ast::ExprRet(exp_opt) => match exp_opt {
-                Some(sub_exp) => walk_expr(cx, &*sub_exp, scope_stack, scope_map),
+            ast::ExprRet(ref exp_opt) => match *exp_opt {
+                Some(ref sub_exp) => walk_expr(cx, &**sub_exp, scope_stack, scope_map),
                 None => ()
             },
 
@@ -3538,7 +3536,7 @@ fn populate_scope_map(cx: &CrateContext,
                                                 .unwrap()
                                                 .scope_metadata);
                     walk_pattern(cx,
-                                 *pattern,
+                                 &**pattern,
                                  scope_stack,
                                  scope_map);
                     walk_block(cx, &**body, scope_stack, scope_map);
@@ -3570,7 +3568,7 @@ fn populate_scope_map(cx: &CrateContext,
                                scope_map,
                                |cx, scope_stack, scope_map| {
                     for &ast::Arg { pat: ref pattern, .. } in decl.inputs.iter() {
-                        walk_pattern(cx, pattern.clone(), scope_stack, scope_map);
+                        walk_pattern(cx, &**pattern, scope_stack, scope_map);
                     }
 
                     walk_block(cx, &**block, scope_stack, scope_map);
@@ -3607,8 +3605,8 @@ fn populate_scope_map(cx: &CrateContext,
                                    scope_stack,
                                    scope_map,
                                    |cx, scope_stack, scope_map| {
-                        for &pat in arm_ref.pats.iter() {
-                            walk_pattern(cx, pat, scope_stack, scope_map);
+                        for pat in arm_ref.pats.iter() {
+                            walk_pattern(cx, &**pat, scope_stack, scope_map);
                         }
 
                         for guard_exp in arm_ref.guard.iter() {
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 54394b8d741..8a6f3dd6ffa 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -77,8 +77,7 @@ use middle::trans::type_::Type;
 use syntax::ast;
 use syntax::codemap;
 use syntax::print::pprust::{expr_to_string};
-
-use std::gc::Gc;
+use syntax::ptr::P;
 
 // Destinations
 
@@ -597,7 +596,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
 
         }
-        ast::ExprLit(ref lit) => trans_immediate_lit(bcx, expr, (**lit).clone()),
+        ast::ExprLit(ref lit) => trans_immediate_lit(bcx, expr, &**lit),
         ast::ExprBinary(op, ref lhs, ref rhs) => {
             trans_binary(bcx, expr, op, &**lhs, &**rhs)
         }
@@ -882,8 +881,8 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprAgain(label_opt) => {
             controlflow::trans_cont(bcx, expr.id, label_opt)
         }
-        ast::ExprRet(ex) => {
-            controlflow::trans_ret(bcx, ex)
+        ast::ExprRet(ref ex) => {
+            controlflow::trans_ret(bcx, ex.as_ref().map(|e| &**e))
         }
         ast::ExprWhile(ref cond, ref body, _) => {
             controlflow::trans_while(bcx, expr.id, &**cond, &**body)
@@ -891,7 +890,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprForLoop(ref pat, ref head, ref body, _) => {
             controlflow::trans_for(bcx,
                                    expr_info(expr),
-                                   *pat,
+                                   &**pat,
                                    &**head,
                                    &**body)
         }
@@ -928,7 +927,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
         ast::ExprAssignOp(op, ref dst, ref src) => {
-            trans_assign_op(bcx, expr, op, &**dst, src.clone())
+            trans_assign_op(bcx, expr, op, &**dst, &**src)
         }
         ast::ExprInlineAsm(ref a) => {
             asm::trans_inline_asm(bcx, a)
@@ -958,8 +957,8 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprPath(_) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
-        ast::ExprIf(ref cond, ref thn, els) => {
-            controlflow::trans_if(bcx, expr.id, &**cond, thn.clone(), els, dest)
+        ast::ExprIf(ref cond, ref thn, ref els) => {
+            controlflow::trans_if(bcx, expr.id, &**cond, &**thn, els.as_ref().map(|e| &**e), dest)
         }
         ast::ExprMatch(ref discr, ref arms) => {
             _match::trans_match(bcx, expr, &**discr, arms.as_slice(), dest)
@@ -967,20 +966,20 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprBlock(ref blk) => {
             controlflow::trans_block(bcx, &**blk, dest)
         }
-        ast::ExprStruct(_, ref fields, base) => {
+        ast::ExprStruct(_, ref fields, ref base) => {
             trans_struct(bcx,
                          fields.as_slice(),
-                         base,
+                         base.as_ref().map(|e| &**e),
                          expr.span,
                          expr.id,
                          dest)
         }
         ast::ExprTup(ref args) => {
-            let numbered_fields: Vec<(uint, Gc<ast::Expr>)> =
-                args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
+            let numbered_fields: Vec<(uint, &ast::Expr)> =
+                args.iter().enumerate().map(|(i, arg)| (i, &**arg)).collect();
             trans_adt(bcx, expr_ty(bcx, expr), 0, numbered_fields.as_slice(), None, dest)
         }
-        ast::ExprLit(lit) => {
+        ast::ExprLit(ref lit) => {
             match lit.node {
                 ast::LitStr(ref s, _) => {
                     tvec::trans_lit_str(bcx, expr, (*s).clone(), dest)
@@ -1005,14 +1004,14 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                    expr_to_string(expr), expr_ty.repr(tcx));
             closure::trans_expr_fn(bcx, store, &**decl, &**body, expr.id, dest)
         }
-        ast::ExprUnboxedFn(_, _, decl, body) => {
-            closure::trans_unboxed_closure(bcx, &*decl, &*body, expr.id, dest)
+        ast::ExprUnboxedFn(_, _, ref decl, ref body) => {
+            closure::trans_unboxed_closure(bcx, &**decl, &**body, expr.id, dest)
         }
         ast::ExprCall(ref f, ref args) => {
             if bcx.tcx().is_method_call(expr.id) {
                 trans_overloaded_call(bcx,
                                       expr,
-                                      *f,
+                                      &**f,
                                       args.as_slice(),
                                       Some(dest))
             } else {
@@ -1061,7 +1060,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
         ast::ExprAssignOp(op, ref dst, ref src) => {
-            trans_assign_op(bcx, expr, op, &**dst, src.clone())
+            trans_assign_op(bcx, expr, op, &**dst, &**src)
         }
         _ => {
             bcx.tcx().sess.span_bug(
@@ -1263,7 +1262,7 @@ pub fn with_field_tys<R>(tcx: &ty::ctxt,
 
 fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             fields: &[ast::Field],
-                            base: Option<Gc<ast::Expr>>,
+                       base: Option<&ast::Expr>,
                             expr_span: codemap::Span,
                             id: ast::NodeId,
                             dest: Dest) -> Block<'blk, 'tcx> {
@@ -1281,7 +1280,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             match opt_pos {
                 Some(i) => {
                     *need_base.get_mut(i) = false;
-                    (i, field.expr)
+                    (i, &*field.expr)
                 }
                 None => {
                     tcx.sess.span_bug(field.span,
@@ -1320,11 +1319,12 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
  * Note that `fields` may be empty; the base expression must always be
  * evaluated for side-effects.
  */
-pub struct StructBaseInfo {
+pub struct StructBaseInfo<'a> {
     /// The base expression; will be evaluated after all explicit fields.
-    expr: Gc<ast::Expr>,
+    expr: &'a ast::Expr,
     /// The indices of fields to copy paired with their types.
-    fields: Vec<(uint, ty::t)> }
+    fields: Vec<(uint, ty::t)>
+}
 
 /**
  * Constructs an ADT instance:
@@ -1339,7 +1339,7 @@ pub struct StructBaseInfo {
 pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                              ty: ty::t,
                              discr: ty::Disr,
-                             fields: &[(uint, Gc<ast::Expr>)],
+                             fields: &[(uint, &ast::Expr)],
                              optbase: Option<StructBaseInfo>,
                              dest: Dest) -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_adt");
@@ -1407,7 +1407,7 @@ pub fn trans_adt<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
 fn trans_immediate_lit<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                    expr: &ast::Expr,
-                                   lit: ast::Lit)
+                                   lit: &ast::Lit)
                                    -> DatumBlock<'blk, 'tcx, Expr> {
     // must not be a string constant, that is a RvalueDpsExpr
     let _icx = push_ctxt("trans_immediate_lit");
@@ -1750,12 +1750,12 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              dest)
 }
 
-fn trans_overloaded_call<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
-                                     expr: &ast::Expr,
-                                     callee: Gc<ast::Expr>,
-                                     args: &[Gc<ast::Expr>],
-                                     dest: Option<Dest>)
-                                     -> Block<'blk, 'tcx> {
+fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
+                                         expr: &ast::Expr,
+                                         callee: &'a ast::Expr,
+                                         args: &'a [P<ast::Expr>],
+                                         dest: Option<Dest>)
+                                         -> Block<'blk, 'tcx> {
     let method_call = MethodCall::expr(expr.id);
     let method_type = bcx.tcx()
                          .method_map
@@ -1763,7 +1763,7 @@ fn trans_overloaded_call<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                          .get(&method_call)
                          .ty;
     let mut all_args = vec!(callee);
-    all_args.push_all(args);
+    all_args.extend(args.iter().map(|e| &**e));
     unpack_result!(bcx,
                    callee::trans_call_inner(bcx,
                                             Some(expr_info(expr)),
@@ -1776,8 +1776,7 @@ fn trans_overloaded_call<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                                     None,
                                                     arg_cleanup_scope)
                                             },
-                                            callee::ArgOverloadedCall(
-                                                all_args.as_slice()),
+                                            callee::ArgOverloadedCall(all_args),
                                             dest));
     bcx
 }
@@ -1957,7 +1956,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                expr: &ast::Expr,
                                op: ast::BinOp,
                                dst: &ast::Expr,
-                               src: Gc<ast::Expr>)
+                               src: &ast::Expr)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_assign_op");
     let mut bcx = bcx;
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index af271d039bd..e1e728fbea0 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -47,12 +47,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             ccx.external().borrow_mut().insert(fn_id, None);
             return None;
         }
-        csearch::found(ast::IIItem(item)) => {
+        csearch::found(&ast::IIItem(ref item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(item.id));
             ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
 
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-            trans_item(ccx, &*item);
+            trans_item(ccx, &**item);
 
             let linkage = match item.node {
                 ast::ItemFn(_, _, _, ref generics, _) => {
@@ -104,12 +104,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
 
             local_def(item.id)
         }
-        csearch::found(ast::IIForeign(item)) => {
+        csearch::found(&ast::IIForeign(ref item)) => {
             ccx.external().borrow_mut().insert(fn_id, Some(item.id));
             ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
             local_def(item.id)
         }
-        csearch::found_parent(parent_id, ast::IIItem(item)) => {
+        csearch::found_parent(parent_id, &ast::IIItem(ref item)) => {
             ccx.external().borrow_mut().insert(parent_id, Some(item.id));
             ccx.external_srcs().borrow_mut().insert(item.id, parent_id);
 
@@ -135,32 +135,37 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             _ => ccx.sess().bug("maybe_instantiate_inline: item has a \
                                  non-enum, non-struct parent")
           }
-          trans_item(ccx, &*item);
+          trans_item(ccx, &**item);
           local_def(my_id)
         }
         csearch::found_parent(_, _) => {
             ccx.sess().bug("maybe_get_item_ast returned a found_parent \
              with a non-item parent");
         }
-        csearch::found(ast::IITraitItem(impl_did, impl_item)) => {
-            match impl_item {
-                ast::ProvidedInlinedTraitItem(mth) |
-                ast::RequiredInlinedTraitItem(mth) => {
+        csearch::found(&ast::IITraitItem(_, ref trait_item)) => {
+            match *trait_item {
+                ast::RequiredMethod(_) => ccx.sess().bug("found RequiredMethod IITraitItem"),
+                ast::ProvidedMethod(ref mth) => {
                     ccx.external().borrow_mut().insert(fn_id, Some(mth.id));
                     ccx.external_srcs().borrow_mut().insert(mth.id, fn_id);
 
                     ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
-                }
-            }
 
-            match impl_item {
-                ast::ProvidedInlinedTraitItem(mth) => {
                     // If this is a default method, we can't look up the
                     // impl type. But we aren't going to translate anyways, so
                     // don't.
                     local_def(mth.id)
                 }
-                ast::RequiredInlinedTraitItem(mth) => {
+            }
+        }
+        csearch::found(&ast::IIImplItem(impl_did, ref impl_item)) => {
+            match *impl_item {
+                ast::MethodImplItem(ref mth) => {
+                    ccx.external().borrow_mut().insert(fn_id, Some(mth.id));
+                    ccx.external_srcs().borrow_mut().insert(mth.id, fn_id);
+
+                    ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
+
                     let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
                     let unparameterized = impl_tpt.generics.types.is_empty() &&
                             mth.pe_generics().ty_params.is_empty();
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 384502025cb..4202c2deff6 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -66,8 +66,8 @@ pub fn trans_impl(ccx: &CrateContext,
         let mut v = TransItemVisitor{ ccx: ccx };
         for impl_item in impl_items.iter() {
             match *impl_item {
-                ast::MethodImplItem(method) => {
-                    visit::walk_method_helper(&mut v, &*method);
+                ast::MethodImplItem(ref method) => {
+                    visit::walk_method_helper(&mut v, &**method);
                 }
             }
         }
@@ -75,14 +75,14 @@ pub fn trans_impl(ccx: &CrateContext,
     }
     for impl_item in impl_items.iter() {
         match *impl_item {
-            ast::MethodImplItem(method) => {
+            ast::MethodImplItem(ref method) => {
                 if method.pe_generics().ty_params.len() == 0u {
                     let trans_everywhere = attr::requests_inline(method.attrs.as_slice());
                     for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
                         let llfn = get_item_val(ccx, method.id);
                         trans_fn(ccx,
-                                 &*method.pe_fn_decl(),
-                                 &*method.pe_body(),
+                                 method.pe_fn_decl(),
+                                 method.pe_body(),
                                  llfn,
                                  &param_substs::empty(),
                                  method.id,
@@ -96,7 +96,7 @@ pub fn trans_impl(ccx: &CrateContext,
                 let mut v = TransItemVisitor {
                     ccx: ccx,
                 };
-                visit::walk_method_helper(&mut v, &*method);
+                visit::walk_method_helper(&mut v, &**method);
             }
         }
     }
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 1cf3e55967d..57004922ef7 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -221,13 +221,13 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         }
         ast_map::NodeImplItem(ii) => {
             match *ii {
-                ast::MethodImplItem(mth) => {
+                ast::MethodImplItem(ref mth) => {
                     let d = mk_lldecl(abi::Rust);
                     let needs_body = setup_lldecl(d, mth.attrs.as_slice());
                     if needs_body {
                         trans_fn(ccx,
-                                 &*mth.pe_fn_decl(),
-                                 &*mth.pe_body(),
+                                 mth.pe_fn_decl(),
+                                 mth.pe_body(),
                                  d,
                                  &psubsts,
                                  mth.id,
@@ -239,11 +239,11 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         }
         ast_map::NodeTraitItem(method) => {
             match *method {
-                ast::ProvidedMethod(mth) => {
+                ast::ProvidedMethod(ref mth) => {
                     let d = mk_lldecl(abi::Rust);
                     let needs_body = setup_lldecl(d, mth.attrs.as_slice());
                     if needs_body {
-                        trans_fn(ccx, &*mth.pe_fn_decl(), &*mth.pe_body(), d,
+                        trans_fn(ccx, mth.pe_fn_decl(), mth.pe_body(), d,
                                  &psubsts, mth.id, []);
                     }
                     d
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 8a915bbfff4..f5c3ed388b7 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -156,7 +156,7 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // Handle the "..." case (returns a slice since strings are always unsized):
     match content_expr.node {
-        ast::ExprLit(lit) => {
+        ast::ExprLit(ref lit) => {
             match lit.node {
                 ast::LitStr(ref s, _) => {
                     let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
@@ -255,7 +255,7 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            bcx.expr_to_string(vstore_expr));
 
     match content_expr.node {
-        ast::ExprLit(lit) => {
+        ast::ExprLit(ref lit) => {
             match lit.node {
                 ast::LitStr(ref s, _) => {
                     match dest {
@@ -363,7 +363,7 @@ pub fn elements_required(bcx: Block, content_expr: &ast::Expr) -> uint {
     //! Figure out the number of elements we need to store this content
 
     match content_expr.node {
-        ast::ExprLit(lit) => {
+        ast::ExprLit(ref lit) => {
             match lit.node {
                 ast::LitStr(ref s, _) => s.get().len(),
                 _ => {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 48173cc6804..bf35e25635a 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -44,7 +44,6 @@ use std::cmp;
 use std::fmt::Show;
 use std::fmt;
 use std::hash::{Hash, sip, Writer};
-use std::gc::Gc;
 use std::iter::AdditiveIterator;
 use std::mem;
 use std::ops;
@@ -459,7 +458,7 @@ pub struct ctxt<'tcx> {
     pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
 
-    pub map: ast_map::Map,
+    pub map: ast_map::Map<'tcx>,
     pub intrinsic_defs: RefCell<DefIdMap<t>>,
     pub freevars: RefCell<freevars::freevar_map>,
     pub tcache: type_cache,
@@ -533,8 +532,8 @@ pub struct ctxt<'tcx> {
 
     /// These two caches are used by const_eval when decoding external statics
     /// and variants that are found.
-    pub extern_const_statics: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
-    pub extern_const_variants: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
+    pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
+    pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
 
     pub method_map: typeck::MethodMap,
     pub vtable_map: typeck::vtable_map,
@@ -1382,7 +1381,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
                      type_arena: &'tcx TypedArena<t_box_>,
                      dm: resolve::DefMap,
                      named_region_map: resolve_lifetime::NamedRegionMap,
-                     map: ast_map::Map,
+                     map: ast_map::Map<'tcx>,
                      freevars: freevars::freevar_map,
                      capture_modes: freevars::CaptureModeMap,
                      region_maps: middle::region::RegionMaps,
@@ -3619,7 +3618,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             RvalueDpsExpr
         }
 
-        ast::ExprLit(lit) if lit_is_str(lit) => {
+        ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
             RvalueDpsExpr
         }
 
@@ -3668,7 +3667,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             RvalueDatumExpr
         }
 
-        ast::ExprBox(place, _) => {
+        ast::ExprBox(ref place, _) => {
             // Special case `Box<T>`/`Gc<T>` for now:
             let definition = match tcx.def_map.borrow().find(&place.id) {
                 Some(&def) => def,
@@ -3959,16 +3958,15 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
             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| {
-                            match impl_or_trait_item(
-                                    cx,
-                                    ast_util::local_def(m.id)) {
-                                MethodTraitItem(m) => m,
+                        ms.iter().filter_map(|m| match *m {
+                            ast::RequiredMethod(_) => None,
+                            ast::ProvidedMethod(ref m) => {
+                                match impl_or_trait_item(cx,
+                                        ast_util::local_def(m.id)) {
+                                    MethodTraitItem(m) => Some(m),
+                                }
                             }
-                         })
-                         .collect()
+                         }).collect()
                     }
                     _ => {
                         cx.sess.bug(format!("provided_trait_methods: `{}` is \
@@ -4289,11 +4287,11 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
           expr, since check_enum_variants also updates the enum_var_cache
          */
         match cx.map.get(id.node) {
-            ast_map::NodeItem(item) => {
+            ast_map::NodeItem(ref item) => {
                 match item.node {
                     ast::ItemEnum(ref enum_definition, _) => {
                         let mut last_discriminant: Option<Disr> = None;
-                        Rc::new(enum_definition.variants.iter().map(|&variant| {
+                        Rc::new(enum_definition.variants.iter().map(|variant| {
 
                             let mut discriminant = match last_discriminant {
                                 Some(val) => val + 1,
@@ -4324,7 +4322,7 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
                             };
 
                             last_discriminant = Some(discriminant);
-                            Rc::new(VariantInfo::from_ast_variant(cx, &*variant,
+                            Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
                                                                   discriminant))
                         }).collect())
                     }
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index f5fa6168a41..f2fe7fe6282 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -451,13 +451,10 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     for inner_ast_type in path.segments
                                               .iter()
                                               .flat_map(|s| s.types.iter()) {
-                        let mt = ast::MutTy {
-                            ty: *inner_ast_type,
-                            mutbl: ast::MutImmutable,
-                        };
                         return Some(mk_pointer(this,
                                                rscope,
-                                               &mt,
+                                               ast::MutImmutable,
+                                               &**inner_ast_type,
                                                Uniq,
                                                |typ| ty::mk_uniq(this.tcx(), typ)));
                     }
@@ -478,13 +475,10 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     for inner_ast_type in path.segments
                                               .iter()
                                               .flat_map(|s| s.types.iter()) {
-                        let mt = ast::MutTy {
-                            ty: *inner_ast_type,
-                            mutbl: ast::MutImmutable,
-                        };
                         return Some(mk_pointer(this,
                                                rscope,
-                                               &mt,
+                                               ast::MutImmutable,
+                                               &**inner_ast_type,
                                                Box,
                                                |typ| {
                             match ty::get(typ).sty {
@@ -578,14 +572,15 @@ pub fn trait_ref_for_unboxed_function<'tcx, AC: AstConv<'tcx>,
 fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
         this: &AC,
         rscope: &RS,
-        a_seq_ty: &ast::MutTy,
+        a_seq_mutbl: ast::Mutability,
+        a_seq_ty: &ast::Ty,
         ptr_ty: PointerTy,
         constr: |ty::t| -> ty::t)
         -> ty::t {
     let tcx = this.tcx();
     debug!("mk_pointer(ptr_ty={})", ptr_ty);
 
-    match a_seq_ty.ty.node {
+    match a_seq_ty.node {
         ast::TyVec(ref ty) => {
             let ty = ast_ty_to_ty(this, rscope, &**ty);
             return constr(ty::mk_vec(tcx, ty, None));
@@ -610,11 +605,11 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                 RPtr(r) => {
                     return ty::mk_rptr(this.tcx(),
                                        r,
-                                       ty::mt {mutbl: a_seq_ty.mutbl, ty: tr});
+                                       ty::mt {mutbl: a_seq_mutbl, ty: tr});
                 }
                 _ => {
                     tcx.sess.span_err(
-                        a_seq_ty.ty.span,
+                        a_seq_ty.span,
                         "~trait or &trait are the only supported \
                          forms of casting-to-trait");
                     return ty::mk_err();
@@ -671,7 +666,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                             return ty::mk_uniq(tcx, tr);
                         }
                         RPtr(r) => {
-                            return ty::mk_rptr(tcx, r, ty::mt{mutbl: a_seq_ty.mutbl, ty: tr});
+                            return ty::mk_rptr(tcx, r, ty::mt{mutbl: a_seq_mutbl, ty: tr});
                         }
                         _ => {
                             tcx.sess.span_err(
@@ -688,7 +683,7 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
         _ => {}
     }
 
-    constr(ast_ty_to_ty(this, rscope, &*a_seq_ty.ty))
+    constr(ast_ty_to_ty(this, rscope, a_seq_ty))
 }
 
 // Parses the programmer's textual representation of a type into our
@@ -716,17 +711,16 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
         match ast_ty.node {
             ast::TyNil => ty::mk_nil(),
             ast::TyBot => ty::mk_bot(),
-            ast::TyBox(ty) => {
-                let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
-                mk_pointer(this, rscope, &mt, Box, |ty| ty::mk_box(tcx, ty))
+            ast::TyBox(ref ty) => {
+                mk_pointer(this, rscope, ast::MutImmutable, &**ty, Box,
+                           |ty| ty::mk_box(tcx, ty))
             }
-            ast::TyUniq(ty) => {
-                let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
-                mk_pointer(this, rscope, &mt, Uniq,
+            ast::TyUniq(ref ty) => {
+                mk_pointer(this, rscope, ast::MutImmutable, &**ty, Uniq,
                            |ty| ty::mk_uniq(tcx, ty))
             }
-            ast::TyVec(ty) => {
-                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &*ty), None)
+            ast::TyVec(ref ty) => {
+                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
             }
             ast::TyPtr(ref mt) => {
                 ty::mk_ptr(tcx, ty::mt {
@@ -737,7 +731,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
             ast::TyRptr(ref region, ref mt) => {
                 let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
                 debug!("ty_rptr r={}", r.repr(this.tcx()));
-                mk_pointer(this, rscope, mt, RPtr(r),
+                mk_pointer(this, rscope, mt.mutbl, &*mt.ty, RPtr(r),
                            |ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
             }
             ast::TyTup(ref fields) => {
@@ -870,15 +864,15 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     }
                 }
             }
-            ast::TyFixedLengthVec(ty, e) => {
-                match const_eval::eval_const_expr_partial(tcx, &*e) {
+            ast::TyFixedLengthVec(ref ty, ref e) => {
+                match const_eval::eval_const_expr_partial(tcx, &**e) {
                     Ok(ref r) => {
                         match *r {
                             const_eval::const_int(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &*ty),
+                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
                                            Some(i as uint)),
                             const_eval::const_uint(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &*ty),
+                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
                                            Some(i as uint)),
                             _ => {
                                 tcx.sess.span_fatal(
@@ -895,7 +889,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
                     }
                 }
             }
-            ast::TyTypeof(_e) => {
+            ast::TyTypeof(ref _e) => {
                 tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
             }
             ast::TyInfer => {
@@ -925,7 +919,7 @@ pub fn ty_of_arg<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(this: &AC, rscope: &R
 
 struct SelfInfo<'a> {
     untransformed_self_ty: ty::t,
-    explicit_self: ast::ExplicitSelf,
+    explicit_self: &'a ast::ExplicitSelf,
 }
 
 pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
@@ -933,7 +927,7 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>(
                     id: ast::NodeId,
                     fn_style: ast::FnStyle,
                     untransformed_self_ty: ty::t,
-                    explicit_self: ast::ExplicitSelf,
+                    explicit_self: &ast::ExplicitSelf,
                     decl: &ast::FnDecl,
                     abi: abi::Abi)
                     -> (ty::BareFnTy, ty::ExplicitSelfCategory) {
@@ -1087,8 +1081,8 @@ fn determine_explicit_self_category<'tcx, AC: AstConv<'tcx>,
                                          lifetime);
             ty::ByReferenceExplicitSelfCategory(region, mutability)
         }
-        ast::SelfExplicit(ast_type, _) => {
-            let explicit_type = ast_ty_to_ty(this, rscope, &*ast_type);
+        ast::SelfExplicit(ref ast_type, _) => {
+            let explicit_type = ast_ty_to_ty(this, rscope, &**ast_type);
 
             {
                 let inference_context = infer::new_infer_ctxt(this.tcx());
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 247178770d2..1602dfeaa28 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -24,12 +24,12 @@ use middle::typeck::require_same_types;
 use util::ppaux;
 
 use std::collections::{HashMap, HashSet};
-use std::gc::Gc;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::parse::token;
 use syntax::codemap::Span;
 use syntax::print::pprust;
+use syntax::ptr::P;
 
 pub fn check_match(fcx: &FnCtxt,
                    expr: &ast::Expr,
@@ -66,17 +66,17 @@ pub fn check_match(fcx: &FnCtxt,
         let mut guard_err = false;
         let mut guard_bot = false;
         match arm.guard {
-          Some(ref e) => {
-              check_expr_has_type(fcx, &**e, ty::mk_bool());
-              let e_ty = fcx.expr_ty(&**e);
-              if ty::type_is_error(e_ty) {
-                  guard_err = true;
-              }
-              else if ty::type_is_bot(e_ty) {
-                  guard_bot = true;
-              }
-          },
-          None => ()
+            Some(ref e) => {
+                check_expr_has_type(fcx, &**e, ty::mk_bool());
+                let e_ty = fcx.expr_ty(&**e);
+                if ty::type_is_error(e_ty) {
+                    guard_err = true;
+                }
+                else if ty::type_is_bot(e_ty) {
+                    guard_bot = true;
+                }
+            },
+            None => ()
         }
         check_expr(fcx, &*arm.body);
         let bty = fcx.node_ty(arm.body.id);
@@ -113,7 +113,7 @@ pub struct pat_ctxt<'a, 'tcx: 'a> {
 }
 
 pub fn check_pat_variant(pcx: &pat_ctxt, pat: &ast::Pat, path: &ast::Path,
-                         subpats: &Option<Vec<Gc<ast::Pat>>>, expected: ty::t) {
+                         subpats: &Option<Vec<P<ast::Pat>>>, expected: ty::t) {
 
     // Typecheck the path.
     let fcx = pcx.fcx;
@@ -457,7 +457,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         demand::suptype(fcx, pat.span, expected, const_pty.ty);
         fcx.write_ty(pat.id, const_pty.ty);
       }
-      ast::PatIdent(bm, ref path1, sub) if pat_is_binding(&tcx.def_map, pat) => {
+      ast::PatIdent(bm, ref path1, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
         let typ = fcx.local_ty(pat.span, pat.id);
 
         match bm {
@@ -491,9 +491,9 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
                ppaux::ty_to_string(tcx, expected),
                pat.id);
 
-        match sub {
-          Some(ref p) => check_pat(pcx, &**p, expected),
-          _ => ()
+        match *sub {
+            Some(ref p) => check_pat(pcx, &**p, expected),
+            _ => ()
         }
       }
       // it's not a binding, it's an enum in disguise:
@@ -624,14 +624,14 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
       ast::PatRegion(ref inner) => {
           check_pointer_pat(pcx, Borrowed, &**inner, pat.id, pat.span, expected);
       }
-      ast::PatVec(ref before, slice, ref after) => {
+      ast::PatVec(ref before, ref slice, ref after) => {
         let default_region_var =
             fcx.infcx().next_region_var(
                 infer::PatternRegion(pat.span));
 
         let check_err = |found: String| {
-            for &elt in before.iter() {
-                check_pat(pcx, &*elt, ty::mk_err());
+            for elt in before.iter() {
+                check_pat(pcx, &**elt, ty::mk_err());
             }
             for elt in slice.iter() {
                 check_pat(pcx, &**elt, ty::mk_err());
@@ -690,7 +690,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         };
 
         let min_len = before.len() + after.len();
-        fixed.and_then(|count| match slice {
+        fixed.and_then(|count| match *slice {
             Some(_) if count < min_len =>
                 Some(format!("a fixed vector pattern of size at least {}", min_len)),
 
@@ -703,7 +703,7 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         for elt in before.iter() {
             check_pat(pcx, &**elt, elt_type);
         }
-        match slice {
+        match *slice {
             Some(ref slice_pat) => {
                 let slice_ty = ty::mk_slice(tcx,
                                             region_var,
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 47a4b6f8622..8ac9f072a0b 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -124,7 +124,7 @@ use std::cell::{Cell, RefCell};
 use std::collections::HashMap;
 use std::mem::replace;
 use std::rc::Rc;
-use std::gc::Gc;
+use std::slice;
 use syntax::abi;
 use syntax::ast::{ProvidedMethod, RequiredMethod};
 use syntax::ast;
@@ -137,6 +137,7 @@ use syntax::codemap;
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token;
 use syntax::print::pprust;
+use syntax::ptr::P;
 use syntax::visit;
 use syntax::visit::Visitor;
 use syntax;
@@ -401,7 +402,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckItemSizedTypesVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
+pub fn check_item_types(ccx: &CrateCtxt) {
+    let krate = ccx.tcx.map.krate();
+
     let mut visit = CheckTypeWellFormedVisitor { ccx: ccx };
     visit::walk_crate(&mut visit, krate);
 
@@ -624,7 +627,7 @@ fn span_for_field(tcx: &ty::ctxt, field: &ty::field_ty, struct_id: ast::DefId) -
     };
 
     match item.node {
-        ast::ItemStruct(struct_def, _) => {
+        ast::ItemStruct(ref struct_def, _) => {
             match struct_def.fields.iter().find(|f| match f.node.kind {
                 ast::NamedField(ident, _) => ident.name == field.name,
                 _ => false,
@@ -818,8 +821,8 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
         for impl_item in impl_items.iter() {
             match *impl_item {
-                ast::MethodImplItem(m) => {
-                    check_method_body(ccx, &impl_pty.generics, &*m);
+                ast::MethodImplItem(ref m) => {
+                    check_method_body(ccx, &impl_pty.generics, &**m);
                 }
             }
         }
@@ -841,14 +844,14 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
       }
       ast::ItemTrait(_, _, _, ref trait_methods) => {
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
-        for trait_method in (*trait_methods).iter() {
+        for trait_method in trait_methods.iter() {
             match *trait_method {
                 RequiredMethod(..) => {
                     // Nothing to do, since required methods don't have
                     // bodies to check.
                 }
-                ProvidedMethod(m) => {
-                    check_method_body(ccx, &trait_def.generics, &*m);
+                ProvidedMethod(ref m) => {
+                    check_method_body(ccx, &trait_def.generics, &**m);
                 }
             }
         }
@@ -930,7 +933,7 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
     // and compatible with trait signature
     for impl_item in impl_items.iter() {
         match *impl_item {
-            ast::MethodImplItem(impl_method) => {
+            ast::MethodImplItem(ref impl_method) => {
                 let impl_method_def_id = local_def(impl_method.id);
                 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
                                                           impl_method_def_id);
@@ -983,7 +986,7 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
                 let is_implemented =
                     impl_items.iter().any(|ii| {
                         match *ii {
-                            ast::MethodImplItem(m) => {
+                            ast::MethodImplItem(ref m) => {
                                 m.pe_ident().name == trait_method.ident.name
                             }
                         }
@@ -1968,9 +1971,9 @@ pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
 /// Attempts to resolve a call expression as an overloaded call.
 fn try_overloaded_call(fcx: &FnCtxt,
                        call_expression: &ast::Expr,
-                       callee: Gc<ast::Expr>,
+                       callee: &ast::Expr,
                        callee_type: ty::t,
-                       args: &[Gc<ast::Expr>])
+                       args: &[P<ast::Expr>])
                        -> bool {
     // Bail out if the callee is a bare function or a closure. We check those
     // manually.
@@ -2072,9 +2075,9 @@ fn try_overloaded_deref(fcx: &FnCtxt,
 fn try_overloaded_index(fcx: &FnCtxt,
                         method_call: Option<MethodCall>,
                         expr: &ast::Expr,
-                        base_expr: Gc<ast::Expr>,
+                        base_expr: &ast::Expr,
                         base_ty: ty::t,
-                        index_expr: Gc<ast::Expr>,
+                        index_expr: &P<ast::Expr>,
                         lvalue_pref: LvaluePreference)
                         -> Option<ty::mt> {
     // Try `IndexMut` first, if preferred.
@@ -2119,7 +2122,7 @@ fn try_overloaded_index(fcx: &FnCtxt,
                                 expr.span,
                                 method_type,
                                 expr,
-                                [base_expr, index_expr],
+                                slice::ref_slice(index_expr),
                                 DoDerefArgs,
                                 DontTupleArguments);
 
@@ -2145,7 +2148,7 @@ fn try_overloaded_index(fcx: &FnCtxt,
 /// The return type of this function represents the concrete element type
 /// `A` in the type `Iterator<A>` that the method returns.
 fn lookup_method_for_for_loop(fcx: &FnCtxt,
-                              iterator_expr: Gc<ast::Expr>,
+                              iterator_expr: &ast::Expr,
                               loop_id: ast::NodeId)
                               -> ty::t {
     let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
@@ -2188,8 +2191,8 @@ fn lookup_method_for_for_loop(fcx: &FnCtxt,
     let return_type = check_method_argument_types(fcx,
                                                   iterator_expr.span,
                                                   method_type,
-                                                  &*iterator_expr,
-                                                  [iterator_expr],
+                                                  iterator_expr,
+                                                  &[],
                                                   DontDerefArgs,
                                                   DontTupleArguments);
 
@@ -2224,23 +2227,17 @@ fn check_method_argument_types(fcx: &FnCtxt,
                                sp: Span,
                                method_fn_ty: ty::t,
                                callee_expr: &ast::Expr,
-                               args: &[Gc<ast::Expr>],
+                               args_no_rcvr: &[P<ast::Expr>],
                                deref_args: DerefArgs,
                                tuple_arguments: TupleArgumentsFlag)
                                -> ty::t {
-    // HACK(eddyb) ignore provided self (it has special typeck rules).
-    let args = if tuple_arguments == DontTupleArguments {
-        args.slice_from(1)
-    } else {
-        args
-    };
     if ty::type_is_error(method_fn_ty) {
-        let err_inputs = err_args(args.len());
+       let err_inputs = err_args(args_no_rcvr.len());
         check_argument_types(fcx,
                              sp,
                              err_inputs.as_slice(),
                              callee_expr,
-                             args,
+                             args_no_rcvr,
                              deref_args,
                              false,
                              tuple_arguments);
@@ -2253,7 +2250,7 @@ fn check_method_argument_types(fcx: &FnCtxt,
                                      sp,
                                      fty.sig.inputs.slice_from(1),
                                      callee_expr,
-                                     args,
+                                     args_no_rcvr,
                                      deref_args,
                                      fty.sig.variadic,
                                      tuple_arguments);
@@ -2271,7 +2268,7 @@ fn check_argument_types(fcx: &FnCtxt,
                         sp: Span,
                         fn_inputs: &[ty::t],
                         callee_expr: &ast::Expr,
-                        args: &[Gc<ast::Expr>],
+                        args: &[P<ast::Expr>],
                         deref_args: DerefArgs,
                         variadic: bool,
                         tuple_arguments: TupleArgumentsFlag) {
@@ -2665,7 +2662,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     fn check_call(fcx: &FnCtxt,
                   call_expr: &ast::Expr,
                   f: &ast::Expr,
-                  args: &[Gc<ast::Expr>]) {
+                  args: &[P<ast::Expr>]) {
         // Store the type of `f` as the type of the callee
         let fn_ty = fcx.expr_ty(f);
 
@@ -2716,9 +2713,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     fn check_method_call(fcx: &FnCtxt,
                          expr: &ast::Expr,
                          method_name: ast::SpannedIdent,
-                         args: &[Gc<ast::Expr>],
-                         tps: &[ast::P<ast::Ty>]) {
-        let rcvr = args[0].clone();
+                         args: &[P<ast::Expr>],
+                         tps: &[P<ast::Ty>]) {
+        let rcvr = &*args[0];
         // We can't know if we need &mut self before we look up the method,
         // so treat the receiver as mutable just in case - only explicit
         // overloaded dereferences care about the distinction.
@@ -2779,7 +2776,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                                  method_name.span,
                                                  fn_ty,
                                                  expr,
-                                                 args,
+                                                 args.slice_from(1),
                                                  DontDerefArgs,
                                                  DontTupleArguments);
 
@@ -2791,7 +2788,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     fn check_then_else(fcx: &FnCtxt,
                        cond_expr: &ast::Expr,
                        then_blk: &ast::Block,
-                       opt_else_expr: Option<Gc<ast::Expr>>,
+                       opt_else_expr: Option<&ast::Expr>,
                        id: ast::NodeId,
                        sp: Span,
                        expected: Expectation) {
@@ -2852,22 +2849,31 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         fcx.write_ty(id, if_ty);
     }
 
-    fn lookup_op_method(fcx: &FnCtxt,
-                        op_ex: &ast::Expr,
-                        self_t: ty::t,
-                        opname: ast::Name,
-                        trait_did: Option<ast::DefId>,
-                        args: &[Gc<ast::Expr>],
-                        autoderef_receiver: AutoderefReceiverFlag,
-                        unbound_method: ||) -> ty::t {
+    fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
+                                  op_ex: &ast::Expr,
+                                  lhs_ty: ty::t,
+                                  opname: ast::Name,
+                                  trait_did: Option<ast::DefId>,
+                                  lhs: &'a ast::Expr,
+                                  rhs: Option<&P<ast::Expr>>,
+                                  autoderef_receiver: AutoderefReceiverFlag,
+                                  unbound_method: ||) -> ty::t {
         let method = match trait_did {
             Some(trait_did) => {
-                method::lookup_in_trait(fcx, op_ex.span, Some(&*args[0]), opname,
-                                        trait_did, self_t, [], autoderef_receiver,
+                method::lookup_in_trait(fcx, op_ex.span, Some(lhs), opname,
+                                        trait_did, lhs_ty, &[], autoderef_receiver,
                                         IgnoreStaticMethods)
             }
             None => None
         };
+        let args = match rhs {
+            Some(rhs) => slice::ref_slice(rhs),
+            None => {
+                // Work around the lack of coercion.
+                let empty: &[_] = &[];
+                empty
+            }
+        };
         match method {
             Some(method) => {
                 let method_ty = method.ty;
@@ -2903,8 +2909,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     fn check_binop(fcx: &FnCtxt,
                    expr: &ast::Expr,
                    op: ast::BinOp,
-                   lhs: Gc<ast::Expr>,
-                   rhs: Gc<ast::Expr>,
+                   lhs: &ast::Expr,
+                   rhs: &P<ast::Expr>,
                    is_binop_assignment: IsBinopAssignment) {
         let tcx = fcx.ccx.tcx;
 
@@ -2920,7 +2926,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
 
         if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
             // Shift is a special case: rhs must be uint, no matter what lhs is
-            check_expr_has_type(fcx, &*rhs, ty::mk_uint());
+            check_expr_has_type(fcx, &**rhs, ty::mk_uint());
             fcx.write_ty(expr.id, lhs_t);
             return;
         }
@@ -2928,7 +2934,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         if ty::is_binopable(tcx, lhs_t, op) {
             let tvar = fcx.infcx().next_ty_var();
             demand::suptype(fcx, expr.span, tvar, lhs_t);
-            check_expr_has_type(fcx, &*rhs, tvar);
+            check_expr_has_type(fcx, &**rhs, tvar);
 
             let result_t = match op {
                 ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
@@ -2993,7 +2999,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                    },
                                    lhs_t,
                                    None);
-            check_expr(fcx, &*rhs);
+            check_expr(fcx, &**rhs);
             ty::mk_err()
         };
 
@@ -3005,10 +3011,10 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
 
     fn check_user_binop(fcx: &FnCtxt,
                         ex: &ast::Expr,
-                        lhs_expr: Gc<ast::Expr>,
+                        lhs_expr: &ast::Expr,
                         lhs_resolved_t: ty::t,
                         op: ast::BinOp,
-                        rhs: Gc<ast::Expr>) -> ty::t {
+                        rhs: &P<ast::Expr>) -> ty::t {
         let tcx = fcx.ccx.tcx;
         let lang = &tcx.lang_items;
         let (name, trait_did) = match op {
@@ -3029,12 +3035,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
             ast::BiEq => ("eq", lang.eq_trait()),
             ast::BiNe => ("ne", lang.eq_trait()),
             ast::BiAnd | ast::BiOr => {
-                check_expr(fcx, &*rhs);
+                check_expr(fcx, &**rhs);
                 return ty::mk_err();
             }
         };
         lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
-                         trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
+                         trait_did, lhs_expr, Some(rhs), DontAutoderefReceiver, || {
             fcx.type_error_message(ex.span, |actual| {
                 format!("binary operation `{}` cannot be applied to type `{}`",
                         ast_util::binop_to_string(op),
@@ -3048,10 +3054,10 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                        mname: &str,
                        trait_did: Option<ast::DefId>,
                        ex: &ast::Expr,
-                       rhs_expr: Gc<ast::Expr>,
+                       rhs_expr: &ast::Expr,
                        rhs_t: ty::t) -> ty::t {
        lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
-                        trait_did, [rhs_expr], DontAutoderefReceiver, || {
+                        trait_did, rhs_expr, None, DontAutoderefReceiver, || {
             fcx.type_error_message(ex.span, |actual| {
                 format!("cannot apply unary operator `{}` to type `{}`",
                         op_str, actual)
@@ -3063,7 +3069,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                              expr: &ast::Expr,
                              kind: ast::UnboxedClosureKind,
                              decl: &ast::FnDecl,
-                             body: ast::P<ast::Block>) {
+                             body: &ast::Block) {
         let mut fn_ty = astconv::ty_of_closure(
             fcx,
             expr.id,
@@ -3131,7 +3137,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                      expr: &ast::Expr,
                      store: ty::TraitStore,
                      decl: &ast::FnDecl,
-                     body: ast::P<ast::Block>,
+                     body: &ast::Block,
                      expected: Expectation) {
         let tcx = fcx.ccx.tcx;
 
@@ -3228,7 +3234,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                    lvalue_pref: LvaluePreference,
                    base: &ast::Expr,
                    field: &ast::SpannedIdent,
-                   tys: &[ast::P<ast::Ty>]) {
+                   tys: &[P<ast::Ty>]) {
         let tcx = fcx.ccx.tcx;
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -3302,7 +3308,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                        lvalue_pref: LvaluePreference,
                        base: &ast::Expr,
                        idx: codemap::Spanned<uint>,
-                       _tys: &[ast::P<ast::Ty>]) {
+                       _tys: &[P<ast::Ty>]) {
         let tcx = fcx.ccx.tcx;
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -3453,7 +3459,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                 span: codemap::Span,
                                 class_id: ast::DefId,
                                 fields: &[ast::Field],
-                                base_expr: Option<Gc<ast::Expr>>) {
+                                base_expr: Option<&ast::Expr>) {
         let tcx = fcx.ccx.tcx;
 
         // Look up the number of type parameters and the raw type, and
@@ -3527,14 +3533,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
     fn check_struct_fields_on_error(fcx: &FnCtxt,
                                     id: ast::NodeId,
                                     fields: &[ast::Field],
-                                    base_expr: Option<Gc<ast::Expr>>) {
+                                    base_expr: &Option<P<ast::Expr>>) {
         // Make sure to still write the types
         // otherwise we might ICE
         fcx.write_error(id);
         for field in fields.iter() {
             check_expr(fcx, &*field.expr);
         }
-        match base_expr {
+        match *base_expr {
             Some(ref base) => check_expr(fcx, &**base),
             None => {}
         }
@@ -3578,12 +3584,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
           }
       }
 
-      ast::ExprLit(lit) => {
-        let typ = check_lit(fcx, &*lit, expected);
+      ast::ExprLit(ref lit) => {
+        let typ = check_lit(fcx, &**lit, expected);
         fcx.write_ty(id, typ);
       }
       ast::ExprBinary(op, ref lhs, ref rhs) => {
-        check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), SimpleBinop);
+        check_binop(fcx, expr, op, &**lhs, rhs, SimpleBinop);
 
         let lhs_ty = fcx.expr_ty(&**lhs);
         let rhs_ty = fcx.expr_ty(&**rhs);
@@ -3597,7 +3603,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         }
       }
       ast::ExprAssignOp(op, ref lhs, ref rhs) => {
-        check_binop(fcx, expr, op, lhs.clone(), rhs.clone(), BinopAssignment);
+        check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
 
         let lhs_t = fcx.expr_ty(&**lhs);
         let result_t = fcx.expr_ty(expr);
@@ -3691,7 +3697,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                          ty::get(oprnd_t).sty == ty::ty_bool) {
                         oprnd_t = check_user_unop(fcx, "!", "not",
                                                   tcx.lang_items.not_trait(),
-                                                  expr, oprnd.clone(), oprnd_t);
+                                                  expr, &**oprnd, oprnd_t);
                     }
                 }
                 ast::UnNeg => {
@@ -3701,7 +3707,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                          ty::type_is_fp(oprnd_t)) {
                         oprnd_t = check_user_unop(fcx, "-", "neg",
                                                   tcx.lang_items.neg_trait(),
-                                                  expr, oprnd.clone(), oprnd_t);
+                                                  expr, &**oprnd, oprnd_t);
                     }
                 }
             }
@@ -3802,12 +3808,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         }
         fcx.write_bot(id);
       }
-      ast::ExprParen(a) => {
+      ast::ExprParen(ref a) => {
         check_expr_with_expectation_and_lvalue_pref(fcx,
-                                                    &*a,
+                                                    &**a,
                                                     expected,
                                                     lvalue_pref);
-        fcx.write_ty(id, fcx.expr_ty(&*a));
+        fcx.write_ty(id, fcx.expr_ty(&**a));
       }
       ast::ExprAssign(ref lhs, ref rhs) => {
         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
@@ -3831,7 +3837,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         }
       }
       ast::ExprIf(ref cond, ref then_blk, ref opt_else_expr) => {
-        check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.clone(),
+        check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
                         id, expr.span, expected);
       }
       ast::ExprWhile(ref cond, ref body, _) => {
@@ -3851,7 +3857,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
       }
       ast::ExprForLoop(ref pat, ref head, ref block, _) => {
         check_expr(fcx, &**head);
-        let typ = lookup_method_for_for_loop(fcx, *head, expr.id);
+        let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
         vtable::early_resolve_expr(expr, fcx, true);
 
         let pcx = pat_ctxt {
@@ -3865,10 +3871,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
       }
       ast::ExprLoop(ref body, _) => {
         check_block_no_value(fcx, &**body);
-        if !may_break(tcx, expr.id, body.clone()) {
+        if !may_break(tcx, expr.id, &**body) {
             fcx.write_bot(id);
-        }
-        else {
+        } else {
             fcx.write_nil(id);
         }
       }
@@ -3884,7 +3889,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                       expr,
                       ty::RegionTraitStore(region, ast::MutMutable),
                       &**decl,
-                      body.clone(),
+                      &**body,
                       expected);
       }
       ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
@@ -3892,14 +3897,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                               expr,
                               kind,
                               &**decl,
-                              *body);
+                              &**body);
       }
       ast::ExprProc(ref decl, ref body) => {
         check_expr_fn(fcx,
                       expr,
                       ty::UniqTraitStore,
                       &**decl,
-                      body.clone(),
+                      &**body,
                       expected);
       }
       ast::ExprBlock(ref b) => {
@@ -3912,7 +3917,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
           check_expr(fcx, &**f);
           let f_ty = fcx.expr_ty(&**f);
 
-          if !try_overloaded_call(fcx, expr, f.clone(), f_ty, args.as_slice()) {
+          if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
               check_call(fcx, expr, &**f, args.as_slice());
               let (args_bot, args_err) = args.iter().fold((false, false),
                  |(rest_bot, rest_err), a| {
@@ -4050,7 +4055,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
             fcx.write_ty(id, typ);
         }
       }
-      ast::ExprStruct(ref path, ref fields, base_expr) => {
+      ast::ExprStruct(ref path, ref fields, ref base_expr) => {
         // Resolve the path.
         let def = tcx.def_map.borrow().find(&id).map(|i| *i);
         let struct_id = match def {
@@ -4079,7 +4084,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                                  expr.span,
                                                  struct_did,
                                                  fields.as_slice(),
-                                                 base_expr);
+                                                 base_expr.as_ref().map(|e| &**e));
                     }
                     _ => {
                         span_err!(tcx.sess, path.span, E0071,
@@ -4168,9 +4173,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                       match try_overloaded_index(fcx,
                                                  Some(method_call),
                                                  expr,
-                                                 *base,
+                                                 &**base,
                                                  base_t,
-                                                 *idx,
+                                                 idx,
                                                  lvalue_pref) {
                           Some(mt) => fcx.write_ty(id, mt.ty),
                           None => {
@@ -4331,7 +4336,7 @@ pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
     let mut saw_bot = false;
     let mut saw_err = false;
     match stmt.node {
-      ast::StmtDecl(decl, id) => {
+      ast::StmtDecl(ref decl, id) => {
         node_id = id;
         match decl.node {
           ast::DeclLocal(ref l) => {
@@ -4404,7 +4409,7 @@ fn check_block_with_expected(fcx: &FnCtxt,
         let s_id = ast_util::stmt_id(&**s);
         let s_ty = fcx.node_ty(s_id);
         if last_was_bot && !warned && match s.node {
-            ast::StmtDecl(decl, _) => {
+            ast::StmtDecl(ref decl, _) => {
                 match decl.node {
                     ast::DeclLocal(_) => true,
                     _ => false,
@@ -4431,14 +4436,12 @@ fn check_block_with_expected(fcx: &FnCtxt,
     match blk.expr {
         None => if any_err {
             fcx.write_error(blk.id);
-        }
-        else if any_bot {
+        } else if any_bot {
             fcx.write_bot(blk.id);
-        }
-        else  {
+        } else {
             fcx.write_nil(blk.id);
         },
-        Some(e) => {
+        Some(ref e) => {
             if any_bot && !warned {
                 fcx.ccx
                     .tcx
@@ -4450,12 +4453,12 @@ fn check_block_with_expected(fcx: &FnCtxt,
             }
             let ety = match expected {
                 ExpectHasType(ety) => {
-                    check_expr_coercable_to_type(fcx, &*e, ety);
+                    check_expr_coercable_to_type(fcx, &**e, ety);
                     ety
                 }
                 _ => {
-                    check_expr_with_expectation(fcx, &*e, expected);
-                    fcx.expr_ty(&*e)
+                    check_expr_with_expectation(fcx, &**e, expected);
+                    fcx.expr_ty(&**e)
                 }
             };
 
@@ -4603,8 +4606,8 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
 
 
 pub fn check_enum_variants_sized(ccx: &CrateCtxt,
-                                 vs: &[ast::P<ast::Variant>]) {
-    for &v in vs.iter() {
+                                 vs: &[P<ast::Variant>]) {
+    for v in vs.iter() {
         match v.node.kind {
             ast::TupleVariantKind(ref args) if args.len() > 0 => {
                 let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
@@ -4626,7 +4629,9 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt,
                     }
                 }
             },
-            ast::StructVariantKind(struct_def) => check_fields_sized(ccx.tcx, &*struct_def),
+            ast::StructVariantKind(ref struct_def) => {
+                check_fields_sized(ccx.tcx, &**struct_def)
+            }
             _ => {}
         }
     }
@@ -4634,7 +4639,7 @@ pub fn check_enum_variants_sized(ccx: &CrateCtxt,
 
 pub fn check_enum_variants(ccx: &CrateCtxt,
                            sp: Span,
-                           vs: &[ast::P<ast::Variant>],
+                           vs: &[P<ast::Variant>],
                            id: ast::NodeId) {
 
     fn disr_in_range(ccx: &CrateCtxt,
@@ -4665,7 +4670,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
     }
 
     fn do_check(ccx: &CrateCtxt,
-                vs: &[ast::P<ast::Variant>],
+                vs: &[P<ast::Variant>],
                 id: ast::NodeId,
                 hint: attr::ReprAttr)
                 -> Vec<Rc<ty::VariantInfo>> {
@@ -4675,7 +4680,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
         let mut disr_vals: Vec<ty::Disr> = Vec::new();
         let mut prev_disr_val: Option<ty::Disr> = None;
 
-        for &v in vs.iter() {
+        for v in vs.iter() {
 
             // If the discriminant value is specified explicitly in the enum check whether the
             // initialization expression is valid, otherwise use the last value plus one.
@@ -4685,8 +4690,8 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
             };
 
             match v.node.disr_expr {
-                Some(e) => {
-                    debug!("disr expr, checking {}", pprust::expr_to_string(&*e));
+                Some(ref e) => {
+                    debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
 
                     let inh = static_inherited_fields(ccx);
                     let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
@@ -4699,12 +4704,12 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
                             ty::mk_mach_uint(ity)
                         },
                     };
-                    check_const_with_ty(&fcx, e.span, &*e, declty);
+                    check_const_with_ty(&fcx, e.span, &**e, declty);
                     // check_expr (from check_const pass) doesn't guarantee
                     // that the expression is in a form that eval_const_expr can
                     // handle, so we may still get an internal compiler error
 
-                    match const_eval::eval_const_expr_partial(ccx.tcx, &*e) {
+                    match const_eval::eval_const_expr_partial(ccx.tcx, &**e) {
                         Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
                         Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
                         Ok(_) => {
@@ -4742,7 +4747,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
             }
             disr_vals.push(current_disr_val);
 
-            let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &*v,
+            let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
                                                                      current_disr_val));
             prev_disr_val = Some(current_disr_val);
 
@@ -5051,8 +5056,8 @@ pub fn instantiate_path(fcx: &FnCtxt,
         {
             let type_count = type_defs.len(space);
             assert_eq!(substs.types.len(space), 0);
-            for (i, &typ) in segment.types.iter().enumerate() {
-                let t = fcx.to_ty(&*typ);
+            for (i, typ) in segment.types.iter().enumerate() {
+                let t = fcx.to_ty(&**typ);
                 if i < type_count {
                     substs.types.push(space, t);
                 } else if i == type_count {
@@ -5256,7 +5261,7 @@ pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
 }
 
 // Returns true if b contains a break that can exit from b
-pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
+pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
     // First: is there an unlabeled break immediately
     // inside the loop?
     (loop_query(&*b, |e| {
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 843d6a582ea..95b7e03e6d9 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -141,7 +141,6 @@ use syntax::visit;
 use syntax::visit::Visitor;
 
 use std::cell::RefCell;
-use std::gc::Gc;
 
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
@@ -614,23 +613,20 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     match expr.node {
         ast::ExprCall(ref callee, ref args) => {
             if has_method_map {
-                constrain_call(rcx, expr, Some(*callee),
-                               args.as_slice(), false);
+                constrain_call(rcx, expr, Some(&**callee),
+                               args.iter().map(|e| &**e), false);
             } else {
                 constrain_callee(rcx, callee.id, expr, &**callee);
-                constrain_call(rcx,
-                               expr,
-                               None,
-                               args.as_slice(),
-                               false);
+                constrain_call(rcx, expr, None,
+                               args.iter().map(|e| &**e), false);
             }
 
             visit::walk_expr(rcx, expr);
         }
 
         ast::ExprMethodCall(_, _, ref args) => {
-            constrain_call(rcx, expr, Some(*args.get(0)),
-                           args.slice_from(1), false);
+            constrain_call(rcx, expr, Some(&**args.get(0)),
+                           args.slice_from(1).iter().map(|e| &**e), false);
 
             visit::walk_expr(rcx, expr);
         }
@@ -642,8 +638,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
 
         ast::ExprAssignOp(_, ref lhs, ref rhs) => {
             if has_method_map {
-                constrain_call(rcx, expr, Some(lhs.clone()),
-                               [rhs.clone()], true);
+                constrain_call(rcx, expr, Some(&**lhs),
+                               Some(&**rhs).move_iter(), true);
             }
 
             adjust_borrow_kind_for_assignment_lhs(rcx, &**lhs);
@@ -657,15 +653,16 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             // overloaded op.  Note that we (sadly) currently use an
             // implicit "by ref" sort of passing style here.  This
             // should be converted to an adjustment!
-            constrain_call(rcx, expr, Some(lhs.clone()),
-                           [rhs.clone()], true);
+            constrain_call(rcx, expr, Some(&**lhs),
+                           Some(&**rhs).move_iter(), true);
 
             visit::walk_expr(rcx, expr);
         }
 
         ast::ExprUnary(_, ref lhs) if has_method_map => {
             // As above.
-            constrain_call(rcx, expr, Some(lhs.clone()), [], true);
+            constrain_call(rcx, expr, Some(&**lhs),
+                           None::<ast::Expr>.iter(), true);
 
             visit::walk_expr(rcx, expr);
         }
@@ -683,7 +680,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             let method_call = MethodCall::expr(expr.id);
             let base_ty = match rcx.fcx.inh.method_map.borrow().find(&method_call) {
                 Some(method) => {
-                    constrain_call(rcx, expr, Some(base.clone()), [], true);
+                    constrain_call(rcx, expr, Some(&**base),
+                                   None::<ast::Expr>.iter(), true);
                     ty::ty_fn_ret(method.ty)
                 }
                 None => rcx.resolve_node_type(base.id)
@@ -1080,11 +1078,11 @@ fn constrain_callee(rcx: &mut Rcx,
     }
 }
 
-fn constrain_call(rcx: &mut Rcx,
-                  call_expr: &ast::Expr,
-                  receiver: Option<Gc<ast::Expr>>,
-                  arg_exprs: &[Gc<ast::Expr>],
-                  implicitly_ref_args: bool) {
+fn constrain_call<'a, I: Iterator<&'a ast::Expr>>(rcx: &mut Rcx,
+                                                  call_expr: &ast::Expr,
+                                                  receiver: Option<&ast::Expr>,
+                                                  mut arg_exprs: I,
+                                                  implicitly_ref_args: bool) {
     //! Invoked on every call site (i.e., normal calls, method calls,
     //! and overloaded operators). Constrains the regions which appear
     //! in the type of the function. Also constrains the regions that
@@ -1093,11 +1091,9 @@ fn constrain_call(rcx: &mut Rcx,
     let tcx = rcx.fcx.tcx();
     debug!("constrain_call(call_expr={}, \
             receiver={}, \
-            arg_exprs={}, \
             implicitly_ref_args={:?})",
             call_expr.repr(tcx),
             receiver.repr(tcx),
-            arg_exprs.repr(tcx),
             implicitly_ref_args);
 
     // `callee_region` is the scope representing the time in which the
@@ -1109,7 +1105,7 @@ fn constrain_call(rcx: &mut Rcx,
 
     debug!("callee_region={}", callee_region.repr(tcx));
 
-    for arg_expr in arg_exprs.iter() {
+    for arg_expr in arg_exprs {
         debug!("Argument: {}", arg_expr.repr(tcx));
 
         // ensure that any regions appearing in the argument type are
@@ -1123,7 +1119,7 @@ fn constrain_call(rcx: &mut Rcx,
         // result. modes are going away and the "DerefArgs" code
         // should be ported to use adjustments
         if implicitly_ref_args {
-            link_by_ref(rcx, &**arg_expr, callee_scope);
+            link_by_ref(rcx, arg_expr, callee_scope);
         }
     }
 
@@ -1292,10 +1288,10 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
     debug!("regionck::for_local()");
     let init_expr = match local.init {
         None => { return; }
-        Some(ref expr) => expr,
+        Some(ref expr) => &**expr,
     };
     let mc = mc::MemCategorizationContext::new(rcx);
-    let discr_cmt = ignore_err!(mc.cat_expr(&**init_expr));
+    let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
     link_pattern(rcx, mc, discr_cmt, &*local.pat);
 }
 
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index ff3372b3072..8de17627e28 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -597,7 +597,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                         ast_items.iter()
                                  .map(|ast_item| {
                             match *ast_item {
-                                ast::MethodImplItem(ast_method) => {
+                                ast::MethodImplItem(ref ast_method) => {
                                     MethodTraitItemId(
                                         local_def(ast_method.id))
                                 }
@@ -820,9 +820,9 @@ fn subst_receiver_types_in_method_ty(tcx: &ty::ctxt,
     )
 }
 
-pub fn check_coherence(crate_context: &CrateCtxt, krate: &Crate) {
+pub fn check_coherence(crate_context: &CrateCtxt) {
     CoherenceChecker {
         crate_context: crate_context,
         inference_context: new_infer_ctxt(crate_context.tcx),
-    }.check(krate);
+    }.check(crate_context.tcx.map.krate());
 }
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 20e76b01317..581bd8acbc9 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -53,22 +53,22 @@ use util::ppaux::{Repr,UserString};
 
 use std::collections::{HashMap, HashSet};
 use std::rc::Rc;
-use std::gc::Gc;
 
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_map;
-use syntax::ast_util::{local_def, split_trait_methods, PostExpansionMethod};
+use syntax::ast_util::{local_def, PostExpansionMethod};
 use syntax::codemap::Span;
 use syntax::parse::token::{special_idents};
 use syntax::parse::token;
 use syntax::print::pprust::{path_to_string};
+use syntax::ptr::P;
 use syntax::visit;
 
 ///////////////////////////////////////////////////////////////////////////
 // Main entry point
 
-pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
+pub fn collect_item_types(ccx: &CrateCtxt) {
     fn collect_intrinsic_type(ccx: &CrateCtxt,
                               lang_item: ast::DefId) {
         let ty::Polytype { ty: ty, .. } =
@@ -84,10 +84,10 @@ pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
     }
 
     let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
-    visit::walk_crate(&mut visitor, krate);
+    visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
 
     let mut visitor = CollectItemTypesVisitor{ ccx: ccx };
-    visit::walk_crate(&mut visitor, krate);
+    visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -179,7 +179,7 @@ impl<'a, 'tcx> AstConv<'tcx> for CrateCtxt<'a, 'tcx> {
 
 pub fn get_enum_variant_types(ccx: &CrateCtxt,
                               enum_ty: ty::t,
-                              variants: &[ast::P<ast::Variant>],
+                              variants: &[P<ast::Variant>],
                               generics: &ast::Generics) {
     let tcx = ccx.tcx;
 
@@ -199,13 +199,13 @@ pub fn get_enum_variant_types(ccx: &CrateCtxt,
                 enum_ty
             }
 
-            ast::StructVariantKind(struct_def) => {
+            ast::StructVariantKind(ref struct_def) => {
                 let pty = Polytype {
                     generics: ty_generics_for_type(ccx, generics),
                     ty: enum_ty
                 };
 
-                convert_struct(ccx, &*struct_def, pty, variant.node.id);
+                convert_struct(ccx, &**struct_def, pty, variant.node.id);
 
                 let input_tys: Vec<_> = struct_def.fields.iter().map(
                     |f| ty::node_id_to_type(ccx.tcx, f.node.id)).collect();
@@ -332,7 +332,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
                                   *m_id,
                                   *m_fn_style,
                                   trait_self_ty,
-                                  *m_explicit_self,
+                                  m_explicit_self,
                                   m_decl,
                                   m_abi);
         let ty_generics =
@@ -386,13 +386,12 @@ pub fn convert_field(ccx: &CrateCtxt,
     }
 }
 
-fn convert_methods(ccx: &CrateCtxt,
-                   container: ImplOrTraitItemContainer,
-                   ms: &[Gc<ast::Method>],
-                   untransformed_rcvr_ty: ty::t,
-                   rcvr_ty_generics: &ty::Generics,
-                   rcvr_visibility: ast::Visibility)
-{
+fn convert_methods<'a, I: Iterator<&'a ast::Method>>(ccx: &CrateCtxt,
+        container: ImplOrTraitItemContainer,
+        mut ms: I,
+        untransformed_rcvr_ty: ty::t,
+        rcvr_ty_generics: &ty::Generics,
+        rcvr_visibility: ast::Visibility) {
     debug!("convert_methods(untransformed_rcvr_ty={}, \
             rcvr_ty_generics={})",
            untransformed_rcvr_ty.repr(ccx.tcx),
@@ -400,14 +399,14 @@ fn convert_methods(ccx: &CrateCtxt,
 
     let tcx = ccx.tcx;
     let mut seen_methods = HashSet::new();
-    for m in ms.iter() {
+    for m in ms {
         if !seen_methods.insert(m.pe_ident().repr(ccx.tcx)) {
             tcx.sess.span_err(m.span, "duplicate method in trait impl");
         }
 
         let mty = Rc::new(ty_of_method(ccx,
                                        container,
-                                       &**m,
+                                       m,
                                        untransformed_rcvr_ty,
                                        rcvr_ty_generics,
                                        rcvr_visibility));
@@ -459,7 +458,7 @@ fn convert_methods(ccx: &CrateCtxt,
                                   m.id,
                                   m.pe_fn_style(),
                                   untransformed_rcvr_ty,
-                                  *m.pe_explicit_self(),
+                                  m.pe_explicit_self(),
                                   &*m.pe_fn_decl(),
                                   real_abi);
 
@@ -524,10 +523,10 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
         },
         ast::ItemImpl(ref generics,
                       ref opt_trait_ref,
-                      selfty,
+                      ref selfty,
                       ref impl_items) => {
             let ty_generics = ty_generics_for_type(ccx, generics);
-            let selfty = ccx.to_ty(&ExplicitRscope, &*selfty);
+            let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
 
             tcx.tcache.borrow_mut().insert(local_def(it.id),
@@ -554,14 +553,14 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
                                                &BindingRscope::new(method.id),
                                                selfty,
                                                method.pe_explicit_self());
-                        methods.push(*method);
+                        methods.push(&**method);
                     }
                 }
             }
 
             convert_methods(ccx,
                             ImplContainer(local_def(it.id)),
-                            methods.as_slice(),
+                            methods.move_iter(),
                             selfty,
                             &ty_generics,
                             parent_visibility);
@@ -600,12 +599,13 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
             }
 
             // Run convert_methods on the provided methods.
-            let (_, provided_methods) =
-                split_trait_methods(trait_methods.as_slice());
             let untransformed_rcvr_ty = ty::mk_self_type(tcx, local_def(it.id));
             convert_methods(ccx,
                             TraitContainer(local_def(it.id)),
-                            provided_methods.as_slice(),
+                            trait_methods.iter().filter_map(|m| match *m {
+                                ast::RequiredMethod(_) => None,
+                                ast::ProvidedMethod(ref m) => Some(&**m)
+                            }),
                             untransformed_rcvr_ty,
                             &trait_def.generics,
                             it.vis);
@@ -615,7 +615,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
             // static trait methods. This is somewhat unfortunate.
             collect_trait_methods(ccx, it.id, &*trait_def);
         },
-        ast::ItemStruct(struct_def, _) => {
+        ast::ItemStruct(ref struct_def, _) => {
             // Write the class type.
             let pty = ty_of_item(ccx, it);
             write_ty_to_tcx(tcx, it.id, pty.ty);
@@ -624,14 +624,14 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
 
             // Write the super-struct type, if it exists.
             match struct_def.super_struct {
-                Some(ty) => {
-                    let supserty = ccx.to_ty(&ExplicitRscope, &*ty);
+                Some(ref ty) => {
+                    let supserty = ccx.to_ty(&ExplicitRscope, &**ty);
                     write_ty_to_tcx(tcx, it.id, supserty);
                 },
                 _ => {},
             }
 
-            convert_struct(ccx, &*struct_def, pty, it.id);
+            convert_struct(ccx, &**struct_def, pty, it.id);
         },
         ast::ItemTy(_, ref generics) => {
             ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
@@ -683,7 +683,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
     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 {
+        Some(ref t) => match t.node {
             ast::TyPath(_, _, path_id) => {
                 let def_map = tcx.def_map.borrow();
                 match def_map.find(&path_id) {
@@ -692,7 +692,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
                         // Check super-struct is virtual.
                         match tcx.map.find(def_id.node) {
                             Some(ast_map::NodeItem(i)) => match i.node {
-                                ast::ItemStruct(struct_def, _) => {
+                                ast::ItemStruct(ref struct_def, _) => {
                                     if !struct_def.is_virtual {
                                         span_err!(tcx.sess, t.span, E0126,
                                                   "struct inheritance is only \
@@ -908,21 +908,21 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
         _ => {}
     }
     match it.node {
-        ast::ItemStatic(t, _, _) => {
-            let typ = ccx.to_ty(&ExplicitRscope, &*t);
+        ast::ItemStatic(ref t, _, _) => {
+            let typ = ccx.to_ty(&ExplicitRscope, &**t);
             let pty = no_params(typ);
 
             tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
             return pty;
         }
-        ast::ItemFn(decl, fn_style, abi, ref generics, _) => {
+        ast::ItemFn(ref decl, fn_style, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn_or_method(ccx, generics,
                                                            ty::Generics::empty());
             let tofd = astconv::ty_of_bare_fn(ccx,
                                               it.id,
                                               fn_style,
                                               abi,
-                                              &*decl);
+                                              &**decl);
             let pty = Polytype {
                 generics: ty_generics,
                 ty: ty::mk_bare_fn(ccx.tcx, tofd)
@@ -935,14 +935,14 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::Item)
             ccx.tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone());
             return pty;
         }
-        ast::ItemTy(t, ref generics) => {
+        ast::ItemTy(ref t, ref generics) => {
             match tcx.tcache.borrow_mut().find(&local_def(it.id)) {
                 Some(pty) => return pty.clone(),
                 None => { }
             }
 
             let pty = {
-                let ty = ccx.to_ty(&ExplicitRscope, &*t);
+                let ty = ccx.to_ty(&ExplicitRscope, &**t);
                 Polytype {
                     generics: ty_generics_for_type(ccx, generics),
                     ty: ty
@@ -990,17 +990,17 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
                           abi: abi::Abi) -> ty::Polytype
 {
     match it.node {
-        ast::ForeignItemFn(fn_decl, ref generics) => {
+        ast::ForeignItemFn(ref fn_decl, ref generics) => {
             ty_of_foreign_fn_decl(ccx,
-                                  &*fn_decl,
+                                  &**fn_decl,
                                   local_def(it.id),
                                   generics,
                                   abi)
         }
-        ast::ForeignItemStatic(t, _) => {
+        ast::ForeignItemStatic(ref t, _) => {
             ty::Polytype {
                 generics: ty::Generics::empty(),
-                ty: ast_ty_to_ty(ccx, &ExplicitRscope, &*t)
+                ty: ast_ty_to_ty(ccx, &ExplicitRscope, &**t)
             }
         }
     }
@@ -1163,8 +1163,8 @@ fn ty_generics(ccx: &CrateCtxt,
                                     &param.unbound,
                                     param.span,
                                     where_clause);
-        let default = param.default.map(|path| {
-            let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*path);
+            let default = param.default.as_ref().map(|path| {
+            let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
             let cur_idx = index;
 
             ty::walk_ty(ty, |t| {
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index e602e6a7b3c..b5b4cc80faa 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -60,7 +60,6 @@ time of error detection.
 */
 
 use std::collections::HashSet;
-use std::gc::GC;
 use middle::def;
 use middle::subst;
 use middle::ty;
@@ -84,12 +83,12 @@ use std::rc::Rc;
 use std::string::String;
 use syntax::ast;
 use syntax::ast_map;
-use syntax::ast_util;
 use syntax::ast_util::{name_to_dummy_lifetime, PostExpansionMethod};
 use syntax::owned_slice::OwnedSlice;
 use syntax::codemap;
 use syntax::parse::token;
 use syntax::print::pprust;
+use syntax::ptr::P;
 use util::ppaux::bound_region_to_string;
 use util::ppaux::note_and_explain_region;
 
@@ -161,7 +160,7 @@ trait ErrorReportingHelpers {
                                 decl: &ast::FnDecl,
                                 fn_style: ast::FnStyle,
                                 ident: ast::Ident,
-                                opt_explicit_self: Option<ast::ExplicitSelf_>,
+                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
                                 generics: &ast::Generics,
                                 span: codemap::Span);
 }
@@ -855,8 +854,8 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
             Some(ref node) => match *node {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
-                        ast::ItemFn(fn_decl, ref pur, _, ref gen, _) => {
-                            Some((fn_decl, gen, *pur, item.ident, None, item.span))
+                        ast::ItemFn(ref fn_decl, pur, _, ref gen, _) => {
+                            Some((&**fn_decl, gen, pur, item.ident, None, item.span))
                         },
                         _ => None
                     }
@@ -868,7 +867,7 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
                                   m.pe_generics(),
                                   m.pe_fn_style(),
                                   m.pe_ident(),
-                                  Some(m.pe_explicit_self().node),
+                                  Some(&m.pe_explicit_self().node),
                                   m.span))
                         }
                     }
@@ -885,7 +884,7 @@ impl<'a, 'tcx> ErrorReporting for InferCtxt<'a, 'tcx> {
                                        generics, same_regions, &life_giver);
         let (fn_decl, expl_self, generics) = rebuilder.rebuild();
         self.give_expl_lifetime_param(&fn_decl, fn_style, ident,
-                                      expl_self, &generics, span);
+                                      expl_self.as_ref(), &generics, span);
     }
 }
 
@@ -902,8 +901,8 @@ struct RebuildPathInfo<'a> {
 
 struct Rebuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    fn_decl: ast::P<ast::FnDecl>,
-    expl_self_opt: Option<ast::ExplicitSelf_>,
+    fn_decl: &'a ast::FnDecl,
+    expl_self_opt: Option<&'a ast::ExplicitSelf_>,
     generics: &'a ast::Generics,
     same_regions: &'a [SameRegions],
     life_giver: &'a LifeGiver,
@@ -918,8 +917,8 @@ enum FreshOrKept {
 
 impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     fn new(tcx: &'a ty::ctxt<'tcx>,
-           fn_decl: ast::P<ast::FnDecl>,
-           expl_self_opt: Option<ast::ExplicitSelf_>,
+           fn_decl: &'a ast::FnDecl,
+           expl_self_opt: Option<&'a ast::ExplicitSelf_>,
            generics: &'a ast::Generics,
            same_regions: &'a [SameRegions],
            life_giver: &'a LifeGiver)
@@ -938,9 +937,9 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
 
     fn rebuild(&self)
                -> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
-        let mut expl_self_opt = self.expl_self_opt;
+        let mut expl_self_opt = self.expl_self_opt.map(|x| x.clone());
         let mut inputs = self.fn_decl.inputs.clone();
-        let mut output = self.fn_decl.output;
+        let mut output = self.fn_decl.output.clone();
         let mut ty_params = self.generics.ty_params.clone();
         let where_clause = self.generics.where_clause.clone();
         let mut kept_lifetimes = HashSet::new();
@@ -958,7 +957,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                                                    &anon_nums, &region_names);
             inputs = self.rebuild_args_ty(inputs.as_slice(), lifetime,
                                           &anon_nums, &region_names);
-            output = self.rebuild_arg_ty_or_output(output, lifetime,
+            output = self.rebuild_arg_ty_or_output(&*output, lifetime,
                                                    &anon_nums, &region_names);
             ty_params = self.rebuild_ty_params(ty_params, lifetime,
                                                &region_names);
@@ -1068,7 +1067,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                 id: ty_param.id,
                 bounds: bounds,
                 unbound: ty_param.unbound.clone(),
-                default: ty_param.default,
+                default: ty_param.default.clone(),
                 span: ty_param.span,
             }
         })
@@ -1087,8 +1086,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     // be passing down a map.
                     ast::RegionTyParamBound(lt)
                 }
-                &ast::UnboxedFnTyParamBound(unboxed_function_type) => {
-                    ast::UnboxedFnTyParamBound(unboxed_function_type)
+                &ast::UnboxedFnTyParamBound(ref unboxed_function_type) => {
+                    ast::UnboxedFnTyParamBound((*unboxed_function_type).clone())
                 }
                 &ast::TraitTyParamBound(ref tr) => {
                     let last_seg = tr.path.segments.last().unwrap();
@@ -1122,7 +1121,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                          region_names: &HashSet<ast::Name>)
                          -> Option<ast::ExplicitSelf_> {
         match expl_self_opt {
-            Some(expl_self) => match expl_self {
+            Some(ref expl_self) => match *expl_self {
                 ast::SelfRegion(lt_opt, muta, id) => match lt_opt {
                     Some(lt) => if region_names.contains(&lt.name) {
                         return Some(ast::SelfRegion(Some(lifetime), muta, id));
@@ -1177,11 +1176,11 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                        -> Vec<ast::Arg> {
         let mut new_inputs = Vec::new();
         for arg in inputs.iter() {
-            let new_ty = self.rebuild_arg_ty_or_output(arg.ty, lifetime,
+            let new_ty = self.rebuild_arg_ty_or_output(&*arg.ty, lifetime,
                                                        anon_nums, region_names);
             let possibly_new_arg = ast::Arg {
                 ty: new_ty,
-                pat: arg.pat,
+                pat: arg.pat.clone(),
                 id: arg.id
             };
             new_inputs.push(possibly_new_arg);
@@ -1190,36 +1189,40 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 
     fn rebuild_arg_ty_or_output(&self,
-                                ty: ast::P<ast::Ty>,
+                                ty: &ast::Ty,
                                 lifetime: ast::Lifetime,
                                 anon_nums: &HashSet<uint>,
                                 region_names: &HashSet<ast::Name>)
-                                -> ast::P<ast::Ty> {
-        let mut new_ty = ty;
+                                -> P<ast::Ty> {
+        let mut new_ty = P(ty.clone());
         let mut ty_queue = vec!(ty);
-        let mut cur_ty;
         while !ty_queue.is_empty() {
-            cur_ty = ty_queue.shift().unwrap();
+            let cur_ty = ty_queue.shift().unwrap();
             match cur_ty.node {
-                ast::TyRptr(lt_opt, mut_ty) => {
-                    match lt_opt {
-                        Some(lt) => if region_names.contains(&lt.name) {
-                            new_ty = self.rebuild_ty(new_ty, cur_ty,
-                                                     lifetime, None);
-                        },
+                ast::TyRptr(lt_opt, ref mut_ty) => {
+                    let rebuild = match lt_opt {
+                        Some(lt) => region_names.contains(&lt.name),
                         None => {
                             let anon = self.cur_anon.get();
-                            if anon_nums.contains(&anon) {
-                                new_ty = self.rebuild_ty(new_ty, cur_ty,
-                                                         lifetime, None);
+                            let rebuild = anon_nums.contains(&anon);
+                            if rebuild {
                                 self.track_anon(anon);
                             }
                             self.inc_and_offset_cur_anon(1);
+                            rebuild
                         }
+                    };
+                    if rebuild {
+                        let to = ast::Ty {
+                            id: cur_ty.id,
+                            node: ast::TyRptr(Some(lifetime), mut_ty.clone()),
+                            span: cur_ty.span
+                        };
+                        new_ty = self.rebuild_ty(new_ty, P(to));
                     }
-                    ty_queue.push(mut_ty.ty);
+                    ty_queue.push(&*mut_ty.ty);
                 }
-                ast::TyPath(ref path, _, id) => {
+                ast::TyPath(ref path, ref bounds, id) => {
                     let a_def = match self.tcx.def_map.borrow().find(&id) {
                         None => {
                             self.tcx
@@ -1232,10 +1235,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     };
                     match a_def {
                         def::DefTy(did) | def::DefStruct(did) => {
-                            let ty::Polytype {
-                                generics: generics,
-                                ty: _
-                            } = ty::lookup_item_type(self.tcx, did);
+                            let generics = ty::lookup_item_type(self.tcx, did).generics;
 
                             let expected =
                                 generics.regions.len(subst::TypeSpace);
@@ -1266,85 +1266,77 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                                 anon_nums: anon_nums,
                                 region_names: region_names
                             };
-                            new_ty = self.rebuild_ty(new_ty, cur_ty,
-                                                     lifetime,
-                                                     Some(rebuild_info));
+                            let new_path = self.rebuild_path(rebuild_info, lifetime);
+                            let to = ast::Ty {
+                                id: cur_ty.id,
+                                node: ast::TyPath(new_path, bounds.clone(), id),
+                                span: cur_ty.span
+                            };
+                            new_ty = self.rebuild_ty(new_ty, P(to));
                         }
                         _ => ()
                     }
 
                 }
-                _ => ty_queue.push_all_move(ast_util::get_inner_tys(cur_ty))
+
+                ast::TyPtr(ref mut_ty) => {
+                    ty_queue.push(&*mut_ty.ty);
+                }
+                ast::TyBox(ref ty) |
+                ast::TyVec(ref ty) |
+                ast::TyUniq(ref ty) |
+                ast::TyFixedLengthVec(ref ty, _) => {
+                    ty_queue.push(&**ty);
+                }
+                ast::TyTup(ref tys) => ty_queue.extend(tys.iter().map(|ty| &**ty)),
+                _ => {}
             }
         }
         new_ty
     }
 
     fn rebuild_ty(&self,
-                  from: ast::P<ast::Ty>,
-                  to: ast::P<ast::Ty>,
-                  lifetime: ast::Lifetime,
-                  rebuild_path_info: Option<RebuildPathInfo>)
-                  -> ast::P<ast::Ty> {
-
-        fn build_to(from: ast::P<ast::Ty>,
-                    to: ast::P<ast::Ty>)
-                    -> ast::P<ast::Ty> {
-            if from.id == to.id {
-                return to;
-            }
-            let new_node = match from.node {
-                ast::TyRptr(ref lifetime, ref mut_ty) => {
-                    let new_mut_ty = ast::MutTy {
-                        ty: build_to(mut_ty.ty, to),
-                        mutbl: mut_ty.mutbl
-                    };
-                    ast::TyRptr(*lifetime, new_mut_ty)
-                }
-                ast::TyPtr(ref mut_ty) => {
-                    let new_mut_ty = ast::MutTy {
-                        ty: build_to(mut_ty.ty, to),
-                        mutbl: mut_ty.mutbl
-                    };
-                    ast::TyPtr(new_mut_ty)
-                }
-                ast::TyBox(ref ty) => ast::TyBox(build_to(*ty, to)),
-                ast::TyVec(ref ty) => ast::TyVec(build_to(*ty, to)),
-                ast::TyUniq(ref ty) => ast::TyUniq(build_to(*ty, to)),
-                ast::TyFixedLengthVec(ref ty, ref e) => {
-                    ast::TyFixedLengthVec(build_to(*ty, to), *e)
-                }
-                ast::TyTup(ref tys) => {
-                    let mut new_tys = Vec::new();
-                    for ty in tys.iter() {
-                        new_tys.push(build_to(*ty, to));
+                  from: P<ast::Ty>,
+                  to: P<ast::Ty>)
+                  -> P<ast::Ty> {
+
+        fn build_to(from: P<ast::Ty>,
+                    to: &mut Option<P<ast::Ty>>)
+                    -> P<ast::Ty> {
+            if Some(from.id) == to.as_ref().map(|ty| ty.id) {
+                return to.take().expect("`to` type found more than once during rebuild");
+            }
+            from.map(|ast::Ty {id, node, span}| {
+                let new_node = match node {
+                    ast::TyRptr(lifetime, mut_ty) => {
+                        ast::TyRptr(lifetime, ast::MutTy {
+                            mutbl: mut_ty.mutbl,
+                            ty: build_to(mut_ty.ty, to),
+                        })
                     }
-                    ast::TyTup(new_tys)
-                }
-                ast::TyParen(ref typ) => ast::TyParen(build_to(*typ, to)),
-                ref other => other.clone()
-            };
-            box(GC) ast::Ty { id: from.id, node: new_node, span: from.span }
+                    ast::TyPtr(mut_ty) => {
+                        ast::TyPtr(ast::MutTy {
+                            mutbl: mut_ty.mutbl,
+                            ty: build_to(mut_ty.ty, to),
+                        })
+                    }
+                    ast::TyBox(ty) => ast::TyBox(build_to(ty, to)),
+                    ast::TyVec(ty) => ast::TyVec(build_to(ty, to)),
+                    ast::TyUniq(ty) => ast::TyUniq(build_to(ty, to)),
+                    ast::TyFixedLengthVec(ty, e) => {
+                        ast::TyFixedLengthVec(build_to(ty, to), e)
+                    }
+                    ast::TyTup(tys) => {
+                        ast::TyTup(tys.move_iter().map(|ty| build_to(ty, to)).collect())
+                    }
+                    ast::TyParen(typ) => ast::TyParen(build_to(typ, to)),
+                    other => other
+                };
+                ast::Ty { id: id, node: new_node, span: span }
+            })
         }
 
-        let new_ty_node = match to.node {
-            ast::TyRptr(_, mut_ty) => ast::TyRptr(Some(lifetime), mut_ty),
-            ast::TyPath(_, ref bounds, id) => {
-                let rebuild_info = match rebuild_path_info {
-                    Some(ri) => ri,
-                    None => fail!("expect index_opt in rebuild_ty/ast::TyPath")
-                };
-                let new_path = self.rebuild_path(rebuild_info, lifetime);
-                ast::TyPath(new_path, bounds.clone(), id)
-            }
-            _ => fail!("expect ast::TyRptr or ast::TyPath")
-        };
-        let new_ty = box(GC) ast::Ty {
-            id: to.id,
-            node: new_ty_node,
-            span: to.span
-        };
-        build_to(from, new_ty)
+        build_to(from, &mut Some(to))
     }
 
     fn rebuild_path(&self,
@@ -1384,8 +1376,8 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                 }
             }
         }
-        let new_types = last_seg.types.map(|&t| {
-            self.rebuild_arg_ty_or_output(t, lifetime, anon_nums, region_names)
+        let new_types = last_seg.types.map(|t| {
+            self.rebuild_arg_ty_or_output(&**t, lifetime, anon_nums, region_names)
         });
         let new_seg = ast::PathSegment {
             identifier: last_seg.identifier,
@@ -1408,7 +1400,7 @@ impl<'a, 'tcx> ErrorReportingHelpers for InferCtxt<'a, 'tcx> {
                                 decl: &ast::FnDecl,
                                 fn_style: ast::FnStyle,
                                 ident: ast::Ident,
-                                opt_explicit_self: Option<ast::ExplicitSelf_>,
+                                opt_explicit_self: Option<&ast::ExplicitSelf_>,
                                 generics: &ast::Generics,
                                 span: codemap::Span) {
         let suggested_fn = pprust::fun_to_string(decl, fn_style, ident,
@@ -1686,7 +1678,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
             },
             ast_map::NodeImplItem(ii) => {
                 match *ii {
-                    ast::MethodImplItem(m) => {
+                    ast::MethodImplItem(ref m) => {
                         taken.push_all(m.pe_generics().lifetimes.as_slice());
                         Some(m.id)
                     }
diff --git a/src/librustc/middle/typeck/infer/test.rs b/src/librustc/middle/typeck/infer/test.rs
index 198857fca50..c0236cefca3 100644
--- a/src/librustc/middle/typeck/infer/test.rs
+++ b/src/librustc/middle/typeck/infer/test.rs
@@ -36,13 +36,12 @@ use middle::typeck::infer::glb::Glb;
 use syntax::codemap;
 use syntax::codemap::{Span, CodeMap, DUMMY_SP};
 use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note};
-use syntax::ast;
+use syntax::{ast, ast_map};
 use util::ppaux::{ty_to_string, UserString};
 
 use arena::TypedArena;
 
 struct Env<'a, 'tcx: 'a> {
-    krate: ast::Crate,
     infcx: &'a infer::InferCtxt<'a, 'tcx>,
 }
 
@@ -117,19 +116,22 @@ fn test_env(_test_name: &str,
     let krate_config = Vec::new();
     let input = driver::StrInput(source_string.to_string());
     let krate = driver::phase_1_parse_input(&sess, krate_config, &input);
-    let (krate, ast_map) =
-        driver::phase_2_configure_and_expand(&sess, krate, "test", None)
-            .expect("phase 2 aborted");
+    let krate = driver::phase_2_configure_and_expand(&sess, krate, "test", None)
+                    .expect("phase 2 aborted");
+
+    let mut forest = ast_map::Forest::new(krate);
+    let ast_map = driver::assign_node_ids_and_map(&sess, &mut forest);
+    let krate = ast_map.krate();
 
     // run just enough stuff to build a tcx:
-    let lang_items = lang_items::collect_language_items(&krate, &sess);
+    let lang_items = lang_items::collect_language_items(krate, &sess);
     let resolve::CrateMap { def_map: def_map, .. } =
-        resolve::resolve_crate(&sess, &lang_items, &krate);
+        resolve::resolve_crate(&sess, &lang_items, krate);
     let (freevars_map, captures_map) = freevars::annotate_freevars(&def_map,
-                                                                   &krate);
-    let named_region_map = resolve_lifetime::krate(&sess, &krate);
-    let region_map = region::resolve_crate(&sess, &krate);
-    let stability_index = stability::Index::build(&krate);
+                                                                   krate);
+    let named_region_map = resolve_lifetime::krate(&sess, krate);
+    let region_map = region::resolve_crate(&sess, krate);
+    let stability_index = stability::Index::build(krate);
     let type_arena = TypedArena::new();
     let tcx = ty::mk_ctxt(sess,
                           &type_arena,
@@ -142,11 +144,7 @@ fn test_env(_test_name: &str,
                           lang_items,
                           stability_index);
     let infcx = infer::new_infer_ctxt(&tcx);
-    let env = Env {
-        krate: krate,
-        infcx: &infcx
-    };
-    body(env);
+    body(Env { infcx: &infcx });
     infcx.resolve_regions_and_report_errors();
     assert_eq!(tcx.sess.err_count(), expected_err_count);
 }
@@ -171,7 +169,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     }
 
     pub fn lookup_item(&self, names: &[String]) -> ast::NodeId {
-        return match search_mod(self, &self.krate.module, 0, names) {
+        return match search_mod(self, &self.infcx.tcx.map.krate().module, 0, names) {
             Some(id) => id,
             None => {
                 fail!("no item found: `{}`", names.connect("::"));
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 7104cb95844..e59f1aa3ce4 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -308,7 +308,7 @@ pub fn write_substs_to_tcx(tcx: &ty::ctxt,
 }
 pub fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
     match tcx.def_map.borrow().find(&id) {
-        Some(&x) => x,
+        Some(x) => x.clone(),
         _ => {
             tcx.sess.span_fatal(sp, "internal error looking up a definition")
         }
@@ -474,9 +474,7 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt,
-                   trait_map: resolve::TraitMap,
-                   krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt, trait_map: resolve::TraitMap) {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         trait_map: trait_map,
@@ -484,20 +482,20 @@ pub fn check_crate(tcx: &ty::ctxt,
     };
 
     time(time_passes, "type collecting", (), |_|
-        collect::collect_item_types(&ccx, krate));
+        collect::collect_item_types(&ccx));
 
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
     tcx.sess.abort_if_errors();
 
     time(time_passes, "variance inference", (), |_|
-         variance::infer_variance(tcx, krate));
+         variance::infer_variance(tcx));
 
     time(time_passes, "coherence checking", (), |_|
-        coherence::check_coherence(&ccx, krate));
+        coherence::check_coherence(&ccx));
 
     time(time_passes, "type checking", (), |_|
-        check::check_item_types(&ccx, krate));
+        check::check_item_types(&ccx));
 
     check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 9526e5d3eb5..547fbce573b 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -208,8 +208,8 @@ use syntax::visit;
 use syntax::visit::Visitor;
 use util::ppaux::Repr;
 
-pub fn infer_variance(tcx: &ty::ctxt,
-                      krate: &ast::Crate) {
+pub fn infer_variance(tcx: &ty::ctxt) {
+    let krate = tcx.map.krate();
     let mut arena = arena::Arena::new();
     let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);
     let constraints_cx = add_constraints_from_crate(terms_cx, krate);
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index b3ac44a3574..c39f011189a 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -99,7 +99,7 @@ impl<'a, 'v> Visitor<'v> for BlockQueryVisitor<'a> {
 
 // Takes a predicate p, returns true iff p is true for any subexpressions
 // of b -- skipping any inner loops (loop, while, loop_body)
-pub fn block_query(b: ast::P<ast::Block>, p: |&ast::Expr| -> bool) -> bool {
+pub fn block_query(b: &ast::Block, p: |&ast::Expr| -> bool) -> bool {
     let mut v = BlockQueryVisitor {
         p: p,
         flag: false,
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 11f16f1ea95..ba1f7ca2cb2 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -27,7 +27,6 @@ use middle::typeck;
 use middle::typeck::check::regionmanip;
 use middle::typeck::infer;
 
-use std::gc::Gc;
 use std::rc::Rc;
 use syntax::abi;
 use syntax::ast_map;
@@ -546,9 +545,9 @@ impl<T:Repr> Repr for Rc<T> {
     }
 }
 
-impl<T:Repr + 'static> Repr for Gc<T> {
+impl<'a, T:Repr> Repr for &'a T {
     fn repr(&self, tcx: &ctxt) -> String {
-        (&**self).repr(tcx)
+        (*self).repr(tcx)
     }
 }
 
@@ -822,21 +821,19 @@ impl Repr for ast::DefId {
         // a path for a def-id, so I'll just make a best effort for now
         // and otherwise fallback to just printing the crate/node pair
         if self.krate == ast::LOCAL_CRATE {
-            {
-                match tcx.map.find(self.node) {
-                    Some(ast_map::NodeItem(..)) |
-                    Some(ast_map::NodeForeignItem(..)) |
-                    Some(ast_map::NodeImplItem(..)) |
-                    Some(ast_map::NodeTraitItem(..)) |
-                    Some(ast_map::NodeVariant(..)) |
-                    Some(ast_map::NodeStructCtor(..)) => {
-                        return format!(
+            match tcx.map.find(self.node) {
+                Some(ast_map::NodeItem(..)) |
+                Some(ast_map::NodeForeignItem(..)) |
+                Some(ast_map::NodeImplItem(..)) |
+                Some(ast_map::NodeTraitItem(..)) |
+                Some(ast_map::NodeVariant(..)) |
+                Some(ast_map::NodeStructCtor(..)) => {
+                    return format!(
                                 "{:?}:{}",
                                 *self,
                                 ty::item_path_str(tcx, *self))
-                    }
-                    _ => {}
                 }
+                _ => {}
             }
         }
         return format!("{:?}", *self)
diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs
index c3d9edecc6e..415141c0b94 100644
--- a/src/librustc_back/svh.rs
+++ b/src/librustc_back/svh.rs
@@ -264,7 +264,7 @@ mod svh_visitor {
             ExprTup(..)              => SawExprTup,
             ExprBinary(op, _, _)     => SawExprBinary(op),
             ExprUnary(op, _)         => SawExprUnary(op),
-            ExprLit(lit)             => SawExprLit(lit.node.clone()),
+            ExprLit(ref lit)         => SawExprLit(lit.node.clone()),
             ExprCast(..)             => SawExprCast,
             ExprIf(..)               => SawExprIf,
             ExprWhile(..)            => SawExprWhile,