about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/back/archive.rs18
-rw-r--r--src/librustc/back/link.rs77
-rw-r--r--src/librustc/back/lto.rs2
-rw-r--r--src/librustc/back/rpath.rs10
-rw-r--r--src/librustc/driver/driver.rs374
-rw-r--r--src/librustc/driver/session.rs88
-rw-r--r--src/librustc/front/assign_node_ids_and_map.rs8
-rw-r--r--src/librustc/front/feature_gate.rs12
-rw-r--r--src/librustc/front/show_span.rs8
-rw-r--r--src/librustc/front/std_inject.rs20
-rw-r--r--src/librustc/front/test.rs12
-rw-r--r--src/librustc/lib.rs40
-rw-r--r--src/librustc/metadata/creader.rs64
-rw-r--r--src/librustc/metadata/csearch.rs100
-rw-r--r--src/librustc/metadata/decoder.rs40
-rw-r--r--src/librustc/metadata/encoder.rs30
-rw-r--r--src/librustc/metadata/filesearch.rs33
-rw-r--r--src/librustc/metadata/loader.rs6
-rw-r--r--src/librustc/metadata/tydecode.rs14
-rw-r--r--src/librustc/metadata/tyencode.rs39
-rw-r--r--src/librustc/middle/astencode.rs187
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs12
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs4
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs9
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs26
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs2
-rw-r--r--src/librustc/middle/borrowck/mod.rs57
-rw-r--r--src/librustc/middle/borrowck/move_data.rs24
-rw-r--r--src/librustc/middle/cfg/construct.rs8
-rw-r--r--src/librustc/middle/cfg/mod.rs2
-rw-r--r--src/librustc/middle/check_const.rs93
-rw-r--r--src/librustc/middle/check_loop.rs10
-rw-r--r--src/librustc/middle/check_match.rs71
-rw-r--r--src/librustc/middle/check_static.rs13
-rw-r--r--src/librustc/middle/const_eval.rs55
-rw-r--r--src/librustc/middle/dataflow.rs54
-rw-r--r--src/librustc/middle/dead.rs30
-rw-r--r--src/librustc/middle/effect.rs10
-rw-r--r--src/librustc/middle/entry.rs4
-rw-r--r--src/librustc/middle/freevars.rs4
-rw-r--r--src/librustc/middle/kind.rs12
-rw-r--r--src/librustc/middle/lang_items.rs25
-rw-r--r--src/librustc/middle/lint.rs16
-rw-r--r--src/librustc/middle/liveness.rs752
-rw-r--r--src/librustc/middle/mem_categorization.rs21
-rw-r--r--src/librustc/middle/moves.rs88
-rw-r--r--src/librustc/middle/privacy.rs18
-rw-r--r--src/librustc/middle/reachable.rs144
-rw-r--r--src/librustc/middle/region.rs8
-rw-r--r--src/librustc/middle/resolve.rs48
-rw-r--r--src/librustc/middle/resolve_lifetime.rs27
-rw-r--r--src/librustc/middle/subst.rs40
-rw-r--r--src/librustc/middle/trans/_match.rs38
-rw-r--r--src/librustc/middle/trans/adt.rs96
-rw-r--r--src/librustc/middle/trans/asm.rs4
-rw-r--r--src/librustc/middle/trans/base.rs720
-rw-r--r--src/librustc/middle/trans/build.rs78
-rw-r--r--src/librustc/middle/trans/builder.rs23
-rw-r--r--src/librustc/middle/trans/cabi.rs2
-rw-r--r--src/librustc/middle/trans/cabi_arm.rs22
-rw-r--r--src/librustc/middle/trans/cabi_mips.rs32
-rw-r--r--src/librustc/middle/trans/cabi_x86.rs12
-rw-r--r--src/librustc/middle/trans/cabi_x86_64.rs25
-rw-r--r--src/librustc/middle/trans/callee.rs20
-rw-r--r--src/librustc/middle/trans/cleanup.rs26
-rw-r--r--src/librustc/middle/trans/closure.rs33
-rw-r--r--src/librustc/middle/trans/common.rs118
-rw-r--r--src/librustc/middle/trans/consts.rs169
-rw-r--r--src/librustc/middle/trans/context.rs208
-rw-r--r--src/librustc/middle/trans/controlflow.rs14
-rw-r--r--src/librustc/middle/trans/datum.rs6
-rw-r--r--src/librustc/middle/trans/debuginfo.rs198
-rw-r--r--src/librustc/middle/trans/expr.rs51
-rw-r--r--src/librustc/middle/trans/foreign.rs89
-rw-r--r--src/librustc/middle/trans/glue.rs67
-rw-r--r--src/librustc/middle/trans/inline.rs20
-rw-r--r--src/librustc/middle/trans/intrinsic.rs55
-rw-r--r--src/librustc/middle/trans/meth.rs46
-rw-r--r--src/librustc/middle/trans/monomorphize.rs50
-rw-r--r--src/librustc/middle/trans/reflect.rs32
-rw-r--r--src/librustc/middle/trans/tvec.rs16
-rw-r--r--src/librustc/middle/trans/type_.rs167
-rw-r--r--src/librustc/middle/trans/type_of.rs92
-rw-r--r--src/librustc/middle/ty.rs415
-rw-r--r--src/librustc/middle/ty_fold.rs17
-rw-r--r--src/librustc/middle/typeck/astconv.rs19
-rw-r--r--src/librustc/middle/typeck/check/_match.rs6
-rw-r--r--src/librustc/middle/typeck/check/demand.rs4
-rw-r--r--src/librustc/middle/typeck/check/method.rs304
-rw-r--r--src/librustc/middle/typeck/check/mod.rs270
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs26
-rw-r--r--src/librustc/middle/typeck/check/regionmanip.rs12
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs10
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs20
-rw-r--r--src/librustc/middle/typeck/coherence.rs44
-rw-r--r--src/librustc/middle/typeck/collect.rs14
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs4
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs10
-rw-r--r--src/librustc/middle/typeck/infer/glb.rs2
-rw-r--r--src/librustc/middle/typeck/infer/lub.rs2
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs22
-rw-r--r--src/librustc/middle/typeck/infer/region_inference/mod.rs16
-rw-r--r--src/librustc/middle/typeck/infer/resolve.rs4
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs2
-rw-r--r--src/librustc/middle/typeck/infer/unify.rs6
-rw-r--r--src/librustc/middle/typeck/mod.rs30
-rw-r--r--src/librustc/middle/typeck/variance.rs8
-rw-r--r--src/librustc/util/ppaux.rs181
-rw-r--r--src/librustdoc/clean.rs21
-rw-r--r--src/librustdoc/core.rs53
-rw-r--r--src/librustdoc/html/highlight.rs15
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/markdown.rs3
-rw-r--r--src/librustdoc/test.rs53
-rw-r--r--src/librustdoc/visit_ast.rs13
-rw-r--r--src/libsyntax/attr.rs6
-rw-r--r--src/libsyntax/codemap.rs121
-rw-r--r--src/libsyntax/diagnostic.rs42
-rw-r--r--src/libsyntax/ext/base.rs8
-rw-r--r--src/libsyntax/ext/build.rs2
-rw-r--r--src/libsyntax/ext/expand.rs27
-rw-r--r--src/libsyntax/ext/format.rs6
-rw-r--r--src/libsyntax/ext/registrar.rs2
-rw-r--r--src/libsyntax/ext/source_util.rs4
-rw-r--r--src/libsyntax/ext/trace_macros.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs8
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs17
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs16
-rw-r--r--src/libsyntax/fold.rs12
-rw-r--r--src/libsyntax/parse/attr.rs2
-rw-r--r--src/libsyntax/parse/comments.rs4
-rw-r--r--src/libsyntax/parse/lexer.rs208
-rw-r--r--src/libsyntax/parse/mod.rs119
-rw-r--r--src/libsyntax/parse/obsolete.rs2
-rw-r--r--src/libsyntax/parse/parser.rs12
-rw-r--r--src/libsyntax/print/pprust.rs4070
-rw-r--r--src/libsyntax/util/parser_testing.rs34
137 files changed, 5575 insertions, 6157 deletions
diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs
index a47b6860014..863b91f9b32 100644
--- a/src/librustc/back/archive.rs
+++ b/src/librustc/back/archive.rs
@@ -28,8 +28,8 @@ use syntax::abi;
 
 pub static METADATA_FILENAME: &'static str = "rust.metadata.bin";
 
-pub struct Archive {
-    priv sess: Session,
+pub struct Archive<'a> {
+    priv sess: &'a Session,
     priv dst: Path,
 }
 
@@ -37,8 +37,8 @@ pub struct ArchiveRO {
     priv ptr: ArchiveRef,
 }
 
-fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
-        paths: &[&Path]) -> ProcessOutput {
+fn run_ar(sess: &Session, args: &str, cwd: Option<&Path>,
+          paths: &[&Path]) -> ProcessOutput {
     let ar = get_ar_prog(sess);
 
     let mut args = vec!(args.to_owned());
@@ -74,16 +74,16 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
     }
 }
 
-impl Archive {
+impl<'a> Archive<'a> {
     /// Initializes a new static archive with the given object file
-    pub fn create<'a>(sess: Session, dst: &'a Path,
-                      initial_object: &'a Path) -> Archive {
+    pub fn create<'b>(sess: &'a Session, dst: &'b Path,
+                      initial_object: &'b Path) -> Archive<'a> {
         run_ar(sess, "crus", None, [dst, initial_object]);
         Archive { sess: sess, dst: dst.clone() }
     }
 
     /// Opens an existing static archive
-    pub fn open(sess: Session, dst: Path) -> Archive {
+    pub fn open(sess: &'a Session, dst: Path) -> Archive<'a> {
         assert!(dst.exists());
         Archive { sess: sess, dst: dst }
     }
@@ -206,7 +206,7 @@ impl Archive {
         let unixlibname = format!("lib{}.a", name);
 
         let mut rustpath = filesearch::rust_path();
-        rustpath.push(self.sess.filesearch.get_target_lib_path());
+        rustpath.push(self.sess.filesearch().get_target_lib_path());
         let addl_lib_search_paths = self.sess
                                         .opts
                                         .addl_lib_search_paths
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index d68fa0ca241..edb9d11b11a 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -54,7 +54,7 @@ pub enum OutputType {
     OutputTypeExe,
 }
 
-pub fn llvm_err(sess: Session, msg: ~str) -> ! {
+pub fn llvm_err(sess: &Session, msg: ~str) -> ! {
     unsafe {
         let cstr = llvm::LLVMRustGetLastError();
         if cstr == ptr::null() {
@@ -68,7 +68,7 @@ pub fn llvm_err(sess: Session, msg: ~str) -> ! {
 }
 
 pub fn WriteOutputFile(
-        sess: Session,
+        sess: &Session,
         target: lib::llvm::TargetMachineRef,
         pm: lib::llvm::PassManagerRef,
         m: ModuleRef,
@@ -125,7 +125,7 @@ pub mod write {
         }
     }
 
-    pub fn run_passes(sess: Session,
+    pub fn run_passes(sess: &Session,
                       trans: &CrateTranslation,
                       output_types: &[OutputType],
                       output: &OutputFilenames) {
@@ -156,7 +156,7 @@ pub mod write {
 
             let tm = sess.targ_cfg.target_strs.target_triple.with_c_str(|t| {
                 sess.opts.cg.target_cpu.with_c_str(|cpu| {
-                    target_feature(&sess).with_c_str(|features| {
+                    target_feature(sess).with_c_str(|features| {
                         llvm::LLVMRustCreateTargetMachine(
                             t, cpu, features,
                             lib::llvm::CodeModelDefault,
@@ -323,7 +323,7 @@ pub mod write {
         }
     }
 
-    pub fn run_assembler(sess: Session, outputs: &OutputFilenames) {
+    pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
         let cc = super::get_cc_prog(sess);
         let assembly = outputs.temp_path(OutputTypeAssembly);
         let object = outputs.path(OutputTypeObject);
@@ -351,7 +351,7 @@ pub mod write {
         }
     }
 
-    unsafe fn configure_llvm(sess: Session) {
+    unsafe fn configure_llvm(sess: &Session) {
         use sync::one::{Once, ONCE_INIT};
         static mut INIT: Once = ONCE_INIT;
 
@@ -534,7 +534,7 @@ fn truncated_hash_result(symbol_hasher: &mut Sha256) -> ~str {
 
 
 // This calculates STH for a symbol, as defined above
-fn symbol_hash(tcx: ty::ctxt, symbol_hasher: &mut Sha256,
+fn symbol_hash(tcx: &ty::ctxt, symbol_hasher: &mut Sha256,
                t: ty::t, link_meta: &LinkMeta) -> ~str {
     // NB: do *not* use abbrevs here as we want the symbol names
     // to be independent of one another in the crate.
@@ -559,7 +559,7 @@ fn get_symbol_hash(ccx: &CrateContext, t: ty::t) -> ~str {
 
     let mut type_hashcodes = ccx.type_hashcodes.borrow_mut();
     let mut symbol_hasher = ccx.symbol_hasher.borrow_mut();
-    let hash = symbol_hash(ccx.tcx, symbol_hasher.get(), t, &ccx.link_meta);
+    let hash = symbol_hash(ccx.tcx(), symbol_hasher.get(), t, &ccx.link_meta);
     type_hashcodes.get().insert(t, hash.clone());
     hash
 }
@@ -694,7 +694,7 @@ pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
 pub fn mangle_internal_name_by_type_only(ccx: &CrateContext,
                                          t: ty::t,
                                          name: &str) -> ~str {
-    let s = ppaux::ty_to_short_str(ccx.tcx, t);
+    let s = ppaux::ty_to_short_str(ccx.tcx(), t);
     let path = [PathName(token::intern(name)),
                 PathName(token::intern(s))];
     let hash = get_symbol_hash(ccx, t);
@@ -704,7 +704,7 @@ pub fn mangle_internal_name_by_type_only(ccx: &CrateContext,
 pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
                                             t: ty::t,
                                             name: &str) -> ~str {
-    let s = ppaux::ty_to_str(ccx.tcx, t);
+    let s = ppaux::ty_to_str(ccx.tcx(), t);
     let path = [PathName(token::intern(s)),
                 gensym_name(name)];
     let hash = get_symbol_hash(ccx, t);
@@ -719,7 +719,7 @@ pub fn output_lib_filename(id: &CrateId) -> ~str {
     format!("{}-{}-{}", id.name, crate_id_hash(id), id.version_or_default())
 }
 
-pub fn get_cc_prog(sess: Session) -> ~str {
+pub fn get_cc_prog(sess: &Session) -> ~str {
     match sess.opts.cg.linker {
         Some(ref linker) => return linker.to_owned(),
         None => {}
@@ -737,7 +737,7 @@ pub fn get_cc_prog(sess: Session) -> ~str {
     get_system_tool(sess, "cc")
 }
 
-pub fn get_ar_prog(sess: Session) -> ~str {
+pub fn get_ar_prog(sess: &Session) -> ~str {
     match sess.opts.cg.ar {
         Some(ref ar) => return ar.to_owned(),
         None => {}
@@ -746,7 +746,7 @@ pub fn get_ar_prog(sess: Session) -> ~str {
     get_system_tool(sess, "ar")
 }
 
-fn get_system_tool(sess: Session, tool: &str) -> ~str {
+fn get_system_tool(sess: &Session, tool: &str) -> ~str {
     match sess.targ_cfg.os {
         abi::OsAndroid => match sess.opts.cg.android_cross_path {
             Some(ref path) => {
@@ -765,7 +765,7 @@ fn get_system_tool(sess: Session, tool: &str) -> ~str {
     }
 }
 
-fn remove(sess: Session, path: &Path) {
+fn remove(sess: &Session, path: &Path) {
     match fs::unlink(path) {
         Ok(..) => {}
         Err(e) => {
@@ -776,7 +776,7 @@ fn remove(sess: Session, path: &Path) {
 
 /// Perform the linkage portion of the compilation phase. This will generate all
 /// of the requested outputs for this compilation session.
-pub fn link_binary(sess: Session,
+pub fn link_binary(sess: &Session,
                    trans: &CrateTranslation,
                    outputs: &OutputFilenames,
                    id: &CrateId) -> Vec<Path> {
@@ -830,7 +830,7 @@ pub fn filename_for_input(sess: &Session, crate_type: session::CrateType,
     }
 }
 
-fn link_binary_output(sess: Session,
+fn link_binary_output(sess: &Session,
                       trans: &CrateTranslation,
                       crate_type: session::CrateType,
                       outputs: &OutputFilenames,
@@ -840,7 +840,7 @@ fn link_binary_output(sess: Session,
         Some(ref file) => file.clone(),
         None => {
             let out_filename = outputs.path(OutputTypeExe);
-            filename_for_input(&sess, crate_type, id, &out_filename)
+            filename_for_input(sess, crate_type, id, &out_filename)
         }
     };
 
@@ -883,10 +883,10 @@ fn link_binary_output(sess: Session,
 // rlib primarily contains the object file of the crate, but it also contains
 // all of the object files from native libraries. This is done by unzipping
 // native libraries and inserting all of the contents into this archive.
-fn link_rlib(sess: Session,
-             trans: Option<&CrateTranslation>, // None == no metadata/bytecode
-             obj_filename: &Path,
-             out_filename: &Path) -> Archive {
+fn link_rlib<'a>(sess: &'a Session,
+                 trans: Option<&CrateTranslation>, // None == no metadata/bytecode
+                 obj_filename: &Path,
+                 out_filename: &Path) -> Archive<'a> {
     let mut a = Archive::create(sess, out_filename, obj_filename);
 
     let used_libraries = sess.cstore.get_used_libraries();
@@ -985,7 +985,7 @@ fn link_rlib(sess: Session,
 // There's no need to include metadata in a static archive, so ensure to not
 // link in the metadata object file (and also don't prepare the archive with a
 // metadata file).
-fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) {
+fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
     let mut a = link_rlib(sess, None, obj_filename, out_filename);
     a.add_native_library("morestack").unwrap();
     a.add_native_library("compiler-rt").unwrap();
@@ -1000,7 +1000,7 @@ fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) {
             }
         };
         a.add_rlib(&p, name, sess.lto()).unwrap();
-        let native_libs = csearch::get_native_libraries(sess.cstore, cnum);
+        let native_libs = csearch::get_native_libraries(&sess.cstore, cnum);
         for &(kind, ref lib) in native_libs.iter() {
             let name = match kind {
                 cstore::NativeStatic => "static library",
@@ -1016,7 +1016,7 @@ fn link_staticlib(sess: Session, obj_filename: &Path, out_filename: &Path) {
 //
 // This will invoke the system linker/cc to create the resulting file. This
 // links to all upstream files as well.
-fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
+fn link_natively(sess: &Session, dylib: bool, obj_filename: &Path,
                  out_filename: &Path) {
     let tmpdir = TempDir::new("rustc").expect("needs a temp dir");
     // The invocations of cc share some flags across platforms
@@ -1066,7 +1066,7 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
     }
 }
 
-fn link_args(sess: Session,
+fn link_args(sess: &Session,
              dylib: bool,
              tmpdir: &Path,
              obj_filename: &Path,
@@ -1075,7 +1075,7 @@ fn link_args(sess: Session,
     // The default library location, we need this to find the runtime.
     // The location of crates will be determined as needed.
     // FIXME (#9639): This needs to handle non-utf8 paths
-    let lib_path = sess.filesearch.get_target_lib_path();
+    let lib_path = sess.filesearch().get_target_lib_path();
     let stage: ~str = ~"-L" + lib_path.as_str().unwrap();
 
     let mut args = vec!(stage);
@@ -1248,7 +1248,7 @@ fn link_args(sess: Session,
 // Also note that the native libraries linked here are only the ones located
 // in the current crate. Upstream crates with native library dependencies
 // may have their native library pulled in above.
-fn add_local_native_libraries(args: &mut Vec<~str> , sess: Session) {
+fn add_local_native_libraries(args: &mut Vec<~str>, sess: &Session) {
     let addl_lib_search_paths = sess.opts.addl_lib_search_paths.borrow();
     for path in addl_lib_search_paths.get().iter() {
         // FIXME (#9639): This needs to handle non-utf8 paths
@@ -1281,7 +1281,7 @@ fn add_local_native_libraries(args: &mut Vec<~str> , sess: Session) {
 // Rust crates are not considered at all when creating an rlib output. All
 // dependencies will be linked when producing the final output (instead of
 // the intermediate rlib version)
-fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
+fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
                             dylib: bool, tmpdir: &Path) {
 
     // As a limitation of the current implementation, we require that everything
@@ -1302,8 +1302,8 @@ fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
     // * If one form of linking fails, the second is also attempted
     // * If both forms fail, then we emit an error message
 
-    let dynamic = get_deps(sess.cstore, cstore::RequireDynamic);
-    let statik = get_deps(sess.cstore, cstore::RequireStatic);
+    let dynamic = get_deps(&sess.cstore, cstore::RequireDynamic);
+    let statik = get_deps(&sess.cstore, cstore::RequireStatic);
     match (dynamic, statik, sess.opts.cg.prefer_dynamic, dylib) {
         (_, Some(deps), false, false) => {
             add_static_crates(args, sess, tmpdir, deps)
@@ -1352,9 +1352,8 @@ fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
     }
 
     // Converts a library file-stem into a cc -l argument
-    fn unlib(config: @session::Config, stem: &str) -> ~str {
-        if stem.starts_with("lib") &&
-            config.os != abi::OsWin32 {
+    fn unlib(config: &session::Config, stem: &str) -> ~str {
+        if stem.starts_with("lib") && config.os != abi::OsWin32 {
             stem.slice(3, stem.len()).to_owned()
         } else {
             stem.to_owned()
@@ -1376,8 +1375,8 @@ fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
     }
 
     // Adds the static "rlib" versions of all crates to the command line.
-    fn add_static_crates(args: &mut Vec<~str> , sess: Session, tmpdir: &Path,
-                         crates: Vec<(ast::CrateNum, Path)> ) {
+    fn add_static_crates(args: &mut Vec<~str>, sess: &Session, tmpdir: &Path,
+                         crates: Vec<(ast::CrateNum, Path)>) {
         for (cnum, cratepath) in crates.move_iter() {
             // When performing LTO on an executable output, all of the
             // bytecode from the upstream libraries has already been
@@ -1423,7 +1422,7 @@ fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
     }
 
     // Same thing as above, but for dynamic crates instead of static crates.
-    fn add_dynamic_crates(args: &mut Vec<~str> , sess: Session,
+    fn add_dynamic_crates(args: &mut Vec<~str>, sess: &Session,
                           crates: Vec<(ast::CrateNum, Path)> ) {
         // If we're performing LTO, then it should have been previously required
         // that all upstream rust dependencies were available in an rlib format.
@@ -1434,7 +1433,7 @@ fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
             // what its name is
             let dir = cratepath.dirname_str().unwrap();
             if !dir.is_empty() { args.push("-L" + dir); }
-            let libarg = unlib(sess.targ_cfg, cratepath.filestem_str().unwrap());
+            let libarg = unlib(&sess.targ_cfg, cratepath.filestem_str().unwrap());
             args.push("-l" + libarg);
         }
     }
@@ -1458,8 +1457,8 @@ fn add_upstream_rust_crates(args: &mut Vec<~str> , sess: Session,
 // generic function calls a native function, then the generic function must
 // be instantiated in the target crate, meaning that the native symbol must
 // also be resolved in the target crate.
-fn add_upstream_native_libraries(args: &mut Vec<~str> , sess: Session) {
-    let cstore = sess.cstore;
+fn add_upstream_native_libraries(args: &mut Vec<~str>, sess: &Session) {
+    let cstore = &sess.cstore;
     cstore.iter_crate_data(|cnum, _| {
         let libs = csearch::get_native_libraries(cstore, cnum);
         for &(kind, ref lib) in libs.iter() {
diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs
index c0d18672a9b..b42e8f1b92e 100644
--- a/src/librustc/back/lto.rs
+++ b/src/librustc/back/lto.rs
@@ -18,7 +18,7 @@ use util::common::time;
 use std::libc;
 use flate;
 
-pub fn run(sess: session::Session, llmod: ModuleRef,
+pub fn run(sess: &session::Session, llmod: ModuleRef,
            tm: TargetMachineRef, reachable: &[~str]) {
     if sess.opts.cg.prefer_dynamic {
         sess.err("cannot prefer dynamic linking when performing LTO");
diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs
index 9b543bb50cc..d8feb0a47b3 100644
--- a/src/librustc/back/rpath.rs
+++ b/src/librustc/back/rpath.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-use driver::session;
+use driver::session::Session;
 use metadata::cstore;
 use metadata::filesearch;
 
@@ -22,7 +22,7 @@ fn not_win32(os: abi::Os) -> bool {
   os != abi::OsWin32
 }
 
-pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> Vec<~str> {
+pub fn get_rpath_flags(sess: &Session, out_filename: &Path) -> Vec<~str> {
     let os = sess.targ_cfg.os;
 
     // No rpath on windows
@@ -40,7 +40,7 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> Vec<~str>
 
     debug!("preparing the RPATH!");
 
-    let sysroot = sess.filesearch.sysroot;
+    let sysroot = sess.filesearch().sysroot;
     let output = out_filename;
     let libs = sess.cstore.get_used_crates(cstore::RequireDynamic);
     let libs = libs.move_iter().filter_map(|(_, l)| l.map(|p| p.clone())).collect();
@@ -54,9 +54,9 @@ pub fn get_rpath_flags(sess: session::Session, out_filename: &Path) -> Vec<~str>
     flags
 }
 
-fn get_sysroot_absolute_rt_lib(sess: session::Session) -> Path {
+fn get_sysroot_absolute_rt_lib(sess: &Session) -> Path {
     let r = filesearch::relative_target_lib_path(sess.opts.target_triple);
-    let mut p = sess.filesearch.sysroot.join(&r);
+    let mut p = sess.filesearch().sysroot.join(&r);
     p.push(os::dll_filename("rustrt"));
     p
 }
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 91425b89ba6..e7c1e214d07 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -13,7 +13,7 @@ use back::link;
 use back::{arm, x86, x86_64, mips};
 use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
                       FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
-use driver::session::{Session, Session_, No, Less, Default};
+use driver::session::{Session, No, Less, Default};
 use driver::session;
 use front;
 use lib::llvm::llvm;
@@ -27,7 +27,7 @@ use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
 use middle;
 use util::common::time;
 use util::ppaux;
-use util::nodemap::NodeSet;
+use util::nodemap::{NodeMap, NodeSet};
 
 use serialize::{json, Encodable};
 
@@ -35,10 +35,10 @@ use std::cell::{Cell, RefCell};
 use std::io;
 use std::io::fs;
 use std::io::MemReader;
+use std::mem::drop;
 use std::os;
 use std::vec_ng::Vec;
 use std::vec_ng;
-use collections::HashMap;
 use getopts::{optopt, optmulti, optflag, optflagopt};
 use getopts;
 use syntax::ast;
@@ -74,13 +74,13 @@ pub fn anon_src() -> ~str {
 
 pub fn source_name(input: &Input) -> ~str {
     match *input {
-      // FIXME (#9639): This needs to handle non-utf8 paths
-      FileInput(ref ifile) => ifile.as_str().unwrap().to_str(),
-      StrInput(_) => anon_src()
+        // FIXME (#9639): This needs to handle non-utf8 paths
+        FileInput(ref ifile) => ifile.as_str().unwrap().to_str(),
+        StrInput(_) => anon_src()
     }
 }
 
-pub fn default_configuration(sess: Session) ->
+pub fn default_configuration(sess: &Session) ->
    ast::CrateConfig {
     let tos = match sess.targ_cfg.os {
         abi::OsWin32 =>   InternedString::new("win32"),
@@ -123,7 +123,7 @@ pub fn append_configuration(cfg: &mut ast::CrateConfig,
     }
 }
 
-pub fn build_configuration(sess: Session) -> ast::CrateConfig {
+pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
     // Combine the configuration requested by the session (command line) with
     // some default and generated configuration items
     let default_cfg = default_configuration(sess);
@@ -146,11 +146,10 @@ pub fn build_configuration(sess: Session) -> ast::CrateConfig {
 fn parse_cfgspecs(cfgspecs: Vec<~str> )
                   -> ast::CrateConfig {
     cfgspecs.move_iter().map(|s| {
-        let sess = parse::new_parse_sess();
         parse::parse_meta_from_source_str("cfgspec".to_str(),
                                           s,
                                           Vec::new(),
-                                          sess)
+                                          &parse::new_parse_sess())
     }).collect::<ast::CrateConfig>()
 }
 
@@ -170,18 +169,18 @@ impl Input {
     }
 }
 
-pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &Input)
+pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
     -> ast::Crate {
     let krate = time(sess.time_passes(), "parsing", (), |_| {
         match *input {
             FileInput(ref file) => {
-                parse::parse_crate_from_file(&(*file), cfg.clone(), sess.parse_sess)
+                parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess)
             }
             StrInput(ref src) => {
                 parse::parse_crate_from_source_str(anon_src(),
                                                    (*src).clone(),
                                                    cfg.clone(),
-                                                   sess.parse_sess)
+                                                   &sess.parse_sess)
             }
         }
     });
@@ -206,15 +205,15 @@ pub fn phase_1_parse_input(sess: Session, cfg: ast::CrateConfig, input: &Input)
 /// syntax expansion, secondary `cfg` expansion, synthesis of a test
 /// harness if one is to be provided and injection of a dependency on the
 /// standard library and prelude.
-pub fn phase_2_configure_and_expand(sess: Session,
+pub fn phase_2_configure_and_expand(sess: &Session,
                                     loader: &mut CrateLoader,
                                     mut krate: ast::Crate,
                                     crate_id: &CrateId)
                                     -> (ast::Crate, syntax::ast_map::Map) {
     let time_passes = sess.time_passes();
 
-    sess.building_library.set(session::building_library(sess.opts, &krate));
-    sess.crate_types.set(session::collect_crate_types(&sess,
+    sess.building_library.set(session::building_library(&sess.opts, &krate));
+    sess.crate_types.set(session::collect_crate_types(sess,
                                                       krate.attrs
                                                            .as_slice()));
 
@@ -241,7 +240,7 @@ pub fn phase_2_configure_and_expand(sess: Session,
             deriving_hash_type_parameter: sess.features.default_type_params.get(),
             crate_id: crate_id.clone(),
         };
-        syntax::ext::expand::expand_crate(sess.parse_sess,
+        syntax::ext::expand::expand_crate(&sess.parse_sess,
                                           cfg,
                                           krate)
     });
@@ -276,7 +275,7 @@ pub struct CrateAnalysis {
     public_items: middle::privacy::PublicItems,
     ty_cx: ty::ctxt,
     maps: astencode::Maps,
-    reachable: @RefCell<NodeSet>,
+    reachable: NodeSet,
 }
 
 /// Run the resolution, typechecking, region checking and other
@@ -289,12 +288,12 @@ pub fn phase_3_run_analysis_passes(sess: Session,
     let time_passes = sess.time_passes();
 
     time(time_passes, "external crate/lib resolution", (), |_|
-         creader::read_crates(sess, krate,
+         creader::read_crates(&sess, krate,
                               session::sess_os_to_meta_os(sess.targ_cfg.os),
                               token::get_ident_interner()));
 
     let lang_items = time(time_passes, "language item collection", (), |_|
-                          middle::lang_items::collect_language_items(krate, sess));
+                          middle::lang_items::collect_language_items(krate, &sess));
 
     let middle::resolve::CrateMap {
         def_map: def_map,
@@ -304,93 +303,92 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         last_private_map: last_private_map
     } =
         time(time_passes, "resolution", (), |_|
-             middle::resolve::resolve_crate(sess, lang_items, krate));
+             middle::resolve::resolve_crate(&sess, lang_items, krate));
 
     let named_region_map = time(time_passes, "lifetime resolution", (),
-                                |_| middle::resolve_lifetime::krate(sess, krate));
+                                |_| 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, krate, &ast_map));
 
     sess.macro_registrar_fn.with_mut(|r| *r =
         time(time_passes, "looking for macro registrar", (), |_|
             syntax::ext::registrar::find_macro_registrar(
-                sess.span_diagnostic, krate)));
+                sess.diagnostic(), krate)));
 
     let freevars = time(time_passes, "freevar finding", (), |_|
                         freevars::annotate_freevars(def_map, krate));
 
     let region_map = time(time_passes, "region resolution", (), |_|
-                          middle::region::resolve_crate(sess, krate));
+                          middle::region::resolve_crate(&sess, krate));
 
     let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map,
                             freevars, region_map, lang_items);
 
     // passes are timed inside typeck
-    let (method_map, vtable_map) = typeck::check_crate(ty_cx, trait_map, krate);
+    let (method_map, vtable_map) = typeck::check_crate(&ty_cx, trait_map, krate);
 
     time(time_passes, "check static items", (), |_|
-         middle::check_static::check_crate(ty_cx, krate));
+         middle::check_static::check_crate(&ty_cx, krate));
 
     // 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(krate, &ty_cx));
 
     time(time_passes, "const checking", (), |_|
-         middle::check_const::check_crate(sess, krate, def_map,
-                                          method_map, ty_cx));
+         middle::check_const::check_crate(krate, def_map, method_map, &ty_cx));
 
     let maps = (external_exports, last_private_map);
     let (exported_items, public_items) =
             time(time_passes, "privacy checking", maps, |(a, b)|
-                 middle::privacy::check_crate(ty_cx, &method_map, &exp_map2,
+                 middle::privacy::check_crate(&ty_cx, &method_map, &exp_map2,
                                               a, b, krate));
 
     time(time_passes, "effect checking", (), |_|
-         middle::effect::check_crate(ty_cx, method_map, krate));
+         middle::effect::check_crate(&ty_cx, method_map, krate));
 
     time(time_passes, "loop checking", (), |_|
-         middle::check_loop::check_crate(ty_cx, krate));
+         middle::check_loop::check_crate(&ty_cx, krate));
 
     let middle::moves::MoveMaps {moves_map, moved_variables_set,
                                  capture_map} =
         time(time_passes, "compute moves", (), |_|
-             middle::moves::compute_moves(ty_cx, method_map, krate));
+             middle::moves::compute_moves(&ty_cx, method_map, krate));
 
     time(time_passes, "match checking", (), |_|
-         middle::check_match::check_crate(ty_cx, method_map,
-                                          moves_map, krate));
+         middle::check_match::check_crate(&ty_cx, method_map,
+                                          &moves_map, krate));
 
     time(time_passes, "liveness checking", (), |_|
-         middle::liveness::check_crate(ty_cx, method_map,
-                                       capture_map, krate));
+         middle::liveness::check_crate(&ty_cx, method_map,
+                                       &capture_map, krate));
 
     let root_map =
         time(time_passes, "borrow checking", (), |_|
-             middle::borrowck::check_crate(ty_cx, method_map,
-                                           moves_map, moved_variables_set,
-                                           capture_map, krate));
+             middle::borrowck::check_crate(&ty_cx, method_map,
+                                           &moves_map, &moved_variables_set,
+                                           &capture_map, krate));
+
+    drop(moves_map);
+    drop(moved_variables_set);
 
     time(time_passes, "kind checking", (), |_|
-         kind::check_crate(ty_cx, method_map, krate));
+         kind::check_crate(&ty_cx, method_map, krate));
 
     let reachable_map =
         time(time_passes, "reachability checking", (), |_|
-             reachable::find_reachable(ty_cx, method_map, &exported_items));
-
-    {
-        let reachable_map = reachable_map.borrow();
-        time(time_passes, "death checking", (), |_| {
-             middle::dead::check_crate(ty_cx,
-                                       method_map,
-                                       &exported_items,
-                                       reachable_map.get(),
-                                       krate)
-        });
-    }
+             reachable::find_reachable(&ty_cx, method_map, &exported_items));
+
+    time(time_passes, "death checking", (), |_| {
+        middle::dead::check_crate(&ty_cx,
+                                  method_map,
+                                  &exported_items,
+                                  &reachable_map,
+                                  krate)
+    });
 
     time(time_passes, "lint checking", (), |_|
-         lint::check_crate(ty_cx, method_map, &exported_items, krate));
+         lint::check_crate(&ty_cx, method_map, &exported_items, krate));
 
     CrateAnalysis {
         exp_map2: exp_map2,
@@ -401,7 +399,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
             root_map: root_map,
             method_map: method_map,
             vtable_map: vtable_map,
-            capture_map: capture_map
+            capture_map: RefCell::new(capture_map)
         },
         reachable: reachable_map
     }
@@ -418,17 +416,19 @@ 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(sess: Session,
-                                 krate: ast::Crate,
-                                 analysis: &CrateAnalysis,
-                                 outputs: &OutputFilenames) -> CrateTranslation {
-    time(sess.time_passes(), "translation", krate, |krate|
-         trans::base::trans_crate(sess, krate, analysis, outputs))
+pub fn phase_4_translate_to_llvm(krate: ast::Crate,
+                                 analysis: CrateAnalysis,
+                                 outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
+    // Option dance to work around the lack of stack once closures.
+    let time_passes = analysis.ty_cx.sess.time_passes();
+    let mut analysis = Some(analysis);
+    time(time_passes, "translation", krate, |krate|
+         trans::base::trans_crate(krate, analysis.take_unwrap(), outputs))
 }
 
 /// Run LLVM itself, producing a bitcode file, assembly file or object file
 /// as a side effect.
-pub fn phase_5_run_llvm_passes(sess: Session,
+pub fn phase_5_run_llvm_passes(sess: &Session,
                                trans: &CrateTranslation,
                                outputs: &OutputFilenames) {
     if sess.opts.cg.no_integrated_as {
@@ -454,7 +454,7 @@ pub fn phase_5_run_llvm_passes(sess: Session,
 
 /// Run the linker on any artifacts that resulted from the LLVM run.
 /// This should produce either a finished executable or library.
-pub fn phase_6_link_output(sess: Session,
+pub fn phase_6_link_output(sess: &Session,
                            trans: &CrateTranslation,
                            outputs: &OutputFilenames) {
     time(sess.time_passes(), "linking", (), |_|
@@ -464,7 +464,7 @@ pub fn phase_6_link_output(sess: Session,
                            &trans.link.crateid));
 }
 
-pub fn stop_after_phase_3(sess: Session) -> bool {
+pub fn stop_after_phase_3(sess: &Session) -> bool {
    if sess.opts.no_trans {
         debug!("invoked with --no-trans, returning early from compile_input");
         return true;
@@ -472,7 +472,7 @@ pub fn stop_after_phase_3(sess: Session) -> bool {
     return false;
 }
 
-pub fn stop_after_phase_1(sess: Session) -> bool {
+pub fn stop_after_phase_1(sess: &Session) -> bool {
     if sess.opts.parse_only {
         debug!("invoked with --parse-only, returning early from compile_input");
         return true;
@@ -483,7 +483,7 @@ pub fn stop_after_phase_1(sess: Session) -> bool {
     return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
 }
 
-pub fn stop_after_phase_2(sess: Session) -> bool {
+pub fn stop_after_phase_2(sess: &Session) -> bool {
     if sess.opts.no_analysis {
         debug!("invoked with --no-analysis, returning early from compile_input");
         return true;
@@ -491,7 +491,7 @@ pub fn stop_after_phase_2(sess: Session) -> bool {
     return sess.opts.debugging_opts & session::AST_JSON != 0;
 }
 
-pub fn stop_after_phase_5(sess: Session) -> bool {
+pub fn stop_after_phase_5(sess: &Session) -> bool {
     if !sess.opts.output_types.iter().any(|&i| i == link::OutputTypeExe) {
         debug!("not building executable, returning early from compile_input");
         return true;
@@ -499,7 +499,7 @@ pub fn stop_after_phase_5(sess: Session) -> bool {
     return false;
 }
 
-fn write_out_deps(sess: Session,
+fn write_out_deps(sess: &Session,
                   input: &Input,
                   outputs: &OutputFilenames,
                   krate: &ast::Crate) -> io::IoResult<()> {
@@ -512,7 +512,7 @@ fn write_out_deps(sess: Session,
             link::OutputTypeExe => {
                 let crate_types = sess.crate_types.borrow();
                 for output in crate_types.get().iter() {
-                    let p = link::filename_for_input(&sess, *output, &id, &file);
+                    let p = link::filename_for_input(sess, *output, &id, &file);
                     out_filenames.push(p);
                 }
             }
@@ -540,19 +540,14 @@ fn write_out_deps(sess: Session,
 
     // Build a list of files used to compile the output and
     // write Makefile-compatible dependency rules
-    let files: Vec<~str> = {
-        let files = sess.codemap.files.borrow();
-        files.get()
-             .iter()
-             .filter_map(|fmap| {
-                 if fmap.is_real_file() {
-                     Some(fmap.name.clone())
-                 } else {
-                     None
-                 }
-             })
-             .collect()
-    };
+    let files: Vec<~str> = sess.codemap().files.borrow().get()
+                               .iter().filter_map(|fmap| {
+                                    if fmap.deref().is_real_file() {
+                                        Some(fmap.deref().name.clone())
+                                    } else {
+                                        None
+                                    }
+                                }).collect();
     let mut file = try!(io::File::create(&deps_filename));
     for path in out_filenames.iter() {
         try!(write!(&mut file as &mut Writer,
@@ -566,65 +561,70 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let outputs;
-    let trans = {
-        let (expanded_crate, ast_map) = {
-            let krate = phase_1_parse_input(sess, cfg, input);
-            if stop_after_phase_1(sess) { return; }
-            outputs = build_output_filenames(input,
-                                             outdir,
-                                             output,
-                                             krate.attrs.as_slice(),
-                                             sess);
-            let loader = &mut Loader::new(sess);
+    let (outputs, trans, sess) = {
+        let (outputs, expanded_crate, ast_map) = {
+            let krate = phase_1_parse_input(&sess, cfg, input);
+            if stop_after_phase_1(&sess) { return; }
+            let outputs = build_output_filenames(input,
+                                                 outdir,
+                                                 output,
+                                                 krate.attrs.as_slice(),
+                                                 &sess);
+            let loader = &mut Loader::new(&sess);
             let id = link::find_crate_id(krate.attrs.as_slice(),
                                          outputs.out_filestem);
-            phase_2_configure_and_expand(sess, loader, krate, &id)
+            let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
+                                                                         krate, &id);
+            (outputs, expanded_crate, ast_map)
         };
+        write_out_deps(&sess, input, &outputs, &expanded_crate).unwrap();
 
-        write_out_deps(sess, input, &outputs, &expanded_crate).unwrap();
-
-        if stop_after_phase_2(sess) { return; }
+        if stop_after_phase_2(&sess) { return; }
 
         let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
-        if stop_after_phase_3(sess) { return; }
-        phase_4_translate_to_llvm(sess, expanded_crate, &analysis, &outputs)
+        if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
+        let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
+                                                     analysis, &outputs);
+        (outputs, trans, tcx.sess)
     };
-    phase_5_run_llvm_passes(sess, &trans, &outputs);
-    if stop_after_phase_5(sess) { return; }
-    phase_6_link_output(sess, &trans, &outputs);
+    phase_5_run_llvm_passes(&sess, &trans, &outputs);
+    if stop_after_phase_5(&sess) { return; }
+    phase_6_link_output(&sess, &trans, &outputs);
 }
 
 struct IdentifiedAnnotation;
 
 impl pprust::PpAnn for IdentifiedAnnotation {
-    fn pre(&self, node: pprust::AnnNode) -> io::IoResult<()> {
+    fn pre(&self,
+           s: &mut pprust::State<IdentifiedAnnotation>,
+           node: pprust::AnnNode) -> io::IoResult<()> {
         match node {
-            pprust::NodeExpr(s, _) => pprust::popen(s),
+            pprust::NodeExpr(_) => s.popen(),
             _ => Ok(())
         }
     }
-    fn post(&self, node: pprust::AnnNode) -> io::IoResult<()> {
+    fn post(&self,
+            s: &mut pprust::State<IdentifiedAnnotation>,
+            node: pprust::AnnNode) -> io::IoResult<()> {
         match node {
-            pprust::NodeItem(s, item) => {
+            pprust::NodeItem(item) => {
                 try!(pp::space(&mut s.s));
-                try!(pprust::synth_comment(s, item.id.to_str()));
+                s.synth_comment(item.id.to_str())
             }
-            pprust::NodeBlock(s, blk) => {
+            pprust::NodeBlock(blk) => {
                 try!(pp::space(&mut s.s));
-                try!(pprust::synth_comment(s, ~"block " + blk.id.to_str()));
+                s.synth_comment(~"block " + blk.id.to_str())
             }
-            pprust::NodeExpr(s, expr) => {
+            pprust::NodeExpr(expr) => {
                 try!(pp::space(&mut s.s));
-                try!(pprust::synth_comment(s, expr.id.to_str()));
-                try!(pprust::pclose(s));
+                try!(s.synth_comment(expr.id.to_str()));
+                s.pclose()
             }
-            pprust::NodePat(s, pat) => {
+            pprust::NodePat(pat) => {
                 try!(pp::space(&mut s.s));
-                try!(pprust::synth_comment(s, ~"pat " + pat.id.to_str()));
+                s.synth_comment(~"pat " + pat.id.to_str())
             }
         }
-        Ok(())
     }
 }
 
@@ -633,26 +633,29 @@ struct TypedAnnotation {
 }
 
 impl pprust::PpAnn for TypedAnnotation {
-    fn pre(&self, node: pprust::AnnNode) -> io::IoResult<()> {
+    fn pre(&self,
+           s: &mut pprust::State<TypedAnnotation>,
+           node: pprust::AnnNode) -> io::IoResult<()> {
         match node {
-            pprust::NodeExpr(s, _) => pprust::popen(s),
+            pprust::NodeExpr(_) => s.popen(),
             _ => Ok(())
         }
     }
-    fn post(&self, node: pprust::AnnNode) -> io::IoResult<()> {
-        let tcx = self.analysis.ty_cx;
+    fn post(&self,
+            s: &mut pprust::State<TypedAnnotation>,
+            node: pprust::AnnNode) -> io::IoResult<()> {
+        let tcx = &self.analysis.ty_cx;
         match node {
-            pprust::NodeExpr(s, expr) => {
+            pprust::NodeExpr(expr) => {
                 try!(pp::space(&mut s.s));
                 try!(pp::word(&mut s.s, "as"));
                 try!(pp::space(&mut s.s));
                 try!(pp::word(&mut s.s,
                                 ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr))));
-                try!(pprust::pclose(s));
+                s.pclose()
             }
-            _ => ()
+            _ => Ok(())
         }
-        Ok(())
     }
 }
 
@@ -660,44 +663,61 @@ pub fn pretty_print_input(sess: Session,
                           cfg: ast::CrateConfig,
                           input: &Input,
                           ppm: PpMode) {
-    let krate = phase_1_parse_input(sess, cfg, input);
+    let krate = phase_1_parse_input(&sess, cfg, input);
     let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
 
     let (krate, ast_map, is_expanded) = match ppm {
         PpmExpanded | PpmExpandedIdentified | PpmTyped => {
-            let loader = &mut Loader::new(sess);
-            let (krate, ast_map) = phase_2_configure_and_expand(sess, loader,
+            let loader = &mut Loader::new(&sess);
+            let (krate, ast_map) = phase_2_configure_and_expand(&sess, loader,
                                                                 krate, &id);
             (krate, Some(ast_map), true)
         }
         _ => (krate, None, false)
     };
 
-    let annotation = match ppm {
+    let src_name = source_name(input);
+    let src = sess.codemap().get_filemap(src_name).deref().src.as_bytes().to_owned();
+    let mut rdr = MemReader::new(src);
+
+    match ppm {
         PpmIdentified | PpmExpandedIdentified => {
-            ~IdentifiedAnnotation as ~pprust::PpAnn
+            pprust::print_crate(sess.codemap(),
+                                sess.diagnostic(),
+                                &krate,
+                                src_name,
+                                &mut rdr,
+                                ~io::stdout(),
+                                &IdentifiedAnnotation,
+                                is_expanded)
         }
         PpmTyped => {
             let ast_map = ast_map.expect("--pretty=typed missing ast_map");
             let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
-            ~TypedAnnotation {
+            let annotation = TypedAnnotation {
                 analysis: analysis
-            } as ~pprust::PpAnn:
+            };
+            pprust::print_crate(annotation.analysis.ty_cx.sess.codemap(),
+                                annotation.analysis.ty_cx.sess.diagnostic(),
+                                &krate,
+                                src_name,
+                                &mut rdr,
+                                ~io::stdout(),
+                                &annotation,
+                                is_expanded)
         }
-        _ => ~pprust::NoAnn as ~pprust::PpAnn:,
-    };
+        _ => {
+            pprust::print_crate(sess.codemap(),
+                                sess.diagnostic(),
+                                &krate,
+                                src_name,
+                                &mut rdr,
+                                ~io::stdout(),
+                                &pprust::NoAnn,
+                                is_expanded)
+        }
+    }.unwrap()
 
-    let src = &sess.codemap.get_filemap(source_name(input)).src;
-    let mut rdr = MemReader::new(src.as_bytes().to_owned());
-    let stdout = io::stdout();
-    pprust::print_crate(sess.codemap,
-                        sess.span_diagnostic,
-                        &krate,
-                        source_name(input),
-                        &mut rdr,
-                        ~stdout as ~io::Writer,
-                        annotation,
-                        is_expanded).unwrap();
 }
 
 pub fn get_os(triple: &str) -> Option<abi::Os> {
@@ -735,8 +755,7 @@ static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'stat
 
     ("mips",   abi::Mips)];
 
-pub fn build_target_config(sopts: @session::Options)
-                           -> @session::Config {
+pub fn build_target_config(sopts: &session::Options) -> session::Config {
     let os = match get_os(sopts.target_triple) {
       Some(os) => os,
       None => early_error("unknown operating system")
@@ -758,14 +777,13 @@ pub fn build_target_config(sopts: @session::Options)
       abi::Arm => arm::get_target_strs(target_triple, os),
       abi::Mips => mips::get_target_strs(target_triple, os)
     };
-    let target_cfg = @session::Config {
+    session::Config {
         os: os,
         arch: arch,
         target_strs: target_strs,
         int_type: int_type,
         uint_type: uint_type,
-    };
-    return target_cfg;
+    }
 }
 
 pub fn host_triple() -> ~str {
@@ -780,8 +798,7 @@ pub fn host_triple() -> ~str {
     (env!("CFG_COMPILER")).to_owned()
 }
 
-pub fn build_session_options(matches: &getopts::Matches)
-                             -> @session::Options {
+pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
     let mut crate_types: Vec<CrateType> = Vec::new();
     let unparsed_crate_types = matches.opt_strs("crate-type");
     for unparsed_crate_type in unparsed_crate_types.iter() {
@@ -871,7 +888,7 @@ pub fn build_session_options(matches: &getopts::Matches)
         output_types.push(link::OutputTypeExe);
     }
 
-    let sysroot_opt = matches.opt_str("sysroot").map(|m| @Path::new(m));
+    let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
     let target = matches.opt_str("target").unwrap_or(host_triple());
     let opt_level = {
         if (debugging_opts & session::NO_OPT) != 0 {
@@ -932,14 +949,14 @@ pub fn build_session_options(matches: &getopts::Matches)
                        matches.opt_present("crate-file-name"));
     let cg = build_codegen_options(matches);
 
-    let sopts = @session::Options {
+    session::Options {
         crate_types: crate_types,
         gc: gc,
         optimize: opt_level,
         debuginfo: debuginfo,
         lint_opts: lint_opts,
         output_types: output_types,
-        addl_lib_search_paths: @RefCell::new(addl_lib_search_paths),
+        addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
         maybe_sysroot: sysroot_opt,
         target_triple: target,
         cfg: cfg,
@@ -951,8 +968,7 @@ pub fn build_session_options(matches: &getopts::Matches)
         write_dependency_info: write_dependency_info,
         print_metas: print_metas,
         cg: cg,
-    };
-    return sopts;
+    }
 }
 
 pub fn build_codegen_options(matches: &getopts::Matches)
@@ -986,30 +1002,28 @@ pub fn build_codegen_options(matches: &getopts::Matches)
     return cg;
 }
 
-pub fn build_session(sopts: @session::Options,
+pub fn build_session(sopts: session::Options,
                      local_crate_source_file: Option<Path>)
                      -> Session {
-    let codemap = @codemap::CodeMap::new();
+    let codemap = codemap::CodeMap::new();
     let diagnostic_handler =
         diagnostic::default_handler();
     let span_diagnostic_handler =
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
-    build_session_(sopts, local_crate_source_file, codemap, span_diagnostic_handler)
+    build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
 }
 
-pub fn build_session_(sopts: @session::Options,
+pub fn build_session_(sopts: session::Options,
                       local_crate_source_file: Option<Path>,
-                      codemap: @codemap::CodeMap,
-                      span_diagnostic_handler: @diagnostic::SpanHandler)
+                      span_diagnostic: diagnostic::SpanHandler)
                       -> Session {
-    let target_cfg = build_target_config(sopts);
-    let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler, codemap);
-    let cstore = @CStore::new(token::get_ident_interner());
-    let filesearch = @filesearch::FileSearch::new(
-        &sopts.maybe_sysroot,
-        sopts.target_triple,
-        sopts.addl_lib_search_paths);
+    let target_cfg = build_target_config(&sopts);
+    let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
+    let default_sysroot = match sopts.maybe_sysroot {
+        Some(_) => None,
+        None => Some(filesearch::get_or_default_sysroot())
+    };
 
     // Make the path absolute, if necessary
     let local_crate_source_file = local_crate_source_file.map(|path|
@@ -1020,30 +1034,28 @@ pub fn build_session_(sopts: @session::Options,
         }
     );
 
-    @Session_ {
+    Session {
         targ_cfg: target_cfg,
         opts: sopts,
-        cstore: cstore,
+        cstore: CStore::new(token::get_ident_interner()),
         parse_sess: p_s,
-        codemap: codemap,
         // For a library crate, this is always none
         entry_fn: RefCell::new(None),
         entry_type: Cell::new(None),
         macro_registrar_fn: RefCell::new(None),
-        span_diagnostic: span_diagnostic_handler,
-        filesearch: filesearch,
+        default_sysroot: default_sysroot,
         building_library: Cell::new(false),
         local_crate_source_file: local_crate_source_file,
         working_dir: os::getcwd(),
-        lints: RefCell::new(HashMap::new()),
+        lints: RefCell::new(NodeMap::new()),
         node_id: Cell::new(1),
-        crate_types: @RefCell::new(Vec::new()),
+        crate_types: RefCell::new(Vec::new()),
         features: front::feature_gate::Features::new(),
         recursion_limit: Cell::new(64),
     }
 }
 
-pub fn parse_pretty(sess: Session, name: &str) -> PpMode {
+pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
     match name {
       &"normal" => PpmNormal,
       &"expanded" => PpmExpanded,
@@ -1143,7 +1155,7 @@ pub fn build_output_filenames(input: &Input,
                               odir: &Option<Path>,
                               ofile: &Option<Path>,
                               attrs: &[ast::Attribute],
-                              sess: Session)
+                              sess: &Session)
                            -> OutputFilenames {
     match *ofile {
         None => {
@@ -1196,7 +1208,7 @@ pub fn early_error(msg: &str) -> ! {
     fail!(diagnostic::FatalError);
 }
 
-pub fn list_metadata(sess: Session, path: &Path,
+pub fn list_metadata(sess: &Session, path: &Path,
                      out: &mut io::Writer) -> io::IoResult<()> {
     metadata::loader::list_file_metadata(
         session::sess_os_to_meta_os(sess.targ_cfg.os), path, out)
@@ -1222,7 +1234,7 @@ mod test {
             };
         let sessopts = build_session_options(matches);
         let sess = build_session(sessopts, None);
-        let cfg = build_configuration(sess);
+        let cfg = build_configuration(&sess);
         assert!((attr::contains_name(cfg.as_slice(), "test")));
     }
 
@@ -1241,7 +1253,7 @@ mod test {
             };
         let sessopts = build_session_options(matches);
         let sess = build_session(sessopts, None);
-        let cfg = build_configuration(sess);
+        let cfg = build_configuration(&sess);
         let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
         assert!(test_items.next().is_some());
         assert!(test_items.next().is_none());
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index b4e1516074e..8d3048a80b2 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -16,6 +16,7 @@ use front;
 use metadata::filesearch;
 use metadata;
 use middle::lint;
+use util::nodemap::NodeMap;
 
 use syntax::attr::AttrMetaMethods;
 use syntax::ast::NodeId;
@@ -28,7 +29,7 @@ use syntax;
 
 use std::cell::{Cell, RefCell};
 use std::vec_ng::Vec;
-use collections::{HashMap,HashSet};
+use collections::HashSet;
 
 pub struct Config {
     os: abi::Os,
@@ -134,8 +135,8 @@ pub struct Options {
     // This was mutable for rustpkg, which updates search paths based on the
     // parsed code. It remains mutable in case its replacements wants to use
     // this.
-    addl_lib_search_paths: @RefCell<HashSet<Path>>,
-    maybe_sysroot: Option<@Path>,
+    addl_lib_search_paths: RefCell<HashSet<Path>>,
+    maybe_sysroot: Option<Path>,
     target_triple: ~str,
     // User-specified cfg meta items. The compiler itself will add additional
     // items to the crate config, and during parsing the entire crate config
@@ -173,27 +174,24 @@ pub enum CrateType {
     CrateTypeStaticlib,
 }
 
-pub struct Session_ {
-    targ_cfg: @Config,
-    opts: @Options,
-    cstore: @metadata::cstore::CStore,
-    parse_sess: @ParseSess,
-    codemap: @codemap::CodeMap,
+pub struct Session {
+    targ_cfg: Config,
+    opts: Options,
+    cstore: metadata::cstore::CStore,
+    parse_sess: ParseSess,
     // For a library crate, this is always none
     entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
     entry_type: Cell<Option<EntryFnType>>,
-    span_diagnostic: @diagnostic::SpanHandler,
     macro_registrar_fn: RefCell<Option<ast::DefId>>,
-    filesearch: @filesearch::FileSearch,
+    default_sysroot: Option<Path>,
     building_library: Cell<bool>,
     // The name of the root source file of the crate, in the local file system. The path is always
     // expected to be absolute. `None` means that there is no source file.
     local_crate_source_file: Option<Path>,
     working_dir: Path,
-    lints: RefCell<HashMap<ast::NodeId,
-                           Vec<(lint::Lint, codemap::Span, ~str)> >>,
+    lints: RefCell<NodeMap<Vec<(lint::Lint, codemap::Span, ~str)>>>,
     node_id: Cell<ast::NodeId>,
-    crate_types: @RefCell<Vec<CrateType> >,
+    crate_types: RefCell<Vec<CrateType>>,
     features: front::feature_gate::Features,
 
     /// The maximum recursion limit for potentially infinitely recursive
@@ -201,56 +199,54 @@ pub struct Session_ {
     recursion_limit: Cell<uint>,
 }
 
-pub type Session = @Session_;
-
-impl Session_ {
+impl Session {
     pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
-        self.span_diagnostic.span_fatal(sp, msg)
+        self.diagnostic().span_fatal(sp, msg)
     }
     pub fn fatal(&self, msg: &str) -> ! {
-        self.span_diagnostic.handler().fatal(msg)
+        self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
-        self.span_diagnostic.span_err(sp, msg)
+        self.diagnostic().span_err(sp, msg)
     }
     pub fn err(&self, msg: &str) {
-        self.span_diagnostic.handler().err(msg)
+        self.diagnostic().handler().err(msg)
     }
     pub fn err_count(&self) -> uint {
-        self.span_diagnostic.handler().err_count()
+        self.diagnostic().handler().err_count()
     }
     pub fn has_errors(&self) -> bool {
-        self.span_diagnostic.handler().has_errors()
+        self.diagnostic().handler().has_errors()
     }
     pub fn abort_if_errors(&self) {
-        self.span_diagnostic.handler().abort_if_errors()
+        self.diagnostic().handler().abort_if_errors()
     }
     pub fn span_warn(&self, sp: Span, msg: &str) {
-        self.span_diagnostic.span_warn(sp, msg)
+        self.diagnostic().span_warn(sp, msg)
     }
     pub fn warn(&self, msg: &str) {
-        self.span_diagnostic.handler().warn(msg)
+        self.diagnostic().handler().warn(msg)
     }
     pub fn span_note(&self, sp: Span, msg: &str) {
-        self.span_diagnostic.span_note(sp, msg)
+        self.diagnostic().span_note(sp, msg)
     }
     pub fn span_end_note(&self, sp: Span, msg: &str) {
-        self.span_diagnostic.span_end_note(sp, msg)
+        self.diagnostic().span_end_note(sp, msg)
     }
     pub fn note(&self, msg: &str) {
-        self.span_diagnostic.handler().note(msg)
+        self.diagnostic().handler().note(msg)
     }
     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
-        self.span_diagnostic.span_bug(sp, msg)
+        self.diagnostic().span_bug(sp, msg)
     }
     pub fn bug(&self, msg: &str) -> ! {
-        self.span_diagnostic.handler().bug(msg)
+        self.diagnostic().handler().bug(msg)
     }
     pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
-        self.span_diagnostic.span_unimpl(sp, msg)
+        self.diagnostic().span_unimpl(sp, msg)
     }
     pub fn unimpl(&self, msg: &str) -> ! {
-        self.span_diagnostic.handler().unimpl(msg)
+        self.diagnostic().handler().unimpl(msg)
     }
     pub fn add_lint(&self,
                     lint: lint::Lint,
@@ -277,12 +273,15 @@ impl Session_ {
 
         v
     }
-    pub fn diagnostic(&self) -> @diagnostic::SpanHandler {
-        self.span_diagnostic
+    pub fn diagnostic<'a>(&'a self) -> &'a diagnostic::SpanHandler {
+        &self.parse_sess.span_diagnostic
     }
     pub fn debugging_opt(&self, opt: u64) -> bool {
         (self.opts.debugging_opts & opt) != 0
     }
+    pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
+        &self.parse_sess.span_diagnostic.cm
+    }
     // This exists to help with refactoring to eliminate impossible
     // cases later on
     pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
@@ -316,18 +315,29 @@ impl Session_ {
     pub fn show_span(&self) -> bool {
         self.debugging_opt(SHOW_SPAN)
     }
+    pub fn filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
+        let sysroot = match self.opts.maybe_sysroot {
+            Some(ref sysroot) => sysroot,
+            None => self.default_sysroot.as_ref()
+                        .expect("missing sysroot and default_sysroot in Session")
+        };
+        filesearch::FileSearch::new(
+            sysroot,
+            self.opts.target_triple,
+            &self.opts.addl_lib_search_paths)
+    }
 }
 
 /// Some reasonable defaults
-pub fn basic_options() -> @Options {
-    @Options {
+pub fn basic_options() -> Options {
+    Options {
         crate_types: Vec::new(),
         gc: false,
         optimize: No,
         debuginfo: NoDebugInfo,
         lint_opts: Vec::new(),
         output_types: Vec::new(),
-        addl_lib_search_paths: @RefCell::new(HashSet::new()),
+        addl_lib_search_paths: RefCell::new(HashSet::new()),
         maybe_sysroot: None,
         target_triple: host_triple(),
         cfg: Vec::new(),
@@ -451,7 +461,7 @@ cgoptions!(
 )
 
 // 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: || -> ~str) -> T {
+pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> ~str) -> 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
index 750d09c2d17..f7c919131a8 100644
--- a/src/librustc/front/assign_node_ids_and_map.rs
+++ b/src/librustc/front/assign_node_ids_and_map.rs
@@ -13,17 +13,17 @@ use driver::session::Session;
 use syntax::ast;
 use syntax::ast_map;
 
-struct NodeIdAssigner {
-    sess: Session
+struct NodeIdAssigner<'a> {
+    sess: &'a Session
 }
 
-impl ast_map::FoldOps for NodeIdAssigner {
+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) {
+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/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 36f6cedb4f1..99de2060eee 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -86,12 +86,12 @@ impl Features {
     }
 }
 
-struct Context {
-    features: Vec<&'static str> ,
-    sess: Session,
+struct Context<'a> {
+    features: Vec<&'static str>,
+    sess: &'a Session,
 }
 
-impl Context {
+impl<'a> Context<'a> {
     fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
         if !self.has_feature(feature) {
             self.sess.span_err(span, explain);
@@ -114,7 +114,7 @@ impl Context {
     }
 }
 
-impl Visitor<()> for Context {
+impl<'a> Visitor<()> for Context<'a> {
     fn visit_ident(&mut self, sp: Span, id: ast::Ident, _: ()) {
         if !token::get_ident(id).get().is_ascii() {
             self.gate_feature("non_ascii_idents", sp,
@@ -293,7 +293,7 @@ impl Visitor<()> for Context {
     }
 }
 
-pub fn check_crate(sess: Session, krate: &ast::Crate) {
+pub fn check_crate(sess: &Session, krate: &ast::Crate) {
     let mut cx = Context {
         features: Vec::new(),
         sess: sess,
diff --git a/src/librustc/front/show_span.rs b/src/librustc/front/show_span.rs
index aa6fa321a31..36db4e422c1 100644
--- a/src/librustc/front/show_span.rs
+++ b/src/librustc/front/show_span.rs
@@ -19,18 +19,18 @@ use syntax::visit::Visitor;
 
 use driver::session::Session;
 
-struct ShowSpanVisitor {
-    sess: Session
+struct ShowSpanVisitor<'a> {
+    sess: &'a Session
 }
 
-impl Visitor<()> for ShowSpanVisitor {
+impl<'a> Visitor<()> for ShowSpanVisitor<'a> {
     fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
         self.sess.span_note(e.span, "expression");
         visit::walk_expr(self, e, ());
     }
 }
 
-pub fn run(sess: Session, krate: &ast::Crate) {
+pub fn run(sess: &Session, krate: &ast::Crate) {
     let mut v = ShowSpanVisitor { sess: sess };
     visit::walk_crate(&mut v, krate, ());
 }
diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs
index c1fd83cab54..40747646167 100644
--- a/src/librustc/front/std_inject.rs
+++ b/src/librustc/front/std_inject.rs
@@ -26,7 +26,7 @@ use syntax::util::small_vector::SmallVector;
 
 pub static VERSION: &'static str = "0.10-pre";
 
-pub fn maybe_inject_crates_ref(sess: Session, krate: ast::Crate)
+pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
                                -> ast::Crate {
     if use_std(&krate) {
         inject_crates_ref(sess, krate)
@@ -35,7 +35,7 @@ pub fn maybe_inject_crates_ref(sess: Session, krate: ast::Crate)
     }
 }
 
-pub fn maybe_inject_prelude(sess: Session, krate: ast::Crate) -> ast::Crate {
+pub fn maybe_inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
     if use_std(&krate) {
         inject_prelude(sess, krate)
     } else {
@@ -55,8 +55,8 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool {
     attr::contains_name(attrs, "no_implicit_prelude")
 }
 
-struct StandardLibraryInjector {
-    sess: Session,
+struct StandardLibraryInjector<'a> {
+    sess: &'a Session,
 }
 
 pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
@@ -71,7 +71,7 @@ pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
     }
 }
 
-impl fold::Folder for StandardLibraryInjector {
+impl<'a> fold::Folder for StandardLibraryInjector<'a> {
     fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
         let mut vis = vec!(ast::ViewItem {
             node: ast::ViewItemExternCrate(token::str_to_ident("std"),
@@ -120,19 +120,19 @@ impl fold::Folder for StandardLibraryInjector {
     }
 }
 
-fn inject_crates_ref(sess: Session, krate: ast::Crate) -> ast::Crate {
+fn inject_crates_ref(sess: &Session, krate: ast::Crate) -> ast::Crate {
     let mut fold = StandardLibraryInjector {
         sess: sess,
     };
     fold.fold_crate(krate)
 }
 
-struct PreludeInjector {
-    sess: Session,
+struct PreludeInjector<'a> {
+    sess: &'a Session,
 }
 
 
-impl fold::Folder for PreludeInjector {
+impl<'a> fold::Folder for PreludeInjector<'a> {
     fn fold_crate(&mut self, krate: ast::Crate) -> ast::Crate {
         if !no_prelude(krate.attrs.as_slice()) {
             // only add `use std::prelude::*;` if there wasn't a
@@ -193,7 +193,7 @@ impl fold::Folder for PreludeInjector {
     }
 }
 
-fn inject_prelude(sess: Session, krate: ast::Crate) -> ast::Crate {
+fn inject_prelude(sess: &Session, krate: ast::Crate) -> ast::Crate {
     let mut fold = PreludeInjector {
         sess: sess,
     };
diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs
index 11556322ef1..cf5373fd17d 100644
--- a/src/librustc/front/test.rs
+++ b/src/librustc/front/test.rs
@@ -13,7 +13,7 @@
 #[allow(dead_code)];
 #[allow(unused_imports)];
 
-use driver::session;
+use driver::session::Session;
 use front::config;
 use front::std_inject::with_version;
 use metadata::creader::Loader;
@@ -47,8 +47,8 @@ struct Test {
 }
 
 struct TestCtxt<'a> {
-    sess: session::Session,
-    path: RefCell<Vec<ast::Ident> >,
+    sess: &'a Session,
+    path: RefCell<Vec<ast::Ident>>,
     ext_cx: ExtCtxt<'a>,
     testfns: RefCell<Vec<Test> >,
     is_test_crate: bool,
@@ -57,7 +57,7 @@ struct TestCtxt<'a> {
 
 // Traverse the crate, collecting all the test functions, eliding any
 // existing main functions, and synthesizing a main test harness
-pub fn modify_for_testing(sess: session::Session,
+pub fn modify_for_testing(sess: &Session,
                           krate: ast::Crate) -> ast::Crate {
     // We generate the test harness when building in the 'test'
     // configuration, either with the '--test' or '--cfg test'
@@ -161,12 +161,12 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
     }
 }
 
-fn generate_test_harness(sess: session::Session, krate: ast::Crate)
+fn generate_test_harness(sess: &Session, krate: ast::Crate)
                          -> ast::Crate {
     let loader = &mut Loader::new(sess);
     let mut cx: TestCtxt = TestCtxt {
         sess: sess,
-        ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone(),
+        ext_cx: ExtCtxt::new(&sess.parse_sess, sess.opts.cfg.clone(),
                              ExpansionConfig {
                                  loader: loader,
                                  deriving_hash_type_parameter: false,
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 00cde129d1e..9409d8c457f 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -290,36 +290,36 @@ pub fn run_compiler(args: &[~str]) {
     let sess = d::build_session(sopts, input_file_path);
     let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
     let ofile = matches.opt_str("o").map(|o| Path::new(o));
-    let cfg = d::build_configuration(sess);
+    let cfg = d::build_configuration(&sess);
     let pretty = matches.opt_default("pretty", "normal").map(|a| {
-        d::parse_pretty(sess, a)
+        d::parse_pretty(&sess, a)
     });
     match pretty {
-      Some::<d::PpMode>(ppm) => {
-        d::pretty_print_input(sess, cfg, &input, ppm);
-        return;
-      }
-      None::<d::PpMode> => {/* continue */ }
+        Some::<d::PpMode>(ppm) => {
+            d::pretty_print_input(sess, cfg, &input, ppm);
+            return;
+        }
+        None::<d::PpMode> => {/* continue */ }
     }
     let ls = matches.opt_present("ls");
     if ls {
         match input {
-          d::FileInput(ref ifile) => {
-            let mut stdout = io::stdout();
-            d::list_metadata(sess, &(*ifile), &mut stdout).unwrap();
-          }
-          d::StrInput(_) => {
-            d::early_error("can not list metadata for stdin");
-          }
+            d::FileInput(ref ifile) => {
+                let mut stdout = io::stdout();
+                d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
+            }
+            d::StrInput(_) => {
+                d::early_error("can not list metadata for stdin");
+            }
         }
         return;
     }
-    let (crate_id, crate_name, crate_file_name) = sopts.print_metas;
+    let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
     // these nasty nested conditions are to avoid doing extra work
     if crate_id || crate_name || crate_file_name {
-        let attrs = parse_crate_attrs(sess, &input);
+        let attrs = parse_crate_attrs(&sess, &input);
         let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
-                                                  attrs.as_slice(), sess);
+                                                  attrs.as_slice(), &sess);
         let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
 
         if crate_id {
@@ -344,19 +344,19 @@ pub fn run_compiler(args: &[~str]) {
     d::compile_input(sess, cfg, &input, &odir, &ofile);
 }
 
-fn parse_crate_attrs(sess: session::Session, input: &d::Input) ->
+fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
                      Vec<ast::Attribute> {
     let result = match *input {
         d::FileInput(ref ifile) => {
             parse::parse_crate_attrs_from_file(ifile,
                                                Vec::new(),
-                                               sess.parse_sess)
+                                               &sess.parse_sess)
         }
         d::StrInput(ref src) => {
             parse::parse_crate_attrs_from_source_str(d::anon_src(),
                                                      (*src).clone(),
                                                      Vec::new(),
-                                                     sess.parse_sess)
+                                                     &sess.parse_sess)
         }
     };
     result.move_iter().collect()
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 7769d53865a..74e180072fa 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -39,7 +39,7 @@ use syntax::visit;
 
 // Traverses an AST, reading all the information about use'd crates and extern
 // libraries necessary for later resolving, typechecking, linking, etc.
-pub fn read_crates(sess: Session,
+pub fn read_crates(sess: &Session,
                    krate: &ast::Crate,
                    os: loader::Os,
                    intr: @IdentInterner) {
@@ -51,12 +51,7 @@ pub fn read_crates(sess: Session,
         intr: intr
     };
     visit_crate(&e, krate);
-    {
-        let mut v = ReadCrateVisitor {
-            e: &mut e
-        };
-        visit::walk_crate(&mut v, krate, ());
-    }
+    visit::walk_crate(&mut e, krate, ());
     let crate_cache = e.crate_cache.borrow();
     dump_crates(crate_cache.get().as_slice());
     warn_if_multiple_versions(&mut e,
@@ -64,17 +59,13 @@ pub fn read_crates(sess: Session,
                               crate_cache.get().as_slice());
 }
 
-struct ReadCrateVisitor<'a> {
-    e: &'a mut Env,
-}
-
-impl<'a> visit::Visitor<()> for ReadCrateVisitor<'a> {
+impl<'a> visit::Visitor<()> for Env<'a> {
     fn visit_view_item(&mut self, a: &ast::ViewItem, _: ()) {
-        visit_view_item(self.e, a);
+        visit_view_item(self, a);
         visit::walk_view_item(self, a, ());
     }
     fn visit_item(&mut self, a: &ast::Item, _: ()) {
-        visit_item(self.e, a);
+        visit_item(self, a);
         visit::walk_item(self, a, ());
     }
 }
@@ -97,7 +88,7 @@ fn dump_crates(crate_cache: &[cache_entry]) {
 }
 
 fn warn_if_multiple_versions(e: &mut Env,
-                             diag: @SpanHandler,
+                             diag: &SpanHandler,
                              crate_cache: &[cache_entry]) {
     if crate_cache.len() != 0u {
         let name = crate_cache[crate_cache.len() - 1].crate_id.name.clone();
@@ -120,8 +111,8 @@ fn warn_if_multiple_versions(e: &mut Env,
     }
 }
 
-struct Env {
-    sess: Session,
+struct Env<'a> {
+    sess: &'a Session,
     os: loader::Os,
     crate_cache: @RefCell<Vec<cache_entry>>,
     next_crate_num: ast::CrateNum,
@@ -129,12 +120,10 @@ struct Env {
 }
 
 fn visit_crate(e: &Env, c: &ast::Crate) {
-    let cstore = e.sess.cstore;
-
     for a in c.attrs.iter().filter(|m| m.name().equiv(&("link_args"))) {
         match a.value_str() {
-          Some(ref linkarg) => cstore.add_used_link_args(linkarg.get()),
-          None => { /* fallthrough */ }
+            Some(ref linkarg) => e.sess.cstore.add_used_link_args(linkarg.get()),
+            None => { /* fallthrough */ }
         }
     }
 }
@@ -204,7 +193,6 @@ fn visit_item(e: &Env, i: &ast::Item) {
             }
 
             // First, add all of the custom link_args attributes
-            let cstore = e.sess.cstore;
             let link_args = i.attrs.iter()
                 .filter_map(|at| if at.name().equiv(&("link_args")) {
                     Some(at)
@@ -214,13 +202,12 @@ fn visit_item(e: &Env, i: &ast::Item) {
                 .to_owned_vec();
             for m in link_args.iter() {
                 match m.value_str() {
-                    Some(linkarg) => cstore.add_used_link_args(linkarg.get()),
+                    Some(linkarg) => e.sess.cstore.add_used_link_args(linkarg.get()),
                     None => { /* fallthrough */ }
                 }
             }
 
             // Next, process all of the #[link(..)]-style arguments
-            let cstore = e.sess.cstore;
             let link_args = i.attrs.iter()
                 .filter_map(|at| if at.name().equiv(&("link")) {
                     Some(at)
@@ -269,7 +256,7 @@ fn visit_item(e: &Env, i: &ast::Item) {
                         if n.get().is_empty() {
                             e.sess.span_err(m.span, "#[link(name = \"\")] given with empty name");
                         } else {
-                            cstore.add_used_library(n.get().to_owned(), kind);
+                            e.sess.cstore.add_used_library(n.get().to_owned(), kind);
                         }
                     }
                     None => {}
@@ -353,18 +340,15 @@ fn resolve_crate(e: &mut Env,
                 cnum: cnum
             };
 
-            let cstore = e.sess.cstore;
-            cstore.set_crate_data(cnum, cmeta);
-            cstore.add_used_crate_source(cstore::CrateSource {
+            e.sess.cstore.set_crate_data(cnum, cmeta);
+            e.sess.cstore.add_used_crate_source(cstore::CrateSource {
                 dylib: dylib,
                 rlib: rlib,
                 cnum: cnum,
             });
-            return cnum;
-        }
-        Some(cnum) => {
-            return cnum;
+            cnum
         }
+        Some(cnum) => cnum
     }
 }
 
@@ -391,12 +375,12 @@ fn resolve_crate_deps(e: &mut Env,
     return @RefCell::new(cnum_map);
 }
 
-pub struct Loader {
-    priv env: Env,
+pub struct Loader<'a> {
+    priv env: Env<'a>,
 }
 
-impl Loader {
-    pub fn new(sess: Session) -> Loader {
+impl<'a> Loader<'a> {
+    pub fn new(sess: &'a Session) -> Loader<'a> {
         let os = driver::get_os(driver::host_triple()).unwrap();
         let os = session::sess_os_to_meta_os(os);
         Loader {
@@ -411,7 +395,7 @@ impl Loader {
     }
 }
 
-impl CrateLoader for Loader {
+impl<'a> CrateLoader for Loader<'a> {
     fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
         let info = extract_crate_info(&self.env, krate).unwrap();
         let cnum = resolve_crate(&mut self.env, None, info.ident,
@@ -424,12 +408,12 @@ impl CrateLoader for Loader {
     }
 
     fn get_exported_macros(&mut self, cnum: ast::CrateNum) -> Vec<~str> {
-        csearch::get_exported_macros(self.env.sess.cstore, cnum).move_iter()
-                                                                .collect()
+        csearch::get_exported_macros(&self.env.sess.cstore, cnum).move_iter()
+                                                                 .collect()
     }
 
     fn get_registrar_symbol(&mut self, cnum: ast::CrateNum) -> Option<~str> {
-        let cstore = self.env.sess.cstore;
+        let cstore = &self.env.sess.cstore;
         csearch::get_macro_registrar_fn(cstore, cnum)
             .map(|did| csearch::get_symbol(cstore, did))
     }
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 360ab4eefe0..d41d01f3c85 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -34,19 +34,19 @@ pub struct StaticMethodInfo {
     vis: ast::Visibility,
 }
 
-pub fn get_symbol(cstore: @cstore::CStore, def: ast::DefId) -> ~str {
+pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> ~str {
     let cdata = cstore.get_crate_data(def.krate).data();
     return decoder::get_symbol(cdata, def.node);
 }
 
-pub fn get_type_param_count(cstore: @cstore::CStore, def: ast::DefId)
+pub fn get_type_param_count(cstore: &cstore::CStore, def: ast::DefId)
                          -> uint {
     let cdata = cstore.get_crate_data(def.krate).data();
     return decoder::get_type_param_count(cdata, def.node);
 }
 
 /// Iterates over all the language items in the given crate.
-pub fn each_lang_item(cstore: @cstore::CStore,
+pub fn each_lang_item(cstore: &cstore::CStore,
                       cnum: ast::CrateNum,
                       f: |ast::NodeId, uint| -> bool)
                       -> bool {
@@ -55,7 +55,7 @@ pub fn each_lang_item(cstore: @cstore::CStore,
 }
 
 /// Iterates over each child of the given item.
-pub fn each_child_of_item(cstore: @cstore::CStore,
+pub fn each_child_of_item(cstore: &cstore::CStore,
                           def_id: ast::DefId,
                           callback: |decoder::DefLike,
                                      ast::Ident,
@@ -72,7 +72,7 @@ pub fn each_child_of_item(cstore: @cstore::CStore,
 }
 
 /// Iterates over each top-level crate item.
-pub fn each_top_level_item_of_crate(cstore: @cstore::CStore,
+pub fn each_top_level_item_of_crate(cstore: &cstore::CStore,
                                     cnum: ast::CrateNum,
                                     callback: |decoder::DefLike,
                                                ast::Ident,
@@ -87,8 +87,8 @@ pub fn each_top_level_item_of_crate(cstore: @cstore::CStore,
                                           callback)
 }
 
-pub fn get_item_path(tcx: ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem> {
-    let cstore = tcx.cstore;
+pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem> {
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     let path = decoder::get_item_path(cdata, def.node);
 
@@ -107,34 +107,34 @@ pub enum found_ast {
 // 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,
+pub fn maybe_get_item_ast(tcx: &ty::ctxt, def: ast::DefId,
                           decode_inlined_item: decoder::DecodeInlinedItem)
                        -> found_ast {
-    let cstore = tcx.cstore;
+    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)
 }
 
-pub fn get_enum_variants(tcx: ty::ctxt, def: ast::DefId)
+pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
                       -> Vec<@ty::VariantInfo> {
-    let cstore = tcx.cstore;
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx)
 }
 
 /// Returns information about the given implementation.
-pub fn get_impl(tcx: ty::ctxt, impl_def_id: ast::DefId)
+pub fn get_impl(tcx: &ty::ctxt, impl_def_id: ast::DefId)
                 -> ty::Impl {
-    let cdata = tcx.cstore.get_crate_data(impl_def_id.krate);
-    decoder::get_impl(tcx.cstore.intr, cdata, impl_def_id.node, tcx)
+    let cdata = tcx.sess.cstore.get_crate_data(impl_def_id.krate);
+    decoder::get_impl(tcx.sess.cstore.intr, cdata, impl_def_id.node, tcx)
 }
 
-pub fn get_method(tcx: ty::ctxt, def: ast::DefId) -> ty::Method {
-    let cdata = tcx.cstore.get_crate_data(def.krate);
-    decoder::get_method(tcx.cstore.intr, cdata, def.node, tcx)
+pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
+    let cdata = tcx.sess.cstore.get_crate_data(def.krate);
+    decoder::get_method(tcx.sess.cstore.intr, cdata, def.node, tcx)
 }
 
-pub fn get_method_name_and_explicit_self(cstore: @cstore::CStore,
+pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
                                          def: ast::DefId)
                                      -> (ast::Ident, ast::ExplicitSelf_)
 {
@@ -142,83 +142,83 @@ pub fn get_method_name_and_explicit_self(cstore: @cstore::CStore,
     decoder::get_method_name_and_explicit_self(cstore.intr, cdata, def.node)
 }
 
-pub fn get_trait_method_def_ids(cstore: @cstore::CStore,
+pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
                                 def: ast::DefId) -> Vec<ast::DefId> {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_trait_method_def_ids(cdata, def.node)
 }
 
-pub fn get_item_variances(cstore: @cstore::CStore,
+pub fn get_item_variances(cstore: &cstore::CStore,
                           def: ast::DefId) -> ty::ItemVariances {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_item_variances(cdata, def.node)
 }
 
-pub fn get_provided_trait_methods(tcx: ty::ctxt,
+pub fn get_provided_trait_methods(tcx: &ty::ctxt,
                                   def: ast::DefId)
                                -> Vec<@ty::Method> {
-    let cstore = tcx.cstore;
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_provided_trait_methods(cstore.intr, cdata, def.node, tcx)
 }
 
-pub fn get_supertraits(tcx: ty::ctxt, def: ast::DefId) -> Vec<@ty::TraitRef> {
-    let cstore = tcx.cstore;
+pub fn get_supertraits(tcx: &ty::ctxt, def: ast::DefId) -> Vec<@ty::TraitRef> {
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_supertraits(cdata, def.node, tcx)
 }
 
-pub fn get_type_name_if_impl(cstore: @cstore::CStore, def: ast::DefId)
+pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: ast::DefId)
                           -> Option<ast::Ident> {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_type_name_if_impl(cdata, def.node)
 }
 
-pub fn get_static_methods_if_impl(cstore: @cstore::CStore,
+pub fn get_static_methods_if_impl(cstore: &cstore::CStore,
                                   def: ast::DefId)
                                -> Option<Vec<StaticMethodInfo> > {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_static_methods_if_impl(cstore.intr, cdata, def.node)
 }
 
-pub fn get_item_attrs(cstore: @cstore::CStore,
+pub fn get_item_attrs(cstore: &cstore::CStore,
                       def_id: ast::DefId,
                       f: |Vec<@ast::MetaItem> |) {
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::get_item_attrs(cdata, def_id.node, f)
 }
 
-pub fn get_struct_fields(cstore: @cstore::CStore,
+pub fn get_struct_fields(cstore: &cstore::CStore,
                          def: ast::DefId)
                       -> Vec<ty::field_ty> {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_struct_fields(cstore.intr, cdata, def.node)
 }
 
-pub fn get_type(tcx: ty::ctxt,
+pub fn get_type(tcx: &ty::ctxt,
                 def: ast::DefId)
              -> ty::ty_param_bounds_and_ty {
-    let cstore = tcx.cstore;
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_type(cdata, def.node, tcx)
 }
 
-pub fn get_trait_def(tcx: ty::ctxt, def: ast::DefId) -> ty::TraitDef {
-    let cstore = tcx.cstore;
+pub fn get_trait_def(tcx: &ty::ctxt, def: ast::DefId) -> ty::TraitDef {
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_trait_def(cdata, def.node, tcx)
 }
 
-pub fn get_field_type(tcx: ty::ctxt, class_id: ast::DefId,
+pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
                       def: ast::DefId) -> ty::ty_param_bounds_and_ty {
-    let cstore = tcx.cstore;
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(class_id.krate);
     let all_items = reader::get_doc(reader::Doc(cdata.data()), tag_items);
-    let class_doc = expect(tcx.diag,
+    let class_doc = expect(tcx.sess.diagnostic(),
                            decoder::maybe_find_item(class_id.node, all_items),
                            || format!("get_field_type: class ID {:?} not found",
                                    class_id) );
-    let the_field = expect(tcx.diag,
+    let the_field = expect(tcx.sess.diagnostic(),
         decoder::maybe_find_item(def.node, class_doc),
         || format!("get_field_type: in class {:?}, field ID {:?} not found",
                  class_id, def) );
@@ -232,22 +232,22 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::DefId,
 
 // Given a def_id for an impl, return the trait it implements,
 // if there is one.
-pub fn get_impl_trait(tcx: ty::ctxt,
+pub fn get_impl_trait(tcx: &ty::ctxt,
                       def: ast::DefId) -> Option<@ty::TraitRef> {
-    let cstore = tcx.cstore;
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_impl_trait(cdata, def.node, tcx)
 }
 
 // Given a def_id for an impl, return information about its vtables
-pub fn get_impl_vtables(tcx: ty::ctxt,
+pub fn get_impl_vtables(tcx: &ty::ctxt,
                         def: ast::DefId) -> typeck::impl_res {
-    let cstore = tcx.cstore;
+    let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_impl_vtables(cdata, def.node, tcx)
 }
 
-pub fn get_impl_method(cstore: @cstore::CStore,
+pub fn get_impl_method(cstore: &cstore::CStore,
                        def: ast::DefId,
                        mname: ast::Ident)
                     -> Option<ast::DefId> {
@@ -255,35 +255,35 @@ pub fn get_impl_method(cstore: @cstore::CStore,
     decoder::get_impl_method(cstore.intr, cdata, def.node, mname)
 }
 
-pub fn get_item_visibility(cstore: @cstore::CStore,
+pub fn get_item_visibility(cstore: &cstore::CStore,
                            def_id: ast::DefId)
                         -> ast::Visibility {
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::get_item_visibility(cdata, def_id.node)
 }
 
-pub fn get_native_libraries(cstore: @cstore::CStore,
+pub fn get_native_libraries(cstore: &cstore::CStore,
                             crate_num: ast::CrateNum)
                                 -> Vec<(cstore::NativeLibaryKind, ~str)> {
     let cdata = cstore.get_crate_data(crate_num);
     decoder::get_native_libraries(cdata)
 }
 
-pub fn each_impl(cstore: @cstore::CStore,
+pub fn each_impl(cstore: &cstore::CStore,
                  crate_num: ast::CrateNum,
                  callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(crate_num);
     decoder::each_impl(cdata, callback)
 }
 
-pub fn each_implementation_for_type(cstore: @cstore::CStore,
+pub fn each_implementation_for_type(cstore: &cstore::CStore,
                                     def_id: ast::DefId,
                                     callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::each_implementation_for_type(cdata, def_id.node, callback)
 }
 
-pub fn each_implementation_for_trait(cstore: @cstore::CStore,
+pub fn each_implementation_for_trait(cstore: &cstore::CStore,
                                      def_id: ast::DefId,
                                      callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(def_id.krate);
@@ -293,22 +293,22 @@ pub fn each_implementation_for_trait(cstore: @cstore::CStore,
 /// If the given def ID describes a method belonging to a trait (either a
 /// default method or an implementation of a trait method), returns the ID of
 /// the trait that the method belongs to. Otherwise, returns `None`.
-pub fn get_trait_of_method(cstore: @cstore::CStore,
+pub fn get_trait_of_method(cstore: &cstore::CStore,
                            def_id: ast::DefId,
-                           tcx: ty::ctxt)
+                           tcx: &ty::ctxt)
                            -> Option<ast::DefId> {
     let cdata = cstore.get_crate_data(def_id.krate);
     decoder::get_trait_of_method(cdata, def_id.node, tcx)
 }
 
-pub fn get_macro_registrar_fn(cstore: @cstore::CStore,
+pub fn get_macro_registrar_fn(cstore: &cstore::CStore,
                               crate_num: ast::CrateNum)
                               -> Option<ast::DefId> {
     let cdata = cstore.get_crate_data(crate_num);
     decoder::get_macro_registrar_fn(cdata)
 }
 
-pub fn get_exported_macros(cstore: @cstore::CStore,
+pub fn get_exported_macros(cstore: &cstore::CStore,
                            crate_num: ast::CrateNum)
                            -> Vec<~str> {
     let cdata = cstore.get_crate_data(crate_num);
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 678e81b7fea..8f785268ae0 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -219,35 +219,35 @@ fn variant_disr_val(d: ebml::Doc) -> Option<ty::Disr> {
     })
 }
 
-fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: Cmd) -> ty::t {
+fn doc_type(doc: ebml::Doc, tcx: &ty::ctxt, cdata: Cmd) -> ty::t {
     let tp = reader::get_doc(doc, tag_items_data_item_type);
     parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
                   |_, did| translate_def_id(cdata, did))
 }
 
-fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: Cmd) -> ty::BareFnTy {
+fn doc_method_fty(doc: ebml::Doc, tcx: &ty::ctxt, cdata: Cmd) -> ty::BareFnTy {
     let tp = reader::get_doc(doc, tag_item_method_fty);
     parse_bare_fn_ty_data(tp.data, cdata.cnum, tp.start, tcx,
                           |_, did| translate_def_id(cdata, did))
 }
 
 pub fn item_type(_item_id: ast::DefId, item: ebml::Doc,
-                 tcx: ty::ctxt, cdata: Cmd) -> ty::t {
+                 tcx: &ty::ctxt, cdata: Cmd) -> ty::t {
     doc_type(item, tcx, cdata)
 }
 
-fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: Cmd) -> ty::TraitRef {
+fn doc_trait_ref(doc: ebml::Doc, tcx: &ty::ctxt, cdata: Cmd) -> ty::TraitRef {
     parse_trait_ref_data(doc.data, cdata.cnum, doc.start, tcx,
                          |_, did| translate_def_id(cdata, did))
 }
 
-fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: Cmd) -> ty::TraitRef {
+fn item_trait_ref(doc: ebml::Doc, tcx: &ty::ctxt, cdata: Cmd) -> ty::TraitRef {
     let tp = reader::get_doc(doc, tag_item_trait_ref);
     doc_trait_ref(tp, tcx, cdata)
 }
 
 fn item_ty_param_defs(item: ebml::Doc,
-                      tcx: ty::ctxt,
+                      tcx: &ty::ctxt,
                       cdata: Cmd,
                       tag: uint)
                       -> Rc<Vec<ty::TypeParameterDef> > {
@@ -378,7 +378,7 @@ fn item_to_def_like(item: ebml::Doc, did: ast::DefId, cnum: ast::CrateNum)
 
 pub fn get_trait_def(cdata: Cmd,
                      item_id: ast::NodeId,
-                     tcx: ty::ctxt) -> ty::TraitDef
+                     tcx: &ty::ctxt) -> ty::TraitDef
 {
     let item_doc = lookup_item(item_id, cdata.data());
     let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
@@ -403,7 +403,7 @@ pub fn get_trait_def(cdata: Cmd,
     }
 }
 
-pub fn get_type(cdata: Cmd, id: ast::NodeId, tcx: ty::ctxt)
+pub fn get_type(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
     -> ty::ty_param_bounds_and_ty {
 
     let item = lookup_item(id, cdata.data());
@@ -427,7 +427,7 @@ pub fn get_type_param_count(data: &[u8], id: ast::NodeId) -> uint {
 
 pub fn get_impl_trait(cdata: Cmd,
                       id: ast::NodeId,
-                      tcx: ty::ctxt) -> Option<@ty::TraitRef>
+                      tcx: &ty::ctxt) -> Option<@ty::TraitRef>
 {
     let item_doc = lookup_item(id, cdata.data());
     reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
@@ -437,7 +437,7 @@ pub fn get_impl_trait(cdata: Cmd,
 
 pub fn get_impl_vtables(cdata: Cmd,
                         id: ast::NodeId,
-                        tcx: ty::ctxt) -> typeck::impl_res
+                        tcx: &ty::ctxt) -> typeck::impl_res
 {
     let item_doc = lookup_item(id, cdata.data());
     let vtables_doc = reader::get_doc(item_doc, tag_item_impl_vtables);
@@ -672,12 +672,12 @@ pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<ast_map::PathElem> {
 }
 
 pub type DecodeInlinedItem<'a> = 'a |cdata: @cstore::crate_metadata,
-                                     tcx: ty::ctxt,
-                                     path: Vec<ast_map::PathElem> ,
+                                     tcx: &ty::ctxt,
+                                     path: Vec<ast_map::PathElem>,
                                      par_doc: ebml::Doc|
                                      -> Result<ast::InlinedItem, Vec<ast_map::PathElem> >;
 
-pub fn maybe_get_item_ast(cdata: Cmd, tcx: ty::ctxt, id: ast::NodeId,
+pub fn maybe_get_item_ast(cdata: Cmd, tcx: &ty::ctxt, id: ast::NodeId,
                           decode_inlined_item: DecodeInlinedItem)
                           -> csearch::found_ast {
     debug!("Looking up item: {}", id);
@@ -702,7 +702,7 @@ pub fn maybe_get_item_ast(cdata: Cmd, tcx: ty::ctxt, id: ast::NodeId,
 }
 
 pub fn get_enum_variants(intr: @IdentInterner, cdata: Cmd, id: ast::NodeId,
-                     tcx: ty::ctxt) -> Vec<@ty::VariantInfo> {
+                     tcx: &ty::ctxt) -> Vec<@ty::VariantInfo> {
     let data = cdata.data();
     let items = reader::get_doc(reader::Doc(data), tag_items);
     let item = find_item(id, items);
@@ -761,7 +761,7 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
 }
 
 fn item_impl_methods(intr: @IdentInterner, cdata: Cmd, item: ebml::Doc,
-                     tcx: ty::ctxt) -> Vec<@ty::Method> {
+                     tcx: &ty::ctxt) -> Vec<@ty::Method> {
     let mut rslt = Vec::new();
     reader::tagged_docs(item, tag_item_impl_method, |doc| {
         let m_did = reader::with_doc_data(doc, parse_def_id);
@@ -774,7 +774,7 @@ fn item_impl_methods(intr: @IdentInterner, cdata: Cmd, item: ebml::Doc,
 
 /// Returns information about the given implementation.
 pub fn get_impl(intr: @IdentInterner, cdata: Cmd, impl_id: ast::NodeId,
-               tcx: ty::ctxt)
+               tcx: &ty::ctxt)
                 -> ty::Impl {
     let data = cdata.data();
     let impl_item = lookup_item(impl_id, data);
@@ -800,7 +800,7 @@ pub fn get_method_name_and_explicit_self(
 }
 
 pub fn get_method(intr: @IdentInterner, cdata: Cmd, id: ast::NodeId,
-                  tcx: ty::ctxt) -> ty::Method
+                  tcx: &ty::ctxt) -> ty::Method
 {
     let method_doc = lookup_item(id, cdata.data());
     let def_id = item_def_id(method_doc, cdata);
@@ -858,7 +858,7 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
 }
 
 pub fn get_provided_trait_methods(intr: @IdentInterner, cdata: Cmd,
-                                  id: ast::NodeId, tcx: ty::ctxt) ->
+                                  id: ast::NodeId, tcx: &ty::ctxt) ->
         Vec<@ty::Method> {
     let data = cdata.data();
     let item = lookup_item(id, data);
@@ -878,7 +878,7 @@ pub fn get_provided_trait_methods(intr: @IdentInterner, cdata: Cmd,
 }
 
 /// Returns the supertraits of the given trait.
-pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: ty::ctxt)
+pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
                     -> Vec<@ty::TraitRef> {
     let mut results = Vec::new();
     let item_doc = lookup_item(id, cdata.data());
@@ -1235,7 +1235,7 @@ pub fn each_implementation_for_trait(cdata: Cmd,
     });
 }
 
-pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: ty::ctxt)
+pub fn get_trait_of_method(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
                            -> Option<ast::DefId> {
     let item_doc = lookup_item(id, cdata.data());
     let parent_item_id = match item_parent_item(item_doc) {
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index b6eab7b8a74..b869e0a7d91 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -68,13 +68,13 @@ pub type EncodeInlinedItem<'a> = 'a |ecx: &EncodeContext,
                                      ii: InlinedItemRef|;
 
 pub struct EncodeParams<'a> {
-    diag: @SpanHandler,
-    tcx: ty::ctxt,
+    diag: &'a SpanHandler,
+    tcx: &'a ty::ctxt,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'a RefCell<NodeMap<~str>>,
     non_inlineable_statics: &'a RefCell<NodeSet>,
     link_meta: &'a LinkMeta,
-    cstore: @cstore::CStore,
+    cstore: &'a cstore::CStore,
     encode_inlined_item: EncodeInlinedItem<'a>,
 }
 
@@ -95,8 +95,8 @@ pub struct Stats {
 }
 
 pub struct EncodeContext<'a> {
-    diag: @SpanHandler,
-    tcx: ty::ctxt,
+    diag: &'a SpanHandler,
+    tcx: &'a ty::ctxt,
     stats: @Stats,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'a RefCell<NodeMap<~str>>,
@@ -129,7 +129,7 @@ fn encode_trait_ref(ebml_w: &mut writer::Encoder,
                     ecx: &EncodeContext,
                     trait_ref: &ty::TraitRef,
                     tag: uint) {
-    let ty_str_ctxt = @tyencode::ctxt {
+    let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
@@ -165,7 +165,7 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
                              ecx: &EncodeContext,
                              params: &[ty::TypeParameterDef],
                              tag: uint) {
-    let ty_str_ctxt = @tyencode::ctxt {
+    let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
@@ -222,7 +222,7 @@ fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
 pub fn write_type(ecx: &EncodeContext,
                   ebml_w: &mut writer::Encoder,
                   typ: ty::t) {
-    let ty_str_ctxt = @tyencode::ctxt {
+    let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
@@ -234,7 +234,7 @@ pub fn write_type(ecx: &EncodeContext,
 pub fn write_vstore(ecx: &EncodeContext,
                     ebml_w: &mut writer::Encoder,
                     vstore: ty::vstore) {
-    let ty_str_ctxt = @tyencode::ctxt {
+    let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
@@ -256,7 +256,7 @@ fn encode_method_fty(ecx: &EncodeContext,
                      typ: &ty::BareFnTy) {
     ebml_w.start_tag(tag_item_method_fty);
 
-    let ty_str_ctxt = @tyencode::ctxt {
+    let ty_str_ctxt = &tyencode::ctxt {
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
@@ -904,7 +904,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
     }
 
     debug!("encoding info for item at {}",
-           ecx.tcx.sess.codemap.span_to_str(item.span));
+           ecx.tcx.sess.codemap().span_to_str(item.span));
 
     let def_id = local_def(item.id);
     match item.node {
@@ -1630,7 +1630,7 @@ impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
     fn visit_item(&mut self, item: &Item, _: ()) {
         match item.node {
             ItemMac(..) => {
-                let def = self.ecx.tcx.sess.codemap.span_to_snippet(item.span)
+                let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
                     .expect("Unable to find source for macro");
                 self.ebml_w.start_tag(tag_macro_def);
                 self.ebml_w.wr_str(def);
@@ -1899,9 +1899,9 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
 }
 
 // Get the encoded string for a type
-pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
-    let cx = @tyencode::ctxt {
-        diag: tcx.diag,
+pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> ~str {
+    let cx = &tyencode::ctxt {
+        diag: tcx.sess.diagnostic(),
         ds: def_to_str,
         tcx: tcx,
         abbrevs: tyencode::ac_no_abbrevs};
diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs
index 9f6b78354e2..f73a3f35c2b 100644
--- a/src/librustc/metadata/filesearch.rs
+++ b/src/librustc/metadata/filesearch.rs
@@ -11,7 +11,6 @@
 #[allow(non_camel_case_types)];
 
 use std::cell::RefCell;
-use std::option;
 use std::os;
 use std::io::fs;
 use std::vec_ng::Vec;
@@ -27,13 +26,13 @@ pub enum FileMatch { FileMatches, FileDoesntMatch }
 /// a file found in that directory.
 pub type pick<'a> = 'a |path: &Path| -> FileMatch;
 
-pub struct FileSearch {
-    sysroot: @Path,
-    addl_lib_search_paths: @RefCell<HashSet<Path>>,
-    target_triple: ~str
+pub struct FileSearch<'a> {
+    sysroot: &'a Path,
+    addl_lib_search_paths: &'a RefCell<HashSet<Path>>,
+    target_triple: &'a str
 }
 
-impl FileSearch {
+impl<'a> FileSearch<'a> {
     pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
         let mut visited_dirs = HashSet::new();
         let mut found = false;
@@ -127,15 +126,14 @@ impl FileSearch {
         });
     }
 
-    pub fn new(maybe_sysroot: &Option<@Path>,
-               target_triple: &str,
-               addl_lib_search_paths: @RefCell<HashSet<Path>>) -> FileSearch {
-        let sysroot = get_sysroot(maybe_sysroot);
+    pub fn new(sysroot: &'a Path,
+               target_triple: &'a str,
+               addl_lib_search_paths: &'a RefCell<HashSet<Path>>) -> FileSearch<'a> {
         debug!("using sysroot = {}", sysroot.display());
-        FileSearch{
+        FileSearch {
             sysroot: sysroot,
             addl_lib_search_paths: addl_lib_search_paths,
-            target_triple: target_triple.to_owned()
+            target_triple: target_triple
         }
     }
 }
@@ -179,15 +177,8 @@ pub fn get_or_default_sysroot() -> Path {
     }
 
     match canonicalize(os::self_exe_name()) {
-      option::Some(p) => { let mut p = p; p.pop(); p.pop(); p }
-      option::None => fail!("can't determine value for sysroot")
-    }
-}
-
-fn get_sysroot(maybe_sysroot: &Option<@Path>) -> @Path {
-    match *maybe_sysroot {
-      option::Some(sr) => sr,
-      option::None => @get_or_default_sysroot()
+        Some(mut p) => { p.pop(); p.pop(); p }
+        None => fail!("can't determine value for sysroot")
     }
 }
 
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 3a0f7edfb5d..28556105c7b 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -46,7 +46,7 @@ pub enum Os {
 }
 
 pub struct Context<'a> {
-    sess: Session,
+    sess: &'a Session,
     span: Span,
     ident: &'a str,
     crate_id: &'a CrateId,
@@ -110,7 +110,7 @@ impl<'a> Context<'a> {
     }
 
     fn find_library_crate(&mut self) -> Option<Library> {
-        let filesearch = self.sess.filesearch;
+        let filesearch = self.sess.filesearch();
         let (dyprefix, dysuffix) = self.dylibname();
 
         // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
@@ -352,7 +352,7 @@ impl<'a> Context<'a> {
     }
 }
 
-pub fn note_crateid_attr(diag: @SpanHandler, crateid: &CrateId) {
+pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
     diag.handler().note(format!("crate_id: {}", crateid.to_str()));
 }
 
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 17e334d05fb..1abbf1307c1 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -62,7 +62,7 @@ pub struct PState<'a> {
     data: &'a [u8],
     krate: ast::CrateNum,
     pos: uint,
-    tcx: ty::ctxt
+    tcx: &'a ty::ctxt
 }
 
 fn peek(st: &PState) -> char {
@@ -105,7 +105,7 @@ fn parse_ident_(st: &mut PState, is_last: |char| -> bool) -> ast::Ident {
 }
 
 pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: ast::CrateNum,
-                             pos: uint, tcx: ty::ctxt) -> PState<'a> {
+                             pos: uint, tcx: &'a ty::ctxt) -> PState<'a> {
     PState {
         data: data,
         krate: crate_num,
@@ -114,25 +114,25 @@ pub fn parse_state_from_data<'a>(data: &'a [u8], crate_num: ast::CrateNum,
     }
 }
 
-pub fn parse_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: ty::ctxt,
+pub fn parse_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
                      conv: conv_did) -> ty::t {
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_ty(&mut st, conv)
 }
 
-pub fn parse_bare_fn_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: ty::ctxt,
+pub fn parse_bare_fn_ty_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
                              conv: conv_did) -> ty::BareFnTy {
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_bare_fn_ty(&mut st, conv)
 }
 
-pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: ty::ctxt,
+pub fn parse_trait_ref_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
                             conv: conv_did) -> ty::TraitRef {
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_trait_ref(&mut st, conv)
 }
 
-pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: ty::ctxt,
+pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx: &ty::ctxt,
                          conv: conv_did) -> ty::substs {
     let mut st = parse_state_from_data(data, crate_num, pos, tcx);
     parse_substs(&mut st, conv)
@@ -565,7 +565,7 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
 }
 
 pub fn parse_type_param_def_data(data: &[u8], start: uint,
-                                 crate_num: ast::CrateNum, tcx: ty::ctxt,
+                                 crate_num: ast::CrateNum, tcx: &ty::ctxt,
                                  conv: conv_did) -> ty::TypeParameterDef
 {
     let mut st = parse_state_from_data(data, crate_num, start, tcx);
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 590487f20d0..e78fe8e72a8 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -29,18 +29,17 @@ use syntax::ast;
 use syntax::ast::*;
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token;
-use syntax::print::pprust::*;
 
 macro_rules! mywrite( ($wr:expr, $($arg:tt)*) => (
     format_args!(|a| { mywrite($wr, a) }, $($arg)*)
 ) )
 
-pub struct ctxt {
-    diag: @SpanHandler,
+pub struct ctxt<'a> {
+    diag: &'a SpanHandler,
     // Def -> str Callback:
-    ds: extern "Rust" fn(DefId) -> ~str,
+    ds: fn(DefId) -> ~str,
     // The type context.
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     abbrevs: abbrev_ctxt
 }
 
@@ -62,7 +61,7 @@ fn mywrite(w: &mut MemWriter, fmt: &fmt::Arguments) {
     fmt::write(&mut *w as &mut io::Writer, fmt);
 }
 
-pub fn enc_ty(w: &mut MemWriter, cx: @ctxt, t: ty::t) {
+pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
     match cx.abbrevs {
       ac_no_abbrevs => {
           let result_str_opt;
@@ -131,7 +130,7 @@ fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
     }
 }
 
-fn enc_mt(w: &mut MemWriter, cx: @ctxt, mt: ty::mt) {
+fn enc_mt(w: &mut MemWriter, cx: &ctxt, mt: ty::mt) {
     enc_mutability(w, mt.mutbl);
     enc_ty(w, cx, mt.ty);
 }
@@ -146,7 +145,7 @@ fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
     }
 }
 
-pub fn enc_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::substs) {
+pub fn enc_substs(w: &mut MemWriter, cx: &ctxt, substs: &ty::substs) {
     enc_region_substs(w, cx, &substs.regions);
     enc_opt(w, substs.self_ty, |w, t| enc_ty(w, cx, t));
     mywrite!(w, "[");
@@ -154,7 +153,7 @@ pub fn enc_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::substs) {
     mywrite!(w, "]");
 }
 
-fn enc_region_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
+fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &ty::RegionSubsts) {
     match *substs {
         ty::ErasedRegions => {
             mywrite!(w, "e");
@@ -169,7 +168,7 @@ fn enc_region_substs(w: &mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
     }
 }
 
-fn enc_region(w: &mut MemWriter, cx: @ctxt, r: ty::Region) {
+fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
     match r {
         ty::ReLateBound(id, br) => {
             mywrite!(w, "b[{}|", id);
@@ -203,7 +202,7 @@ fn enc_region(w: &mut MemWriter, cx: @ctxt, r: ty::Region) {
     }
 }
 
-fn enc_bound_region(w: &mut MemWriter, cx: @ctxt, br: ty::BoundRegion) {
+fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
     match br {
         ty::BrAnon(idx) => {
             mywrite!(w, "a{}|", idx);
@@ -219,7 +218,7 @@ fn enc_bound_region(w: &mut MemWriter, cx: @ctxt, br: ty::BoundRegion) {
     }
 }
 
-pub fn enc_vstore(w: &mut MemWriter, cx: @ctxt, v: ty::vstore) {
+pub fn enc_vstore(w: &mut MemWriter, cx: &ctxt, v: ty::vstore) {
     mywrite!(w, "/");
     match v {
         ty::vstore_fixed(u) => mywrite!(w, "{}|", u),
@@ -231,12 +230,12 @@ pub fn enc_vstore(w: &mut MemWriter, cx: @ctxt, v: ty::vstore) {
     }
 }
 
-pub fn enc_trait_ref(w: &mut MemWriter, cx: @ctxt, s: &ty::TraitRef) {
+pub fn enc_trait_ref(w: &mut MemWriter, cx: &ctxt, s: &ty::TraitRef) {
     mywrite!(w, "{}|", (cx.ds)(s.def_id));
     enc_substs(w, cx, &s.substs);
 }
 
-pub fn enc_trait_store(w: &mut MemWriter, cx: @ctxt, s: ty::TraitStore) {
+pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
     match s {
         ty::UniqTraitStore => mywrite!(w, "~"),
         ty::RegionTraitStore(re) => {
@@ -246,7 +245,7 @@ pub fn enc_trait_store(w: &mut MemWriter, cx: @ctxt, s: ty::TraitStore) {
     }
 }
 
-fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
+fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
     match *st {
         ty::ty_nil => mywrite!(w, "n"),
         ty::ty_bot => mywrite!(w, "z"),
@@ -372,13 +371,13 @@ fn enc_onceness(w: &mut MemWriter, o: Onceness) {
     }
 }
 
-pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::BareFnTy) {
+pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
     enc_purity(w, ft.purity);
     enc_abi_set(w, ft.abis);
     enc_fn_sig(w, cx, &ft.sig);
 }
 
-fn enc_closure_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
+fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
     enc_sigil(w, ft.sigil);
     enc_purity(w, ft.purity);
     enc_onceness(w, ft.onceness);
@@ -389,7 +388,7 @@ fn enc_closure_ty(w: &mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
     enc_fn_sig(w, cx, &ft.sig);
 }
 
-fn enc_fn_sig(w: &mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
+fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
     mywrite!(w, "[{}|", fsig.binder_id);
     for ty in fsig.inputs.iter() {
         enc_ty(w, cx, *ty);
@@ -403,7 +402,7 @@ fn enc_fn_sig(w: &mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
     enc_ty(w, cx, fsig.output);
 }
 
-fn enc_bounds(w: &mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
+fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
     for bound in bs.builtin_bounds.iter() {
         match bound {
             ty::BoundSend => mywrite!(w, "S"),
@@ -422,7 +421,7 @@ fn enc_bounds(w: &mut MemWriter, cx: @ctxt, bs: &ty::ParamBounds) {
     mywrite!(w, ".");
 }
 
-pub fn enc_type_param_def(w: &mut MemWriter, cx: @ctxt, v: &ty::TypeParameterDef) {
+pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
     mywrite!(w, "{}:{}|", token::get_ident(v.ident), (cx.ds)(v.def_id));
     enc_bounds(w, cx, v.bounds);
     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index fed35922a90..883883e5046 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -34,6 +34,7 @@ use syntax;
 
 use std::libc;
 use std::cast;
+use std::cell::RefCell;
 use std::io::Seek;
 use std::rc::Rc;
 use std::vec_ng::Vec;
@@ -53,27 +54,27 @@ pub struct Maps {
     root_map: middle::borrowck::root_map,
     method_map: middle::typeck::MethodMap,
     vtable_map: middle::typeck::vtable_map,
-    capture_map: middle::moves::CaptureMap,
+    capture_map: RefCell<middle::moves::CaptureMap>,
 }
 
-struct DecodeContext {
+struct DecodeContext<'a> {
     cdata: @cstore::crate_metadata,
-    tcx: ty::ctxt,
-    maps: Maps
+    tcx: &'a ty::ctxt,
+    maps: &'a Maps
 }
 
-struct ExtendedDecodeContext {
-    dcx: @DecodeContext,
+struct ExtendedDecodeContext<'a> {
+    dcx: &'a DecodeContext<'a>,
     from_id_range: ast_util::IdRange,
     to_id_range: ast_util::IdRange
 }
 
 trait tr {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> Self;
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> Self;
 }
 
 trait tr_intern {
-    fn tr_intern(&self, xcx: @ExtendedDecodeContext) -> ast::DefId;
+    fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
 }
 
 // ______________________________________________________________________
@@ -82,7 +83,7 @@ trait tr_intern {
 pub fn encode_inlined_item(ecx: &e::EncodeContext,
                            ebml_w: &mut writer::Encoder,
                            ii: e::InlinedItemRef,
-                           maps: Maps) {
+                           maps: &Maps) {
     let id = match ii {
         e::IIItemRef(i) => i.id,
         e::IIForeignRef(i) => i.id,
@@ -114,12 +115,12 @@ pub fn encode_exported_macro(ebml_w: &mut writer::Encoder, i: &ast::Item) {
 }
 
 pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
-                           tcx: ty::ctxt,
-                           maps: Maps,
-                           path: Vec<ast_map::PathElem> ,
+                           tcx: &ty::ctxt,
+                           maps: &Maps,
+                           path: Vec<ast_map::PathElem>,
                            par_doc: ebml::Doc)
-                           -> Result<ast::InlinedItem, Vec<ast_map::PathElem> > {
-    let dcx = @DecodeContext {
+                           -> Result<ast::InlinedItem, Vec<ast_map::PathElem>> {
+    let dcx = &DecodeContext {
         cdata: cdata,
         tcx: tcx,
         maps: maps
@@ -137,8 +138,8 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
         });
         let mut ast_dsr = reader::Decoder(ast_doc);
         let from_id_range = Decodable::decode(&mut ast_dsr);
-        let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range);
-        let xcx = @ExtendedDecodeContext {
+        let to_id_range = reserve_id_range(&dcx.tcx.sess, from_id_range);
+        let xcx = &ExtendedDecodeContext {
             dcx: dcx,
             from_id_range: from_id_range,
             to_id_range: to_id_range
@@ -154,7 +155,7 @@ 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);
+        region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, &ii);
         decode_side_tables(xcx, ast_doc);
         match ii {
           ast::IIItem(i) => {
@@ -178,7 +179,7 @@ pub fn decode_exported_macro(par_doc: ebml::Doc) -> @ast::Item {
 // ______________________________________________________________________
 // Enumerating the IDs which appear in an AST
 
-fn reserve_id_range(sess: Session,
+fn reserve_id_range(sess: &Session,
                     from_id_range: ast_util::IdRange) -> ast_util::IdRange {
     // Handle the case of an empty range:
     if from_id_range.empty() { return from_id_range; }
@@ -188,7 +189,7 @@ fn reserve_id_range(sess: Session,
     ast_util::IdRange { min: to_id_min, max: to_id_max }
 }
 
-impl ExtendedDecodeContext {
+impl<'a> ExtendedDecodeContext<'a> {
     pub fn tr_id(&self, id: ast::NodeId) -> ast::NodeId {
         /*!
          * Translates an internal id, meaning a node id that is known
@@ -245,25 +246,25 @@ impl ExtendedDecodeContext {
 }
 
 impl tr_intern for ast::DefId {
-    fn tr_intern(&self, xcx: @ExtendedDecodeContext) -> ast::DefId {
+    fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId {
         xcx.tr_intern_def_id(*self)
     }
 }
 
 impl tr for ast::DefId {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::DefId {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> ast::DefId {
         xcx.tr_def_id(*self)
     }
 }
 
 impl tr for Option<ast::DefId> {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> Option<ast::DefId> {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> Option<ast::DefId> {
         self.map(|d| xcx.tr_def_id(d))
     }
 }
 
 impl tr for Span {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> Span {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> Span {
         xcx.tr_span(*self)
     }
 }
@@ -279,13 +280,13 @@ impl<S:serialize::Encoder> 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(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId;
     fn read_def_id_noxcx(&mut self,
                          cdata: @cstore::crate_metadata) -> ast::DefId;
 }
 
 impl<D:serialize::Decoder> def_id_decoder_helpers for D {
-    fn read_def_id(&mut self, xcx: @ExtendedDecodeContext) -> ast::DefId {
+    fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId {
         let did: ast::DefId = Decodable::decode(self);
         did.tr(xcx)
     }
@@ -375,11 +376,11 @@ fn decode_ast(par_doc: ebml::Doc) -> ast::InlinedItem {
     Decodable::decode(&mut d)
 }
 
-struct AstRenumberer {
-    xcx: @ExtendedDecodeContext,
+struct AstRenumberer<'a> {
+    xcx: &'a ExtendedDecodeContext<'a>,
 }
 
-impl ast_map::FoldOps for AstRenumberer {
+impl<'a> ast_map::FoldOps for AstRenumberer<'a> {
     fn new_id(&self, id: ast::NodeId) -> ast::NodeId {
         if id == ast::DUMMY_NODE_ID {
             // Used by ast_map to map the NodeInlinedParent.
@@ -393,7 +394,7 @@ impl ast_map::FoldOps for AstRenumberer {
     }
 }
 
-fn renumber_and_map_ast(xcx: @ExtendedDecodeContext,
+fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
                         map: &ast_map::Map,
                         path: Vec<ast_map::PathElem> ,
                         ii: ast::InlinedItem) -> ast::InlinedItem {
@@ -416,14 +417,14 @@ fn renumber_and_map_ast(xcx: @ExtendedDecodeContext,
 // ______________________________________________________________________
 // Encoding and decoding of ast::def
 
-fn decode_def(xcx: @ExtendedDecodeContext, doc: ebml::Doc) -> ast::Def {
+fn decode_def(xcx: &ExtendedDecodeContext, doc: ebml::Doc) -> ast::Def {
     let mut dsr = reader::Decoder(doc);
     let def: ast::Def = Decodable::decode(&mut dsr);
     def.tr(xcx)
 }
 
 impl tr for ast::Def {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::Def {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> ast::Def {
         match *self {
           ast::DefFn(did, p) => ast::DefFn(did.tr(xcx), p),
           ast::DefStaticMethod(did, wrapped_did2, p) => {
@@ -476,7 +477,7 @@ impl tr for ast::Def {
 // Encoding and decoding of adjustment information
 
 impl tr for ty::AutoDerefRef {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoDerefRef {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::AutoDerefRef {
         ty::AutoDerefRef {
             autoderefs: self.autoderefs,
             autoref: match self.autoref {
@@ -488,13 +489,13 @@ impl tr for ty::AutoDerefRef {
 }
 
 impl tr for ty::AutoRef {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoRef {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::AutoRef {
         self.map_region(|r| r.tr(xcx))
     }
 }
 
 impl tr for ty::Region {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::Region {
         match *self {
             ty::ReLateBound(id, br) => ty::ReLateBound(xcx.tr_id(id),
                                                        br.tr(xcx)),
@@ -512,7 +513,7 @@ impl tr for ty::Region {
 }
 
 impl tr for ty::BoundRegion {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::BoundRegion {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> ty::BoundRegion {
         match *self {
             ty::BrAnon(_) |
             ty::BrFresh(_) => *self,
@@ -530,12 +531,12 @@ fn encode_freevar_entry(ebml_w: &mut writer::Encoder, fv: @freevar_entry) {
 }
 
 trait ebml_decoder_helper {
-    fn read_freevar_entry(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
                           -> freevar_entry;
 }
 
 impl<'a> ebml_decoder_helper for reader::Decoder<'a> {
-    fn read_freevar_entry(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_freevar_entry(&mut self, xcx: &ExtendedDecodeContext)
                           -> freevar_entry {
         let fv: freevar_entry = Decodable::decode(self);
         fv.tr(xcx)
@@ -543,7 +544,7 @@ impl<'a> ebml_decoder_helper for reader::Decoder<'a> {
 }
 
 impl tr for freevar_entry {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> freevar_entry {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> freevar_entry {
         freevar_entry {
             def: self.def.tr(xcx),
             span: self.span.tr(xcx),
@@ -555,12 +556,12 @@ impl tr for freevar_entry {
 // Encoding and decoding of CaptureVar information
 
 trait capture_var_helper {
-    fn read_capture_var(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
                         -> moves::CaptureVar;
 }
 
 impl<'a> capture_var_helper for reader::Decoder<'a> {
-    fn read_capture_var(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
                         -> moves::CaptureVar {
         let cvar: moves::CaptureVar = Decodable::decode(self);
         cvar.tr(xcx)
@@ -568,7 +569,7 @@ impl<'a> capture_var_helper for reader::Decoder<'a> {
 }
 
 impl tr for moves::CaptureVar {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> moves::CaptureVar {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> moves::CaptureVar {
         moves::CaptureVar {
             def: self.def.tr(xcx),
             span: self.span.tr(xcx),
@@ -581,7 +582,7 @@ impl tr for moves::CaptureVar {
 // Encoding and decoding of MethodCallee
 
 trait read_method_callee_helper {
-    fn read_method_callee(&mut self, xcx: @ExtendedDecodeContext) -> MethodCallee;
+    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee;
 }
 
 fn encode_method_callee(ecx: &e::EncodeContext,
@@ -601,7 +602,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) -> MethodCallee {
+    fn read_method_callee(&mut self, xcx: &ExtendedDecodeContext) -> MethodCallee {
         self.read_struct("MethodCallee", 3, |this| {
             MethodCallee {
                 origin: this.read_struct_field("origin", 0, |this| {
@@ -621,7 +622,7 @@ impl<'a> read_method_callee_helper for reader::Decoder<'a> {
 }
 
 impl tr for MethodOrigin {
-    fn tr(&self, xcx: @ExtendedDecodeContext) -> MethodOrigin {
+    fn tr(&self, xcx: &ExtendedDecodeContext) -> MethodOrigin {
         match *self {
             typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(xcx)),
             typeck::MethodParam(ref mp) => {
@@ -702,19 +703,19 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
 
 pub trait vtable_decoder_helpers {
     fn read_vtable_res(&mut self,
-                       tcx: ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_res;
     fn read_vtable_param_res(&mut self,
-                       tcx: ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_param_res;
     fn read_vtable_origin(&mut self,
-                          tcx: ty::ctxt, cdata: @cstore::crate_metadata)
+                          tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                           -> typeck::vtable_origin;
 }
 
 impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     fn read_vtable_res(&mut self,
-                       tcx: ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_res {
         @self.read_to_vec(|this|
                           this.read_vtable_param_res(tcx, cdata))
@@ -723,7 +724,7 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn read_vtable_param_res(&mut self,
-                             tcx: ty::ctxt, cdata: @cstore::crate_metadata)
+                             tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
                       -> typeck::vtable_param_res {
         @self.read_to_vec(|this|
                           this.read_vtable_origin(tcx, cdata))
@@ -732,7 +733,7 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn read_vtable_origin(&mut self,
-                          tcx: ty::ctxt, cdata: @cstore::crate_metadata)
+                          tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
         -> typeck::vtable_origin {
         self.read_enum("vtable_origin", |this| {
             this.read_enum_variant(["vtable_static",
@@ -775,12 +776,12 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
 // Encoding and decoding the side tables
 
 trait get_ty_str_ctxt {
-    fn ty_str_ctxt(&self) -> @tyencode::ctxt;
+    fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a>;
 }
 
 impl<'a> get_ty_str_ctxt for e::EncodeContext<'a> {
-    fn ty_str_ctxt(&self) -> @tyencode::ctxt {
-        @tyencode::ctxt {
+    fn ty_str_ctxt<'a>(&'a self) -> tyencode::ctxt<'a> {
+        tyencode::ctxt {
             diag: self.tcx.sess.diagnostic(),
             ds: e::def_to_str,
             tcx: self.tcx,
@@ -821,7 +822,7 @@ impl<'a> ebml_writer_helpers for writer::Encoder<'a> {
                            type_param_def: &ty::TypeParameterDef) {
         self.emit_opaque(|this| {
             tyencode::enc_type_param_def(this.writer,
-                                         ecx.ty_str_ctxt(),
+                                         &ecx.ty_str_ctxt(),
                                          type_param_def)
         })
     }
@@ -850,7 +851,7 @@ impl<'a> ebml_writer_helpers for writer::Encoder<'a> {
     }
 
     fn emit_substs(&mut self, ecx: &e::EncodeContext, substs: &ty::substs) {
-        self.emit_opaque(|this| tyencode::enc_substs(this.writer, ecx.ty_str_ctxt(), substs))
+        self.emit_opaque(|this| tyencode::enc_substs(this.writer, &ecx.ty_str_ctxt(), substs))
     }
 
     fn emit_auto_adjustment(&mut self, ecx: &e::EncodeContext, adj: &ty::AutoAdjustment) {
@@ -906,7 +907,7 @@ impl<'a> write_tag_and_id for writer::Encoder<'a> {
 struct SideTableEncodingIdVisitor<'a,'b> {
     ecx_ptr: *libc::c_void,
     new_ebml_w: &'a mut writer::Encoder<'b>,
-    maps: Maps,
+    maps: &'a Maps,
 }
 
 impl<'a,'b> ast_util::IdVisitingOperation for
@@ -929,7 +930,7 @@ impl<'a,'b> ast_util::IdVisitingOperation for
 }
 
 fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
-                             maps: Maps,
+                             maps: &Maps,
                              ebml_w: &mut writer::Encoder,
                              ii: &ast::InlinedItem) {
     ebml_w.start_tag(c::tag_table as uint);
@@ -951,7 +952,7 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
 }
 
 fn encode_side_tables_for_id(ecx: &e::EncodeContext,
-                             maps: Maps,
+                             maps: &Maps,
                              ebml_w: &mut writer::Encoder,
                              id: ast::NodeId) {
     let tcx = ecx.tcx;
@@ -1075,20 +1076,16 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         }
     }
 
-    {
-        let capture_map = maps.capture_map.borrow();
-        let r = capture_map.get().find(&id);
-        for &cap_vars in r.iter() {
-            ebml_w.tag(c::tag_table_capture_map, |ebml_w| {
-                ebml_w.id(id);
-                ebml_w.tag(c::tag_table_val, |ebml_w| {
-                    ebml_w.emit_from_vec(cap_vars.deref().as_slice(),
-                                         |ebml_w, cap_var| {
-                        cap_var.encode(ebml_w);
-                    })
+    for &cap_vars in maps.capture_map.borrow().get().find(&id).iter() {
+        ebml_w.tag(c::tag_table_capture_map, |ebml_w| {
+            ebml_w.id(id);
+            ebml_w.tag(c::tag_table_val, |ebml_w| {
+                ebml_w.emit_from_vec(cap_vars.deref().as_slice(),
+                                        |ebml_w, cap_var| {
+                    cap_var.encode(ebml_w);
                 })
             })
-        }
+        })
     }
 }
 
@@ -1105,16 +1102,16 @@ impl<'a> doc_decoder_helpers for ebml::Doc<'a> {
 }
 
 trait ebml_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, xcx: &ExtendedDecodeContext) -> ty::t;
+    fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t>;
+    fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
                            -> ty::TypeParameterDef;
-    fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_ty_param_bounds_and_ty(&mut self, xcx: &ExtendedDecodeContext)
                                 -> ty::ty_param_bounds_and_ty;
-    fn read_substs(&mut self, xcx: @ExtendedDecodeContext) -> ty::substs;
-    fn read_auto_adjustment(&mut self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment;
+    fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> ty::substs;
+    fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment;
     fn convert_def_id(&mut self,
-                      xcx: @ExtendedDecodeContext,
+                      xcx: &ExtendedDecodeContext,
                       source: DefIdSource,
                       did: ast::DefId)
                       -> ast::DefId;
@@ -1122,15 +1119,15 @@ trait ebml_decoder_decoder_helpers {
     // Versions of the type reading functions that don't need the full
     // ExtendedDecodeContext.
     fn read_ty_noxcx(&mut self,
-                     tcx: ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t;
+                     tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t;
     fn read_tys_noxcx(&mut self,
-                      tcx: ty::ctxt,
-                      cdata: @cstore::crate_metadata) -> Vec<ty::t> ;
+                      tcx: &ty::ctxt,
+                      cdata: @cstore::crate_metadata) -> Vec<ty::t>;
 }
 
 impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     fn read_ty_noxcx(&mut self,
-                     tcx: ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
+                     tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
         self.read_opaque(|_, doc| {
             tydecode::parse_ty_data(
                 doc.data,
@@ -1142,14 +1139,14 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn read_tys_noxcx(&mut self,
-                      tcx: ty::ctxt,
+                      tcx: &ty::ctxt,
                       cdata: @cstore::crate_metadata) -> Vec<ty::t> {
         self.read_to_vec(|this| this.read_ty_noxcx(tcx, cdata) )
             .move_iter()
             .collect()
     }
 
-    fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t {
+    fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> 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
@@ -1177,11 +1174,11 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
         }
     }
 
-    fn read_tys(&mut self, xcx: @ExtendedDecodeContext) -> Vec<ty::t> {
+    fn read_tys(&mut self, xcx: &ExtendedDecodeContext) -> Vec<ty::t> {
         self.read_to_vec(|this| this.read_ty(xcx)).move_iter().collect()
     }
 
-    fn read_type_param_def(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_type_param_def(&mut self, xcx: &ExtendedDecodeContext)
                            -> ty::TypeParameterDef {
         self.read_opaque(|this, doc| {
             tydecode::parse_type_param_def_data(
@@ -1193,7 +1190,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
         })
     }
 
-    fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
+    fn read_ty_param_bounds_and_ty(&mut self, xcx: &ExtendedDecodeContext)
                                    -> ty::ty_param_bounds_and_ty {
         self.read_struct("ty_param_bounds_and_ty", 2, |this| {
             ty::ty_param_bounds_and_ty {
@@ -1225,7 +1222,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
         })
     }
 
-    fn read_substs(&mut self, xcx: @ExtendedDecodeContext) -> ty::substs {
+    fn read_substs(&mut self, xcx: &ExtendedDecodeContext) -> ty::substs {
         self.read_opaque(|this, doc| {
             tydecode::parse_substs_data(doc.data,
                                         xcx.dcx.cdata.cnum,
@@ -1235,7 +1232,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
         })
     }
 
-    fn read_auto_adjustment(&mut self, xcx: @ExtendedDecodeContext) -> ty::AutoAdjustment {
+    fn read_auto_adjustment(&mut self, xcx: &ExtendedDecodeContext) -> ty::AutoAdjustment {
         self.read_enum("AutoAdjustment", |this| {
             let variants = ["AutoAddEnv", "AutoDerefRef", "AutoObject"];
             this.read_enum_variant(variants, |this, i| {
@@ -1281,7 +1278,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn convert_def_id(&mut self,
-                      xcx: @ExtendedDecodeContext,
+                      xcx: &ExtendedDecodeContext,
                       source: tydecode::DefIdSource,
                       did: ast::DefId)
                       -> ast::DefId {
@@ -1322,7 +1319,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     }
 }
 
-fn decode_side_tables(xcx: @ExtendedDecodeContext,
+fn decode_side_tables(xcx: &ExtendedDecodeContext,
                       ast_doc: ebml::Doc) {
     let dcx = xcx.dcx;
     let tbl_doc = ast_doc.get(c::tag_table as uint);
@@ -1446,17 +1443,17 @@ fn decode_item_ast(par_doc: ebml::Doc) -> @ast::Item {
 #[cfg(test)]
 trait fake_ext_ctxt {
     fn cfg(&self) -> ast::CrateConfig;
-    fn parse_sess(&self) -> @parse::ParseSess;
+    fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess;
     fn call_site(&self) -> Span;
     fn ident_of(&self, st: &str) -> ast::Ident;
 }
 
 #[cfg(test)]
-impl fake_ext_ctxt for @parse::ParseSess {
+impl fake_ext_ctxt for parse::ParseSess {
     fn cfg(&self) -> ast::CrateConfig {
         Vec::new()
     }
-    fn parse_sess(&self) -> @parse::ParseSess { *self }
+    fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { self }
     fn call_site(&self) -> Span {
         codemap::Span {
             lo: codemap::BytePos(0),
@@ -1470,7 +1467,7 @@ impl fake_ext_ctxt for @parse::ParseSess {
 }
 
 #[cfg(test)]
-fn mk_ctxt() -> @parse::ParseSess {
+fn mk_ctxt() -> parse::ParseSess {
     parse::new_parse_sess()
 }
 
@@ -1520,7 +1517,7 @@ fn test_more() {
 #[test]
 fn test_simplification() {
     let cx = mk_ctxt();
-    let item = quote_item!(cx,
+    let item = quote_item!(&cx,
         fn new_int_alist<B>() -> alist<int, B> {
             fn eq_int(a: int, b: int) -> bool { a == b }
             return alist {eq_fn: eq_int, data: Vec::new()};
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index e50d2456070..5faf9c9986b 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -32,9 +32,9 @@ use syntax::visit;
 use util::ppaux::Repr;
 
 struct CheckLoanCtxt<'a> {
-    bccx: &'a BorrowckCtxt,
-    dfcx_loans: &'a LoanDataFlow,
-    move_data: move_data::FlowedMoveData,
+    bccx: &'a BorrowckCtxt<'a>,
+    dfcx_loans: &'a LoanDataFlow<'a>,
+    move_data: move_data::FlowedMoveData<'a>,
     all_loans: &'a [Loan],
 }
 
@@ -87,7 +87,7 @@ enum MoveError {
 }
 
 impl<'a> CheckLoanCtxt<'a> {
-    pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx }
+    pub fn tcx(&self) -> &'a ty::ctxt { self.bccx.tcx }
 
     pub fn each_issued_loan(&self, scope_id: ast::NodeId, op: |&Loan| -> bool)
                             -> bool {
@@ -715,9 +715,7 @@ impl<'a> CheckLoanCtxt<'a> {
     fn check_captured_variables(&self,
                                 closure_id: ast::NodeId,
                                 span: Span) {
-        let capture_map = self.bccx.capture_map.borrow();
-        let cap_vars = capture_map.get().get(&closure_id);
-        for cap_var in cap_vars.deref().iter() {
+        for cap_var in self.bccx.capture_map.get(&closure_id).deref().iter() {
             let var_id = ast_util::def_id_of_def(cap_var.def).node;
             let var_path = @LpVar(var_id);
             self.check_if_path_is_moved(closure_id, span,
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index cfc4b3de38d..3d5ea0e89b2 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -47,9 +47,7 @@ pub fn gather_move_from_pat(bccx: &BorrowckCtxt,
 pub fn gather_captures(bccx: &BorrowckCtxt,
                        move_data: &MoveData,
                        closure_expr: &ast::Expr) {
-    let capture_map = bccx.capture_map.borrow();
-    let captured_vars = capture_map.get().get(&closure_expr.id);
-    for captured_var in captured_vars.deref().iter() {
+    for captured_var in bccx.capture_map.get(&closure_expr.id).deref().iter() {
         match captured_var.mode {
             moves::CapMove => {
                 let cmt = bccx.cat_captured_var(closure_expr.id,
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index 9714da3abf5..7f810aabf0f 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -48,7 +48,7 @@ pub fn guarantee_lifetime(bccx: &BorrowckCtxt,
 // Private
 
 struct GuaranteeLifetimeContext<'a> {
-    bccx: &'a BorrowckCtxt,
+    bccx: &'a BorrowckCtxt<'a>,
 
     // the node id of the function body for the enclosing item
     item_scope_id: ast::NodeId,
@@ -65,7 +65,7 @@ struct GuaranteeLifetimeContext<'a> {
 }
 
 impl<'a> GuaranteeLifetimeContext<'a> {
-    fn tcx(&self) -> ty::ctxt {
+    fn tcx(&self) -> &'a ty::ctxt {
         self.bccx.tcx
     }
 
@@ -261,10 +261,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         match cmt.guarantor().cat {
             mc::cat_local(id) |
             mc::cat_arg(id) => {
-                let moved_variables_set = self.bccx
-                                              .moved_variables_set
-                                              .borrow();
-                moved_variables_set.get().contains(&id)
+                self.bccx.moved_variables_set.contains(&id)
             }
             mc::cat_rvalue(..) |
             mc::cat_static_item |
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index f6168feb2b8..3c3c4371ebb 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -27,7 +27,6 @@ use middle::typeck::MethodCall;
 use util::common::indenter;
 use util::ppaux::{Repr};
 
-use std::cell::RefCell;
 use std::vec_ng::Vec;
 use syntax::ast;
 use syntax::ast_util;
@@ -69,10 +68,10 @@ mod gather_moves;
 /// body of the while loop and we will refuse to root the pointer `&*x`
 /// because it would have to be rooted for a region greater than `root_ub`.
 struct GatherLoanCtxt<'a> {
-    bccx: &'a BorrowckCtxt,
+    bccx: &'a BorrowckCtxt<'a>,
     id_range: IdRange,
     move_data: move_data::MoveData,
-    all_loans: @RefCell<Vec<Loan> >,
+    all_loans: Vec<Loan>,
     item_ub: ast::NodeId,
     repeating_ids: Vec<ast::NodeId> }
 
@@ -104,11 +103,11 @@ impl<'a> visit::Visitor<()> for GatherLoanCtxt<'a> {
 }
 
 pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
-                    -> (IdRange, @RefCell<Vec<Loan> >, move_data::MoveData) {
+                    -> (IdRange, Vec<Loan>, move_data::MoveData) {
     let mut glcx = GatherLoanCtxt {
         bccx: bccx,
         id_range: IdRange::max(),
-        all_loans: @RefCell::new(Vec::new()),
+        all_loans: Vec::new(),
         item_ub: body.id,
         repeating_ids: vec!(body.id),
         move_data: MoveData::new()
@@ -116,7 +115,8 @@ pub fn gather_loans(bccx: &BorrowckCtxt, decl: &ast::FnDecl, body: &ast::Block)
     glcx.gather_fn_arg_patterns(decl, body);
 
     glcx.visit_block(body, ());
-    return (glcx.id_range, glcx.all_loans, glcx.move_data);
+    let GatherLoanCtxt { id_range, all_loans, move_data, .. } = glcx;
+    (id_range, all_loans, move_data)
 }
 
 fn add_pat_to_id_range(this: &mut GatherLoanCtxt,
@@ -315,7 +315,7 @@ fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |@LoanPath
 }
 
 impl<'a> GatherLoanCtxt<'a> {
-    pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx }
+    pub fn tcx(&self) -> &'a ty::ctxt { self.bccx.tcx }
 
     pub fn push_repeating_id(&mut self, id: ast::NodeId) {
         self.repeating_ids.push(id);
@@ -440,9 +440,7 @@ impl<'a> GatherLoanCtxt<'a> {
 
     fn guarantee_captures(&mut self,
                           closure_expr: &ast::Expr) {
-        let capture_map = self.bccx.capture_map.borrow();
-        let captured_vars = capture_map.get().get(&closure_expr.id);
-        for captured_var in captured_vars.deref().iter() {
+        for captured_var in self.bccx.capture_map.get(&closure_expr.id).deref().iter() {
             match captured_var.mode {
                 moves::CapCopy | moves::CapMove => { continue; }
                 moves::CapRef => { }
@@ -584,9 +582,8 @@ impl<'a> GatherLoanCtxt<'a> {
                     self.mark_loan_path_as_mutated(loan_path);
                 }
 
-                let all_loans = self.all_loans.borrow();
                 Loan {
-                    index: all_loans.get().len(),
+                    index: self.all_loans.len(),
                     loan_path: loan_path,
                     cmt: cmt,
                     kind: req_kind,
@@ -605,10 +602,7 @@ impl<'a> GatherLoanCtxt<'a> {
         // let loan_path = loan.loan_path;
         // let loan_gen_scope = loan.gen_scope;
         // let loan_kill_scope = loan.kill_scope;
-        {
-            let mut all_loans = self.all_loans.borrow_mut();
-            all_loans.get().push(loan);
-        }
+        self.all_loans.push(loan);
 
         // if loan_gen_scope != borrow_id {
             // FIXME(#6268) Nested method calls
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index aa296bf0a62..228e02fa0ac 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -46,7 +46,7 @@ pub fn compute_restrictions(bccx: &BorrowckCtxt,
 // Private
 
 struct RestrictionsContext<'a> {
-    bccx: &'a BorrowckCtxt,
+    bccx: &'a BorrowckCtxt<'a>,
     span: Span,
     cmt_original: mc::cmt,
     loan_region: ty::Region,
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 44a5acc7f1b..bb6956556b5 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -18,6 +18,7 @@ use middle::typeck;
 use middle::moves;
 use middle::dataflow::DataFlowContext;
 use middle::dataflow::DataFlowOperator;
+use util::nodemap::NodeSet;
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
 use std::cell::{Cell, RefCell};
@@ -61,20 +62,20 @@ impl Clone for LoanDataFlowOperator {
     }
 }
 
-pub type LoanDataFlow = DataFlowContext<LoanDataFlowOperator>;
+pub type LoanDataFlow<'a> = DataFlowContext<'a, LoanDataFlowOperator>;
 
-impl Visitor<()> for BorrowckCtxt {
+impl<'a> Visitor<()> for BorrowckCtxt<'a> {
     fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl,
                 b: &Block, s: Span, n: NodeId, _: ()) {
         borrowck_fn(self, fk, fd, b, s, n);
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: typeck::MethodMap,
-                   moves_map: moves::MovesMap,
-                   moved_variables_set: moves::MovedVariablesSet,
-                   capture_map: moves::CaptureMap,
+                   moves_map: &NodeSet,
+                   moved_variables_set: &NodeSet,
+                   capture_map: &moves::CaptureMap,
                    krate: &ast::Crate)
                    -> root_map {
     let mut bccx = BorrowckCtxt {
@@ -127,14 +128,13 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
     // Check the body of fn items.
     let (id_range, all_loans, move_data) =
         gather_loans::gather_loans(this, decl, body);
-    let all_loans = all_loans.borrow();
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
                              this.method_map,
                              LoanDataFlowOperator,
                              id_range,
-                             all_loans.get().len());
-    for (loan_idx, loan) in all_loans.get().iter().enumerate() {
+                             all_loans.len());
+    for (loan_idx, loan) in all_loans.iter().enumerate() {
         loan_dfcx.add_gen(loan.gen_scope, loan_idx);
         loan_dfcx.add_kill(loan.kill_scope, loan_idx);
     }
@@ -147,7 +147,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
                                                       body);
 
     check_loans::check_loans(this, &loan_dfcx, flowed_moves,
-                             all_loans.get().as_slice(), body);
+                             all_loans.as_slice(), body);
 
     visit::walk_fn(this, fk, decl, body, sp, id, ());
 }
@@ -155,12 +155,12 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 // ----------------------------------------------------------------------
 // Type definitions
 
-pub struct BorrowckCtxt {
-    tcx: ty::ctxt,
+pub struct BorrowckCtxt<'a> {
+    tcx: &'a ty::ctxt,
     method_map: typeck::MethodMap,
-    moves_map: moves::MovesMap,
-    moved_variables_set: moves::MovedVariablesSet,
-    capture_map: moves::CaptureMap,
+    moves_map: &'a NodeSet,
+    moved_variables_set: &'a NodeSet,
+    capture_map: &'a moves::CaptureMap,
     root_map: root_map,
 
     // Statistics:
@@ -335,7 +335,7 @@ impl BitAnd<RestrictionSet,RestrictionSet> for RestrictionSet {
 }
 
 impl Repr for RestrictionSet {
-    fn repr(&self, _tcx: ty::ctxt) -> ~str {
+    fn repr(&self, _tcx: &ty::ctxt) -> ~str {
         format!("RestrictionSet(0x{:x})", self.bits as uint)
     }
 }
@@ -405,7 +405,7 @@ pub enum MovedValueUseKind {
 ///////////////////////////////////////////////////////////////////////////
 // Misc
 
-impl BorrowckCtxt {
+impl<'a> BorrowckCtxt<'a> {
     pub fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region)
                            -> bool {
         self.tcx.region_maps.is_subregion_of(r_sub, r_sup)
@@ -417,11 +417,10 @@ impl BorrowckCtxt {
     }
 
     pub fn is_move(&self, id: ast::NodeId) -> bool {
-        let moves_map = self.moves_map.borrow();
-        moves_map.get().contains(&id)
+        self.moves_map.contains(&id)
     }
 
-    pub fn mc(&self) -> mc::MemCategorizationContext<TcxTyper> {
+    pub fn mc(&self) -> mc::MemCategorizationContext<TcxTyper<'a>> {
         mc::MemCategorizationContext {
             typer: TcxTyper {
                 tcx: self.tcx,
@@ -601,7 +600,7 @@ impl BorrowckCtxt {
             }
         }
 
-        fn move_suggestion(tcx: ty::ctxt, ty: ty::t, default_msg: &'static str)
+        fn move_suggestion(tcx: &ty::ctxt, ty: ty::t, default_msg: &'static str)
                           -> &'static str {
             match ty::get(ty).sty {
                 ty::ty_closure(ref cty) if cty.sigil == ast::BorrowedSigil =>
@@ -871,7 +870,7 @@ impl DataFlowOperator for LoanDataFlowOperator {
 }
 
 impl Repr for Loan {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("Loan_{:?}({}, {:?}, {:?}-{:?}, {})",
              self.index,
              self.loan_path.repr(tcx),
@@ -883,7 +882,7 @@ impl Repr for Loan {
 }
 
 impl Repr for Restriction {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("Restriction({}, {:x})",
              self.loan_path.repr(tcx),
              self.set.bits as uint)
@@ -891,7 +890,7 @@ impl Repr for Restriction {
 }
 
 impl Repr for LoanPath {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match self {
             &LpVar(id) => {
                 format!("$({})", tcx.map.node_to_str(id))
@@ -910,13 +909,13 @@ impl Repr for LoanPath {
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub struct TcxTyper {
-    tcx: ty::ctxt,
+pub struct TcxTyper<'a> {
+    tcx: &'a ty::ctxt,
     method_map: typeck::MethodMap,
 }
 
-impl mc::Typer for TcxTyper {
-    fn tcx(&self) -> ty::ctxt {
+impl<'a> mc::Typer for TcxTyper<'a> {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt {
         self.tcx
     }
 
@@ -924,7 +923,7 @@ impl mc::Typer for TcxTyper {
         Ok(ty::node_id_to_type(self.tcx, id))
     }
 
-    fn node_method_ty(&mut self, method_call: typeck::MethodCall) -> Option<ty::t> {
+    fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t> {
         self.method_map.borrow().get().find(&method_call).map(|method| method.ty)
     }
 
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 5f4d5b43231..66e92583edb 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -55,15 +55,15 @@ pub struct MoveData {
     assignee_ids: RefCell<HashSet<ast::NodeId>>,
 }
 
-pub struct FlowedMoveData {
+pub struct FlowedMoveData<'a> {
     move_data: MoveData,
 
-    dfcx_moves: MoveDataFlow,
+    dfcx_moves: MoveDataFlow<'a>,
 
     // We could (and maybe should, for efficiency) combine both move
     // and assign data flow into one, but this way it's easier to
     // distinguish the bits that correspond to moves and assignments.
-    dfcx_assign: AssignDataFlow
+    dfcx_assign: AssignDataFlow<'a>
 }
 
 /// Index into `MoveData.paths`, used like a pointer
@@ -159,7 +159,7 @@ impl Clone for MoveDataFlowOperator {
     }
 }
 
-pub type MoveDataFlow = DataFlowContext<MoveDataFlowOperator>;
+pub type MoveDataFlow<'a> = DataFlowContext<'a, MoveDataFlowOperator>;
 
 pub struct AssignDataFlowOperator;
 
@@ -171,7 +171,7 @@ impl Clone for AssignDataFlowOperator {
     }
 }
 
-pub type AssignDataFlow = DataFlowContext<AssignDataFlowOperator>;
+pub type AssignDataFlow<'a> = DataFlowContext<'a, AssignDataFlowOperator>;
 
 impl MoveData {
     pub fn new() -> MoveData {
@@ -236,7 +236,7 @@ impl MoveData {
     }
 
     pub fn move_path(&self,
-                     tcx: ty::ctxt,
+                     tcx: &ty::ctxt,
                      lp: @LoanPath) -> MovePathIndex {
         /*!
          * Returns the existing move path index for `lp`, if any,
@@ -355,7 +355,7 @@ impl MoveData {
     }
 
     pub fn add_move(&self,
-                    tcx: ty::ctxt,
+                    tcx: &ty::ctxt,
                     lp: @LoanPath,
                     id: ast::NodeId,
                     kind: MoveKind) {
@@ -390,7 +390,7 @@ impl MoveData {
     }
 
     pub fn add_assignment(&self,
-                          tcx: ty::ctxt,
+                          tcx: &ty::ctxt,
                           lp: @LoanPath,
                           assign_id: ast::NodeId,
                           span: Span,
@@ -435,7 +435,7 @@ impl MoveData {
     }
 
     fn add_gen_kills(&self,
-                     tcx: ty::ctxt,
+                     tcx: &ty::ctxt,
                      dfcx_moves: &mut MoveDataFlow,
                      dfcx_assign: &mut AssignDataFlow) {
         /*!
@@ -566,13 +566,13 @@ impl MoveData {
     }
 }
 
-impl FlowedMoveData {
+impl<'a> FlowedMoveData<'a> {
     pub fn new(move_data: MoveData,
-               tcx: ty::ctxt,
+               tcx: &'a ty::ctxt,
                method_map: typeck::MethodMap,
                id_range: ast_util::IdRange,
                body: &ast::Block)
-               -> FlowedMoveData {
+               -> FlowedMoveData<'a> {
         let mut dfcx_moves = {
             let moves = move_data.moves.borrow();
             DataFlowContext::new(tcx,
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index 2306a25592b..1c3f62df73f 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -18,8 +18,8 @@ use syntax::ast_util;
 use syntax::opt_vec;
 use util::nodemap::NodeMap;
 
-struct CFGBuilder {
-    tcx: ty::ctxt,
+struct CFGBuilder<'a> {
+    tcx: &'a ty::ctxt,
     method_map: typeck::MethodMap,
     exit_map: NodeMap<CFGIndex>,
     graph: CFGGraph,
@@ -32,7 +32,7 @@ struct LoopScope {
     break_index: CFGIndex,    // where to go on a `break
 }
 
-pub fn construct(tcx: ty::ctxt,
+pub fn construct(tcx: &ty::ctxt,
                  method_map: typeck::MethodMap,
                  blk: &ast::Block) -> CFG {
     let mut cfg_builder = CFGBuilder {
@@ -51,7 +51,7 @@ pub fn construct(tcx: ty::ctxt,
          exit: exit}
 }
 
-impl CFGBuilder {
+impl<'a> CFGBuilder<'a> {
     fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
         let mut stmts_exit = pred;
         for &stmt in blk.stmts.iter() {
diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs
index bdf39e3e8ec..5b4a5f89ea9 100644
--- a/src/librustc/middle/cfg/mod.rs
+++ b/src/librustc/middle/cfg/mod.rs
@@ -53,7 +53,7 @@ pub struct CFGIndices {
 }
 
 impl CFG {
-    pub fn new(tcx: ty::ctxt,
+    pub fn new(tcx: &ty::ctxt,
                method_map: typeck::MethodMap,
                blk: &ast::Block) -> CFG {
         construct::construct(tcx, method_map, blk)
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 6841e09f7f2..53a53a66335 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -21,50 +21,42 @@ use syntax::{ast_util, ast_map};
 use syntax::visit::Visitor;
 use syntax::visit;
 
-pub struct CheckCrateVisitor {
-    sess: Session,
+pub struct CheckCrateVisitor<'a> {
     def_map: resolve::DefMap,
     method_map: typeck::MethodMap,
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
 }
 
-impl Visitor<bool> for CheckCrateVisitor {
+impl<'a> Visitor<bool> for CheckCrateVisitor<'a> {
     fn visit_item(&mut self, i: &Item, env: bool) {
-        check_item(self, self.sess, self.def_map, i, env);
+        check_item(self, i, env);
     }
     fn visit_pat(&mut self, p: &Pat, env: bool) {
         check_pat(self, p, env);
     }
     fn visit_expr(&mut self, ex: &Expr, env: bool) {
-        check_expr(self, self.sess, self.def_map, self.method_map,
-                   self.tcx, ex, env);
+        check_expr(self, ex, env);
     }
 }
 
-pub fn check_crate(sess: Session,
-                   krate: &Crate,
+pub fn check_crate(krate: &Crate,
                    def_map: resolve::DefMap,
                    method_map: typeck::MethodMap,
-                   tcx: ty::ctxt) {
+                   tcx: &ty::ctxt) {
     let mut v = CheckCrateVisitor {
-        sess: sess,
         def_map: def_map,
         method_map: method_map,
         tcx: tcx,
     };
     visit::walk_crate(&mut v, krate, false);
-    sess.abort_if_errors();
+    tcx.sess.abort_if_errors();
 }
 
-pub fn check_item(v: &mut CheckCrateVisitor,
-                  sess: Session,
-                  def_map: resolve::DefMap,
-                  it: &Item,
-                  _is_const: bool) {
+fn check_item(v: &mut CheckCrateVisitor, it: &Item, _is_const: bool) {
     match it.node {
         ItemStatic(_, _, ex) => {
             v.visit_expr(ex, true);
-            check_item_recursion(sess, &v.tcx.map, def_map, it);
+            check_item_recursion(&v.tcx.sess, &v.tcx.map, v.def_map, it);
         }
         ItemEnum(ref enum_definition, _) => {
             for var in (*enum_definition).variants.iter() {
@@ -77,8 +69,8 @@ pub fn check_item(v: &mut CheckCrateVisitor,
     }
 }
 
-pub fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
-    fn is_str(e: @Expr) -> bool {
+fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
+    fn is_str(e: &Expr) -> bool {
         match e.node {
             ExprVstore(expr, ExprVstoreUniq) => {
                 match expr.node {
@@ -100,36 +92,30 @@ pub fn check_pat(v: &mut CheckCrateVisitor, p: &Pat, _is_const: bool) {
     }
 }
 
-pub fn check_expr(v: &mut CheckCrateVisitor,
-                  sess: Session,
-                  def_map: resolve::DefMap,
-                  method_map: typeck::MethodMap,
-                  tcx: ty::ctxt,
-                  e: &Expr,
-                  is_const: bool) {
+fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
     if is_const {
         match e.node {
           ExprUnary(UnDeref, _) => { }
           ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => {
-            sess.span_err(e.span,
-                          "cannot do allocations in constant expressions");
+            v.tcx.sess.span_err(e.span,
+                                "cannot do allocations in constant expressions");
             return;
           }
           ExprLit(lit) if ast_util::lit_is_str(lit) => {}
           ExprBinary(..) | ExprUnary(..) => {
-              let method_call = typeck::MethodCall::expr(e.id);
-            if method_map.borrow().get().contains_key(&method_call) {
-                sess.span_err(e.span, "user-defined operators are not \
-                                       allowed in constant expressions");
+            let method_call = typeck::MethodCall::expr(e.id);
+            if v.method_map.borrow().get().contains_key(&method_call) {
+                v.tcx.sess.span_err(e.span, "user-defined operators are not \
+                                             allowed in constant expressions");
             }
           }
           ExprLit(_) => (),
           ExprCast(_, _) => {
-            let ety = ty::expr_ty(tcx, e);
+            let ety = ty::expr_ty(v.tcx, e);
             if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
-                sess.span_err(e.span, ~"can not cast to `" +
-                              ppaux::ty_to_str(tcx, ety) +
-                              "` in a constant expression");
+                v.tcx.sess.span_err(e.span, ~"can not cast to `" +
+                                              ppaux::ty_to_str(v.tcx, ety) +
+                                             "` in a constant expression");
             }
           }
           ExprPath(ref pth) => {
@@ -138,12 +124,11 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
             // foo::<bar> in a const. Currently that is only done on
             // a path in trans::callee that only works in block contexts.
             if !pth.segments.iter().all(|segment| segment.types.is_empty()) {
-                sess.span_err(
-                    e.span, "paths in constants may only refer to \
-                             items without type parameters");
+                v.tcx.sess.span_err(e.span,
+                                    "paths in constants may only refer to \
+                                     items without type parameters");
             }
-            let def_map = def_map.borrow();
-            match def_map.get().find(&e.id) {
+            match v.def_map.borrow().get().find(&e.id) {
               Some(&DefStatic(..)) |
               Some(&DefFn(_, _)) |
               Some(&DefVariant(_, _, _)) |
@@ -151,24 +136,21 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
 
               Some(&def) => {
                 debug!("(checking const) found bad def: {:?}", def);
-                sess.span_err(
-                    e.span,
+                v.tcx.sess.span_err(e.span,
                     "paths in constants may only refer to \
                      constants or functions");
               }
               None => {
-                sess.span_bug(e.span, "unbound path in const?!");
+                v.tcx.sess.span_bug(e.span, "unbound path in const?!");
               }
             }
           }
           ExprCall(callee, _) => {
-            let def_map = def_map.borrow();
-            match def_map.get().find(&callee.id) {
+            match v.def_map.borrow().get().find(&callee.id) {
                 Some(&DefStruct(..)) => {}    // OK.
                 Some(&DefVariant(..)) => {}    // OK.
                 _ => {
-                    sess.span_err(
-                        e.span,
+                    v.tcx.sess.span_err(e.span,
                         "function calls in constants are limited to \
                          struct and enum constructors");
                 }
@@ -184,18 +166,17 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
           ExprRepeat(..) |
           ExprStruct(..) => { }
           ExprAddrOf(..) => {
-                sess.span_err(
-                    e.span,
+                v.tcx.sess.span_err(e.span,
                     "references in constants may only refer to \
                      immutable values");
           },
           ExprVstore(_, ExprVstoreUniq) => {
-              sess.span_err(e.span, "cannot allocate vectors in constant expressions")
+              v.tcx.sess.span_err(e.span, "cannot allocate vectors in constant expressions")
           },
 
           _ => {
-            sess.span_err(e.span,
-                          "constant contains unimplemented expression type");
+            v.tcx.sess.span_err(e.span,
+                                "constant contains unimplemented expression type");
             return;
           }
         }
@@ -205,14 +186,14 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
 
 struct CheckItemRecursionVisitor<'a> {
     root_it: &'a Item,
-    sess: Session,
+    sess: &'a Session,
     ast_map: &'a ast_map::Map,
     def_map: resolve::DefMap,
     idstack: Vec<NodeId> }
 
 // Make sure a const item doesn't recursively refer to itself
 // FIXME: Should use the dependency graph when it's available (#1356)
-pub fn check_item_recursion<'a>(sess: Session,
+pub fn check_item_recursion<'a>(sess: &'a Session,
                                 ast_map: &'a ast_map::Map,
                                 def_map: resolve::DefMap,
                                 it: &'a Item) {
diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs
index 2c3d4a3e22f..4b99ce28505 100644
--- a/src/librustc/middle/check_loop.rs
+++ b/src/librustc/middle/check_loop.rs
@@ -20,15 +20,15 @@ enum Context {
     Normal, Loop, Closure
 }
 
-struct CheckLoopVisitor {
-    tcx: ty::ctxt,
+struct CheckLoopVisitor<'a> {
+    tcx: &'a ty::ctxt,
 }
 
-pub fn check_crate(tcx: ty::ctxt, krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt, krate: &ast::Crate) {
     visit::walk_crate(&mut CheckLoopVisitor { tcx: tcx }, krate, Normal)
 }
 
-impl Visitor<Context> for CheckLoopVisitor {
+impl<'a> Visitor<Context> for CheckLoopVisitor<'a> {
     fn visit_item(&mut self, i: &ast::Item, _cx: Context) {
         visit::walk_item(self, i, Normal);
     }
@@ -52,7 +52,7 @@ impl Visitor<Context> for CheckLoopVisitor {
     }
 }
 
-impl CheckLoopVisitor {
+impl<'a> CheckLoopVisitor<'a> {
     fn require_loop(&self, name: &str, cx: Context, span: Span) {
         match cx {
             Loop => {}
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index fddad9214e8..610abe749c6 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -16,7 +16,7 @@ use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
 use middle::typeck::MethodMap;
-use middle::moves;
+use util::nodemap::NodeSet;
 use util::ppaux::ty_to_str;
 
 use std::cmp;
@@ -30,47 +30,41 @@ use syntax::parse::token;
 use syntax::visit;
 use syntax::visit::{Visitor, FnKind};
 
-struct MatchCheckCtxt {
-    tcx: ty::ctxt,
+struct MatchCheckCtxt<'a> {
+    tcx: &'a ty::ctxt,
     method_map: MethodMap,
-    moves_map: moves::MovesMap
+    moves_map: &'a NodeSet
 }
 
-struct CheckMatchVisitor {
-    cx: @MatchCheckCtxt
-}
-
-impl Visitor<()> for CheckMatchVisitor {
+impl<'a> Visitor<()> for MatchCheckCtxt<'a> {
     fn visit_expr(&mut self, ex: &Expr, _: ()) {
-        check_expr(self, self.cx, ex, ());
+        check_expr(self, ex);
     }
     fn visit_local(&mut self, l: &Local, _: ()) {
-        check_local(self, self.cx, l, ());
+        check_local(self, l);
     }
     fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, n: NodeId, _: ()) {
-        check_fn(self, self.cx, fk, fd, b, s, n, ());
+        check_fn(self, fk, fd, b, s, n);
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: MethodMap,
-                   moves_map: moves::MovesMap,
+                   moves_map: &NodeSet,
                    krate: &Crate) {
-    let cx = @MatchCheckCtxt {tcx: tcx,
-                              method_map: method_map,
-                              moves_map: moves_map};
-    let mut v = CheckMatchVisitor { cx: cx };
+    let mut cx = MatchCheckCtxt {
+        tcx: tcx,
+        method_map: method_map,
+        moves_map: moves_map
+    };
 
-    visit::walk_crate(&mut v, krate, ());
+    visit::walk_crate(&mut cx, krate, ());
 
     tcx.sess.abort_if_errors();
 }
 
-fn check_expr(v: &mut CheckMatchVisitor,
-                  cx: @MatchCheckCtxt,
-                  ex: &Expr,
-                  s: ()) {
-    visit::walk_expr(v, ex, s);
+fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
+    visit::walk_expr(cx, ex, ());
     match ex.node {
       ExprMatch(scrut, ref arms) => {
         // First, check legality of move bindings.
@@ -871,11 +865,8 @@ fn default(cx: &MatchCheckCtxt, r: &[@Pat]) -> Option<Vec<@Pat> > {
     }
 }
 
-fn check_local(v: &mut CheckMatchVisitor,
-                   cx: &MatchCheckCtxt,
-                   loc: &Local,
-                   s: ()) {
-    visit::walk_local(v, loc, s);
+fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
+    visit::walk_local(cx, loc, ());
     if is_refutable(cx, loc.pat) {
         cx.tcx.sess.span_err(loc.pat.span,
                              "refutable pattern in local binding");
@@ -885,15 +876,13 @@ fn check_local(v: &mut CheckMatchVisitor,
     check_legality_of_move_bindings(cx, false, [ loc.pat ]);
 }
 
-fn check_fn(v: &mut CheckMatchVisitor,
-                cx: &MatchCheckCtxt,
-                kind: &FnKind,
-                decl: &FnDecl,
-                body: &Block,
-                sp: Span,
-                id: NodeId,
-                s: ()) {
-    visit::walk_fn(v, kind, decl, body, sp, id, s);
+fn check_fn(cx: &mut MatchCheckCtxt,
+            kind: &FnKind,
+            decl: &FnDecl,
+            body: &Block,
+            sp: Span,
+            id: NodeId) {
+    visit::walk_fn(cx, kind, decl, body, sp, id, ());
     for input in decl.inputs.iter() {
         if is_refutable(cx, input.pat) {
             cx.tcx.sess.span_err(input.pat.span,
@@ -964,8 +953,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                     by_ref_span = Some(span);
                 }
                 BindByValue(_) => {
-                    let moves_map = cx.moves_map.borrow();
-                    if moves_map.get().contains(&id) {
+                    if cx.moves_map.contains(&id) {
                         any_by_move = true;
                     }
                 }
@@ -1002,8 +990,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
             if pat_is_binding(def_map, p) {
                 match p.node {
                     PatIdent(_, _, sub) => {
-                        let moves_map = cx.moves_map.borrow();
-                        if moves_map.get().contains(&p.id) {
+                        if cx.moves_map.contains(&p.id) {
                             check_move(p, sub);
                         }
                     }
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
index ebf1904d3cb..e80c60ad015 100644
--- a/src/librustc/middle/check_static.rs
+++ b/src/librustc/middle/check_static.rs
@@ -30,7 +30,7 @@ use syntax::visit;
 use syntax::print::pprust;
 
 
-fn safe_type_for_static_mut(cx: ty::ctxt, e: &ast::Expr) -> Option<~str> {
+fn safe_type_for_static_mut(cx: &ty::ctxt, e: &ast::Expr) -> Option<~str> {
     let node_ty = ty::node_id_to_type(cx, e.id);
     let tcontents = ty::type_contents(cx, node_ty);
     debug!("safe_type_for_static_mut(dtor={}, managed={}, owned={})",
@@ -49,16 +49,15 @@ fn safe_type_for_static_mut(cx: ty::ctxt, e: &ast::Expr) -> Option<~str> {
     Some(format!("mutable static items are not allowed to have {}", suffix))
 }
 
-struct CheckStaticVisitor {
-    tcx: ty::ctxt,
+struct CheckStaticVisitor<'a> {
+    tcx: &'a ty::ctxt,
 }
 
-pub fn check_crate(tcx: ty::ctxt, krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt, krate: &ast::Crate) {
     visit::walk_crate(&mut CheckStaticVisitor { tcx: tcx }, krate, false)
 }
 
-impl CheckStaticVisitor {
-
+impl<'a> CheckStaticVisitor<'a> {
     fn report_error(&self, span: Span, result: Option<~str>) -> bool {
         match result {
             None => { false }
@@ -70,7 +69,7 @@ impl CheckStaticVisitor {
     }
 }
 
-impl Visitor<bool> for CheckStaticVisitor {
+impl<'a> Visitor<bool> for CheckStaticVisitor<'a> {
 
     fn visit_item(&mut self, i: &ast::Item, _is_const: bool) {
         debug!("visit_item(item={})", pprust::item_to_str(i));
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index 1f675b7bb4a..c5a466f599d 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -15,7 +15,6 @@ use middle::astencode;
 
 use middle::ty;
 use middle::typeck::astconv;
-use middle;
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
 
 use syntax::ast::*;
@@ -84,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<@Expr> {
+pub fn lookup_const(tcx: &ty::ctxt, e: &Expr) -> Option<@Expr> {
     let opt_def = {
         let def_map = tcx.def_map.borrow();
         def_map.get().find_copy(&e.id)
@@ -100,7 +99,7 @@ pub fn lookup_const(tcx: ty::ctxt, e: &Expr) -> Option<@Expr> {
     }
 }
 
-pub fn lookup_variant_by_id(tcx: ty::ctxt,
+pub fn lookup_variant_by_id(tcx: &ty::ctxt,
                             enum_def: ast::DefId,
                             variant_def: ast::DefId)
                        -> Option<@Expr> {
@@ -127,23 +126,18 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
             }
         }
     } else {
-        {
-            let extern_const_variants = tcx.extern_const_variants.borrow();
-            match extern_const_variants.get().find(&variant_def) {
-                Some(&e) => return e,
-                None => {}
-            }
+        match tcx.extern_const_variants.borrow().get().find(&variant_def) {
+            Some(&e) => return e,
+            None => {}
         }
         let maps = astencode::Maps {
             root_map: @RefCell::new(HashMap::new()),
             method_map: @RefCell::new(FnvHashMap::new()),
             vtable_map: @RefCell::new(NodeMap::new()),
-            capture_map: @RefCell::new(NodeMap::new())
+            capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, enum_def,
-            |a, b, c, d| astencode::decode_inlined_item(a, b,
-                                                        maps,
-                                                        c, d)) {
+            |a, b, c, d| astencode::decode_inlined_item(a, b, &maps, c, d)) {
             csearch::found(ast::IIItem(item)) => match item.node {
                 ItemEnum(ast::EnumDef { variants: ref variants }, _) => {
                     variant_expr(variants.as_slice(), variant_def.node)
@@ -152,16 +146,12 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
             },
             _ => None
         };
-        {
-            let mut extern_const_variants = tcx.extern_const_variants
-                                               .borrow_mut();
-            extern_const_variants.get().insert(variant_def, e);
-            return e;
-        }
+        tcx.extern_const_variants.borrow_mut().get().insert(variant_def, e);
+        return e;
     }
 }
 
-pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
+pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId)
                           -> Option<@Expr> {
     if ast_util::is_local(def_id) {
         {
@@ -188,10 +178,10 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
             root_map: @RefCell::new(HashMap::new()),
             method_map: @RefCell::new(FnvHashMap::new()),
             vtable_map: @RefCell::new(NodeMap::new()),
-            capture_map: @RefCell::new(NodeMap::new())
+            capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, def_id,
-            |a, b, c, d| astencode::decode_inlined_item(a, b, maps, c, d)) {
+            |a, b, c, d| astencode::decode_inlined_item(a, b, &maps, c, d)) {
             csearch::found(ast::IIItem(item)) => match item.node {
                 ItemStatic(_, ast::MutImmutable, const_expr) => Some(const_expr),
                 _ => None
@@ -207,12 +197,12 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
     }
 }
 
-struct ConstEvalVisitor {
-    tcx: ty::ctxt,
+struct ConstEvalVisitor<'a> {
+    tcx: &'a ty::ctxt,
     ccache: constness_cache,
 }
 
-impl ConstEvalVisitor {
+impl<'a> ConstEvalVisitor<'a> {
     fn classify(&mut self, e: &Expr) -> constness {
         let did = ast_util::local_def(e.id);
         match self.ccache.find(&did) {
@@ -297,14 +287,14 @@ impl ConstEvalVisitor {
 
 }
 
-impl Visitor<()> for ConstEvalVisitor {
+impl<'a> Visitor<()> for ConstEvalVisitor<'a> {
     fn visit_expr_post(&mut self, e: &Expr, _: ()) {
         self.classify(e);
     }
 }
 
 pub fn process_crate(krate: &ast::Crate,
-                     tcx: ty::ctxt) {
+                     tcx: &ty::ctxt) {
     let mut v = ConstEvalVisitor {
         tcx: tcx,
         ccache: DefIdMap::new(),
@@ -326,8 +316,8 @@ pub enum const_val {
     const_bool(bool)
 }
 
-pub fn eval_const_expr(tcx: middle::ty::ctxt, e: &Expr) -> const_val {
-    match eval_const_expr_partial(&tcx, e) {
+pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
+    match eval_const_expr_partial(tcx, e) {
         Ok(r) => r,
         Err(s) => tcx.sess.span_fatal(e.span, s)
     }
@@ -335,7 +325,6 @@ pub fn eval_const_expr(tcx: middle::ty::ctxt, e: &Expr) -> const_val {
 
 pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
                             -> Result<const_val, ~str> {
-    use middle::ty;
     fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
     match e.node {
       ExprUnary(UnNeg, inner) => {
@@ -496,7 +485,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
       }
       ExprPath(_) => {
           match lookup_const(tcx.ty_ctxt(), e) {
-              Some(actual_e) => eval_const_expr_partial(&tcx.ty_ctxt(), actual_e),
+              Some(actual_e) => eval_const_expr_partial(tcx.ty_ctxt(), actual_e),
               None => Err(~"non-constant path in constant expr")
           }
       }
@@ -540,11 +529,11 @@ pub fn compare_const_vals(a: &const_val, b: &const_val) -> Option<int> {
     }
 }
 
-pub fn compare_lit_exprs(tcx: middle::ty::ctxt, a: &Expr, b: &Expr) -> Option<int> {
+pub fn compare_lit_exprs(tcx: &ty::ctxt, a: &Expr, b: &Expr) -> Option<int> {
     compare_const_vals(&eval_const_expr(tcx, a), &eval_const_expr(tcx, b))
 }
 
-pub fn lit_expr_eq(tcx: middle::ty::ctxt, a: &Expr, b: &Expr) -> Option<bool> {
+pub fn lit_expr_eq(tcx: &ty::ctxt, a: &Expr, b: &Expr) -> Option<bool> {
     compare_lit_exprs(tcx, a, b).map(|val| val == 0)
 }
 
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 683ef11aff1..4253f90ef79 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -31,8 +31,8 @@ use util::ppaux::Repr;
 use util::nodemap::NodeMap;
 
 #[deriving(Clone)]
-pub struct DataFlowContext<O> {
-    priv tcx: ty::ctxt,
+pub struct DataFlowContext<'a, O> {
+    priv tcx: &'a ty::ctxt,
     priv method_map: typeck::MethodMap,
 
     /// the data flow operator
@@ -73,8 +73,8 @@ pub trait DataFlowOperator {
     fn join(&self, succ: uint, pred: uint) -> uint;
 }
 
-struct PropagationContext<'a, O> {
-    dfcx: &'a mut DataFlowContext<O>,
+struct PropagationContext<'a, 'b, O> {
+    dfcx: &'a mut DataFlowContext<'b, O>,
     changed: bool
 }
 
@@ -83,13 +83,15 @@ struct LoopScope<'a> {
     break_bits: Vec<uint>
 }
 
-impl<O:DataFlowOperator> pprust::PpAnn for DataFlowContext<O> {
-    fn pre(&self, node: pprust::AnnNode) -> io::IoResult<()> {
-        let (ps, id) = match node {
-            pprust::NodeExpr(ps, expr) => (ps, expr.id),
-            pprust::NodeBlock(ps, blk) => (ps, blk.id),
-            pprust::NodeItem(ps, _) => (ps, 0),
-            pprust::NodePat(ps, pat) => (ps, pat.id)
+impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> {
+    fn pre(&self,
+           ps: &mut pprust::State<DataFlowContext<'a, O>>,
+           node: pprust::AnnNode) -> io::IoResult<()> {
+        let id = match node {
+            pprust::NodeExpr(expr) => expr.id,
+            pprust::NodeBlock(blk) => blk.id,
+            pprust::NodeItem(_) => 0,
+            pprust::NodePat(pat) => pat.id
         };
 
         if self.nodeid_to_bitset.contains_key(&id) {
@@ -111,21 +113,20 @@ impl<O:DataFlowOperator> pprust::PpAnn for DataFlowContext<O> {
                 ~""
             };
 
-            let comment_str = format!("id {}: {}{}{}",
-                                      id, entry_str, gens_str, kills_str);
-            try!(pprust::synth_comment(ps, comment_str));
+            try!(ps.synth_comment(format!("id {}: {}{}{}", id, entry_str,
+                                          gens_str, kills_str)));
             try!(pp::space(&mut ps.s));
         }
         Ok(())
     }
 }
 
-impl<O:DataFlowOperator> DataFlowContext<O> {
-    pub fn new(tcx: ty::ctxt,
+impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
+    pub fn new(tcx: &'a ty::ctxt,
                method_map: typeck::MethodMap,
                oper: O,
                id_range: IdRange,
-               bits_per_id: uint) -> DataFlowContext<O> {
+               bits_per_id: uint) -> DataFlowContext<'a, O> {
         let words_per_id = (bits_per_id + uint::BITS - 1) / uint::BITS;
 
         debug!("DataFlowContext::new(id_range={:?}, bits_per_id={:?}, words_per_id={:?})",
@@ -315,8 +316,8 @@ impl<O:DataFlowOperator> DataFlowContext<O> {
     }
 }
 
-impl<O:DataFlowOperator+Clone+'static> DataFlowContext<O> {
-//                      ^^^^^^^^^^^^^ only needed for pretty printing
+impl<'a, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, O> {
+//                          ^^^^^^^^^^^^^ only needed for pretty printing
     pub fn propagate(&mut self, blk: &ast::Block) {
         //! Performs the data flow analysis.
 
@@ -327,7 +328,7 @@ impl<O:DataFlowOperator+Clone+'static> DataFlowContext<O> {
 
         {
             let mut propcx = PropagationContext {
-                dfcx: self,
+                dfcx: &mut *self,
                 changed: true
             };
 
@@ -351,16 +352,15 @@ impl<O:DataFlowOperator+Clone+'static> DataFlowContext<O> {
     fn pretty_print_to(&self, wr: ~io::Writer,
                        blk: &ast::Block) -> io::IoResult<()> {
         let mut ps = pprust::rust_printer_annotated(wr, self);
-        try!(pprust::cbox(&mut ps, pprust::indent_unit));
-        try!(pprust::ibox(&mut ps, 0u));
-        try!(pprust::print_block(&mut ps, blk));
-        try!(pp::eof(&mut ps.s));
-        Ok(())
+        try!(ps.cbox(pprust::indent_unit));
+        try!(ps.ibox(0u));
+        try!(ps.print_block(blk));
+        pp::eof(&mut ps.s)
     }
 }
 
-impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
-    fn tcx(&self) -> ty::ctxt {
+impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> {
+    fn tcx(&self) -> &'b ty::ctxt {
         self.dfcx.tcx
     }
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 310feb88892..03d51f06ab5 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -35,7 +35,7 @@ pub static DEAD_CODE_LINT_STR: &'static str = "dead_code";
 // explored. For example, if it's a live NodeItem that is a
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
-fn should_explore(tcx: ty::ctxt, def_id: ast::DefId) -> bool {
+fn should_explore(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
     if !is_local(def_id) {
         return false;
     }
@@ -49,17 +49,17 @@ fn should_explore(tcx: ty::ctxt, def_id: ast::DefId) -> bool {
     }
 }
 
-struct MarkSymbolVisitor {
-    worklist: Vec<ast::NodeId> ,
+struct MarkSymbolVisitor<'a> {
+    worklist: Vec<ast::NodeId>,
     method_map: typeck::MethodMap,
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     live_symbols: ~HashSet<ast::NodeId>,
 }
 
-impl MarkSymbolVisitor {
-    fn new(tcx: ty::ctxt,
+impl<'a> MarkSymbolVisitor<'a> {
+    fn new(tcx: &'a ty::ctxt,
            method_map: typeck::MethodMap,
-           worklist: Vec<ast::NodeId> ) -> MarkSymbolVisitor {
+           worklist: Vec<ast::NodeId>) -> MarkSymbolVisitor<'a> {
         MarkSymbolVisitor {
             worklist: worklist,
             method_map: method_map,
@@ -175,7 +175,7 @@ impl MarkSymbolVisitor {
     }
 }
 
-impl Visitor<()> for MarkSymbolVisitor {
+impl<'a> Visitor<()> for MarkSymbolVisitor<'a> {
 
     fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
         match expr.node {
@@ -253,7 +253,7 @@ impl Visitor<()> for LifeSeeder {
     }
 }
 
-fn create_and_seed_worklist(tcx: ty::ctxt,
+fn create_and_seed_worklist(tcx: &ty::ctxt,
                             exported_items: &privacy::ExportedItems,
                             reachable_symbols: &NodeSet,
                             krate: &ast::Crate) -> Vec<ast::NodeId> {
@@ -286,7 +286,7 @@ fn create_and_seed_worklist(tcx: ty::ctxt,
     return life_seeder.worklist;
 }
 
-fn find_live(tcx: ty::ctxt,
+fn find_live(tcx: &ty::ctxt,
              method_map: typeck::MethodMap,
              exported_items: &privacy::ExportedItems,
              reachable_symbols: &NodeSet,
@@ -316,12 +316,12 @@ fn get_struct_ctor_id(item: &ast::Item) -> Option<ast::NodeId> {
     }
 }
 
-struct DeadVisitor {
-    tcx: ty::ctxt,
+struct DeadVisitor<'a> {
+    tcx: &'a ty::ctxt,
     live_symbols: ~HashSet<ast::NodeId>,
 }
 
-impl DeadVisitor {
+impl<'a> DeadVisitor<'a> {
     // id := node id of an item's definition.
     // ctor_id := `Some` if the item is a struct_ctor (tuple struct),
     //            `None` otherwise.
@@ -368,7 +368,7 @@ impl DeadVisitor {
     }
 }
 
-impl Visitor<()> for DeadVisitor {
+impl<'a> Visitor<()> for DeadVisitor<'a> {
     fn visit_item(&mut self, item: &ast::Item, _: ()) {
         let ctor_id = get_struct_ctor_id(item);
         if !self.symbol_is_live(item.id, ctor_id) && should_warn(item) {
@@ -409,7 +409,7 @@ impl Visitor<()> for DeadVisitor {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    reachable_symbols: &NodeSet,
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index d3ec7044040..592c4f7e29e 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -35,8 +35,8 @@ fn type_is_unsafe_function(ty: ty::t) -> bool {
     }
 }
 
-struct EffectCheckVisitor {
-    tcx: ty::ctxt,
+struct EffectCheckVisitor<'a> {
+    tcx: &'a ty::ctxt,
 
     /// The method map.
     method_map: MethodMap,
@@ -44,7 +44,7 @@ struct EffectCheckVisitor {
     unsafe_context: UnsafeContext,
 }
 
-impl EffectCheckVisitor {
+impl<'a> EffectCheckVisitor<'a> {
     fn require_unsafe(&mut self, span: Span, description: &str) {
         match self.unsafe_context {
             SafeContext => {
@@ -80,7 +80,7 @@ impl EffectCheckVisitor {
     }
 }
 
-impl Visitor<()> for EffectCheckVisitor {
+impl<'a> Visitor<()> for EffectCheckVisitor<'a> {
     fn visit_fn(&mut self, fn_kind: &visit::FnKind, fn_decl: &ast::FnDecl,
                 block: &ast::Block, span: Span, node_id: ast::NodeId, _:()) {
 
@@ -191,7 +191,7 @@ impl Visitor<()> for EffectCheckVisitor {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt, method_map: MethodMap, krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt, method_map: MethodMap, krate: &ast::Crate) {
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
         method_map: method_map,
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index a4ff72d55f2..88a6f7aa1e2 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -21,7 +21,7 @@ use syntax::visit;
 use syntax::visit::Visitor;
 
 struct EntryContext<'a> {
-    session: Session,
+    session: &'a Session,
 
     ast_map: &'a ast_map::Map,
 
@@ -48,7 +48,7 @@ impl<'a> Visitor<()> for EntryContext<'a> {
     }
 }
 
-pub fn find_entry_point(session: Session, krate: &Crate, ast_map: &ast_map::Map) {
+pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map) {
     if session.building_library.get() {
         // No need to find a main function
         return;
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index 8b8807e46f5..1ccc5e51487 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -141,7 +141,7 @@ pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) ->
     freevars
 }
 
-pub fn get_freevars(tcx: ty::ctxt, fid: ast::NodeId) -> freevar_info {
+pub fn get_freevars(tcx: &ty::ctxt, fid: ast::NodeId) -> freevar_info {
     let freevars = tcx.freevars.borrow();
     match freevars.get().find(&fid) {
         None => fail!("get_freevars: {} has no freevars", fid),
@@ -149,6 +149,6 @@ pub fn get_freevars(tcx: ty::ctxt, fid: ast::NodeId) -> freevar_info {
     }
 }
 
-pub fn has_freevars(tcx: ty::ctxt, fid: ast::NodeId) -> bool {
+pub fn has_freevars(tcx: &ty::ctxt, fid: ast::NodeId) -> bool {
     !get_freevars(tcx, fid).is_empty()
 }
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 7771cb0ab3c..cc1fdc76991 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -52,12 +52,12 @@ use syntax::visit::Visitor;
 // types.
 
 #[deriving(Clone)]
-pub struct Context {
-    tcx: ty::ctxt,
+pub struct Context<'a> {
+    tcx: &'a ty::ctxt,
     method_map: typeck::MethodMap,
 }
 
-impl Visitor<()> for Context {
+impl<'a> Visitor<()> for Context<'a> {
 
     fn visit_expr(&mut self, ex: &Expr, _: ()) {
         check_expr(self, ex);
@@ -76,7 +76,7 @@ impl Visitor<()> for Context {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: typeck::MethodMap,
                    krate: &Crate) {
     let mut ctx = Context {
@@ -324,7 +324,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
             check_trait_cast(cx, source_ty, target_ty, source.span);
         }
         ExprRepeat(element, count_expr, _) => {
-            let count = ty::eval_repeat_count(&cx.tcx, count_expr);
+            let count = ty::eval_repeat_count(cx.tcx, count_expr);
             if count > 1 {
                 let element_ty = ty::expr_ty(cx.tcx, element);
                 check_copy(cx, element_ty, element.span,
@@ -476,7 +476,7 @@ pub fn check_send(cx: &Context, ty: ty::t, sp: Span) -> bool {
     }
 }
 
-pub fn check_static(tcx: ty::ctxt, ty: ty::t, sp: Span) -> bool {
+pub fn check_static(tcx: &ty::ctxt, ty: ty::t, sp: Span) -> bool {
     if !ty::type_is_static(tcx, ty) {
         match ty::get(ty).sty {
           ty::ty_param(..) => {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index ccf81840a41..2ce34a31129 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -103,27 +103,23 @@ impl LanguageItems {
     )*
 }
 
-struct LanguageItemCollector {
+struct LanguageItemCollector<'a> {
     items: LanguageItems,
 
-    session: Session,
+    session: &'a Session,
 
     item_refs: HashMap<&'static str, uint>,
 }
 
-struct LanguageItemVisitor<'a> {
-    this: &'a mut LanguageItemCollector,
-}
-
-impl<'a> Visitor<()> for LanguageItemVisitor<'a> {
+impl<'a> Visitor<()> for LanguageItemCollector<'a> {
     fn visit_item(&mut self, item: &ast::Item, _: ()) {
         match extract(item.attrs.as_slice()) {
             Some(value) => {
-                let item_index = self.this.item_refs.find_equiv(&value).map(|x| *x);
+                let item_index = self.item_refs.find_equiv(&value).map(|x| *x);
 
                 match item_index {
                     Some(item_index) => {
-                        self.this.collect_item(item_index, local_def(item.id))
+                        self.collect_item(item_index, local_def(item.id))
                     }
                     None => {}
                 }
@@ -135,8 +131,8 @@ impl<'a> Visitor<()> for LanguageItemVisitor<'a> {
     }
 }
 
-impl LanguageItemCollector {
-    pub fn new(session: Session) -> LanguageItemCollector {
+impl<'a> LanguageItemCollector<'a> {
+    pub fn new(session: &'a Session) -> LanguageItemCollector<'a> {
         let mut item_refs = HashMap::new();
 
         $( item_refs.insert($name, $variant as uint); )*
@@ -165,12 +161,11 @@ impl LanguageItemCollector {
     }
 
     pub fn collect_local_language_items(&mut self, krate: &ast::Crate) {
-        let mut v = LanguageItemVisitor { this: self };
-        visit::walk_crate(&mut v, krate, ());
+        visit::walk_crate(self, krate, ());
     }
 
     pub fn collect_external_language_items(&mut self) {
-        let crate_store = self.session.cstore;
+        let crate_store = &self.session.cstore;
         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
             each_lang_item(crate_store, crate_number, |node_id, item_index| {
                 let def_id = ast::DefId { krate: crate_number, node: node_id };
@@ -200,7 +195,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
 }
 
 pub fn collect_language_items(krate: &ast::Crate,
-                              session: Session) -> @LanguageItems {
+                              session: &Session) -> @LanguageItems {
     let mut collector = LanguageItemCollector::new(session);
     collector.collect(krate);
     let LanguageItemCollector { items, .. } = collector;
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 9a6ea297af0..6ea26a9c5aa 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -427,7 +427,7 @@ struct Context<'a> {
     // Current levels of each lint warning
     cur: SmallIntMap<(level, LintSource)>,
     // context we're checking in (used to access fields like sess)
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     // maps from an expression id that corresponds to a method call to the
     // details of the method to be invoked
     method_map: typeck::MethodMap,
@@ -530,7 +530,7 @@ impl<'a> Context<'a> {
         // of what we changed so we can roll everything back after invoking the
         // specified closure
         let mut pushed = 0u;
-        each_lint(self.tcx.sess, attrs, |meta, level, lintname| {
+        each_lint(&self.tcx.sess, attrs, |meta, level, lintname| {
             match self.dict.find_equiv(&lintname) {
                 None => {
                     self.span_lint(
@@ -594,7 +594,7 @@ impl<'a> Context<'a> {
 
 // Check that every lint from the list of attributes satisfies `f`.
 // Return true if that's the case. Otherwise return false.
-pub fn each_lint(sess: session::Session,
+pub fn each_lint(sess: &session::Session,
                  attrs: &[ast::Attribute],
                  f: |@ast::MetaItem, level, InternedString| -> bool)
                  -> bool {
@@ -670,7 +670,7 @@ fn check_while_true_expr(cx: &Context, e: &ast::Expr) {
     }
 }
 impl<'a> AstConv for Context<'a>{
-    fn tcx(&self) -> ty::ctxt { self.tcx }
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
 
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
         ty::lookup_item_type(self.tcx, id)
@@ -795,7 +795,7 @@ fn check_type_limits(cx: &Context, e: &ast::Expr) {
         }
     }
 
-    fn check_limits(tcx: ty::ctxt, binop: ast::BinOp,
+    fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp,
                     l: &ast::Expr, r: &ast::Expr) -> bool {
         let (lit, expr, swap) = match (&l.node, &r.node) {
             (&ast::ExprLit(_), _) => (l, r, true),
@@ -1100,7 +1100,7 @@ fn check_unused_result(cx: &Context, s: &ast::Stmt) {
                     _ => {}
                 }
             } else {
-                csearch::get_item_attrs(cx.tcx.sess.cstore, did, |attrs| {
+                csearch::get_item_attrs(&cx.tcx.sess.cstore, did, |attrs| {
                     if attr::contains_name(attrs.as_slice(), "must_use") {
                         cx.span_lint(UnusedMustUse, s.span,
                                      "unused result which must be used");
@@ -1562,7 +1562,7 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
         let mut s = None;
         // run through all the attributes and take the first
         // stability one.
-        csearch::get_item_attrs(cx.tcx.cstore, id, |meta_items| {
+        csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |meta_items| {
             if s.is_none() {
                 s = attr::find_stability(meta_items.move_iter())
             }
@@ -1749,7 +1749,7 @@ impl<'a> IdVisitingOperation for Context<'a> {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    krate: &ast::Crate) {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 38cbde70ad1..2d4cbee243e 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -111,9 +111,9 @@ use middle::moves;
 use util::nodemap::NodeMap;
 
 use std::cast::transmute;
-use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::io;
+use std::rc::Rc;
 use std::str;
 use std::uint;
 use std::vec_ng::Vec;
@@ -126,9 +126,9 @@ use syntax::{visit, ast_util};
 use syntax::visit::{Visitor, FnKind};
 
 #[deriving(Eq)]
-pub struct Variable(uint);
+struct Variable(uint);
 #[deriving(Eq)]
-pub struct LiveNode(uint);
+struct LiveNode(uint);
 
 impl Variable {
     fn get(&self) -> uint { let Variable(v) = *self; v }
@@ -145,15 +145,15 @@ impl Clone for LiveNode {
 }
 
 #[deriving(Eq)]
-pub enum LiveNodeKind {
+enum LiveNodeKind {
     FreeVarNode(Span),
     ExprNode(Span),
     VarDefNode(Span),
     ExitNode
 }
 
-fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str {
-    let cm = cx.sess.codemap;
+fn live_node_kind_to_str(lnk: LiveNodeKind, cx: &ty::ctxt) -> ~str {
+    let cm = cx.sess.codemap();
     match lnk {
         FreeVarNode(s) => format!("Free var node [{}]", cm.span_to_str(s)),
         ExprNode(s)    => format!("Expr node [{}]", cm.span_to_str(s)),
@@ -162,25 +162,20 @@ fn live_node_kind_to_str(lnk: LiveNodeKind, cx: ty::ctxt) -> ~str {
     }
 }
 
-struct LivenessVisitor;
-
-impl Visitor<@IrMaps> for LivenessVisitor {
-    fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, n: NodeId, e: @IrMaps) {
-        visit_fn(self, fk, fd, b, s, n, e);
+impl<'a> Visitor<()> for IrMaps<'a> {
+    fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, n: NodeId, _: ()) {
+        visit_fn(self, fk, fd, b, s, n);
     }
-    fn visit_local(&mut self, l: &Local, e: @IrMaps) { visit_local(self, l, e); }
-    fn visit_expr(&mut self, ex: &Expr, e: @IrMaps) { visit_expr(self, ex, e); }
-    fn visit_arm(&mut self, a: &Arm, e: @IrMaps) { visit_arm(self, a, e); }
+    fn visit_local(&mut self, l: &Local, _: ()) { visit_local(self, l); }
+    fn visit_expr(&mut self, ex: &Expr, _: ()) { visit_expr(self, ex); }
+    fn visit_arm(&mut self, a: &Arm, _: ()) { visit_arm(self, a); }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: typeck::MethodMap,
-                   capture_map: moves::CaptureMap,
+                   capture_map: &moves::CaptureMap,
                    krate: &Crate) {
-    let mut visitor = LivenessVisitor;
-
-    let initial_maps = @IrMaps(tcx, method_map, capture_map);
-    visit::walk_crate(&mut visitor, krate, initial_maps);
+    visit::walk_crate(&mut IrMaps(tcx, method_map, capture_map), krate, ());
     tcx.sess.abort_if_errors();
 }
 
@@ -219,77 +214,75 @@ impl fmt::Show for Variable {
 // assignment.  And so forth.
 
 impl LiveNode {
-    pub fn is_valid(&self) -> bool {
+    fn is_valid(&self) -> bool {
         self.get() != uint::MAX
     }
 }
 
 fn invalid_node() -> LiveNode { LiveNode(uint::MAX) }
 
-pub struct CaptureInfo {
+struct CaptureInfo {
     ln: LiveNode,
     is_move: bool,
     var_nid: NodeId
 }
 
-pub enum LocalKind {
+enum LocalKind {
     FromMatch(BindingMode),
     FromLetWithInitializer,
     FromLetNoInitializer
 }
 
-pub struct LocalInfo {
+struct LocalInfo {
     id: NodeId,
     ident: Ident,
     is_mutbl: bool,
     kind: LocalKind,
 }
 
-pub enum VarKind {
+enum VarKind {
     Arg(NodeId, Ident),
     Local(LocalInfo),
     ImplicitRet
 }
 
-pub struct IrMaps {
-    tcx: ty::ctxt,
+struct IrMaps<'a> {
+    tcx: &'a ty::ctxt,
     method_map: typeck::MethodMap,
-    capture_map: moves::CaptureMap,
-
-    num_live_nodes: Cell<uint>,
-    num_vars: Cell<uint>,
-    live_node_map: RefCell<NodeMap<LiveNode>>,
-    variable_map: RefCell<NodeMap<Variable>>,
-    capture_info_map: RefCell<NodeMap<@Vec<CaptureInfo> >>,
-    var_kinds: RefCell<Vec<VarKind> >,
-    lnks: RefCell<Vec<LiveNodeKind> >,
+    capture_map: &'a moves::CaptureMap,
+
+    num_live_nodes: uint,
+    num_vars: uint,
+    live_node_map: NodeMap<LiveNode>,
+    variable_map: NodeMap<Variable>,
+    capture_info_map: NodeMap<Rc<Vec<CaptureInfo>>>,
+    var_kinds: Vec<VarKind>,
+    lnks: Vec<LiveNodeKind>,
 }
 
-fn IrMaps(tcx: ty::ctxt,
-          method_map: typeck::MethodMap,
-          capture_map: moves::CaptureMap)
-       -> IrMaps {
+fn IrMaps<'a>(tcx: &'a ty::ctxt,
+              method_map: typeck::MethodMap,
+              capture_map: &'a moves::CaptureMap)
+              -> IrMaps<'a> {
     IrMaps {
         tcx: tcx,
         method_map: method_map,
         capture_map: capture_map,
-        num_live_nodes: Cell::new(0),
-        num_vars: Cell::new(0),
-        live_node_map: RefCell::new(NodeMap::new()),
-        variable_map: RefCell::new(NodeMap::new()),
-        capture_info_map: RefCell::new(NodeMap::new()),
-        var_kinds: RefCell::new(Vec::new()),
-        lnks: RefCell::new(Vec::new()),
+        num_live_nodes: 0,
+        num_vars: 0,
+        live_node_map: NodeMap::new(),
+        variable_map: NodeMap::new(),
+        capture_info_map: NodeMap::new(),
+        var_kinds: Vec::new(),
+        lnks: Vec::new(),
     }
 }
 
-impl IrMaps {
-    pub fn add_live_node(&self, lnk: LiveNodeKind) -> LiveNode {
-        let num_live_nodes = self.num_live_nodes.get();
-        let ln = LiveNode(num_live_nodes);
-        let mut lnks = self.lnks.borrow_mut();
-        lnks.get().push(lnk);
-        self.num_live_nodes.set(num_live_nodes + 1);
+impl<'a> IrMaps<'a> {
+    fn add_live_node(&mut self, lnk: LiveNodeKind) -> LiveNode {
+        let ln = LiveNode(self.num_live_nodes);
+        self.lnks.push(lnk);
+        self.num_live_nodes += 1;
 
         debug!("{} is of kind {}", ln.to_str(),
                live_node_kind_to_str(lnk, self.tcx));
@@ -297,26 +290,21 @@ impl IrMaps {
         ln
     }
 
-    pub fn add_live_node_for_node(&self, node_id: NodeId, lnk: LiveNodeKind) {
+    fn add_live_node_for_node(&mut self, node_id: NodeId, lnk: LiveNodeKind) {
         let ln = self.add_live_node(lnk);
-        let mut live_node_map = self.live_node_map.borrow_mut();
-        live_node_map.get().insert(node_id, ln);
+        self.live_node_map.insert(node_id, ln);
 
         debug!("{} is node {}", ln.to_str(), node_id);
     }
 
-    pub fn add_variable(&self, vk: VarKind) -> Variable {
-        let v = Variable(self.num_vars.get());
-        {
-            let mut var_kinds = self.var_kinds.borrow_mut();
-            var_kinds.get().push(vk);
-        }
-        self.num_vars.set(self.num_vars.get() + 1);
+    fn add_variable(&mut self, vk: VarKind) -> Variable {
+        let v = Variable(self.num_vars);
+        self.var_kinds.push(vk);
+        self.num_vars += 1;
 
         match vk {
             Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => {
-                let mut variable_map = self.variable_map.borrow_mut();
-                variable_map.get().insert(node_id, v);
+                self.variable_map.insert(node_id, v);
             },
             ImplicitRet => {}
         }
@@ -326,9 +314,8 @@ impl IrMaps {
         v
     }
 
-    pub fn variable(&self, node_id: NodeId, span: Span) -> Variable {
-        let variable_map = self.variable_map.borrow();
-        match variable_map.get().find(&node_id) {
+    fn variable(&self, node_id: NodeId, span: Span) -> Variable {
+        match self.variable_map.find(&node_id) {
           Some(&var) => var,
           None => {
             self.tcx.sess.span_bug(
@@ -337,9 +324,8 @@ impl IrMaps {
         }
     }
 
-    pub fn variable_name(&self, var: Variable) -> ~str {
-        let var_kinds = self.var_kinds.borrow();
-        match var_kinds.get().get(var.get()) {
+    fn variable_name(&self, var: Variable) -> ~str {
+        match self.var_kinds.get(var.get()) {
             &Local(LocalInfo { ident: nm, .. }) | &Arg(_, nm) => {
                 token::get_ident(nm).get().to_str()
             },
@@ -347,28 +333,16 @@ impl IrMaps {
         }
     }
 
-    pub fn set_captures(&self, node_id: NodeId, cs: Vec<CaptureInfo> ) {
-        let mut capture_info_map = self.capture_info_map.borrow_mut();
-        capture_info_map.get().insert(node_id, @cs);
+    fn set_captures(&mut self, node_id: NodeId, cs: Vec<CaptureInfo>) {
+        self.capture_info_map.insert(node_id, Rc::new(cs));
     }
 
-    pub fn captures(&self, expr: &Expr) -> @Vec<CaptureInfo> {
-        let capture_info_map = self.capture_info_map.borrow();
-        match capture_info_map.get().find(&expr.id) {
-          Some(&caps) => caps,
-          None => {
-            self.tcx.sess.span_bug(expr.span, "no registered caps");
-          }
-        }
-    }
-
-    pub fn lnk(&self, ln: LiveNode) -> LiveNodeKind {
-        let lnks = self.lnks.borrow();
-        *lnks.get().get(ln.get())
+    fn lnk(&self, ln: LiveNode) -> LiveNodeKind {
+        *self.lnks.get(ln.get())
     }
 }
 
-impl Visitor<()> for Liveness {
+impl<'a> Visitor<()> for Liveness<'a> {
     fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, n: NodeId, _: ()) {
         check_fn(self, fk, fd, b, s, n);
     }
@@ -383,25 +357,24 @@ impl Visitor<()> for Liveness {
     }
 }
 
-fn visit_fn(v: &mut LivenessVisitor,
+fn visit_fn(ir: &mut IrMaps,
             fk: &FnKind,
             decl: &FnDecl,
             body: &Block,
             sp: Span,
-            id: NodeId,
-            this: @IrMaps) {
+            id: NodeId) {
     debug!("visit_fn: id={}", id);
     let _i = ::util::common::indenter();
 
     // swap in a new set of IR maps for this function body:
-    let fn_maps = @IrMaps(this.tcx, this.method_map, this.capture_map);
+    let mut fn_maps = IrMaps(ir.tcx, ir.method_map, ir.capture_map);
 
     unsafe {
-        debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(fn_maps));
+        debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(&fn_maps));
     }
 
     for arg in decl.inputs.iter() {
-        pat_util::pat_bindings(this.tcx.def_map,
+        pat_util::pat_bindings(ir.tcx.def_map,
                                arg.pat,
                                |_bm, arg_id, _x, path| {
             debug!("adding argument {}", arg_id);
@@ -412,7 +385,7 @@ fn visit_fn(v: &mut LivenessVisitor,
 
     // gather up the various local variables, significant expressions,
     // and so forth:
-    visit::walk_fn(v, fk, decl, body, sp, id, fn_maps);
+    visit::walk_fn(&mut fn_maps, fk, decl, body, sp, id, ());
 
     // Special nodes and variables:
     // - exit_ln represents the end of the fn, either by return or fail
@@ -425,7 +398,7 @@ fn visit_fn(v: &mut LivenessVisitor,
     };
 
     // compute liveness
-    let mut lsets = Liveness(fn_maps, specials);
+    let mut lsets = Liveness(&mut fn_maps, specials);
     let entry_ln = lsets.compute(decl, body);
 
     // check for various error conditions
@@ -434,12 +407,11 @@ fn visit_fn(v: &mut LivenessVisitor,
     lsets.warn_about_unused_args(decl, entry_ln);
 }
 
-fn visit_local(v: &mut LivenessVisitor, local: &Local, this: @IrMaps) {
-    let def_map = this.tcx.def_map;
-    pat_util::pat_bindings(def_map, local.pat, |bm, p_id, sp, path| {
+fn visit_local(ir: &mut IrMaps, local: &Local) {
+    pat_util::pat_bindings(ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
         debug!("adding local variable {}", p_id);
         let name = ast_util::path_to_ident(path);
-        this.add_live_node_for_node(p_id, VarDefNode(sp));
+        ir.add_live_node_for_node(p_id, VarDefNode(sp));
         let kind = match local.init {
           Some(_) => FromLetWithInitializer,
           None => FromLetNoInitializer
@@ -448,20 +420,19 @@ fn visit_local(v: &mut LivenessVisitor, local: &Local, this: @IrMaps) {
             BindByValue(MutMutable) => true,
             _ => false
         };
-        this.add_variable(Local(LocalInfo {
+        ir.add_variable(Local(LocalInfo {
           id: p_id,
           ident: name,
           is_mutbl: mutbl,
           kind: kind
         }));
     });
-    visit::walk_local(v, local, this);
+    visit::walk_local(ir, local, ());
 }
 
-fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @IrMaps) {
-    let def_map = this.tcx.def_map;
+fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
     for pat in arm.pats.iter() {
-        pat_util::pat_bindings(def_map, *pat, |bm, p_id, sp, path| {
+        pat_util::pat_bindings(ir.tcx.def_map, *pat, |bm, p_id, sp, path| {
             debug!("adding local variable {} from match with bm {:?}",
                    p_id, bm);
             let name = ast_util::path_to_ident(path);
@@ -469,8 +440,8 @@ fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @IrMaps) {
                 BindByValue(MutMutable) => true,
                 _ => false
             };
-            this.add_live_node_for_node(p_id, VarDefNode(sp));
-            this.add_variable(Local(LocalInfo {
+            ir.add_live_node_for_node(p_id, VarDefNode(sp));
+            ir.add_variable(Local(LocalInfo {
                 id: p_id,
                 ident: name,
                 is_mutbl: mutbl,
@@ -478,37 +449,34 @@ fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @IrMaps) {
             }));
         })
     }
-    visit::walk_arm(v, arm, this);
+    visit::walk_arm(ir, arm, ());
 }
 
-fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
+fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
       ExprPath(_) => {
-        let def_map = this.tcx.def_map.borrow();
-        let def = def_map.get().get_copy(&expr.id);
+        let def = ir.tcx.def_map.borrow().get().get_copy(&expr.id);
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if moves::moved_variable_node_id_from_def(def).is_some() {
-            this.add_live_node_for_node(expr.id, ExprNode(expr.span));
+            ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
         }
-        visit::walk_expr(v, expr, this);
+        visit::walk_expr(ir, expr, ());
       }
       ExprFnBlock(..) | ExprProc(..) => {
         // Interesting control flow (for loops can contain labeled
         // breaks or continues)
-        this.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
 
         // Make a live_node for each captured variable, with the span
         // being the location that the variable is used.  This results
         // in better error messages than just pointing at the closure
         // construction site.
-        let capture_map = this.capture_map.borrow();
-        let cvs = capture_map.get().get(&expr.id);
         let mut call_caps = Vec::new();
-        for cv in cvs.deref().iter() {
+        for cv in ir.capture_map.get(&expr.id).deref().iter() {
             match moves::moved_variable_node_id_from_def(cv.def) {
               Some(rv) => {
-                let cv_ln = this.add_live_node(FreeVarNode(cv.span));
+                let cv_ln = ir.add_live_node(FreeVarNode(cv.span));
                 let is_move = match cv.mode {
                     // var must be dead afterwards
                     moves::CapMove => true,
@@ -523,20 +491,20 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
               None => {}
             }
         }
-        this.set_captures(expr.id, call_caps);
+        ir.set_captures(expr.id, call_caps);
 
-        visit::walk_expr(v, expr, this);
+        visit::walk_expr(ir, expr, ());
       }
 
       // live nodes required for interesting control flow:
       ExprIf(..) | ExprMatch(..) | ExprWhile(..) | ExprLoop(..) => {
-        this.add_live_node_for_node(expr.id, ExprNode(expr.span));
-        visit::walk_expr(v, expr, this);
+        ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        visit::walk_expr(ir, expr, ());
       }
       ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
       ExprBinary(op, _, _) if ast_util::lazy_binop(op) => {
-        this.add_live_node_for_node(expr.id, ExprNode(expr.span));
-        visit::walk_expr(v, expr, this);
+        ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
+        visit::walk_expr(ir, expr, ());
       }
 
       // otherwise, live nodes are not required:
@@ -548,7 +516,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
       ExprAssign(..) | ExprAssignOp(..) | ExprMac(..) |
       ExprStruct(..) | ExprRepeat(..) | ExprParen(..) |
       ExprInlineAsm(..) | ExprBox(..) => {
-          visit::walk_expr(v, expr, this);
+          visit::walk_expr(ir, expr, ());
       }
     }
 }
@@ -560,7 +528,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
 // the same basic propagation framework in all cases.
 
 #[deriving(Clone)]
-pub struct Users {
+struct Users {
     reader: LiveNode,
     writer: LiveNode,
     used: bool
@@ -574,7 +542,7 @@ fn invalid_users() -> Users {
     }
 }
 
-pub struct Specials {
+struct Specials {
     exit_ln: LiveNode,
     fallthrough_ln: LiveNode,
     no_ret_var: Variable
@@ -584,76 +552,66 @@ static ACC_READ: uint = 1u;
 static ACC_WRITE: uint = 2u;
 static ACC_USE: uint = 4u;
 
-pub type LiveNodeMap = @RefCell<NodeMap<LiveNode>>;
-
-pub struct Liveness {
-    tcx: ty::ctxt,
-    ir: @IrMaps,
+struct Liveness<'a> {
+    ir: &'a mut IrMaps<'a>,
     s: Specials,
-    successors: @RefCell<Vec<LiveNode> >,
-    users: @RefCell<Vec<Users> >,
+    successors: Vec<LiveNode>,
+    users: Vec<Users>,
     // The list of node IDs for the nested loop scopes
     // we're in.
-    loop_scope: @RefCell<Vec<NodeId> >,
+    loop_scope: Vec<NodeId>,
     // mappings from loop node ID to LiveNode
     // ("break" label should map to loop node ID,
     // it probably doesn't now)
-    break_ln: LiveNodeMap,
-    cont_ln: LiveNodeMap
+    break_ln: NodeMap<LiveNode>,
+    cont_ln: NodeMap<LiveNode>
 }
 
-fn Liveness(ir: @IrMaps, specials: Specials) -> Liveness {
+fn Liveness<'a>(ir: &'a mut IrMaps<'a>, specials: Specials) -> Liveness<'a> {
     Liveness {
         ir: ir,
-        tcx: ir.tcx,
         s: specials,
-        successors: @RefCell::new(Vec::from_elem(ir.num_live_nodes.get(),
-                                                 invalid_node())),
-        users: @RefCell::new(Vec::from_elem(ir.num_live_nodes.get() *
-                                            ir.num_vars.get(),
-                                            invalid_users())),
-        loop_scope: @RefCell::new(Vec::new()),
-        break_ln: @RefCell::new(NodeMap::new()),
-        cont_ln: @RefCell::new(NodeMap::new()),
+        successors: Vec::from_elem(ir.num_live_nodes, invalid_node()),
+        users: Vec::from_elem(ir.num_live_nodes * ir.num_vars, invalid_users()),
+        loop_scope: Vec::new(),
+        break_ln: NodeMap::new(),
+        cont_ln: NodeMap::new(),
     }
 }
 
-impl Liveness {
-    pub fn live_node(&self, node_id: NodeId, span: Span) -> LiveNode {
-        let ir: &IrMaps = self.ir;
-        let live_node_map = ir.live_node_map.borrow();
-        match live_node_map.get().find(&node_id) {
+impl<'a> Liveness<'a> {
+    fn live_node(&self, node_id: NodeId, span: Span) -> LiveNode {
+        match self.ir.live_node_map.find(&node_id) {
           Some(&ln) => ln,
           None => {
             // This must be a mismatch between the ir_map construction
             // above and the propagation code below; the two sets of
             // code have to agree about which AST nodes are worth
             // creating liveness nodes for.
-            self.tcx.sess.span_bug(
+            self.ir.tcx.sess.span_bug(
                 span, format!("no live node registered for node {}",
                            node_id));
           }
         }
     }
 
-    pub fn variable(&self, node_id: NodeId, span: Span) -> Variable {
+    fn variable(&self, node_id: NodeId, span: Span) -> Variable {
         self.ir.variable(node_id, span)
     }
 
-    pub fn pat_bindings(&self,
-                        pat: @Pat,
-                        f: |LiveNode, Variable, Span, NodeId|) {
-        let def_map = self.tcx.def_map;
-        pat_util::pat_bindings(def_map, pat, |_bm, p_id, sp, _n| {
+    fn pat_bindings(&mut self,
+                    pat: &Pat,
+                    f: |&mut Liveness<'a>, LiveNode, Variable, Span, NodeId|) {
+        pat_util::pat_bindings(self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
             let ln = self.live_node(p_id, sp);
             let var = self.variable(p_id, sp);
-            f(ln, var, sp, p_id);
+            f(self, ln, var, sp, p_id);
         })
     }
 
-    pub fn arm_pats_bindings(&self,
-                             pats: &[@Pat],
-                             f: |LiveNode, Variable, Span, NodeId|) {
+    fn arm_pats_bindings(&mut self,
+                         pats: &[@Pat],
+                         f: |&mut Liveness<'a>, 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 "authoratative" set of ids
@@ -662,86 +620,77 @@ impl Liveness {
         }
     }
 
-    pub fn define_bindings_in_pat(&self, pat: @Pat, succ: LiveNode)
-                                  -> LiveNode {
+    fn define_bindings_in_pat(&mut self, pat: @Pat, succ: LiveNode)
+                              -> LiveNode {
         self.define_bindings_in_arm_pats([pat], succ)
     }
 
-    pub fn define_bindings_in_arm_pats(&self, pats: &[@Pat], succ: LiveNode)
-                                       -> LiveNode {
+    fn define_bindings_in_arm_pats(&mut self, pats: &[@Pat], succ: LiveNode)
+                                   -> LiveNode {
         let mut succ = succ;
-        self.arm_pats_bindings(pats, |ln, var, _sp, _id| {
-            self.init_from_succ(ln, succ);
-            self.define(ln, var);
+        self.arm_pats_bindings(pats, |this, ln, var, _sp, _id| {
+            this.init_from_succ(ln, succ);
+            this.define(ln, var);
             succ = ln;
         });
         succ
     }
 
-    pub fn idx(&self, ln: LiveNode, var: Variable) -> uint {
-        ln.get() * self.ir.num_vars.get() + var.get()
+    fn idx(&self, ln: LiveNode, var: Variable) -> uint {
+        ln.get() * self.ir.num_vars + var.get()
     }
 
-    pub fn live_on_entry(&self, ln: LiveNode, var: Variable)
-                         -> Option<LiveNodeKind> {
+    fn live_on_entry(&self, ln: LiveNode, var: Variable)
+                      -> Option<LiveNodeKind> {
         assert!(ln.is_valid());
-        let users = self.users.borrow();
-        let reader = users.get().get(self.idx(ln, var)).reader;
+        let reader = self.users.get(self.idx(ln, var)).reader;
         if reader.is_valid() {Some(self.ir.lnk(reader))} else {None}
     }
 
     /*
     Is this variable live on entry to any of its successor nodes?
     */
-    pub fn live_on_exit(&self, ln: LiveNode, var: Variable)
-                        -> Option<LiveNodeKind> {
-        let successor = {
-            let successors = self.successors.borrow();
-            *successors.get().get(ln.get())
-        };
+    fn live_on_exit(&self, ln: LiveNode, var: Variable)
+                    -> Option<LiveNodeKind> {
+        let successor = *self.successors.get(ln.get());
         self.live_on_entry(successor, var)
     }
 
-    pub fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
+    fn used_on_entry(&self, ln: LiveNode, var: Variable) -> bool {
         assert!(ln.is_valid());
-        let users = self.users.borrow();
-        users.get().get(self.idx(ln, var)).used
+        self.users.get(self.idx(ln, var)).used
     }
 
-    pub fn assigned_on_entry(&self, ln: LiveNode, var: Variable)
-                             -> Option<LiveNodeKind> {
+    fn assigned_on_entry(&self, ln: LiveNode, var: Variable)
+                         -> Option<LiveNodeKind> {
         assert!(ln.is_valid());
-        let users = self.users.borrow();
-        let writer = users.get().get(self.idx(ln, var)).writer;
+        let writer = self.users.get(self.idx(ln, var)).writer;
         if writer.is_valid() {Some(self.ir.lnk(writer))} else {None}
     }
 
-    pub fn assigned_on_exit(&self, ln: LiveNode, var: Variable)
-                            -> Option<LiveNodeKind> {
-        let successor = {
-            let successors = self.successors.borrow();
-            *successors.get().get(ln.get())
-        };
+    fn assigned_on_exit(&self, ln: LiveNode, var: Variable)
+                        -> Option<LiveNodeKind> {
+        let successor = *self.successors.get(ln.get());
         self.assigned_on_entry(successor, var)
     }
 
-    pub fn indices2(&self,
-                    ln: LiveNode,
-                    succ_ln: LiveNode,
-                    op: |uint, uint|) {
+    fn indices2(&mut self,
+                ln: LiveNode,
+                succ_ln: LiveNode,
+                op: |&mut Liveness<'a>, uint, uint|) {
         let node_base_idx = self.idx(ln, Variable(0u));
         let succ_base_idx = self.idx(succ_ln, Variable(0u));
-        for var_idx in range(0u, self.ir.num_vars.get()) {
-            op(node_base_idx + var_idx, succ_base_idx + var_idx);
+        for var_idx in range(0u, self.ir.num_vars) {
+            op(self, node_base_idx + var_idx, succ_base_idx + var_idx);
         }
     }
 
-    pub fn write_vars(&self,
-                      wr: &mut io::Writer,
-                      ln: LiveNode,
-                      test: |uint| -> LiveNode) -> io::IoResult<()> {
+    fn write_vars(&self,
+                  wr: &mut io::Writer,
+                  ln: LiveNode,
+                  test: |uint| -> LiveNode) -> io::IoResult<()> {
         let node_base_idx = self.idx(ln, Variable(0));
-        for var_idx in range(0u, self.ir.num_vars.get()) {
+        for var_idx in range(0u, self.ir.num_vars) {
             let idx = node_base_idx + var_idx;
             if test(idx).is_valid() {
                 try!(write!(wr, " {}", Variable(var_idx).to_str()));
@@ -750,28 +699,26 @@ impl Liveness {
         Ok(())
     }
 
-    pub fn find_loop_scope(&self,
-                           opt_label: Option<Ident>,
-                           id: NodeId,
-                           sp: Span)
-                           -> NodeId {
+    fn find_loop_scope(&self,
+                       opt_label: Option<Ident>,
+                       id: NodeId,
+                       sp: Span)
+                       -> NodeId {
         match opt_label {
             Some(_) => {
                 // Refers to a labeled loop. Use the results of resolve
                 // to find with one
-                let def_map = self.tcx.def_map.borrow();
-                match def_map.get().find(&id) {
+                match self.ir.tcx.def_map.borrow().get().find(&id) {
                     Some(&DefLabel(loop_id)) => loop_id,
-                    _ => self.tcx.sess.span_bug(sp, "label on break/loop \
-                                                     doesn't refer to a loop")
+                    _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
+                                                        doesn't refer to a loop")
                 }
             }
             None => {
                 // Vanilla 'break' or 'loop', so use the enclosing
                 // loop scope
-                let loop_scope = self.loop_scope.borrow();
-                if loop_scope.get().len() == 0 {
-                    self.tcx.sess.span_bug(sp, "break outside loop");
+                if self.loop_scope.len() == 0 {
+                    self.ir.tcx.sess.span_bug(sp, "break outside loop");
                 } else {
                     // FIXME(#5275): this shouldn't have to be a method...
                     self.last_loop_scope()
@@ -780,54 +727,26 @@ impl Liveness {
         }
     }
 
-    pub fn last_loop_scope(&self) -> NodeId {
-        let loop_scope = self.loop_scope.borrow();
-        *loop_scope.get().last().unwrap()
+    fn last_loop_scope(&self) -> NodeId {
+        *self.loop_scope.last().unwrap()
     }
 
     #[allow(unused_must_use)]
-    pub fn ln_str(&self, ln: LiveNode) -> ~str {
+    fn ln_str(&self, ln: LiveNode) -> ~str {
         let mut wr = io::MemWriter::new();
         {
             let wr = &mut wr as &mut io::Writer;
-            {
-                let lnks = self.ir.lnks.try_borrow();
-                write!(wr,
-                       "[ln({}) of kind {:?} reads",
-                       ln.get(),
-                       lnks.and_then(|lnks| Some(*lnks.get().get(ln.get()))));
-            }
-            let users = self.users.try_borrow();
-            match users {
-                Some(users) => {
-                    self.write_vars(wr, ln, |idx| users.get().get(idx).reader);
-                    write!(wr, "  writes");
-                    self.write_vars(wr, ln, |idx| users.get().get(idx).writer);
-                }
-                None => {
-                    write!(wr, "  (users borrowed)");
-                }
-            }
-            let successors = self.successors.try_borrow();
-            match successors {
-                Some(successors) => {
-                    write!(wr,
-                           "  precedes {}]",
-                           successors.get().get(ln.get()).to_str());
-                }
-                None => {
-                    write!(wr, "  precedes (successors borrowed)]");
-                }
-            }
+            write!(wr, "[ln({}) of kind {:?} reads", ln.get(), self.ir.lnk(ln));
+            self.write_vars(wr, ln, |idx| self.users.get(idx).reader);
+            write!(wr, "  writes");
+            self.write_vars(wr, ln, |idx| self.users.get(idx).writer);
+            write!(wr, "  precedes {}]", self.successors.get(ln.get()).to_str());
         }
         str::from_utf8_owned(wr.unwrap()).unwrap()
     }
 
-    pub fn init_empty(&self, ln: LiveNode, succ_ln: LiveNode) {
-        {
-            let mut successors = self.successors.borrow_mut();
-            *successors.get().get_mut(ln.get()) = succ_ln;
-        }
+    fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) {
+        *self.successors.get_mut(ln.get()) = succ_ln;
 
         // It is not necessary to initialize the
         // values to empty because this is the value
@@ -839,37 +758,32 @@ impl Liveness {
         // }
     }
 
-    pub fn init_from_succ(&self, ln: LiveNode, succ_ln: LiveNode) {
+    fn init_from_succ(&mut self, ln: LiveNode, succ_ln: LiveNode) {
         // more efficient version of init_empty() / merge_from_succ()
-        {
-            let mut successors = self.successors.borrow_mut();
-            *successors.get().get_mut(ln.get()) = succ_ln;
-        }
+        *self.successors.get_mut(ln.get()) = succ_ln;
 
-        self.indices2(ln, succ_ln, |idx, succ_idx| {
-            let mut users = self.users.borrow_mut();
-            *users.get().get_mut(idx) = *users.get().get(succ_idx)
+        self.indices2(ln, succ_ln, |this, idx, succ_idx| {
+            *this.users.get_mut(idx) = *this.users.get(succ_idx)
         });
         debug!("init_from_succ(ln={}, succ={})",
                self.ln_str(ln), self.ln_str(succ_ln));
     }
 
-    pub fn merge_from_succ(&self,
-                           ln: LiveNode,
-                           succ_ln: LiveNode,
-                           first_merge: bool)
-                           -> bool {
+    fn merge_from_succ(&mut self,
+                       ln: LiveNode,
+                       succ_ln: LiveNode,
+                       first_merge: bool)
+                       -> bool {
         if ln == succ_ln { return false; }
 
         let mut changed = false;
-        self.indices2(ln, succ_ln, |idx, succ_idx| {
-            let mut users = self.users.borrow_mut();
-            changed |= copy_if_invalid(users.get().get(succ_idx).reader,
-                                       &mut users.get().get_mut(idx).reader);
-            changed |= copy_if_invalid(users.get().get(succ_idx).writer,
-                                       &mut users.get().get_mut(idx).writer);
-            if users.get().get(succ_idx).used && !users.get().get(idx).used {
-                users.get().get_mut(idx).used = true;
+        self.indices2(ln, succ_ln, |this, idx, succ_idx| {
+            changed |= copy_if_invalid(this.users.get(succ_idx).reader,
+                                       &mut this.users.get_mut(idx).reader);
+            changed |= copy_if_invalid(this.users.get(succ_idx).writer,
+                                       &mut this.users.get_mut(idx).writer);
+            if this.users.get(succ_idx).used && !this.users.get(idx).used {
+                this.users.get_mut(idx).used = true;
                 changed = true;
             }
         });
@@ -879,34 +793,34 @@ impl Liveness {
         return changed;
 
         fn copy_if_invalid(src: LiveNode, dst: &mut LiveNode) -> bool {
-            if src.is_valid() {
-                if !dst.is_valid() {
-                    *dst = src;
-                    return true;
-                }
+            if src.is_valid() && !dst.is_valid() {
+                *dst = src;
+                true
+            } else {
+                false
             }
-            return false;
         }
     }
 
     // Indicates that a local variable was *defined*; we know that no
     // uses of the variable can precede the definition (resolve checks
     // this) so we just clear out all the data.
-    pub fn define(&self, writer: LiveNode, var: Variable) {
+    fn define(&mut self, writer: LiveNode, var: Variable) {
         let idx = self.idx(writer, var);
-        let mut users = self.users.borrow_mut();
-        users.get().get_mut(idx).reader = invalid_node();
-        users.get().get_mut(idx).writer = invalid_node();
+        self.users.get_mut(idx).reader = invalid_node();
+        self.users.get_mut(idx).writer = invalid_node();
 
         debug!("{} defines {} (idx={}): {}", writer.to_str(), var.to_str(),
                idx, self.ln_str(writer));
     }
 
     // Either read, write, or both depending on the acc bitset
-    pub fn acc(&self, ln: LiveNode, var: Variable, acc: uint) {
+    fn acc(&mut self, ln: LiveNode, var: Variable, acc: uint) {
+        debug!("{} accesses[{:x}] {}: {}",
+               ln.to_str(), acc, var.to_str(), self.ln_str(ln));
+
         let idx = self.idx(ln, var);
-        let mut users = self.users.borrow_mut();
-        let user = users.get().get_mut(idx);
+        let user = self.users.get_mut(idx);
 
         if (acc & ACC_WRITE) != 0 {
             user.reader = invalid_node();
@@ -922,14 +836,11 @@ impl Liveness {
         if (acc & ACC_USE) != 0 {
             user.used = true;
         }
-
-        debug!("{} accesses[{:x}] {}: {}",
-               ln.to_str(), acc, var.to_str(), self.ln_str(ln));
     }
 
     // _______________________________________________________________________
 
-    pub fn compute(&self, decl: &FnDecl, body: &Block) -> LiveNode {
+    fn compute(&mut self, decl: &FnDecl, body: &Block) -> LiveNode {
         // if there is a `break` or `again` at the top level, then it's
         // effectively a return---this only occurs in `for` loops,
         // where the body is really a closure.
@@ -938,12 +849,12 @@ impl Liveness {
 
         let entry_ln: LiveNode =
             self.with_loop_nodes(body.id, self.s.exit_ln, self.s.exit_ln,
-              || { self.propagate_through_fn_block(decl, body) });
+              |this| this.propagate_through_fn_block(decl, body));
 
         // hack to skip the loop unless debug! is enabled:
         debug!("^^ liveness computation results for body {} (entry={})",
                {
-                   for ln_idx in range(0u, self.ir.num_live_nodes.get()) {
+                   for ln_idx in range(0u, self.ir.num_live_nodes) {
                        debug!("{}", self.ln_str(LiveNode(ln_idx)));
                    }
                    body.id
@@ -953,8 +864,8 @@ impl Liveness {
         entry_ln
     }
 
-    pub fn propagate_through_fn_block(&self, _: &FnDecl, blk: &Block)
-                                      -> LiveNode {
+    fn propagate_through_fn_block(&mut self, _: &FnDecl, blk: &Block)
+                                  -> LiveNode {
         // the fallthrough exit is only for those cases where we do not
         // explicitly return:
         self.init_from_succ(self.s.fallthrough_ln, self.s.exit_ln);
@@ -965,33 +876,33 @@ impl Liveness {
         self.propagate_through_block(blk, self.s.fallthrough_ln)
     }
 
-    pub fn propagate_through_block(&self, blk: &Block, succ: LiveNode)
-                                   -> LiveNode {
+    fn propagate_through_block(&mut self, blk: &Block, succ: LiveNode)
+                               -> LiveNode {
         let succ = self.propagate_through_opt_expr(blk.expr, succ);
         blk.stmts.rev_iter().fold(succ, |succ, stmt| {
             self.propagate_through_stmt(*stmt, succ)
         })
     }
 
-    pub fn propagate_through_stmt(&self, stmt: &Stmt, succ: LiveNode)
-                                  -> LiveNode {
+    fn propagate_through_stmt(&mut self, stmt: &Stmt, succ: LiveNode)
+                              -> LiveNode {
         match stmt.node {
-          StmtDecl(decl, _) => {
-            return self.propagate_through_decl(decl, succ);
-          }
+            StmtDecl(decl, _) => {
+                self.propagate_through_decl(decl, succ)
+            }
 
-          StmtExpr(expr, _) | StmtSemi(expr, _) => {
-            return self.propagate_through_expr(expr, succ);
-          }
+            StmtExpr(expr, _) | StmtSemi(expr, _) => {
+                self.propagate_through_expr(expr, succ)
+            }
 
-          StmtMac(..) => {
-            self.tcx.sess.span_bug(stmt.span, "unexpanded macro");
-          }
+            StmtMac(..) => {
+                self.ir.tcx.sess.span_bug(stmt.span, "unexpanded macro");
+            }
         }
     }
 
-    pub fn propagate_through_decl(&self, decl: &Decl, succ: LiveNode)
-                                  -> LiveNode {
+    fn propagate_through_decl(&mut self, decl: &Decl, succ: LiveNode)
+                              -> LiveNode {
         match decl.node {
             DeclLocal(ref local) => {
                 self.propagate_through_local(*local, succ)
@@ -1000,8 +911,8 @@ impl Liveness {
         }
     }
 
-    pub fn propagate_through_local(&self, local: &Local, succ: LiveNode)
-                                   -> LiveNode {
+    fn propagate_through_local(&mut self, local: &Local, succ: LiveNode)
+                               -> LiveNode {
         // Note: we mark the variable as defined regardless of whether
         // there is an initializer.  Initially I had thought to only mark
         // the live variable as defined if it was initialized, and then we
@@ -1020,24 +931,24 @@ impl Liveness {
         self.define_bindings_in_pat(local.pat, succ)
     }
 
-    pub fn propagate_through_exprs(&self, exprs: &[@Expr], succ: LiveNode)
-                                   -> LiveNode {
+    fn propagate_through_exprs(&mut self, exprs: &[@Expr], succ: LiveNode)
+                               -> LiveNode {
         exprs.rev_iter().fold(succ, |succ, expr| {
             self.propagate_through_expr(*expr, succ)
         })
     }
 
-    pub fn propagate_through_opt_expr(&self,
-                                      opt_expr: Option<@Expr>,
-                                      succ: LiveNode)
-                                      -> LiveNode {
+    fn propagate_through_opt_expr(&mut self,
+                                  opt_expr: Option<@Expr>,
+                                  succ: LiveNode)
+                                  -> LiveNode {
         opt_expr.iter().fold(succ, |succ, expr| {
             self.propagate_through_expr(*expr, succ)
         })
     }
 
-    pub fn propagate_through_expr(&self, expr: @Expr, succ: LiveNode)
-                                  -> LiveNode {
+    fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
+                              -> LiveNode {
         debug!("propagate_through_expr: {}", expr_to_str(expr));
 
         match expr.node {
@@ -1058,16 +969,21 @@ impl Liveness {
               The next-node for a break is the successor of the entire
               loop. The next-node for a continue is the top of this loop.
               */
-              self.with_loop_nodes(blk.id, succ,
-                  self.live_node(expr.id, expr.span), || {
+              let node = self.live_node(expr.id, expr.span);
+              self.with_loop_nodes(blk.id, succ, node, |this| {
 
                  // the construction of a closure itself is not important,
                  // but we have to consider the closed over variables.
-                 let caps = self.ir.captures(expr);
-                 caps.rev_iter().fold(succ, |succ, cap| {
-                     self.init_from_succ(cap.ln, succ);
-                     let var = self.variable(cap.var_nid, expr.span);
-                     self.acc(cap.ln, var, ACC_READ | ACC_USE);
+                 let caps = match this.ir.capture_info_map.find(&expr.id) {
+                    Some(caps) => caps.clone(),
+                    None => {
+                        this.ir.tcx.sess.span_bug(expr.span, "no registered caps");
+                     }
+                 };
+                 caps.deref().rev_iter().fold(succ, |succ, cap| {
+                     this.init_from_succ(cap.ln, succ);
+                     let var = this.variable(cap.var_nid, expr.span);
+                     this.acc(cap.ln, var, ACC_READ | ACC_USE);
                      cap.ln
                  })
               })
@@ -1151,11 +1067,10 @@ impl Liveness {
               // Now that we know the label we're going to,
               // look it up in the break loop nodes table
 
-              let break_ln = self.break_ln.borrow();
-              match break_ln.get().find(&sc) {
+              match self.break_ln.find(&sc) {
                   Some(&b) => b,
-                  None => self.tcx.sess.span_bug(expr.span,
-                                                 "break to unknown label")
+                  None => self.ir.tcx.sess.span_bug(expr.span,
+                                                    "break to unknown label")
               }
           }
 
@@ -1166,11 +1081,10 @@ impl Liveness {
               // Now that we know the label we're going to,
               // look it up in the continue loop nodes table
 
-              let cont_ln = self.cont_ln.borrow();
-              match cont_ln.get().find(&sc) {
+              match self.cont_ln.find(&sc) {
                   Some(&b) => b,
-                  None => self.tcx.sess.span_bug(expr.span,
-                                                 "loop to unknown label")
+                  None => self.ir.tcx.sess.span_bug(expr.span,
+                                                    "loop to unknown label")
               }
           }
 
@@ -1215,7 +1129,7 @@ impl Liveness {
           ExprCall(f, ref args) => {
             // calling a fn with bot return type means that the fn
             // will fail, and hence the successors can be ignored
-            let t_ret = ty::ty_fn_ret(ty::expr_ty(self.tcx, f));
+            let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, f));
             let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
                        else {succ};
             let succ = self.propagate_through_exprs(args.as_slice(), succ);
@@ -1225,7 +1139,7 @@ impl Liveness {
           ExprMethodCall(_, _, ref args) => {
             // calling a method with bot return type means that the method
             // will fail, and hence the successors can be ignored
-            let t_ret = ty::node_id_to_type(self.tcx, expr.id);
+            let t_ret = ty::node_id_to_type(self.ir.tcx, expr.id);
             let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
                        else {succ};
             self.propagate_through_exprs(args.as_slice(), succ)
@@ -1280,15 +1194,15 @@ impl Liveness {
           }
 
           ExprMac(..) => {
-            self.tcx.sess.span_bug(expr.span, "unexpanded macro");
+            self.ir.tcx.sess.span_bug(expr.span, "unexpanded macro");
           }
         }
     }
 
-    pub fn propagate_through_lvalue_components(&self,
-                                               expr: @Expr,
-                                               succ: LiveNode)
-                                               -> LiveNode {
+    fn propagate_through_lvalue_components(&mut self,
+                                           expr: &Expr,
+                                           succ: LiveNode)
+                                           -> LiveNode {
         // # Lvalues
         //
         // In general, the full flow graph structure for an
@@ -1346,8 +1260,8 @@ impl Liveness {
     }
 
     // see comment on propagate_through_lvalue()
-    pub fn write_lvalue(&self, expr: &Expr, succ: LiveNode, acc: uint)
-                        -> LiveNode {
+    fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
+                    -> LiveNode {
         match expr.node {
           ExprPath(_) => self.access_path(expr, succ, acc),
 
@@ -1359,10 +1273,9 @@ impl Liveness {
         }
     }
 
-    pub fn access_path(&self, expr: &Expr, succ: LiveNode, acc: uint)
-                       -> LiveNode {
-        let def_map = self.tcx.def_map.borrow();
-        let def = def_map.get().get_copy(&expr.id);
+    fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
+                   -> LiveNode {
+        let def = self.ir.tcx.def_map.borrow().get().get_copy(&expr.id);
         match moves::moved_variable_node_id_from_def(def) {
           Some(nid) => {
             let ln = self.live_node(expr.id, expr.span);
@@ -1377,12 +1290,12 @@ impl Liveness {
         }
     }
 
-    pub fn propagate_through_loop(&self,
-                                  expr: &Expr,
-                                  cond: Option<@Expr>,
-                                  body: &Block,
-                                  succ: LiveNode)
-                                  -> LiveNode {
+    fn propagate_through_loop(&mut self,
+                              expr: &Expr,
+                              cond: Option<@Expr>,
+                              body: &Block,
+                              succ: LiveNode)
+                              -> LiveNode {
 
         /*
 
@@ -1418,8 +1331,8 @@ impl Liveness {
                expr.id, block_to_str(body));
 
         let cond_ln = self.propagate_through_opt_expr(cond, ln);
-        let body_ln = self.with_loop_nodes(expr.id, succ, ln, || {
-            self.propagate_through_block(body, cond_ln)
+        let body_ln = self.with_loop_nodes(expr.id, succ, ln, |this| {
+            this.propagate_through_block(body, cond_ln)
         });
 
         // repeat until fixed point is reached:
@@ -1428,37 +1341,24 @@ impl Liveness {
             assert!(cond_ln == self.propagate_through_opt_expr(cond,
                                                                     ln));
             assert!(body_ln == self.with_loop_nodes(expr.id, succ, ln,
-            || {
-                self.propagate_through_block(body, cond_ln)
-            }));
+            |this| this.propagate_through_block(body, cond_ln)));
         }
 
         cond_ln
     }
 
-    pub fn with_loop_nodes<R>(
-                           &self,
-                           loop_node_id: NodeId,
-                           break_ln: LiveNode,
-                           cont_ln: LiveNode,
-                           f: || -> R)
-                           -> R {
+    fn with_loop_nodes<R>(&mut self,
+                          loop_node_id: NodeId,
+                          break_ln: LiveNode,
+                          cont_ln: LiveNode,
+                          f: |&mut Liveness<'a>| -> R)
+                          -> R {
         debug!("with_loop_nodes: {} {}", loop_node_id, break_ln.get());
-        {
-            let mut loop_scope = self.loop_scope.borrow_mut();
-            loop_scope.get().push(loop_node_id);
-        }
-        {
-            let mut this_break_ln = self.break_ln.borrow_mut();
-            let mut this_cont_ln = self.cont_ln.borrow_mut();
-            this_break_ln.get().insert(loop_node_id, break_ln);
-            this_cont_ln.get().insert(loop_node_id, cont_ln);
-        }
-        let r = f();
-        {
-            let mut loop_scope = self.loop_scope.borrow_mut();
-            loop_scope.get().pop();
-        }
+        self.loop_scope.push(loop_node_id);
+        self.break_ln.insert(loop_node_id, break_ln);
+        self.cont_ln.insert(loop_node_id, cont_ln);
+        let r = f(self);
+        self.loop_scope.pop();
         r
     }
 }
@@ -1472,7 +1372,7 @@ fn check_local(this: &mut Liveness, local: &Local) {
             this.warn_about_unused_or_dead_vars_in_pat(local.pat);
         },
         None => {
-            this.pat_bindings(local.pat, |ln, var, sp, id| {
+            this.pat_bindings(local.pat, |this, ln, var, sp, id| {
                 this.warn_about_unused(sp, id, ln, var);
             })
         }
@@ -1482,7 +1382,7 @@ fn check_local(this: &mut Liveness, local: &Local) {
 }
 
 fn check_arm(this: &mut Liveness, arm: &Arm) {
-    this.arm_pats_bindings(arm.pats.as_slice(), |ln, var, sp, id| {
+    this.arm_pats_bindings(arm.pats.as_slice(), |this, ln, var, sp, id| {
         this.warn_about_unused(sp, id, ln, var);
     });
     visit::walk_arm(this, arm, ());
@@ -1542,37 +1442,30 @@ fn check_fn(_v: &Liveness,
     // do not check contents of nested fns
 }
 
-pub enum ReadKind {
-    PossiblyUninitializedVariable,
-    PossiblyUninitializedField,
-    MovedValue,
-    PartiallyMovedValue
-}
-
-impl Liveness {
-    pub fn check_ret(&self,
-                     id: NodeId,
-                     sp: Span,
-                     _fk: &FnKind,
-                     entry_ln: LiveNode,
-                     body: &Block) {
+impl<'a> Liveness<'a> {
+    fn check_ret(&self,
+                 id: NodeId,
+                 sp: Span,
+                 _fk: &FnKind,
+                 entry_ln: LiveNode,
+                 body: &Block) {
         if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
             // if no_ret_var is live, then we fall off the end of the
             // function without any kind of return expression:
 
-            let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, id));
+            let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.ir.tcx, id));
             if ty::type_is_nil(t_ret) {
                 // for nil return types, it is ok to not return a value expl.
             } else if ty::type_is_bot(t_ret) {
                 // for bot return types, not ok.  Function should fail.
-                self.tcx.sess.span_err(
+                self.ir.tcx.sess.span_err(
                     sp, "some control paths may return");
             } else {
                 let ends_with_stmt = match body.expr {
                     None if body.stmts.len() > 0 =>
                         match body.stmts.last().unwrap().node {
                             StmtSemi(e, _) => {
-                                let t_stmt = ty::expr_ty(self.tcx, e);
+                                let t_stmt = ty::expr_ty(self.ir.tcx, e);
                                 ty::get(t_stmt).sty == ty::get(t_ret).sty
                             },
                             _ => false
@@ -1586,20 +1479,19 @@ impl Liveness {
                         hi: last_stmt.span.hi,
                         expn_info: last_stmt.span.expn_info
                     };
-                    self.tcx.sess.span_note(
+                    self.ir.tcx.sess.span_note(
                         span_semicolon, "consider removing this semicolon:");
                 }
-                self.tcx.sess.span_err(
+                self.ir.tcx.sess.span_err(
                     sp, "not all control paths return a value");
            }
         }
     }
 
-    pub fn check_lvalue(&mut self, expr: @Expr) {
+    fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
           ExprPath(_) => {
-            let def_map = self.tcx.def_map.borrow();
-            match def_map.get().get_copy(&expr.id) {
+            match self.ir.tcx.def_map.borrow().get().get_copy(&expr.id) {
               DefLocal(nid, _) => {
                 // Assignment to an immutable variable or argument: only legal
                 // if there is no later assignment. If this local is actually
@@ -1630,14 +1522,14 @@ impl Liveness {
        }
     }
 
-    pub fn should_warn(&self, var: Variable) -> Option<~str> {
+    fn should_warn(&self, var: Variable) -> Option<~str> {
         let name = self.ir.variable_name(var);
         if name.len() == 0 || name[0] == ('_' as u8) { None } else { Some(name) }
     }
 
-    pub fn warn_about_unused_args(&self, decl: &FnDecl, entry_ln: LiveNode) {
+    fn warn_about_unused_args(&self, decl: &FnDecl, entry_ln: LiveNode) {
         for arg in decl.inputs.iter() {
-            pat_util::pat_bindings(self.tcx.def_map,
+            pat_util::pat_bindings(self.ir.tcx.def_map,
                                    arg.pat,
                                    |_bm, p_id, sp, path| {
                 let var = self.variable(p_id, sp);
@@ -1650,20 +1542,20 @@ impl Liveness {
         }
     }
 
-    pub fn warn_about_unused_or_dead_vars_in_pat(&self, pat: @Pat) {
-        self.pat_bindings(pat, |ln, var, sp, id| {
-            if !self.warn_about_unused(sp, id, ln, var) {
-                self.warn_about_dead_assign(sp, id, ln, var);
+    fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &Pat) {
+        self.pat_bindings(pat, |this, ln, var, sp, id| {
+            if !this.warn_about_unused(sp, id, ln, var) {
+                this.warn_about_dead_assign(sp, id, ln, var);
             }
         })
     }
 
-    pub fn warn_about_unused(&self,
-                             sp: Span,
-                             id: NodeId,
-                             ln: LiveNode,
-                             var: Variable)
-                             -> bool {
+    fn warn_about_unused(&self,
+                         sp: Span,
+                         id: NodeId,
+                         ln: LiveNode,
+                         var: Variable)
+                         -> bool {
         if !self.used_on_entry(ln, var) {
             let r = self.should_warn(var);
             for name in r.iter() {
@@ -1678,11 +1570,11 @@ impl Liveness {
                 };
 
                 if is_assigned {
-                    self.tcx.sess.add_lint(UnusedVariable, id, sp,
+                    self.ir.tcx.sess.add_lint(UnusedVariable, id, sp,
                         format!("variable `{}` is assigned to, \
                                   but never used", *name));
                 } else {
-                    self.tcx.sess.add_lint(UnusedVariable, id, sp,
+                    self.ir.tcx.sess.add_lint(UnusedVariable, id, sp,
                         format!("unused variable: `{}`", *name));
                 }
             }
@@ -1692,15 +1584,15 @@ impl Liveness {
         }
     }
 
-    pub fn warn_about_dead_assign(&self,
-                                  sp: Span,
-                                  id: NodeId,
-                                  ln: LiveNode,
-                                  var: Variable) {
+    fn warn_about_dead_assign(&self,
+                              sp: Span,
+                              id: NodeId,
+                              ln: LiveNode,
+                              var: Variable) {
         if self.live_on_exit(ln, var).is_none() {
             let r = self.should_warn(var);
             for name in r.iter() {
-                self.tcx.sess.add_lint(DeadAssignment, id, sp,
+                self.ir.tcx.sess.add_lint(DeadAssignment, id, sp,
                     format!("value assigned to `{}` is never read", *name));
             }
         }
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 127f835d5f6..be0aef64351 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -216,7 +216,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
     }
 }
 
-pub fn deref_kind(tcx: ty::ctxt, t: ty::t) -> deref_kind {
+pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind {
     match opt_deref_kind(t) {
       Some(k) => k,
       None => {
@@ -267,9 +267,9 @@ pub type McResult<T> = Result<T, ()>;
  * can be sure that only `Ok` results will occur.
  */
 pub trait Typer {
-    fn tcx(&self) -> ty::ctxt;
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt;
     fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t>;
-    fn node_method_ty(&mut self, method_call: typeck::MethodCall) -> Option<ty::t>;
+    fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t>;
     fn adjustment(&mut self, node_id: ast::NodeId) -> Option<@ty::AutoAdjustment>;
     fn is_method_call(&mut self, id: ast::NodeId) -> bool;
     fn temporary_scope(&mut self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
@@ -351,7 +351,7 @@ macro_rules! if_ok(
 )
 
 impl<TYPER:Typer> MemCategorizationContext<TYPER> {
-    fn tcx(&self) -> ty::ctxt {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt {
         self.typer.tcx()
     }
 
@@ -886,7 +886,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         let cmt_slice = self.cat_index(slice_pat, vec_cmt, 0);
         return Ok((cmt_slice, slice_mutbl, slice_r));
 
-        fn vec_slice_info(tcx: ty::ctxt,
+        fn vec_slice_info(tcx: &ty::ctxt,
                           pat: @ast::Pat,
                           slice_ty: ty::t)
                           -> (ast::Mutability, ty::Region) {
@@ -996,10 +996,9 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         // step out of sync again. So you'll see below that we always
         // get the type of the *subpattern* and use that.
 
-        let tcx = self.tcx();
         debug!("cat_pattern: id={} pat={} cmt={}",
                pat.id, pprust::pat_to_str(pat),
-               cmt.repr(tcx));
+               cmt.repr(self.tcx()));
 
         op(self, cmt, pat);
 
@@ -1187,7 +1186,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
 /// The node_id here is the node of the expression that references the field.
 /// This function looks it up in the def map in case the type happens to be
 /// an enum to determine which variant is in use.
-pub fn field_mutbl(tcx: ty::ctxt,
+pub fn field_mutbl(tcx: &ty::ctxt,
                    base_ty: ty::t,
                    // FIXME #6993: change type to Name
                    f_name: ast::Ident,
@@ -1312,7 +1311,7 @@ impl cmt_ {
 }
 
 impl Repr for cmt_ {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("\\{{} id:{} m:{:?} ty:{}\\}",
              self.cat.repr(tcx),
              self.id,
@@ -1322,7 +1321,7 @@ impl Repr for cmt_ {
 }
 
 impl Repr for categorization {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             cat_static_item |
             cat_rvalue(..) |
@@ -1365,7 +1364,7 @@ pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
 }
 
 impl Repr for InteriorKind {
-    fn repr(&self, _tcx: ty::ctxt) -> ~str {
+    fn repr(&self, _tcx: &ty::ctxt) -> ~str {
         match *self {
             InteriorField(NamedField(fld)) => {
                 token::get_name(fld).get().to_str()
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 22b3fb8ad6e..3d476832fd6 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -137,7 +137,6 @@ use util::common::indenter;
 use util::ppaux::UserString;
 use util::nodemap::{NodeMap, NodeSet};
 
-use std::cell::RefCell;
 use std::rc::Rc;
 use std::vec_ng::Vec;
 use syntax::ast::*;
@@ -160,29 +159,25 @@ pub struct CaptureVar {
     mode: CaptureMode // How variable is being accessed
 }
 
-pub type CaptureMap = @RefCell<NodeMap<Rc<Vec<CaptureVar> >>>;
-
-pub type MovesMap = @RefCell<NodeSet>;
-
-/**
- * Set of variable node-ids that are moved.
- *
- * Note: The `VariableMovesMap` stores expression ids that
- * are moves, whereas this set stores the ids of the variables
- * that are moved at some point */
-pub type MovedVariablesSet = @RefCell<NodeSet>;
+pub type CaptureMap = NodeMap<Rc<Vec<CaptureVar>>>;
 
 /** See the section Output on the module comment for explanation. */
 #[deriving(Clone)]
 pub struct MoveMaps {
-    moves_map: MovesMap,
-    moved_variables_set: MovedVariablesSet,
+    moves_map: NodeSet,
+    /**
+     * Set of variable node-ids that are moved.
+     *
+     * Note: The `moves_map` stores expression ids that are moves,
+     * whereas this set stores the ids of the variables that are
+     * moved at some point */
+    moved_variables_set: NodeSet,
     capture_map: CaptureMap
 }
 
 #[deriving(Clone)]
-struct VisitContext {
-    tcx: ty::ctxt,
+struct VisitContext<'a> {
+    tcx: &'a ty::ctxt,
     method_map: MethodMap,
     move_maps: MoveMaps
 }
@@ -193,7 +188,7 @@ enum UseMode {
     Read         // Read no matter what the type.
 }
 
-impl visit::Visitor<()> for VisitContext {
+impl<'a> visit::Visitor<()> for VisitContext<'a> {
     fn visit_fn(&mut self, fk: &visit::FnKind, fd: &FnDecl,
                 b: &Block, s: Span, n: NodeId, _: ()) {
         compute_modes_for_fn(self, fk, fd, b, s, n);
@@ -208,7 +203,7 @@ impl visit::Visitor<()> for VisitContext {
     fn visit_ty(&mut self, _t: &Ty, _: ()) {}
 }
 
-pub fn compute_moves(tcx: ty::ctxt,
+pub fn compute_moves(tcx: &ty::ctxt,
                      method_map: MethodMap,
                      krate: &Crate) -> MoveMaps
 {
@@ -216,14 +211,13 @@ pub fn compute_moves(tcx: ty::ctxt,
         tcx: tcx,
         method_map: method_map,
         move_maps: MoveMaps {
-            moves_map: @RefCell::new(NodeSet::new()),
-            capture_map: @RefCell::new(NodeMap::new()),
-            moved_variables_set: @RefCell::new(NodeSet::new())
+            moves_map: NodeSet::new(),
+            moved_variables_set: NodeSet::new(),
+            capture_map: NodeMap::new()
         }
     };
-    let visit_cx = &mut visit_cx;
-    visit::walk_crate(visit_cx, krate, ());
-    return visit_cx.move_maps;
+    visit::walk_crate(&mut visit_cx, krate, ());
+    visit_cx.move_maps
 }
 
 pub fn moved_variable_node_id_from_def(def: Def) -> Option<NodeId> {
@@ -265,7 +259,7 @@ fn compute_modes_for_expr(cx: &mut VisitContext,
     cx.consume_expr(expr);
 }
 
-impl VisitContext {
+impl<'a> VisitContext<'a> {
     pub fn consume_exprs(&mut self, exprs: &[@Expr]) {
         for expr in exprs.iter() {
             self.consume_expr(*expr);
@@ -284,7 +278,7 @@ impl VisitContext {
         let expr_ty = ty::expr_ty_adjusted(self.tcx, expr,
                                            self.method_map.borrow().get());
         if ty::type_moves_by_default(self.tcx, expr_ty) {
-            self.move_maps.moves_map.borrow_mut().get().insert(expr.id);
+            self.move_maps.moves_map.insert(expr.id);
             self.use_expr(expr, Move);
         } else {
             self.use_expr(expr, Read);
@@ -349,11 +343,7 @@ impl VisitContext {
                         let def = def_map.get().get_copy(&expr.id);
                         let r = moved_variable_node_id_from_def(def);
                         for &id in r.iter() {
-                            let mut moved_variables_set =
-                                self.move_maps
-                                    .moved_variables_set
-                                    .borrow_mut();
-                            moved_variables_set.get().insert(id);
+                            self.move_maps.moved_variables_set.insert(id);
                         }
                     }
                     Read => {}
@@ -361,8 +351,7 @@ impl VisitContext {
             }
 
             ExprUnary(UnDeref, base) => {      // *base
-                if !self.use_overloaded_operator(expr, base, [])
-                {
+                if !self.use_overloaded_operator(expr, base, []) {
                     // Moving out of *base moves out of base.
                     self.use_expr(base, comp_mode);
                 }
@@ -374,8 +363,7 @@ impl VisitContext {
             }
 
             ExprIndex(lhs, rhs) => {           // lhs[rhs]
-                if !self.use_overloaded_operator(expr, lhs, [rhs])
-                {
+                if !self.use_overloaded_operator(expr, lhs, [rhs]) {
                     self.use_expr(lhs, comp_mode);
                     self.consume_expr(rhs);
                 }
@@ -400,12 +388,7 @@ impl VisitContext {
                 // closures should be noncopyable, they shouldn't move by default;
                 // calling a closure should only consume it if it's once.
                 if mode == Move {
-                    {
-                        let mut moves_map = self.move_maps
-                                                .moves_map
-                                                .borrow_mut();
-                        moves_map.get().insert(callee.id);
-                    }
+                    self.move_maps.moves_map.insert(callee.id);
                 }
                 self.use_expr(callee, mode);
                 self.use_fn_args(args.as_slice());
@@ -444,7 +427,7 @@ impl VisitContext {
                             ty::type_moves_by_default(self.tcx, tf.mt.ty)
                     });
 
-                    fn has_dtor(tcx: ty::ctxt, ty: ty::t) -> bool {
+                    fn has_dtor(tcx: &ty::ctxt, ty: ty::t) -> bool {
                         use middle::ty::{get,ty_struct,ty_enum};
                         match get(ty).sty {
                             ty_struct(did, _) | ty_enum(did, _) => ty::has_dtor(tcx, did),
@@ -520,15 +503,13 @@ impl VisitContext {
             ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
 
             ExprUnary(_, lhs) => {
-                if !self.use_overloaded_operator(expr, lhs, [])
-                {
+                if !self.use_overloaded_operator(expr, lhs, []) {
                     self.consume_expr(lhs);
                 }
             }
 
             ExprBinary(_, lhs, rhs) => {
-                if !self.use_overloaded_operator(expr, lhs, [rhs])
-                {
+                if !self.use_overloaded_operator(expr, lhs, [rhs]) {
                     self.consume_expr(lhs);
                     self.consume_expr(rhs);
                 }
@@ -574,12 +555,7 @@ impl VisitContext {
                     self.use_pat(a.pat);
                 }
                 let cap_vars = self.compute_captures(expr.id);
-                {
-                    let mut capture_map = self.move_maps
-                                              .capture_map
-                                              .borrow_mut();
-                    capture_map.get().insert(expr.id, cap_vars);
-                }
+                self.move_maps.capture_map.insert(expr.id, cap_vars);
                 self.consume_block(body);
             }
 
@@ -657,16 +633,12 @@ impl VisitContext {
                    id, bm, binding_moves);
 
             if binding_moves {
-                {
-                    let mut moves_map = self.move_maps.moves_map.borrow_mut();
-                    moves_map.get().insert(id);
-                }
+                self.move_maps.moves_map.insert(id);
             }
         })
     }
 
-    pub fn use_fn_args(&mut self,
-                       arg_exprs: &[@Expr]) {
+    pub fn use_fn_args(&mut self, arg_exprs: &[@Expr]) {
         //! Uses the argument expressions.
         for arg_expr in arg_exprs.iter() {
             self.use_fn_arg(*arg_expr);
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index b8a40f623d9..1de38d8a461 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -142,7 +142,7 @@ impl Visitor<()> for ParentVisitor {
 ////////////////////////////////////////////////////////////////////////////////
 
 struct EmbargoVisitor<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     exp_map2: &'a resolve::ExportMap2,
 
     // This flag is an indicator of whether the previous item in the
@@ -345,7 +345,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
 ////////////////////////////////////////////////////////////////////////////////
 
 struct PrivacyVisitor<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     curitem: ast::NodeId,
     in_fn: bool,
     in_foreign: bool,
@@ -585,7 +585,7 @@ impl<'a> PrivacyVisitor<'a> {
                 }
             }
         } else {
-            let cstore = self.tcx.sess.cstore;
+            let cstore = &self.tcx.sess.cstore;
             match enum_id {
                 Some(enum_id) => {
                     let v = csearch::get_enum_variants(self.tcx, enum_id);
@@ -920,12 +920,12 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
 /// The privacy sanity check visitor, ensures unnecessary visibility isn't here
 ////////////////////////////////////////////////////////////////////////////////
 
-struct SanePrivacyVisitor {
-    tcx: ty::ctxt,
+struct SanePrivacyVisitor<'a> {
+    tcx: &'a ty::ctxt,
     in_fn: bool,
 }
 
-impl Visitor<()> for SanePrivacyVisitor {
+impl<'a> Visitor<()> for SanePrivacyVisitor<'a> {
     fn visit_item(&mut self, item: &ast::Item, _: ()) {
         if self.in_fn {
             self.check_all_inherited(item);
@@ -976,7 +976,7 @@ impl Visitor<()> for SanePrivacyVisitor {
     }
 }
 
-impl SanePrivacyVisitor {
+impl<'a> SanePrivacyVisitor<'a> {
     /// Validates all of the visibility qualifers placed on the item given. This
     /// ensures that there are no extraneous qualifiers that don't actually do
     /// anything. In theory these qualifiers wouldn't parse, but that may happen
@@ -1159,7 +1159,7 @@ impl SanePrivacyVisitor {
 }
 
 struct VisiblePrivateTypesVisitor<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     exported_items: &'a ExportedItems,
     public_items: &'a PublicItems,
 }
@@ -1403,7 +1403,7 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
     fn visit_expr(&mut self, _: &ast::Expr, _: ()) {}
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    method_map: &MethodMap,
                    exp_map2: &resolve::ExportMap2,
                    external_exports: resolve::ExternalExports,
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index e9d01713e1c..44a0fb61b24 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -20,7 +20,6 @@ use middle::typeck;
 use middle::privacy;
 use util::nodemap::NodeSet;
 
-use std::cell::RefCell;
 use std::vec_ng::Vec;
 use collections::HashSet;
 use syntax::ast;
@@ -59,7 +58,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
     }
 }
 
-fn method_might_be_inlined(tcx: ty::ctxt, method: &ast::Method,
+fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
                            impl_src: ast::DefId) -> bool {
     if attributes_specify_inlining(method.attrs.as_slice()) ||
         generics_require_inlining(&method.generics) {
@@ -83,34 +82,26 @@ fn method_might_be_inlined(tcx: ty::ctxt, method: &ast::Method,
 }
 
 // Information needed while computing reachability.
-struct ReachableContext {
+struct ReachableContext<'a> {
     // The type context.
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     // The method map, which links node IDs of method call expressions to the
     // methods they've been resolved to.
     method_map: typeck::MethodMap,
     // The set of items which must be exported in the linkage sense.
-    reachable_symbols: @RefCell<NodeSet>,
+    reachable_symbols: NodeSet,
     // A worklist of item IDs. Each item ID in this worklist will be inlined
     // and will be scanned for further references.
-    worklist: @RefCell<Vec<ast::NodeId> >,
+    worklist: Vec<ast::NodeId>,
 }
 
-struct MarkSymbolVisitor {
-    worklist: @RefCell<Vec<ast::NodeId> >,
-    method_map: typeck::MethodMap,
-    tcx: ty::ctxt,
-    reachable_symbols: @RefCell<NodeSet>,
-}
-
-impl Visitor<()> for MarkSymbolVisitor {
+impl<'a> Visitor<()> for ReachableContext<'a> {
 
     fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
 
         match expr.node {
             ast::ExprPath(_) => {
-                let def_map = self.tcx.def_map.borrow();
-                let def = match def_map.get().find(&expr.id) {
+                let def = match self.tcx.def_map.borrow().get().find(&expr.id) {
                     Some(&def) => def,
                     None => {
                         self.tcx.sess.span_bug(expr.span,
@@ -120,12 +111,8 @@ impl Visitor<()> for MarkSymbolVisitor {
 
                 let def_id = def_id_of_def(def);
                 if is_local(def_id) {
-                    if ReachableContext::
-                        def_id_represents_local_inlined_item(self.tcx, def_id) {
-                            {
-                                let mut worklist = self.worklist.borrow_mut();
-                                worklist.get().push(def_id.node)
-                            }
+                    if self.def_id_represents_local_inlined_item(def_id) {
+                        self.worklist.push(def_id.node)
                     } else {
                         match def {
                             // If this path leads to a static, then we may have
@@ -133,16 +120,13 @@ impl Visitor<()> for MarkSymbolVisitor {
                             // is indeed reachable (address_insignificant
                             // statics are *never* reachable).
                             ast::DefStatic(..) => {
-                                let mut worklist = self.worklist.borrow_mut();
-                                worklist.get().push(def_id.node);
+                                self.worklist.push(def_id.node);
                             }
 
                             // If this wasn't a static, then this destination is
                             // surely reachable.
                             _ => {
-                                let mut reachable_symbols =
-                                    self.reachable_symbols.borrow_mut();
-                                reachable_symbols.get().insert(def_id.node);
+                                self.reachable_symbols.insert(def_id.node);
                             }
                         }
                     }
@@ -153,13 +137,10 @@ impl Visitor<()> for MarkSymbolVisitor {
                 match self.method_map.borrow().get().get(&method_call).origin {
                     typeck::MethodStatic(def_id) => {
                         if is_local(def_id) {
-                            if ReachableContext::
-                                def_id_represents_local_inlined_item(
-                                    self.tcx,
-                                    def_id) {
-                                self.worklist.borrow_mut().get().push(def_id.node)
+                            if self.def_id_represents_local_inlined_item(def_id) {
+                                self.worklist.push(def_id.node)
                             }
-                            self.reachable_symbols.borrow_mut().get().insert(def_id.node);
+                            self.reachable_symbols.insert(def_id.node);
                         }
                     }
                     _ => {}
@@ -177,27 +158,26 @@ impl Visitor<()> for MarkSymbolVisitor {
     }
 }
 
-impl ReachableContext {
+impl<'a> ReachableContext<'a> {
     // Creates a new reachability computation context.
-    fn new(tcx: ty::ctxt, method_map: typeck::MethodMap) -> ReachableContext {
+    fn new(tcx: &'a ty::ctxt, method_map: typeck::MethodMap) -> ReachableContext<'a> {
         ReachableContext {
             tcx: tcx,
             method_map: method_map,
-            reachable_symbols: @RefCell::new(NodeSet::new()),
-            worklist: @RefCell::new(Vec::new()),
+            reachable_symbols: NodeSet::new(),
+            worklist: Vec::new(),
         }
     }
 
     // Returns true if the given def ID represents a local item that is
     // eligible for inlining and false otherwise.
-    fn def_id_represents_local_inlined_item(tcx: ty::ctxt, def_id: ast::DefId)
-                                            -> bool {
+    fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
         if def_id.krate != ast::LOCAL_CRATE {
             return false
         }
 
         let node_id = def_id.node;
-        match tcx.map.find(node_id) {
+        match self.tcx.map.find(node_id) {
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
                     ast::ItemFn(..) => item_might_be_inlined(item),
@@ -215,11 +195,11 @@ impl ReachableContext {
                         attributes_specify_inlining(method.attrs.as_slice()) {
                     true
                 } else {
-                    let impl_did = tcx.map.get_parent_did(node_id);
+                    let impl_did = self.tcx.map.get_parent_did(node_id);
                     // Check the impl. If the generics on the self type of the
                     // impl require inlining, this method does too.
                     assert!(impl_did.krate == ast::LOCAL_CRATE);
-                    match tcx.map.expect_item(impl_did.node).node {
+                    match self.tcx.map.expect_item(impl_did.node).node {
                         ast::ItemImpl(ref generics, _, _, _) => {
                             generics_require_inlining(generics)
                         }
@@ -232,40 +212,21 @@ impl ReachableContext {
         }
     }
 
-    // Helper function to set up a visitor for `propagate()` below.
-    fn init_visitor(&self) -> MarkSymbolVisitor {
-        let (worklist, method_map) = (self.worklist, self.method_map);
-        let (tcx, reachable_symbols) = (self.tcx, self.reachable_symbols);
-
-        MarkSymbolVisitor {
-            worklist: worklist,
-            method_map: method_map,
-            tcx: tcx,
-            reachable_symbols: reachable_symbols,
-        }
-    }
-
     // Step 2: Mark all symbols that the symbols on the worklist touch.
-    fn propagate(&self) {
-        let mut visitor = self.init_visitor();
+    fn propagate(&mut self) {
         let mut scanned = HashSet::new();
         loop {
-            let search_item = {
-                let mut worklist = self.worklist.borrow_mut();
-                if worklist.get().len() == 0 {
-                    break
-                }
-                let search_item = worklist.get().pop().unwrap();
-                if scanned.contains(&search_item) {
-                    continue
-                }
-                search_item
-            };
+            if self.worklist.len() == 0 {
+                break
+            }
+            let search_item = self.worklist.pop().unwrap();
+            if scanned.contains(&search_item) {
+                continue
+            }
 
             scanned.insert(search_item);
             match self.tcx.map.find(search_item) {
-                Some(ref item) => self.propagate_node(item, search_item,
-                                                  &mut visitor),
+                Some(ref item) => self.propagate_node(item, search_item),
                 None if search_item == ast::CRATE_NODE_ID => {}
                 None => {
                     self.tcx.sess.bug(format!("found unmapped ID in worklist: \
@@ -276,9 +237,8 @@ impl ReachableContext {
         }
     }
 
-    fn propagate_node(&self, node: &ast_map::Node,
-                      search_item: ast::NodeId,
-                      visitor: &mut MarkSymbolVisitor) {
+    fn propagate_node(&mut self, node: &ast_map::Node,
+                      search_item: ast::NodeId) {
         if !self.tcx.sess.building_library.get() {
             // If we are building an executable, then there's no need to flag
             // anything as external except for `extern fn` types. These
@@ -289,9 +249,7 @@ impl ReachableContext {
                 ast_map::NodeItem(item) => {
                     match item.node {
                         ast::ItemFn(_, ast::ExternFn, _, _, _) => {
-                            let mut reachable_symbols =
-                                self.reachable_symbols.borrow_mut();
-                            reachable_symbols.get().insert(search_item);
+                            self.reachable_symbols.insert(search_item);
                         }
                         _ => {}
                     }
@@ -303,8 +261,7 @@ impl ReachableContext {
             // continue to participate in linkage after this product is
             // produced. In this case, we traverse the ast node, recursing on
             // all reachable nodes from this one.
-            let mut reachable_symbols = self.reachable_symbols.borrow_mut();
-            reachable_symbols.get().insert(search_item);
+            self.reachable_symbols.insert(search_item);
         }
 
         match *node {
@@ -312,7 +269,7 @@ impl ReachableContext {
                 match item.node {
                     ast::ItemFn(_, _, _, _, search_block) => {
                         if item_might_be_inlined(item) {
-                            visit::walk_block(visitor, search_block, ())
+                            visit::walk_block(self, search_block, ())
                         }
                     }
 
@@ -321,9 +278,7 @@ impl ReachableContext {
                     ast::ItemStatic(..) => {
                         if attr::contains_name(item.attrs.as_slice(),
                                                "address_insignificant") {
-                            let mut reachable_symbols =
-                                self.reachable_symbols.borrow_mut();
-                            reachable_symbols.get().remove(&search_item);
+                            self.reachable_symbols.remove(&search_item);
                         }
                     }
 
@@ -348,14 +303,14 @@ impl ReachableContext {
                         // Keep going, nothing to get exported
                     }
                     ast::Provided(ref method) => {
-                        visit::walk_block(visitor, method.body, ())
+                        visit::walk_block(self, method.body, ())
                     }
                 }
             }
             ast_map::NodeMethod(method) => {
                 let did = self.tcx.map.get_parent_did(search_item);
                 if method_might_be_inlined(self.tcx, method, did) {
-                    visit::walk_block(visitor, method.body, ())
+                    visit::walk_block(self, method.body, ())
                 }
             }
             // Nothing to recurse on for these
@@ -375,42 +330,37 @@ impl ReachableContext {
     // FIXME(pcwalton): This is a conservative overapproximation, but fixing
     // this properly would result in the necessity of computing *type*
     // reachability, which might result in a compile time loss.
-    fn mark_destructors_reachable(&self) {
-        let destructor_for_type = self.tcx.destructor_for_type.borrow();
-        for (_, destructor_def_id) in destructor_for_type.get().iter() {
+    fn mark_destructors_reachable(&mut self) {
+        for (_, destructor_def_id) in self.tcx.destructor_for_type.borrow().get().iter() {
             if destructor_def_id.krate == ast::LOCAL_CRATE {
-                let mut reachable_symbols = self.reachable_symbols
-                                                .borrow_mut();
-                reachable_symbols.get().insert(destructor_def_id.node);
+                self.reachable_symbols.insert(destructor_def_id.node);
             }
         }
     }
 }
 
-pub fn find_reachable(tcx: ty::ctxt,
+pub fn find_reachable(tcx: &ty::ctxt,
                       method_map: typeck::MethodMap,
                       exported_items: &privacy::ExportedItems)
-                      -> @RefCell<NodeSet> {
-    let reachable_context = ReachableContext::new(tcx, method_map);
+                      -> NodeSet {
+    let mut reachable_context = ReachableContext::new(tcx, method_map);
 
     // Step 1: Seed the worklist with all nodes which were found to be public as
     //         a result of the privacy pass along with all local lang items. If
     //         other crates link to us, they're going to expect to be able to
     //         use the lang items, so we need to be sure to mark them as
     //         exported.
-    let mut worklist = reachable_context.worklist.borrow_mut();
     for &id in exported_items.iter() {
-        worklist.get().push(id);
+        reachable_context.worklist.push(id);
     }
     for (_, item) in tcx.lang_items.items() {
         match *item {
             Some(did) if is_local(did) => {
-                worklist.get().push(did.node);
+                reachable_context.worklist.push(did.node);
             }
             _ => {}
         }
     }
-    drop(worklist);
 
     // Step 2: Mark all symbols that the symbols on the worklist touch.
     reachable_context.propagate();
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 15d228662c7..a13dce65f51 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -92,7 +92,7 @@ pub struct Context {
 }
 
 struct RegionResolutionVisitor<'a> {
-    sess: Session,
+    sess: &'a Session,
 
     // Generated maps:
     region_maps: &'a RegionMaps,
@@ -847,7 +847,7 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
                                body.id={}, \
                                cx.parent={})",
            id,
-           visitor.sess.codemap.span_to_str(sp),
+           visitor.sess.codemap().span_to_str(sp),
            body.id,
            cx.parent);
 
@@ -909,7 +909,7 @@ impl<'a> Visitor<Context> for RegionResolutionVisitor<'a> {
     }
 }
 
-pub fn resolve_crate(sess: Session, krate: &ast::Crate) -> RegionMaps {
+pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps {
     let maps = RegionMaps {
         scope_map: RefCell::new(NodeMap::new()),
         var_map: RefCell::new(NodeMap::new()),
@@ -928,7 +928,7 @@ pub fn resolve_crate(sess: Session, krate: &ast::Crate) -> RegionMaps {
     return maps;
 }
 
-pub fn resolve_inlined_item(sess: Session,
+pub fn resolve_inlined_item(sess: &Session,
                             region_maps: &RegionMaps,
                             item: &ast::InlinedItem) {
     let cx = Context {parent: None,
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 77e44c137a9..2784be5a01b 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -153,7 +153,7 @@ enum NameDefinition {
     ImportNameDefinition(Def, LastPrivate) //< The name identifies an import.
 }
 
-impl Visitor<()> for Resolver {
+impl<'a> Visitor<()> for Resolver<'a> {
     fn visit_item(&mut self, item: &Item, _: ()) {
         self.resolve_item(item);
     }
@@ -787,9 +787,9 @@ fn namespace_error_to_str(ns: NamespaceError) -> &'static str {
     }
 }
 
-fn Resolver(session: Session,
-            lang_items: @LanguageItems,
-            crate_span: Span) -> Resolver {
+fn Resolver<'a>(session: &'a Session,
+                lang_items: @LanguageItems,
+                crate_span: Span) -> Resolver<'a> {
     let graph_root = @NameBindings();
 
     graph_root.define_module(NoParentLink,
@@ -802,7 +802,7 @@ fn Resolver(session: Session,
     let current_module = graph_root.get_module();
 
     let this = Resolver {
-        session: @session,
+        session: session,
         lang_items: lang_items,
 
         // The outermost module has def ID 0; this is not reflected in the
@@ -843,8 +843,8 @@ fn Resolver(session: Session,
 }
 
 /// The main resolver class.
-struct Resolver {
-    session: @Session,
+struct Resolver<'a> {
+    session: &'a Session,
     lang_items: @LanguageItems,
 
     graph_root: @NameBindings,
@@ -896,11 +896,11 @@ struct Resolver {
     used_imports: HashSet<(NodeId, Namespace)>,
 }
 
-struct BuildReducedGraphVisitor<'a> {
-    resolver: &'a mut Resolver,
+struct BuildReducedGraphVisitor<'a, 'b> {
+    resolver: &'a mut Resolver<'b>,
 }
 
-impl<'a> Visitor<ReducedGraphParent> for BuildReducedGraphVisitor<'a> {
+impl<'a, 'b> Visitor<ReducedGraphParent> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_item(&mut self, item: &Item, context: ReducedGraphParent) {
         let p = self.resolver.build_reduced_graph_for_item(item, context);
@@ -928,16 +928,16 @@ impl<'a> Visitor<ReducedGraphParent> for BuildReducedGraphVisitor<'a> {
 
 }
 
-struct UnusedImportCheckVisitor<'a> { resolver: &'a mut Resolver }
+struct UnusedImportCheckVisitor<'a, 'b> { resolver: &'a mut Resolver<'b> }
 
-impl<'a> Visitor<()> for UnusedImportCheckVisitor<'a> {
+impl<'a, 'b> Visitor<()> for UnusedImportCheckVisitor<'a, 'b> {
     fn visit_view_item(&mut self, vi: &ViewItem, _: ()) {
         self.resolver.check_for_item_unused_imports(vi);
         visit::walk_view_item(self, vi, ());
     }
 }
 
-impl Resolver {
+impl<'a> Resolver<'a> {
     /// The main name resolution procedure.
     fn resolve(&mut self, krate: &ast::Crate) {
         self.build_reduced_graph(krate);
@@ -1690,11 +1690,11 @@ impl Resolver {
               // to the trait info.
 
               let method_def_ids =
-                csearch::get_trait_method_def_ids(self.session.cstore, def_id);
+                csearch::get_trait_method_def_ids(&self.session.cstore, def_id);
               let mut interned_method_names = HashSet::new();
               for &method_def_id in method_def_ids.iter() {
                   let (method_name, explicit_self) =
-                      csearch::get_method_name_and_explicit_self(self.session.cstore,
+                      csearch::get_method_name_and_explicit_self(&self.session.cstore,
                                                                  method_def_id);
 
                   debug!("(building reduced graph for \
@@ -1743,7 +1743,7 @@ impl Resolver {
                     crate) building type and value for {}",
                    final_ident);
             child_name_bindings.define_type(def, DUMMY_SP, is_public);
-            if csearch::get_struct_fields(self.session.cstore, def_id).len() == 0 {
+            if csearch::get_struct_fields(&self.session.cstore, def_id).len() == 0 {
                 child_name_bindings.define_value(def, DUMMY_SP, is_public);
             }
             self.structs.insert(def_id);
@@ -1775,7 +1775,7 @@ impl Resolver {
                     DefForeignMod(def_id) => {
                         // Foreign modules have no names. Recur and populate
                         // eagerly.
-                        csearch::each_child_of_item(self.session.cstore,
+                        csearch::each_child_of_item(&self.session.cstore,
                                                     def_id,
                                                     |def_like,
                                                      child_ident,
@@ -1805,11 +1805,11 @@ impl Resolver {
             }
             DlImpl(def) => {
                 // We only process static methods of impls here.
-                match csearch::get_type_name_if_impl(self.session.cstore, def) {
+                match csearch::get_type_name_if_impl(&self.session.cstore, def) {
                     None => {}
                     Some(final_ident) => {
                         let static_methods_opt =
-                            csearch::get_static_methods_if_impl(self.session.cstore, def);
+                            csearch::get_static_methods_if_impl(&self.session.cstore, def);
                         match static_methods_opt {
                             Some(ref static_methods) if
                                 static_methods.len() >= 1 => {
@@ -1910,7 +1910,7 @@ impl Resolver {
             Some(def_id) => def_id,
         };
 
-        csearch::each_child_of_item(self.session.cstore,
+        csearch::each_child_of_item(&self.session.cstore,
                                     def_id,
                                     |def_like, child_ident, visibility| {
             debug!("(populating external module) ... found ident: {}",
@@ -1936,7 +1936,7 @@ impl Resolver {
     /// crate.
     fn build_reduced_graph_for_external_crate(&mut self,
                                               root: @Module) {
-        csearch::each_top_level_item_of_crate(self.session.cstore,
+        csearch::each_top_level_item_of_crate(&self.session.cstore,
                                               root.def_id
                                                   .get()
                                                   .unwrap()
@@ -3275,7 +3275,7 @@ impl Resolver {
         let import_count = imports.get().len();
         if index != import_count {
             let sn = self.session
-                         .codemap
+                         .codemap()
                          .span_to_snippet(imports.get().get(index).span)
                          .unwrap();
             if sn.contains("::") {
@@ -5449,7 +5449,7 @@ impl Resolver {
     // public or private item, we will check the correct thing, dependent on how the import
     // is used.
     fn finalize_import(&mut self, id: NodeId, span: Span) {
-        debug!("finalizing import uses for {}", self.session.codemap.span_to_snippet(span));
+        debug!("finalizing import uses for {}", self.session.codemap().span_to_snippet(span));
 
         if !self.used_imports.contains(&(id, TypeNS)) &&
            !self.used_imports.contains(&(id, ValueNS)) {
@@ -5571,7 +5571,7 @@ pub struct CrateMap {
 }
 
 /// Entry point to crate resolution.
-pub fn resolve_crate(session: Session,
+pub fn resolve_crate(session: &Session,
                      lang_items: @LanguageItems,
                      krate: &Crate)
                   -> CrateMap {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 88eaf256be8..da424ea2e15 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -17,8 +17,7 @@
  * way. Therefore we break lifetime name resolution into a separate pass.
  */
 
-use driver::session;
-use std::cell::RefCell;
+use driver::session::Session;
 use std::vec_ng::Vec;
 use util::nodemap::NodeMap;
 use syntax::ast;
@@ -40,9 +39,9 @@ fn lifetime_show(lt_name: &ast::Name) -> token::InternedString {
     token::get_name(*lt_name)
 }
 
-struct LifetimeContext {
-    sess: session::Session,
-    named_region_map: @RefCell<NamedRegionMap>,
+struct LifetimeContext<'a> {
+    sess: &'a Session,
+    named_region_map: NamedRegionMap,
 }
 
 enum ScopeChain<'a> {
@@ -60,18 +59,17 @@ enum ScopeChain<'a> {
 
 type Scope<'a> = &'a ScopeChain<'a>;
 
-pub fn krate(sess: session::Session, krate: &ast::Crate)
-             -> @RefCell<NamedRegionMap> {
+pub fn krate(sess: &Session, krate: &ast::Crate) -> NamedRegionMap {
     let mut ctxt = LifetimeContext {
         sess: sess,
-        named_region_map: @RefCell::new(NodeMap::new())
+        named_region_map: NodeMap::new()
     };
     visit::walk_crate(&mut ctxt, krate, &RootScope);
     sess.abort_if_errors();
     ctxt.named_region_map
 }
 
-impl<'a> Visitor<Scope<'a>> for LifetimeContext {
+impl<'a, 'b> Visitor<Scope<'a>> for LifetimeContext<'b> {
     fn visit_item(&mut self,
                   item: &ast::Item,
                   _: Scope<'a>) {
@@ -181,7 +179,7 @@ impl<'a> ScopeChain<'a> {
     }
 }
 
-impl LifetimeContext {
+impl<'a> LifetimeContext<'a> {
     /// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
     fn visit_fn_decl(&mut self,
                      n: ast::NodeId,
@@ -237,7 +235,7 @@ impl LifetimeContext {
         debug!("popping fn scope id={} due to fn item/method", n);
     }
 
-    fn resolve_lifetime_ref(&self,
+    fn resolve_lifetime_ref(&mut self,
                             lifetime_ref: &ast::Lifetime,
                             scope: Scope) {
         // Walk up the scope chain, tracking the number of fn scopes
@@ -293,7 +291,7 @@ impl LifetimeContext {
         self.unresolved_lifetime_ref(lifetime_ref);
     }
 
-    fn resolve_free_lifetime_ref(&self,
+    fn resolve_free_lifetime_ref(&mut self,
                                  scope_id: ast::NodeId,
                                  lifetime_ref: &ast::Lifetime,
                                  scope: Scope) {
@@ -374,7 +372,7 @@ impl LifetimeContext {
         }
     }
 
-    fn insert_lifetime(&self,
+    fn insert_lifetime(&mut self,
                        lifetime_ref: &ast::Lifetime,
                        def: ast::DefRegion) {
         if lifetime_ref.id == ast::DUMMY_NODE_ID {
@@ -387,8 +385,7 @@ impl LifetimeContext {
                 lifetime_to_str(lifetime_ref),
                 lifetime_ref.id,
                 def);
-        let mut named_region_map = self.named_region_map.borrow_mut();
-        named_region_map.get().insert(lifetime_ref.id, def);
+        self.named_region_map.insert(lifetime_ref.id, def);
     }
 }
 
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 82458a69ee6..f82b43adc43 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -29,10 +29,10 @@ use syntax::opt_vec::OptVec;
 // information available (for better errors).
 
 pub trait Subst {
-    fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> Self {
+    fn subst(&self, tcx: &ty::ctxt, substs: &ty::substs) -> Self {
         self.subst_spanned(tcx, substs, None)
     }
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> Self;
 }
@@ -46,7 +46,7 @@ pub trait Subst {
 // our current method/trait matching algorithm. - Niko
 
 impl Subst for ty::t {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::t {
         if ty::substs_is_noop(substs) && !ty::type_has_params(*self) {
@@ -64,7 +64,7 @@ impl Subst for ty::t {
 }
 
 struct SubstFolder<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     substs: &'a ty::substs,
 
     // The location for which the substitution is performed, if available.
@@ -75,7 +75,7 @@ struct SubstFolder<'a> {
 }
 
 impl<'a> TypeFolder for SubstFolder<'a> {
-    fn tcx(&self) -> ty::ctxt { self.tcx }
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
 
     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
         r.subst(self.tcx, self.substs)
@@ -132,14 +132,14 @@ impl<'a> TypeFolder for SubstFolder<'a> {
 // Other types
 
 impl<T:Subst> Subst for Vec<T> {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> Vec<T> {
         self.map(|t| t.subst_spanned(tcx, substs, span))
     }
 }
 impl<T:Subst> Subst for Rc<T> {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> Rc<T> {
         Rc::new(self.deref().subst_spanned(tcx, substs, span))
@@ -147,7 +147,7 @@ impl<T:Subst> Subst for Rc<T> {
 }
 
 impl<T:Subst> Subst for OptVec<T> {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> OptVec<T> {
         self.map(|t| t.subst_spanned(tcx, substs, span))
@@ -155,7 +155,7 @@ impl<T:Subst> Subst for OptVec<T> {
 }
 
 impl<T:Subst + 'static> Subst for @T {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> @T {
         match self {
@@ -165,7 +165,7 @@ impl<T:Subst + 'static> Subst for @T {
 }
 
 impl<T:Subst> Subst for Option<T> {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> Option<T> {
         self.as_ref().map(|t| t.subst_spanned(tcx, substs, span))
@@ -173,7 +173,7 @@ impl<T:Subst> Subst for Option<T> {
 }
 
 impl Subst for ty::TraitRef {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::TraitRef {
         ty::TraitRef {
@@ -184,7 +184,7 @@ impl Subst for ty::TraitRef {
 }
 
 impl Subst for ty::substs {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::substs {
         ty::substs {
@@ -196,7 +196,7 @@ impl Subst for ty::substs {
 }
 
 impl Subst for ty::RegionSubsts {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::RegionSubsts {
         match *self {
@@ -211,7 +211,7 @@ impl Subst for ty::RegionSubsts {
 }
 
 impl Subst for ty::BareFnTy {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::BareFnTy {
         let mut folder = SubstFolder {
@@ -225,7 +225,7 @@ impl Subst for ty::BareFnTy {
 }
 
 impl Subst for ty::ParamBounds {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::ParamBounds {
         ty::ParamBounds {
@@ -236,7 +236,7 @@ impl Subst for ty::ParamBounds {
 }
 
 impl Subst for ty::TypeParameterDef {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::TypeParameterDef {
         ty::TypeParameterDef {
@@ -249,7 +249,7 @@ impl Subst for ty::TypeParameterDef {
 }
 
 impl Subst for ty::Generics {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::Generics {
         ty::Generics {
@@ -260,7 +260,7 @@ impl Subst for ty::Generics {
 }
 
 impl Subst for ty::RegionParameterDef {
-    fn subst_spanned(&self, _: ty::ctxt,
+    fn subst_spanned(&self, _: &ty::ctxt,
                      _: &ty::substs,
                      _: Option<Span>) -> ty::RegionParameterDef {
         *self
@@ -268,7 +268,7 @@ impl Subst for ty::RegionParameterDef {
 }
 
 impl Subst for ty::Region {
-    fn subst_spanned(&self, _tcx: ty::ctxt,
+    fn subst_spanned(&self, _tcx: &ty::ctxt,
                      substs: &ty::substs,
                      _: Option<Span>) -> ty::Region {
         // Note: This routine only handles regions that are bound on
@@ -290,7 +290,7 @@ impl Subst for ty::Region {
 }
 
 impl Subst for ty::ty_param_bounds_and_ty {
-    fn subst_spanned(&self, tcx: ty::ctxt,
+    fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
                      span: Option<Span>) -> ty::ty_param_bounds_and_ty {
         ty::ty_param_bounds_and_ty {
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 4f190c5d697..7d69db92af2 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -257,7 +257,7 @@ enum Opt {
     vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
 
-fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
+fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
     match (a, b) {
         (&lit(a), &lit(b)) => {
             match (a, b) {
@@ -359,7 +359,7 @@ fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
     let def_map = ccx.tcx.def_map.borrow();
     match def_map.get().get_copy(&pat_id) {
         ast::DefVariant(enum_id, var_id, _) => {
-            let variants = ty::enum_variants(ccx.tcx, enum_id);
+            let variants = ty::enum_variants(ccx.tcx(), enum_id);
             for v in (*variants).iter() {
                 if var_id == v.id {
                     return var(v.disr_val,
@@ -373,7 +373,7 @@ fn variant_opt(bcx: &Block, pat_id: ast::NodeId) -> Opt {
             return lit(UnitLikeStructLit(pat_id));
         }
         _ => {
-            ccx.sess.bug("non-variant or struct in variant_opt()");
+            ccx.sess().bug("non-variant or struct in variant_opt()");
         }
     }
 }
@@ -427,7 +427,7 @@ struct Match<'a,'b> {
     bound_ptrs: Vec<(Ident, ValueRef)> }
 
 impl<'a,'b> Repr for Match<'a,'b> {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         if tcx.sess.verbose() {
             // for many programs, this just take too long to serialize
             self.pats.repr(tcx)
@@ -931,7 +931,7 @@ fn enter_region<'r,
 // on a set of enum variants or a literal.
 fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec<Opt> {
     let ccx = bcx.ccx();
-    fn add_to_set(tcx: ty::ctxt, set: &mut Vec<Opt> , val: Opt) {
+    fn add_to_set(tcx: &ty::ctxt, set: &mut Vec<Opt>, val: Opt) {
         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
         set.push(val);
     }
@@ -960,7 +960,7 @@ fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec<Opt> {
         let cur = *br.pats.get(col);
         match cur.node {
             ast::PatLit(l) => {
-                add_to_set(ccx.tcx, &mut found, lit(ExprLit(l)));
+                add_to_set(ccx.tcx(), &mut found, lit(ExprLit(l)));
             }
             ast::PatIdent(..) => {
                 // This is one of: an enum variant, a unit-like struct, or a
@@ -971,15 +971,15 @@ fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec<Opt> {
                 };
                 match opt_def {
                     Some(ast::DefVariant(..)) => {
-                        add_to_set(ccx.tcx, &mut found,
+                        add_to_set(ccx.tcx(), &mut found,
                                    variant_opt(bcx, cur.id));
                     }
                     Some(ast::DefStruct(..)) => {
-                        add_to_set(ccx.tcx, &mut found,
+                        add_to_set(ccx.tcx(), &mut found,
                                    lit(UnitLikeStructLit(cur.id)));
                     }
                     Some(ast::DefStatic(const_did, false)) => {
-                        add_to_set(ccx.tcx, &mut found,
+                        add_to_set(ccx.tcx(), &mut found,
                                    lit(ConstLit(const_did)));
                     }
                     _ => {}
@@ -995,18 +995,18 @@ fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec<Opt> {
                 match opt_def {
                     Some(ast::DefFn(..)) |
                     Some(ast::DefVariant(..)) => {
-                        add_to_set(ccx.tcx, &mut found,
+                        add_to_set(ccx.tcx(), &mut found,
                                    variant_opt(bcx, cur.id));
                     }
                     Some(ast::DefStatic(const_did, false)) => {
-                        add_to_set(ccx.tcx, &mut found,
+                        add_to_set(ccx.tcx(), &mut found,
                                    lit(ConstLit(const_did)));
                     }
                     _ => {}
                 }
             }
             ast::PatRange(l1, l2) => {
-                add_to_set(ccx.tcx, &mut found, range(l1, l2));
+                add_to_set(ccx.tcx(), &mut found, range(l1, l2));
             }
             ast::PatVec(ref before, slice, ref after) => {
                 let (len, vec_opt) = match slice {
@@ -1324,8 +1324,7 @@ fn compare_values<'a>(
             }
         }
         _ => {
-            cx.tcx().sess.bug("only scalars and strings supported in \
-                                compare_values");
+            cx.sess().bug("only scalars and strings supported in compare_values");
         }
     }
 }
@@ -1585,7 +1584,7 @@ fn compile_submatch_continue<'r,
         let tup_repr = adt::represent_type(bcx.ccx(), tup_ty);
         let n_tup_elts = match ty::get(tup_ty).sty {
           ty::ty_tup(ref elts) => elts.len(),
-          _ => ccx.sess.bug("non-tuple type in tuple pattern")
+          _ => ccx.sess().bug("non-tuple type in tuple pattern")
         };
         let tup_vals = Vec::from_fn(n_tup_elts, |i| {
             adt::trans_field_ptr(bcx, tup_repr, val, 0, i)
@@ -1612,7 +1611,7 @@ fn compile_submatch_continue<'r,
                     ty::lookup_struct_fields(tcx, struct_id).len();
             }
             _ => {
-                ccx.sess.bug("non-struct type in tuple struct pattern");
+                ccx.sess().bug("non-struct type in tuple struct pattern");
             }
         }
 
@@ -2093,7 +2092,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
             // like `x: T`
             let arg_ty = node_id_type(bcx, pat.id);
             if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
-                && bcx.ccx().sess.opts.debuginfo != FullDebugInfo {
+                && bcx.sess().opts.debuginfo != FullDebugInfo {
                 // Don't copy an indirect argument to an alloca, the caller
                 // already put it in a temporary alloca and gave it up, unless
                 // we emit extra-debug-info, which requires local allocas :(.
@@ -2225,7 +2224,7 @@ fn bind_irrefutable_pat<'a>(
             match def_map.get().find(&pat.id) {
                 Some(&ast::DefVariant(enum_id, var_id, _)) => {
                     let repr = adt::represent_node(bcx, pat.id);
-                    let vinfo = ty::enum_variant_with_id(ccx.tcx,
+                    let vinfo = ty::enum_variant_with_id(ccx.tcx(),
                                                          enum_id,
                                                          var_id);
                     let args = extract_variant_args(bcx,
@@ -2297,8 +2296,7 @@ fn bind_irrefutable_pat<'a>(
             bcx = bind_irrefutable_pat(bcx, inner, loaded_val, binding_mode, cleanup_scope);
         }
         ast::PatVec(..) => {
-            bcx.tcx().sess.span_bug(
-                pat.span,
+            bcx.sess().span_bug(pat.span,
                 format!("vector patterns are never irrefutable!"));
         }
         ast::PatWild | ast::PatWildMulti | ast::PatLit(_) | ast::PatRange(_, _) => ()
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 00a93b66ce0..eb57ad022b6 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -118,7 +118,7 @@ pub fn represent_node(bcx: &Block, node: ast::NodeId) -> @Repr {
 
 /// Decides how to represent a given type.
 pub fn represent_type(cx: &CrateContext, t: ty::t) -> @Repr {
-    debug!("Representing: {}", ty_to_str(cx.tcx, t));
+    debug!("Representing: {}", ty_to_str(cx.tcx(), t));
     {
         let adt_reprs = cx.adt_reprs.borrow();
         match adt_reprs.get().find(&t) {
@@ -140,19 +140,19 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
             return Univariant(mk_struct(cx, elems.as_slice(), false), false)
         }
         ty::ty_struct(def_id, ref substs) => {
-            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
+            let fields = ty::lookup_struct_fields(cx.tcx(), def_id);
             let mut ftys = fields.map(|field| {
-                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
+                ty::lookup_field_type(cx.tcx(), def_id, field.id, substs)
             });
-            let packed = ty::lookup_packed(cx.tcx, def_id);
-            let dtor = ty::ty_dtor(cx.tcx, def_id).has_drop_flag();
+            let packed = ty::lookup_packed(cx.tcx(), def_id);
+            let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
             if dtor { ftys.push(ty::mk_bool()); }
 
             return Univariant(mk_struct(cx, ftys.as_slice(), packed), dtor)
         }
         ty::ty_enum(def_id, ref substs) => {
-            let cases = get_cases(cx.tcx, def_id, substs);
-            let hint = ty::lookup_repr_hint(cx.tcx, def_id);
+            let cases = get_cases(cx.tcx(), def_id, substs);
+            let hint = ty::lookup_repr_hint(cx.tcx(), def_id);
 
             if cases.len() == 0 {
                 // Uninhabitable; represent as unit
@@ -177,9 +177,9 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
             // non-empty body, explicit discriminants should have
             // been rejected by a checker before this point.
             if !cases.iter().enumerate().all(|(i,c)| c.discr == (i as Disr)) {
-                cx.sess.bug(format!("non-C-like enum {} with specified \
-                                  discriminants",
-                                 ty::item_path_str(cx.tcx, def_id)))
+                cx.sess().bug(format!("non-C-like enum {} with specified \
+                                      discriminants",
+                                      ty::item_path_str(cx.tcx(), def_id)))
             }
 
             if cases.len() == 1 {
@@ -230,13 +230,13 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
                           false)
             }))
         }
-        _ => cx.sess.bug("adt::represent_type called on non-ADT type")
+        _ => cx.sess().bug("adt::represent_type called on non-ADT type")
     }
 }
 
 /// Determine, without doing translation, whether an ADT must be FFI-safe.
 /// For use in lint or similar, where being sound but slightly incomplete is acceptable.
-pub fn is_ffi_safe(tcx: ty::ctxt, def_id: ast::DefId) -> bool {
+pub fn is_ffi_safe(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
     match ty::get(ty::lookup_item_type(tcx, def_id).ty).sty {
         ty::ty_enum(def_id, _) => {
             let variants = ty::enum_variants(tcx, def_id);
@@ -274,7 +274,7 @@ impl Case {
     }
 }
 
-fn get_cases(tcx: ty::ctxt, def_id: ast::DefId, substs: &ty::substs) -> Vec<Case> {
+fn get_cases(tcx: &ty::ctxt, def_id: ast::DefId, substs: &ty::substs) -> Vec<Case> {
     ty::enum_variants(tcx, def_id).map(|vi| {
         let arg_tys = vi.args.map(|&raw_ty| {
             ty::subst(tcx, substs, raw_ty)
@@ -286,7 +286,7 @@ fn get_cases(tcx: ty::ctxt, def_id: ast::DefId, substs: &ty::substs) -> Vec<Case
 
 fn mk_struct(cx: &CrateContext, tys: &[ty::t], packed: bool) -> Struct {
     let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
-    let llty_rec = Type::struct_(lltys, packed);
+    let llty_rec = Type::struct_(cx, lltys, packed);
     Struct {
         size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
         align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
@@ -324,12 +324,12 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
     match hint {
         attr::ReprInt(span, ity) => {
             if !bounds_usable(cx, ity, bounds) {
-                cx.sess.span_bug(span, "representation hint insufficient for discriminant range")
+                cx.sess().span_bug(span, "representation hint insufficient for discriminant range")
             }
             return ity;
         }
         attr::ReprExtern => {
-            attempts = match cx.sess.targ_cfg.arch {
+            attempts = match cx.sess().targ_cfg.arch {
                 X86 | X86_64 => at_least_32,
                 // WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32`
                 // appears to be used on Linux and NetBSD, but some systems may use the variant
@@ -415,10 +415,10 @@ fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool
         Univariant(ref st, _) | NullablePointer{ nonnull: ref st, .. } => {
             match name {
                 None => {
-                    Type::struct_(struct_llfields(cx, st, sizing).as_slice(),
+                    Type::struct_(cx, struct_llfields(cx, st, sizing).as_slice(),
                                   st.packed)
                 }
-                Some(name) => { assert_eq!(sizing, false); Type::named_struct(name) }
+                Some(name) => { assert_eq!(sizing, false); Type::named_struct(cx, name) }
             }
         }
         General(ity, ref sts) => {
@@ -441,12 +441,12 @@ fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool
             let discr_size = machine::llsize_of_alloc(cx, discr_ty) as u64;
             let align_units = (size + align - 1) / align - 1;
             let pad_ty = match align {
-                1 => Type::array(&Type::i8(), align_units),
-                2 => Type::array(&Type::i16(), align_units),
-                4 => Type::array(&Type::i32(), align_units),
-                8 if machine::llalign_of_min(cx, Type::i64()) == 8 =>
-                                 Type::array(&Type::i64(), align_units),
-                a if a.count_ones() == 1 => Type::array(&Type::vector(&Type::i32(), a / 4),
+                1 => Type::array(&Type::i8(cx), align_units),
+                2 => Type::array(&Type::i16(cx), align_units),
+                4 => Type::array(&Type::i32(cx), align_units),
+                8 if machine::llalign_of_min(cx, Type::i64(cx)) == 8 =>
+                                 Type::array(&Type::i64(cx), align_units),
+                a if a.count_ones() == 1 => Type::array(&Type::vector(&Type::i32(cx), a / 4),
                                                               align_units),
                 _ => fail!("unsupported enum alignment: {:?}", align)
             };
@@ -456,9 +456,9 @@ fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool
                            Type::array(&discr_ty, align / discr_size - 1),
                            pad_ty);
             match name {
-                None => Type::struct_(fields.as_slice(), false),
+                None => Type::struct_(cx, fields.as_slice(), false),
                 Some(name) => {
-                    let mut llty = Type::named_struct(name);
+                    let mut llty = Type::named_struct(cx, name);
                     llty.set_struct_body(fields.as_slice(), false);
                     llty
                 }
@@ -514,7 +514,7 @@ pub fn trans_get_discr(bcx: &Block, r: &Repr, scrutinee: ValueRef, cast_to: Opti
             signed = ity.is_signed();
         }
         Univariant(..) => {
-            val = C_u8(0);
+            val = C_u8(bcx.ccx(), 0);
             signed = false;
         }
         NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, .. } => {
@@ -577,11 +577,11 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
                                                        discr as u64, true)))
         }
         Univariant(..) => {
-            bcx.ccx().sess.bug("no cases for univariants or structs")
+            bcx.ccx().sess().bug("no cases for univariants or structs")
         }
         NullablePointer{ .. } => {
             assert!(discr == 0 || discr == 1);
-            _match::single_result(rslt(bcx, C_i1(discr != 0)))
+            _match::single_result(rslt(bcx, C_i1(bcx.ccx(), discr != 0)))
         }
     }
 }
@@ -604,7 +604,7 @@ pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
         }
         Univariant(ref st, true) => {
             assert_eq!(discr, 0);
-            Store(bcx, C_bool(true),
+            Store(bcx, C_bool(bcx.ccx(), true),
                   GEPi(bcx, val, [0, st.fields.len() - 1]))
         }
         Univariant(..) => {
@@ -651,7 +651,7 @@ pub fn num_args(r: &Repr, discr: Disr) -> uint {
 pub fn deref_ty(ccx: &CrateContext, r: &Repr) -> ty::t {
     match *r {
         CEnum(..) => {
-            ccx.sess.bug("deref of c-like enum")
+            ccx.sess().bug("deref of c-like enum")
         }
         Univariant(ref st, _) => {
             *st.fields.get(0)
@@ -661,7 +661,7 @@ pub fn deref_ty(ccx: &CrateContext, r: &Repr) -> ty::t {
             *cases.get(0).fields.get(0)
         }
         NullablePointer{ .. } => {
-            ccx.sess.bug("deref of nullable ptr")
+            ccx.sess().bug("deref of nullable ptr")
         }
     }
 }
@@ -674,7 +674,7 @@ pub fn trans_field_ptr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr,
     // someday), it will need to return a possibly-new bcx as well.
     match *r {
         CEnum(..) => {
-            bcx.ccx().sess.bug("element access in C-like enum")
+            bcx.ccx().sess().bug("element access in C-like enum")
         }
         Univariant(ref st, _dtor) => {
             assert_eq!(discr, 0);
@@ -706,7 +706,7 @@ fn struct_field_ptr(bcx: &Block, st: &Struct, val: ValueRef, ix: uint,
 
     let val = if needs_cast {
         let fields = st.fields.map(|&ty| type_of::type_of(ccx, ty));
-        let real_ty = Type::struct_(fields.as_slice(), st.packed);
+        let real_ty = Type::struct_(ccx, fields.as_slice(), st.packed);
         PointerCast(bcx, val, real_ty.ptr_to())
     } else {
         val
@@ -719,7 +719,7 @@ fn struct_field_ptr(bcx: &Block, st: &Struct, val: ValueRef, ix: uint,
 pub fn trans_drop_flag_ptr(bcx: &Block, r: &Repr, val: ValueRef) -> ValueRef {
     match *r {
         Univariant(ref st, true) => GEPi(bcx, val, [0, st.fields.len() - 1]),
-        _ => bcx.ccx().sess.bug("tried to get drop flag of non-droppable type")
+        _ => bcx.ccx().sess().bug("tried to get drop flag of non-droppable type")
     }
 }
 
@@ -761,21 +761,21 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr,
                                               vec_ng::append(
                                                   vec!(lldiscr),
                                                   vals).as_slice());
-            C_struct(vec_ng::append(
+            C_struct(ccx, vec_ng::append(
                         contents,
-                        &[padding(max_sz - case.size)]).as_slice(),
+                        &[padding(ccx, max_sz - case.size)]).as_slice(),
                      false)
         }
         Univariant(ref st, _dro) => {
             assert!(discr == 0);
             let contents = build_const_struct(ccx, st, vals);
-            C_struct(contents.as_slice(), st.packed)
+            C_struct(ccx, contents.as_slice(), st.packed)
         }
         NullablePointer{ nonnull: ref nonnull, nndiscr, .. } => {
             if discr == nndiscr {
-                C_struct(build_const_struct(ccx,
-                                            nonnull,
-                                            vals.as_slice()).as_slice(),
+                C_struct(ccx, build_const_struct(ccx,
+                                                 nonnull,
+                                                 vals).as_slice(),
                          false)
             } else {
                 let vals = nonnull.fields.map(|&ty| {
@@ -783,9 +783,9 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr,
                     // field; see #8506.
                     C_null(type_of::sizing_type_of(ccx, ty))
                 }).move_iter().collect::<Vec<ValueRef> >();
-                C_struct(build_const_struct(ccx,
-                                            nonnull,
-                                            vals.as_slice()).as_slice(),
+                C_struct(ccx, build_const_struct(ccx,
+                                                 nonnull,
+                                                 vals.as_slice()).as_slice(),
                          false)
             }
         }
@@ -817,7 +817,7 @@ fn build_const_struct(ccx: &CrateContext, st: &Struct, vals: &[ValueRef])
         let target_offset = roundup(offset, type_align);
         offset = roundup(offset, val_align);
         if offset != target_offset {
-            cfields.push(padding(target_offset - offset));
+            cfields.push(padding(ccx, target_offset - offset));
             offset = target_offset;
         }
         assert!(!is_undef(vals[i]));
@@ -828,8 +828,8 @@ fn build_const_struct(ccx: &CrateContext, st: &Struct, vals: &[ValueRef])
     return cfields;
 }
 
-fn padding(size: u64) -> ValueRef {
-    C_undef(Type::array(&Type::i8(), size))
+fn padding(ccx: &CrateContext, size: u64) -> ValueRef {
+    C_undef(Type::array(&Type::i8(ccx), size))
 }
 
 // FIXME this utility routine should be somewhere more general
@@ -874,7 +874,7 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
 pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
                        _discr: Disr, ix: uint) -> ValueRef {
     match *r {
-        CEnum(..) => ccx.sess.bug("element access in C-like enum const"),
+        CEnum(..) => ccx.sess().bug("element access in C-like enum const"),
         Univariant(..) => const_struct_field(ccx, val, ix),
         General(..) => const_struct_field(ccx, val, ix + 1),
         NullablePointer{ .. } => const_struct_field(ccx, val, ix)
diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs
index 1a398a73771..7b04b519101 100644
--- a/src/librustc/middle/trans/asm.rs
+++ b/src/librustc/middle/trans/asm.rs
@@ -86,11 +86,11 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
 
     // Depending on how many outputs we have, the return type is different
     let output_type = if num_outputs == 0 {
-        Type::void()
+        Type::void(bcx.ccx())
     } else if num_outputs == 1 {
         *output_types.get(0)
     } else {
-        Type::struct_(output_types.as_slice(), false)
+        Type::struct_(bcx.ccx(), output_types.as_slice(), false)
     };
 
     let dialect = match ia.dialect {
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index a2ee57d6df1..bcf0b5d5f64 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -34,7 +34,6 @@ use driver::driver::{CrateAnalysis, CrateTranslation};
 use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
 use lib::llvm::{llvm, Vector};
 use lib;
-use metadata::common::LinkMeta;
 use metadata::{csearch, encoder};
 use middle::astencode;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
@@ -73,7 +72,6 @@ use util::sha2::Sha256;
 use util::nodemap::NodeMap;
 
 use arena::TypedArena;
-use collections::HashMap;
 use std::c_str::ToCStr;
 use std::cell::{Cell, RefCell};
 use std::libc::c_uint;
@@ -93,8 +91,6 @@ use syntax::{ast, ast_util, ast_map};
 
 use time;
 
-pub use middle::trans::context::task_llcx;
-
 local_data_key!(task_local_insn_key: Vec<&'static str> )
 
 pub fn with_insn_ctxt(blk: |&[&'static str]|) {
@@ -135,16 +131,16 @@ pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
     _InsnCtxt { _x: () }
 }
 
-pub struct StatRecorder {
-    ccx: @CrateContext,
+pub struct StatRecorder<'a> {
+    ccx: &'a CrateContext,
     name: Option<~str>,
     start: u64,
     istart: uint,
 }
 
-impl StatRecorder {
-    pub fn new(ccx: @CrateContext, name: ~str) -> StatRecorder {
-        let start = if ccx.sess.trans_stats() {
+impl<'a> StatRecorder<'a> {
+    pub fn new(ccx: &'a CrateContext, name: ~str) -> StatRecorder<'a> {
+        let start = if ccx.sess().trans_stats() {
             time::precise_time_ns()
         } else {
             0
@@ -160,9 +156,9 @@ impl StatRecorder {
 }
 
 #[unsafe_destructor]
-impl Drop for StatRecorder {
+impl<'a> Drop for StatRecorder<'a> {
     fn drop(&mut self) {
-        if self.ccx.sess.trans_stats() {
+        if self.ccx.sess().trans_stats() {
             let end = time::precise_time_ns();
             let elapsed = ((end - self.start) / 1_000_000) as uint;
             let iend = self.ccx.stats.n_llvm_insns.get();
@@ -246,7 +242,7 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
     }
 
     let f = decl_rust_fn(ccx, false, inputs, output, name);
-    csearch::get_item_attrs(ccx.tcx.cstore, did, |meta_items| {
+    csearch::get_item_attrs(&ccx.sess().cstore, did, |meta_items| {
         set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).to_owned_vec(), f)
     });
 
@@ -355,8 +351,8 @@ pub fn malloc_raw_dyn<'a>(
         match li.require(it) {
             Ok(id) => id,
             Err(s) => {
-                bcx.tcx().sess.fatal(format!("allocation of `{}` {}",
-                                          bcx.ty_to_str(t), s));
+                bcx.sess().fatal(format!("allocation of `{}` {}",
+                                         bcx.ty_to_str(t), s));
             }
         }
     }
@@ -393,7 +389,11 @@ pub fn malloc_raw_dyn<'a>(
         let r = callee::trans_lang_call(
             bcx,
             langcall,
-            [PointerCast(bcx, drop_glue, Type::glue_fn(Type::i8p()).ptr_to()), size, llalign],
+            [
+                PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()),
+                size,
+                llalign
+            ],
             None);
         rslt(r.bcx, PointerCast(r.bcx, r.val, llty))
     }
@@ -522,13 +522,13 @@ pub fn set_no_split_stack(f: ValueRef) {
 pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: ~str) {
     let mut all_llvm_symbols = ccx.all_llvm_symbols.borrow_mut();
     if all_llvm_symbols.get().contains(&sym) {
-        ccx.sess.bug(~"duplicate LLVM symbol: " + sym);
+        ccx.sess().bug(~"duplicate LLVM symbol: " + sym);
     }
     all_llvm_symbols.get().insert(sym);
 }
 
 
-pub fn get_res_dtor(ccx: @CrateContext,
+pub fn get_res_dtor(ccx: &CrateContext,
                     did: ast::DefId,
                     parent_id: ast::DefId,
                     substs: &[ty::t])
@@ -547,15 +547,15 @@ pub fn get_res_dtor(ccx: @CrateContext,
             tps: Vec::from_slice(substs),
         };
 
-        let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx, did.node, &tsubsts);
+        let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, &tsubsts);
         let (val, _) = monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None);
 
         val
     } else if did.krate == ast::LOCAL_CRATE {
         get_item_val(ccx, did.node)
     } else {
-        let tcx = ccx.tcx;
-        let name = csearch::get_symbol(ccx.sess.cstore, did);
+        let tcx = ccx.tcx();
+        let name = csearch::get_symbol(&ccx.sess().cstore, did);
         let class_ty = ty::subst_tps(tcx,
                                      substs,
                                      None,
@@ -572,7 +572,7 @@ pub fn get_res_dtor(ccx: @CrateContext,
 
 // Structural comparison: a rather involved form of glue.
 pub fn maybe_name_value(cx: &CrateContext, v: ValueRef, s: &str) {
-    if cx.sess.opts.cg.save_temps {
+    if cx.sess().opts.cg.save_temps {
         s.with_c_str(|buf| {
             unsafe {
                 llvm::LLVMSetValueName(v, buf)
@@ -617,16 +617,15 @@ pub fn compare_scalar_values<'a>(
                              -> ValueRef {
     let _icx = push_ctxt("compare_scalar_values");
     fn die(cx: &Block) -> ! {
-        cx.tcx().sess.bug("compare_scalar_values: must be a\
-                           comparison operator");
+        cx.sess().bug("compare_scalar_values: must be a comparison operator");
     }
     match nt {
       nil_type => {
         // We don't need to do actual comparisons for nil.
         // () == () holds but () < () does not.
         match op {
-          ast::BiEq | ast::BiLe | ast::BiGe => return C_i1(true),
-          ast::BiNe | ast::BiLt | ast::BiGt => return C_i1(false),
+          ast::BiEq | ast::BiLe | ast::BiGe => return C_i1(cx.ccx(), true),
+          ast::BiNe | ast::BiLt | ast::BiGt => return C_i1(cx.ccx(), false),
           // refinements would be nice
           _ => die(cx)
         }
@@ -745,7 +744,7 @@ pub fn iter_structural_ty<'r,
           let ccx = fcx.ccx;
 
           let repr = adt::represent_type(ccx, t);
-          let variants = ty::enum_variants(ccx.tcx, tid);
+          let variants = ty::enum_variants(ccx.tcx(), tid);
           let n_variants = (*variants).len();
 
           // NB: we must hit the discriminant first so that structural
@@ -772,8 +771,8 @@ pub fn iter_structural_ty<'r,
                           _match::single_result(r) => {
                               AddCase(llswitch, r.val, variant_cx.llbb)
                           }
-                          _ => ccx.sess.unimpl("value from adt::trans_case \
-                                                in iter_structural_ty")
+                          _ => ccx.sess().unimpl("value from adt::trans_case \
+                                                  in iter_structural_ty")
                       }
                       let variant_cx =
                           iter_variant(variant_cx,
@@ -786,8 +785,8 @@ pub fn iter_structural_ty<'r,
                   }
                   cx = next_cx;
               }
-              _ => ccx.sess.unimpl("value from adt::trans_switch \
-                                    in iter_structural_ty")
+              _ => ccx.sess().unimpl("value from adt::trans_switch \
+                                      in iter_structural_ty")
           }
       }
       _ => cx.sess().unimpl("type in iter_structural_ty")
@@ -865,8 +864,8 @@ pub fn fail_if_zero<'a>(
         ICmp(cx, lib::llvm::IntEQ, rhs, zero)
       }
       _ => {
-        cx.tcx().sess.bug(~"fail-if-zero on unexpected type: " +
-                          ty_to_str(cx.ccx().tcx, rhs_t));
+        cx.sess().bug(~"fail-if-zero on unexpected type: " +
+                      ty_to_str(cx.tcx(), rhs_t));
       }
     };
     with_cond(cx, is_zero, |bcx| {
@@ -875,11 +874,11 @@ pub fn fail_if_zero<'a>(
 }
 
 pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> ValueRef {
-    let name = csearch::get_symbol(ccx.sess.cstore, did);
+    let name = csearch::get_symbol(&ccx.sess().cstore, did);
     match ty::get(t).sty {
         ty::ty_bare_fn(ref fn_ty) => {
-            match fn_ty.abis.for_target(ccx.sess.targ_cfg.os,
-                                        ccx.sess.targ_cfg.arch) {
+            match fn_ty.abis.for_target(ccx.sess().targ_cfg.os,
+                                        ccx.sess().targ_cfg.arch) {
                 Some(Rust) | Some(RustIntrinsic) => {
                     get_extern_rust_fn(ccx,
                                        fn_ty.sig.inputs.as_slice(),
@@ -921,7 +920,7 @@ pub fn invoke<'a>(
               -> (ValueRef, &'a Block<'a>) {
     let _icx = push_ctxt("invoke_");
     if bcx.unreachable.get() {
-        return (C_null(Type::i8()), bcx);
+        return (C_null(Type::i8(bcx.ccx())), bcx);
     }
 
     match bcx.opt_node_id {
@@ -970,7 +969,7 @@ pub fn invoke<'a>(
 }
 
 pub fn need_invoke(bcx: &Block) -> bool {
-    if bcx.ccx().sess.no_landing_pads() {
+    if bcx.sess().no_landing_pads() {
         return false;
     }
 
@@ -984,7 +983,7 @@ pub fn need_invoke(bcx: &Block) -> bool {
 
 pub fn do_spill(bcx: &Block, v: ValueRef, t: ty::t) -> ValueRef {
     if ty::type_is_bot(t) {
-        return C_null(Type::i8p());
+        return C_null(Type::i8p(bcx.ccx()));
     }
     let llptr = alloc_ty(bcx, t, "");
     Store(bcx, v, llptr);
@@ -1081,16 +1080,16 @@ pub fn with_cond<'a>(
 pub fn call_memcpy(cx: &Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
     let _icx = push_ctxt("call_memcpy");
     let ccx = cx.ccx();
-    let key = match ccx.sess.targ_cfg.arch {
+    let key = match ccx.sess().targ_cfg.arch {
         X86 | Arm | Mips => "llvm.memcpy.p0i8.p0i8.i32",
         X86_64 => "llvm.memcpy.p0i8.p0i8.i64"
     };
     let memcpy = ccx.intrinsics.get_copy(&key);
-    let src_ptr = PointerCast(cx, src, Type::i8p());
-    let dst_ptr = PointerCast(cx, dst, Type::i8p());
+    let src_ptr = PointerCast(cx, src, Type::i8p(ccx));
+    let dst_ptr = PointerCast(cx, dst, Type::i8p(ccx));
     let size = IntCast(cx, n_bytes, ccx.int_type);
-    let align = C_i32(align as i32);
-    let volatile = C_i1(false);
+    let align = C_i32(ccx, align as i32);
+    let volatile = C_i1(ccx, false);
     Call(cx, memcpy, [dst_ptr, src_ptr, size, align, volatile], []);
 }
 
@@ -1125,17 +1124,17 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) {
     let _icx = push_ctxt("memzero");
     let ccx = b.ccx;
 
-    let intrinsic_key = match ccx.sess.targ_cfg.arch {
+    let intrinsic_key = match ccx.sess().targ_cfg.arch {
         X86 | Arm | Mips => "llvm.memset.p0i8.i32",
         X86_64 => "llvm.memset.p0i8.i64"
     };
 
     let llintrinsicfn = ccx.intrinsics.get_copy(&intrinsic_key);
-    let llptr = b.pointercast(llptr, Type::i8().ptr_to());
-    let llzeroval = C_u8(0);
+    let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to());
+    let llzeroval = C_u8(ccx, 0);
     let size = machine::llsize_of(ccx, ty);
-    let align = C_i32(llalign_of_min(ccx, ty) as i32);
-    let volatile = C_i1(false);
+    let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32);
+    let volatile = C_i1(ccx, false);
     b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], []);
 }
 
@@ -1184,24 +1183,6 @@ pub struct BasicBlocks {
     sa: BasicBlockRef,
 }
 
-pub fn mk_staticallocas_basic_block(llfn: ValueRef) -> BasicBlockRef {
-    unsafe {
-        let cx = task_llcx();
-        "static_allocas".with_c_str(|buf| {
-            llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
-        })
-    }
-}
-
-pub fn mk_return_basic_block(llfn: ValueRef) -> BasicBlockRef {
-    unsafe {
-        let cx = task_llcx();
-        "return".with_c_str(|buf| {
-            llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)
-        })
-    }
-}
-
 // Creates and returns space for, or returns the argument representing, the
 // slot where the return value of the function must go.
 pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
@@ -1226,7 +1207,7 @@ pub fn make_return_pointer(fcx: &FunctionContext, output_type: ty::t)
 //
 // Be warned! You must call `init_function` before doing anything with the
 // returned function context.
-pub fn new_fn_ctxt<'a>(ccx: @CrateContext,
+pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
                        llfndecl: ValueRef,
                        id: ast::NodeId,
                        has_env: bool,
@@ -1239,12 +1220,12 @@ pub fn new_fn_ctxt<'a>(ccx: @CrateContext,
 
     debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
            if id == -1 { ~"" } else { ccx.tcx.map.path_to_str(id) },
-           id, param_substs.repr(ccx.tcx));
+           id, param_substs.repr(ccx.tcx()));
 
     let substd_output_type = match param_substs {
         None => output_type,
         Some(substs) => {
-            ty::subst_tps(ccx.tcx,
+            ty::subst_tps(ccx.tcx(),
                           substs.tys.as_slice(),
                           substs.self_ty,
                           output_type)
@@ -1297,14 +1278,14 @@ pub fn init_function<'a>(
     // Use a dummy instruction as the insertion point for all allocas.
     // This is later removed in FunctionContext::cleanup.
     fcx.alloca_insert_pt.set(Some(unsafe {
-        Load(entry_bcx, C_null(Type::i8p()));
+        Load(entry_bcx, C_null(Type::i8p(fcx.ccx)));
         llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
     }));
 
     let substd_output_type = match param_substs {
         None => output_type,
         Some(substs) => {
-            ty::subst_tps(fcx.ccx.tcx,
+            ty::subst_tps(fcx.ccx.tcx(),
                           substs.tys.as_slice(),
                           substs.self_ty,
                           output_type)
@@ -1384,7 +1365,7 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
 
         bcx = _match::store_arg(bcx, args[i].pat, arg_datum, arg_scope_id);
 
-        if fcx.ccx.sess.opts.debuginfo == FullDebugInfo {
+        if fcx.ccx.sess().opts.debuginfo == FullDebugInfo {
             debuginfo::create_argument_metadata(bcx, &args[i]);
         }
     }
@@ -1444,24 +1425,24 @@ pub fn build_return_block(fcx: &FunctionContext, ret_cx: &Block) {
 // trans_closure: Builds an LLVM function out of a source function.
 // If the function closes over its environment a closure will be
 // returned.
-pub fn trans_closure<'a>(ccx: @CrateContext,
-                         decl: &ast::FnDecl,
-                         body: &ast::Block,
-                         llfndecl: ValueRef,
-                         param_substs: Option<@param_substs>,
-                         id: ast::NodeId,
-                         _attributes: &[ast::Attribute],
-                         output_type: ty::t,
-                         maybe_load_env: <'b> |&'b Block<'b>| -> &'b Block<'b>) {
+pub fn trans_closure(ccx: &CrateContext,
+                     decl: &ast::FnDecl,
+                     body: &ast::Block,
+                     llfndecl: ValueRef,
+                     param_substs: Option<@param_substs>,
+                     id: ast::NodeId,
+                     _attributes: &[ast::Attribute],
+                     output_type: ty::t,
+                     maybe_load_env: <'a> |&'a Block<'a>| -> &'a Block<'a>) {
     ccx.stats.n_closures.set(ccx.stats.n_closures.get() + 1);
 
     let _icx = push_ctxt("trans_closure");
     set_uwtable(llfndecl);
 
     debug!("trans_closure(..., param_substs={})",
-           param_substs.repr(ccx.tcx));
+           param_substs.repr(ccx.tcx()));
 
-    let has_env = match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
+    let has_env = match ty::get(ty::node_id_to_type(ccx.tcx(), id)).sty {
         ty::ty_closure(_) => true,
         _ => false
     };
@@ -1544,7 +1525,7 @@ pub fn trans_closure<'a>(ccx: @CrateContext,
 
 // trans_fn: creates an LLVM function corresponding to a source language
 // function.
-pub fn trans_fn(ccx: @CrateContext,
+pub fn trans_fn(ccx: &CrateContext,
                 decl: &ast::FnDecl,
                 body: &ast::Block,
                 llfndecl: ValueRef,
@@ -1552,14 +1533,14 @@ pub fn trans_fn(ccx: @CrateContext,
                 id: ast::NodeId,
                 attrs: &[ast::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id));
-    debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx));
+    debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
     let _icx = push_ctxt("trans_fn");
-    let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
+    let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), id));
     trans_closure(ccx, decl, body, llfndecl,
                   param_substs, id, attrs, output_type, |bcx| bcx);
 }
 
-pub fn trans_enum_variant(ccx: @CrateContext,
+pub fn trans_enum_variant(ccx: &CrateContext,
                           _enum_id: ast::NodeId,
                           variant: &ast::Variant,
                           _args: &[ast::VariantArg],
@@ -1576,7 +1557,7 @@ pub fn trans_enum_variant(ccx: @CrateContext,
         llfndecl);
 }
 
-pub fn trans_tuple_struct(ccx: @CrateContext,
+pub fn trans_tuple_struct(ccx: &CrateContext,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
                           param_substs: Option<@param_substs>,
@@ -1591,7 +1572,7 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
         llfndecl);
 }
 
-fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
+fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
                                            ctor_id: ast::NodeId,
                                            disr: ty::Disr,
                                            param_substs: Option<@param_substs>,
@@ -1608,17 +1589,17 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
         }
     };
 
-    let ctor_ty = ty::subst_tps(ccx.tcx,
+    let ctor_ty = ty::subst_tps(ccx.tcx(),
                                 ty_param_substs,
                                 None,
-                                ty::node_id_to_type(ccx.tcx, ctor_id));
+                                ty::node_id_to_type(ccx.tcx(), ctor_id));
 
     let result_ty = match ty::get(ctor_ty).sty {
         ty::ty_bare_fn(ref bft) => bft.sig.output,
-        _ => ccx.sess.bug(
+        _ => ccx.sess().bug(
             format!("trans_enum_variant_or_tuple_like_struct: \
                   unexpected ctor return type {}",
-                 ty_to_str(ccx.tcx, ctor_ty)))
+                 ty_to_str(ccx.tcx(), ctor_ty)))
     };
 
     let arena = TypedArena::new();
@@ -1648,8 +1629,8 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
     finish_fn(&fcx, bcx);
 }
 
-pub fn trans_enum_def(ccx: @CrateContext, enum_definition: &ast::EnumDef,
-                      id: ast::NodeId, vi: @Vec<@ty::VariantInfo> ,
+pub fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
+                      id: ast::NodeId, vi: @Vec<@ty::VariantInfo>,
                       i: &mut uint) {
     for &variant in enum_definition.variants.iter() {
         let disr_val = vi.get(*i).disr_val;
@@ -1671,17 +1652,17 @@ pub fn trans_enum_def(ccx: @CrateContext, enum_definition: &ast::EnumDef,
     }
 }
 
-pub struct TransItemVisitor {
-    ccx: @CrateContext,
+pub struct TransItemVisitor<'a> {
+    ccx: &'a CrateContext,
 }
 
-impl Visitor<()> for TransItemVisitor {
+impl<'a> Visitor<()> for TransItemVisitor<'a> {
     fn visit_item(&mut self, i: &ast::Item, _:()) {
         trans_item(self.ccx, i);
     }
 }
 
-pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
+pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
     let _icx = push_ctxt("trans_item");
     match item.node {
       ast::ItemFn(decl, purity, _abis, ref generics, body) => {
@@ -1713,7 +1694,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
       }
       ast::ItemEnum(ref enum_definition, ref generics) => {
         if !generics.is_type_parameterized() {
-            let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
+            let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
             let mut i = 0;
             trans_enum_def(ccx, enum_definition, item.id, vi, &mut i);
         }
@@ -1724,16 +1705,16 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
           // because we need to get the value of the bool out of LLVM
           if attr::contains_name(item.attrs.as_slice(), "static_assert") {
               if m == ast::MutMutable {
-                  ccx.sess.span_fatal(expr.span,
-                                      "cannot have static_assert on a mutable \
-                                       static");
+                  ccx.sess().span_fatal(expr.span,
+                                        "cannot have static_assert on a mutable \
+                                         static");
               }
 
               let const_values = ccx.const_values.borrow();
               let v = const_values.get().get_copy(&item.id);
               unsafe {
                   if !(llvm::LLVMConstIntGetZExtValue(v) != 0) {
-                      ccx.sess.span_fatal(expr.span, "static assertion failed");
+                      ccx.sess().span_fatal(expr.span, "static assertion failed");
                   }
               }
           }
@@ -1758,7 +1739,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
     }
 }
 
-pub fn trans_struct_def(ccx: @CrateContext, struct_def: @ast::StructDef) {
+pub fn trans_struct_def(ccx: &CrateContext, struct_def: @ast::StructDef) {
     // If this is a tuple-like struct, translate the constructor.
     match struct_def.ctor_id {
         // We only need to translate a constructor if there are fields;
@@ -1777,33 +1758,27 @@ pub fn trans_struct_def(ccx: @CrateContext, struct_def: @ast::StructDef) {
 // separate modules in the compiled program.  That's because modules exist
 // only as a convenience for humans working with the code, to organize names
 // and control visibility.
-pub fn trans_mod(ccx: @CrateContext, m: &ast::Mod) {
+pub fn trans_mod(ccx: &CrateContext, m: &ast::Mod) {
     let _icx = push_ctxt("trans_mod");
     for item in m.items.iter() {
         trans_item(ccx, *item);
     }
 }
 
-fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId,
+fn finish_register_fn(ccx: &CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId,
                       llfn: ValueRef) {
-    {
-        let mut item_symbols = ccx.item_symbols.borrow_mut();
-        item_symbols.get().insert(node_id, sym);
-    }
+    ccx.item_symbols.borrow_mut().get().insert(node_id, sym);
 
-    {
-        let reachable = ccx.reachable.borrow();
-        if !reachable.get().contains(&node_id) {
-            lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
-        }
+    if !ccx.reachable.contains(&node_id) {
+        lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     }
 
-    if is_entry_fn(&ccx.sess, node_id) && !ccx.sess.building_library.get() {
+    if is_entry_fn(ccx.sess(), node_id) && !ccx.sess().building_library.get() {
         create_entry_wrapper(ccx, sp, llfn);
     }
 }
 
-fn register_fn(ccx: @CrateContext,
+fn register_fn(ccx: &CrateContext,
                sp: Span,
                sym: ~str,
                node_id: ast::NodeId,
@@ -1827,7 +1802,7 @@ fn register_fn(ccx: @CrateContext,
 }
 
 // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
-pub fn register_fn_llvmty(ccx: @CrateContext,
+pub fn register_fn_llvmty(ccx: &CrateContext,
                           sp: Span,
                           sym: ~str,
                           node_id: ast::NodeId,
@@ -1850,10 +1825,10 @@ pub fn is_entry_fn(sess: &Session, node_id: ast::NodeId) -> bool {
 
 // Create a _rust_main(args: ~[str]) function which will be called from the
 // runtime rust_start function
-pub fn create_entry_wrapper(ccx: @CrateContext,
+pub fn create_entry_wrapper(ccx: &CrateContext,
                            _sp: Span,
                            main_llfn: ValueRef) {
-    let et = ccx.sess.entry_type.get().unwrap();
+    let et = ccx.sess().entry_type.get().unwrap();
     match et {
         session::EntryMain => {
             create_entry_fn(ccx, main_llfn, true);
@@ -1862,10 +1837,10 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
         session::EntryNone => {}    // Do nothing.
     }
 
-    fn create_entry_fn(ccx: @CrateContext,
+    fn create_entry_fn(ccx: &CrateContext,
                        rust_main: ValueRef,
                        use_start_lang_item: bool) {
-        let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()],
+        let llfty = Type::func([ccx.int_type, Type::i8p(ccx).ptr_to()],
                                &ccx.int_type);
 
         let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
@@ -1881,19 +1856,19 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
             let (start_fn, args) = if use_start_lang_item {
                 let start_def_id = match ccx.tcx.lang_items.require(StartFnLangItem) {
                     Ok(id) => id,
-                    Err(s) => { ccx.tcx.sess.fatal(s); }
+                    Err(s) => { ccx.sess().fatal(s); }
                 };
                 let start_fn = if start_def_id.krate == ast::LOCAL_CRATE {
                     get_item_val(ccx, start_def_id.node)
                 } else {
-                    let start_fn_type = csearch::get_type(ccx.tcx,
+                    let start_fn_type = csearch::get_type(ccx.tcx(),
                                                           start_def_id).ty;
                     trans_external_path(ccx, start_def_id, start_fn_type)
                 };
 
                 let args = {
                     let opaque_rust_main = "rust_main".with_c_str(|buf| {
-                        llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p().to_ref(), buf)
+                        llvm::LLVMBuildPointerCast(bld, rust_main, Type::i8p(ccx).to_ref(), buf)
                     });
 
                     vec!(
@@ -1942,7 +1917,7 @@ fn exported_name(ccx: &CrateContext, id: ast::NodeId,
     }
 }
 
-pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
+pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
     debug!("get_item_val(id=`{:?}`)", id);
 
     let val = {
@@ -1957,7 +1932,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
             let item = ccx.tcx.map.get(id);
             let val = match item {
                 ast_map::NodeItem(i) => {
-                    let ty = ty::node_id_to_type(ccx.tcx, i.id);
+                    let ty = ty::node_id_to_type(ccx.tcx(), i.id);
                     let sym = exported_name(ccx, id, ty, i.attrs.as_slice());
 
                     let v = match i.node {
@@ -1973,7 +1948,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                                 match external_srcs.get().find(&i.id) {
                                     Some(&did) => {
                                         debug!("but found in other crate...");
-                                        (csearch::get_symbol(ccx.sess.cstore,
+                                        (csearch::get_symbol(&ccx.sess().cstore,
                                                              did), false)
                                     }
                                     None => (sym, true)
@@ -1996,27 +1971,17 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                                     llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
                                 });
 
-                                {
-                                    let reachable = ccx.reachable.borrow();
-                                    if !reachable.get().contains(&id) {
-                                        lib::llvm::SetLinkage(
-                                            g,
-                                            lib::llvm::InternalLinkage);
-                                    }
+                                if !ccx.reachable.contains(&id) {
+                                    lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
                                 }
 
                                 // Apply the `unnamed_addr` attribute if
                                 // requested
                                 if attr::contains_name(i.attrs.as_slice(),
-                                                       "address_insignificant"){
-                                    {
-                                        let reachable =
-                                            ccx.reachable.borrow();
-                                        if reachable.get().contains(&id) {
-                                            ccx.sess.span_bug(i.span,
-                                                "insignificant static is \
-                                                 reachable");
-                                        }
+                                                       "address_insignificant") {
+                                    if ccx.reachable.contains(&id) {
+                                        ccx.sess().span_bug(i.span,
+                                            "insignificant static is reachable");
                                     }
                                     lib::llvm::SetUnnamedAddr(g, true);
 
@@ -2093,8 +2058,8 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                     debug!("get_item_val(): processing a NodeTraitMethod");
                     match *trait_method {
                         ast::Required(_) => {
-                            ccx.sess.bug("unexpected variant: required trait method in \
-                                         get_item_val()");
+                            ccx.sess().bug("unexpected variant: required trait method in \
+                                           get_item_val()");
                         }
                         ast::Provided(m) => {
                             register_method(ccx, id, m)
@@ -2125,7 +2090,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                     match v.node.kind {
                         ast::TupleVariantKind(ref args) => {
                             assert!(args.len() != 0u);
-                            let ty = ty::node_id_to_type(ccx.tcx, id);
+                            let ty = ty::node_id_to_type(ccx.tcx(), id);
                             let parent = ccx.tcx.map.get_parent(id);
                             let enm = ccx.tcx.map.expect_item(parent);
                             let sym = exported_name(ccx,
@@ -2152,13 +2117,13 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                     // Only register the constructor if this is a tuple-like struct.
                     match struct_def.ctor_id {
                         None => {
-                            ccx.tcx.sess.bug("attempt to register a constructor of \
-                                              a non-tuple-like struct")
+                            ccx.sess().bug("attempt to register a constructor of \
+                                            a non-tuple-like struct")
                         }
                         Some(ctor_id) => {
                             let parent = ccx.tcx.map.get_parent(id);
                             let struct_item = ccx.tcx.map.expect_item(parent);
-                            let ty = ty::node_id_to_type(ccx.tcx, ctor_id);
+                            let ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
                             let sym = exported_name(ccx,
                                                     id,
                                                     ty,
@@ -2173,19 +2138,16 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
                 }
 
                 ref variant => {
-                    ccx.sess.bug(format!("get_item_val(): unexpected variant: {:?}",
-                                 variant))
+                    ccx.sess().bug(format!("get_item_val(): unexpected variant: {:?}",
+                                   variant))
                 }
             };
 
             // foreign items (extern fns and extern statics) don't have internal
             // linkage b/c that doesn't quite make sense. Otherwise items can
             // have internal linkage if they're not reachable.
-            {
-                let reachable = ccx.reachable.borrow();
-                if !foreign && !reachable.get().contains(&id) {
-                    lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage);
-                }
+            if !foreign && !ccx.reachable.contains(&id) {
+                lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage);
             }
 
             let mut item_vals = ccx.item_vals.borrow_mut();
@@ -2195,9 +2157,9 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
     }
 }
 
-fn register_method(ccx: @CrateContext, id: ast::NodeId,
+fn register_method(ccx: &CrateContext, id: ast::NodeId,
                    m: &ast::Method) -> ValueRef {
-    let mty = ty::node_id_to_type(ccx.tcx, id);
+    let mty = ty::node_id_to_type(ccx.tcx(), id);
 
     let sym = exported_name(ccx, id, mty, m.attrs.as_slice());
 
@@ -2217,184 +2179,166 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
     }
 }
 
-macro_rules! ifn (
-    ($intrinsics:ident, $name:expr, $args:expr, $ret:expr) => ({
-        let name = $name;
-        // HACK(eddyb) dummy output type, shouln't affect anything.
-        let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret), ty::mk_nil());
-        $intrinsics.insert(name, f);
-    })
-)
-
-pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> {
-    let i8p = Type::i8p();
-    let mut intrinsics = HashMap::new();
-
-    ifn!(intrinsics, "llvm.memcpy.p0i8.p0i8.i32",
-         [i8p, i8p, Type::i32(), Type::i32(), Type::i1()], Type::void());
-    ifn!(intrinsics, "llvm.memcpy.p0i8.p0i8.i64",
-         [i8p, i8p, Type::i64(), Type::i32(), Type::i1()], Type::void());
-    ifn!(intrinsics, "llvm.memmove.p0i8.p0i8.i32",
-         [i8p, i8p, Type::i32(), Type::i32(), Type::i1()], Type::void());
-    ifn!(intrinsics, "llvm.memmove.p0i8.p0i8.i64",
-         [i8p, i8p, Type::i64(), Type::i32(), Type::i1()], Type::void());
-    ifn!(intrinsics, "llvm.memset.p0i8.i32",
-         [i8p, Type::i8(), Type::i32(), Type::i32(), Type::i1()], Type::void());
-    ifn!(intrinsics, "llvm.memset.p0i8.i64",
-         [i8p, Type::i8(), Type::i64(), Type::i32(), Type::i1()], Type::void());
-
-    ifn!(intrinsics, "llvm.trap", [], Type::void());
-    ifn!(intrinsics, "llvm.debugtrap", [], Type::void());
-    ifn!(intrinsics, "llvm.frameaddress", [Type::i32()], i8p);
-
-    ifn!(intrinsics, "llvm.powi.f32", [Type::f32(), Type::i32()], Type::f32());
-    ifn!(intrinsics, "llvm.powi.f64", [Type::f64(), Type::i32()], Type::f64());
-    ifn!(intrinsics, "llvm.pow.f32",  [Type::f32(), Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.pow.f64",  [Type::f64(), Type::f64()], Type::f64());
-
-    ifn!(intrinsics, "llvm.sqrt.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.sqrt.f64", [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.sin.f32",  [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.sin.f64",  [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.cos.f32",  [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.cos.f64",  [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.exp.f32",  [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.exp.f64",  [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.exp2.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.exp2.f64", [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.log.f32",  [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.log.f64",  [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.log10.f32",[Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.log10.f64",[Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.log2.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.log2.f64", [Type::f64()], Type::f64());
-
-    ifn!(intrinsics, "llvm.fma.f32",  [Type::f32(), Type::f32(), Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.fma.f64",  [Type::f64(), Type::f64(), Type::f64()], Type::f64());
-
-    ifn!(intrinsics, "llvm.fabs.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.fabs.f64", [Type::f64()], Type::f64());
-
-    ifn!(intrinsics, "llvm.floor.f32",[Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.floor.f64",[Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.ceil.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.ceil.f64", [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.trunc.f32",[Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.trunc.f64",[Type::f64()], Type::f64());
-
-    ifn!(intrinsics, "llvm.rint.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.rint.f64", [Type::f64()], Type::f64());
-    ifn!(intrinsics, "llvm.nearbyint.f32", [Type::f32()], Type::f32());
-    ifn!(intrinsics, "llvm.nearbyint.f64", [Type::f64()], Type::f64());
-
-    ifn!(intrinsics, "llvm.ctpop.i8", [Type::i8()], Type::i8());
-    ifn!(intrinsics, "llvm.ctpop.i16",[Type::i16()], Type::i16());
-    ifn!(intrinsics, "llvm.ctpop.i32",[Type::i32()], Type::i32());
-    ifn!(intrinsics, "llvm.ctpop.i64",[Type::i64()], Type::i64());
-
-    ifn!(intrinsics, "llvm.ctlz.i8",  [Type::i8() , Type::i1()], Type::i8());
-    ifn!(intrinsics, "llvm.ctlz.i16", [Type::i16(), Type::i1()], Type::i16());
-    ifn!(intrinsics, "llvm.ctlz.i32", [Type::i32(), Type::i1()], Type::i32());
-    ifn!(intrinsics, "llvm.ctlz.i64", [Type::i64(), Type::i1()], Type::i64());
-
-    ifn!(intrinsics, "llvm.cttz.i8",  [Type::i8() , Type::i1()], Type::i8());
-    ifn!(intrinsics, "llvm.cttz.i16", [Type::i16(), Type::i1()], Type::i16());
-    ifn!(intrinsics, "llvm.cttz.i32", [Type::i32(), Type::i1()], Type::i32());
-    ifn!(intrinsics, "llvm.cttz.i64", [Type::i64(), Type::i1()], Type::i64());
-
-    ifn!(intrinsics, "llvm.bswap.i16",[Type::i16()], Type::i16());
-    ifn!(intrinsics, "llvm.bswap.i32",[Type::i32()], Type::i32());
-    ifn!(intrinsics, "llvm.bswap.i64",[Type::i64()], Type::i64());
-
-    ifn!(intrinsics, "llvm.sadd.with.overflow.i8",
-        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.sadd.with.overflow.i16",
-        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.sadd.with.overflow.i32",
-        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.sadd.with.overflow.i64",
-        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
-
-    ifn!(intrinsics, "llvm.uadd.with.overflow.i8",
-        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.uadd.with.overflow.i16",
-        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.uadd.with.overflow.i32",
-        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.uadd.with.overflow.i64",
-        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
-
-    ifn!(intrinsics, "llvm.ssub.with.overflow.i8",
-        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.ssub.with.overflow.i16",
-        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.ssub.with.overflow.i32",
-        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.ssub.with.overflow.i64",
-        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
-
-    ifn!(intrinsics, "llvm.usub.with.overflow.i8",
-        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.usub.with.overflow.i16",
-        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.usub.with.overflow.i32",
-        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.usub.with.overflow.i64",
-        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
-
-    ifn!(intrinsics, "llvm.smul.with.overflow.i8",
-        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.smul.with.overflow.i16",
-        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.smul.with.overflow.i32",
-        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.smul.with.overflow.i64",
-        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
-
-    ifn!(intrinsics, "llvm.umul.with.overflow.i8",
-        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.umul.with.overflow.i16",
-        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.umul.with.overflow.i32",
-        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
-    ifn!(intrinsics, "llvm.umul.with.overflow.i64",
-        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
-
-    ifn!(intrinsics, "llvm.expect.i1", [Type::i1(), Type::i1()], Type::i1());
+
+pub fn declare_intrinsics(ccx: &mut CrateContext) {
+    macro_rules! ifn (
+        ($name:expr fn() -> $ret:expr) => ({
+            let name = $name;
+            // HACK(eddyb) dummy output type, shouln't affect anything.
+            let f = decl_cdecl_fn(ccx.llmod, name, Type::func([], &$ret), ty::mk_nil());
+            ccx.intrinsics.insert(name, f);
+        });
+        ($name:expr fn($($arg:expr),*) -> $ret:expr) => ({
+            let name = $name;
+            // HACK(eddyb) dummy output type, shouln't affect anything.
+            let f = decl_cdecl_fn(ccx.llmod, name,
+                                  Type::func([$($arg),*], &$ret), ty::mk_nil());
+            ccx.intrinsics.insert(name, f);
+        })
+    )
+    macro_rules! mk_struct (
+        ($($field_ty:expr),*) => (Type::struct_(ccx, [$($field_ty),*], false))
+    )
+
+    let i8p = Type::i8p(ccx);
+    let void = Type::void(ccx);
+    let i1 = Type::i1(ccx);
+    let t_i8 = Type::i8(ccx);
+    let t_i16 = Type::i16(ccx);
+    let t_i32 = Type::i32(ccx);
+    let t_i64 = Type::i64(ccx);
+    let t_f32 = Type::f32(ccx);
+    let t_f64 = Type::f64(ccx);
+
+    ifn!("llvm.memcpy.p0i8.p0i8.i32" fn(i8p, i8p, t_i32, t_i32, i1) -> void);
+    ifn!("llvm.memcpy.p0i8.p0i8.i64" fn(i8p, i8p, t_i64, t_i32, i1) -> void);
+    ifn!("llvm.memmove.p0i8.p0i8.i32" fn(i8p, i8p, t_i32, t_i32, i1) -> void);
+    ifn!("llvm.memmove.p0i8.p0i8.i64" fn(i8p, i8p, t_i64, t_i32, i1) -> void);
+    ifn!("llvm.memset.p0i8.i32" fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
+    ifn!("llvm.memset.p0i8.i64" fn(i8p, t_i8, t_i64, t_i32, i1) -> void);
+
+    ifn!("llvm.trap" fn() -> void);
+    ifn!("llvm.debugtrap" fn() -> void);
+    ifn!("llvm.frameaddress" fn(t_i32) -> i8p);
+
+    ifn!("llvm.powi.f32" fn(t_f32, t_i32) -> t_f32);
+    ifn!("llvm.powi.f64" fn(t_f64, t_i32) -> t_f64);
+    ifn!("llvm.pow.f32" fn(t_f32, t_f32) -> t_f32);
+    ifn!("llvm.pow.f64" fn(t_f64, t_f64) -> t_f64);
+
+    ifn!("llvm.sqrt.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.sqrt.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.sin.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.sin.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.cos.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.cos.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.exp.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.exp.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.exp2.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.exp2.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.log.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.log.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.log10.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.log10.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.log2.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.log2.f64" fn(t_f64) -> t_f64);
+
+    ifn!("llvm.fma.f32" fn(t_f32, t_f32, t_f32) -> t_f32);
+    ifn!("llvm.fma.f64" fn(t_f64, t_f64, t_f64) -> t_f64);
+
+    ifn!("llvm.fabs.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.fabs.f64" fn(t_f64) -> t_f64);
+
+    ifn!("llvm.floor.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.floor.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.ceil.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.ceil.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.trunc.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.trunc.f64" fn(t_f64) -> t_f64);
+
+    ifn!("llvm.rint.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.rint.f64" fn(t_f64) -> t_f64);
+    ifn!("llvm.nearbyint.f32" fn(t_f32) -> t_f32);
+    ifn!("llvm.nearbyint.f64" fn(t_f64) -> t_f64);
+
+    ifn!("llvm.ctpop.i8" fn(t_i8) -> t_i8);
+    ifn!("llvm.ctpop.i16" fn(t_i16) -> t_i16);
+    ifn!("llvm.ctpop.i32" fn(t_i32) -> t_i32);
+    ifn!("llvm.ctpop.i64" fn(t_i64) -> t_i64);
+
+    ifn!("llvm.ctlz.i8" fn(t_i8 , i1) -> t_i8);
+    ifn!("llvm.ctlz.i16" fn(t_i16, i1) -> t_i16);
+    ifn!("llvm.ctlz.i32" fn(t_i32, i1) -> t_i32);
+    ifn!("llvm.ctlz.i64" fn(t_i64, i1) -> t_i64);
+
+    ifn!("llvm.cttz.i8" fn(t_i8 , i1) -> t_i8);
+    ifn!("llvm.cttz.i16" fn(t_i16, i1) -> t_i16);
+    ifn!("llvm.cttz.i32" fn(t_i32, i1) -> t_i32);
+    ifn!("llvm.cttz.i64" fn(t_i64, i1) -> t_i64);
+
+    ifn!("llvm.bswap.i16" fn(t_i16) -> t_i16);
+    ifn!("llvm.bswap.i32" fn(t_i32) -> t_i32);
+    ifn!("llvm.bswap.i64" fn(t_i64) -> t_i64);
+
+    ifn!("llvm.sadd.with.overflow.i8" fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
+    ifn!("llvm.sadd.with.overflow.i16" fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
+    ifn!("llvm.sadd.with.overflow.i32" fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
+    ifn!("llvm.sadd.with.overflow.i64" fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+
+    ifn!("llvm.uadd.with.overflow.i8" fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
+    ifn!("llvm.uadd.with.overflow.i16" fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
+    ifn!("llvm.uadd.with.overflow.i32" fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
+    ifn!("llvm.uadd.with.overflow.i64" fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+
+    ifn!("llvm.ssub.with.overflow.i8" fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
+    ifn!("llvm.ssub.with.overflow.i16" fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
+    ifn!("llvm.ssub.with.overflow.i32" fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
+    ifn!("llvm.ssub.with.overflow.i64" fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+
+    ifn!("llvm.usub.with.overflow.i8" fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
+    ifn!("llvm.usub.with.overflow.i16" fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
+    ifn!("llvm.usub.with.overflow.i32" fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
+    ifn!("llvm.usub.with.overflow.i64" fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+
+    ifn!("llvm.smul.with.overflow.i8" fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
+    ifn!("llvm.smul.with.overflow.i16" fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
+    ifn!("llvm.smul.with.overflow.i32" fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
+    ifn!("llvm.smul.with.overflow.i64" fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+
+    ifn!("llvm.umul.with.overflow.i8" fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
+    ifn!("llvm.umul.with.overflow.i16" fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
+    ifn!("llvm.umul.with.overflow.i32" fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
+    ifn!("llvm.umul.with.overflow.i64" fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+
+    ifn!("llvm.expect.i1" fn(i1, i1) -> i1);
 
     // Some intrinsics were introduced in later versions of LLVM, but they have
     // fallbacks in libc or libm and such. Currently, all of these intrinsics
     // were introduced in LLVM 3.4, so we case on that.
     macro_rules! compatible_ifn (
-        ($intrinsics:ident, $name:expr, $cname:expr, $args:expr, $ret:expr) => ({
+        ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => ({
             let name = $name;
             if unsafe { llvm::LLVMVersionMinor() >= 4 } {
-                ifn!($intrinsics, $name, $args, $ret);
+                ifn!(name fn($($arg),*) -> $ret);
             } else {
-                let f = decl_cdecl_fn(llmod, $cname,
-                                      Type::func($args, &$ret),
+                let f = decl_cdecl_fn(ccx.llmod, stringify!($cname),
+                                      Type::func([$($arg),*], &$ret),
                                       ty::mk_nil());
-                $intrinsics.insert(name, f);
+                ccx.intrinsics.insert(name, f);
             }
         })
     )
 
-    compatible_ifn!(intrinsics, "llvm.copysign.f32", "copysignf",
-                    [Type::f32(), Type::f32()], Type::f32());
-    compatible_ifn!(intrinsics, "llvm.copysign.f64", "copysign",
-                    [Type::f64(), Type::f64()], Type::f64());
-    compatible_ifn!(intrinsics, "llvm.round.f32", "roundf",
-                    [Type::f32()], Type::f32());
-    compatible_ifn!(intrinsics, "llvm.round.f64", "round",
-                    [Type::f64()], Type::f64());
+    compatible_ifn!("llvm.copysign.f32", copysignf(t_f32, t_f32) -> t_f32);
+    compatible_ifn!("llvm.copysign.f64", copysign(t_f64, t_f64) -> t_f64);
+    compatible_ifn!("llvm.round.f32", roundf(t_f32) -> t_f32);
+    compatible_ifn!("llvm.round.f64", round(t_f64) -> t_f64);
 
-    return intrinsics;
-}
 
-pub fn declare_dbg_intrinsics(llmod: ModuleRef, intrinsics: &mut HashMap<&'static str, ValueRef>) {
-    ifn!(intrinsics, "llvm.dbg.declare", [Type::metadata(), Type::metadata()], Type::void());
-    ifn!(intrinsics,
-         "llvm.dbg.value",   [Type::metadata(), Type::i64(), Type::metadata()], Type::void());
+    if ccx.sess().opts.debuginfo != NoDebugInfo {
+        ifn!("llvm.dbg.declare" fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
+        ifn!("llvm.dbg.value" fn(Type::metadata(ccx), t_i64, Type::metadata(ccx)) -> void);
+    }
 }
 
 pub fn trap(bcx: &Block) {
@@ -2409,50 +2353,49 @@ pub fn symname(name: &str, hash: &str, vers: &str) -> ~str {
     link::exported_name(ast_map::Values(path.iter()).chain(None), hash, vers)
 }
 
-pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
-                      llmod: ModuleRef) -> (~str, ValueRef) {
-    let targ_cfg = sess.targ_cfg;
-    let int_type = Type::int(targ_cfg.arch);
+pub fn decl_crate_map(ccx: &mut CrateContext) {
     let mut n_subcrates = 1;
-    let cstore = sess.cstore;
-    while cstore.have_crate_data(n_subcrates) { n_subcrates += 1; }
-    let is_top = !sess.building_library.get() || sess.opts.cg.gen_crate_map;
+    while ccx.sess().cstore.have_crate_data(n_subcrates) {
+        n_subcrates += 1;
+    }
+    let is_top = !ccx.sess().building_library.get() || ccx.sess().opts.cg.gen_crate_map;
     let sym_name = if is_top {
         ~"_rust_crate_map_toplevel"
     } else {
-        symname("_rust_crate_map_" + mapmeta.crateid.name,
-                mapmeta.crate_hash.as_str(),
-                mapmeta.crateid.version_or_default())
+        symname("_rust_crate_map_" + ccx.link_meta.crateid.name,
+                ccx.link_meta.crate_hash.as_str(),
+                ccx.link_meta.crateid.version_or_default())
     };
 
-    let maptype = Type::struct_([
-        Type::i32(),        // version
-        int_type.ptr_to(),  // event loop factory
+    let maptype = Type::struct_(ccx, [
+        Type::i32(ccx),        // version
+        ccx.int_type.ptr_to(), // event loop factory
     ], false);
     let map = sym_name.with_c_str(|buf| {
         unsafe {
-            llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
         }
     });
     lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
 
     // On windows we'd like to export the toplevel cratemap
     // such that we can find it from libstd.
-    if targ_cfg.os == OsWin32 && is_top {
+    if ccx.sess().targ_cfg.os == OsWin32 && is_top {
         unsafe { llvm::LLVMRustSetDLLExportStorageClass(map) }
     }
 
-    return (sym_name, map);
+    ccx.crate_map_name = sym_name;
+    ccx.crate_map = map;
 }
 
-pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) {
+pub fn fill_crate_map(ccx: &CrateContext, map: ValueRef) {
     let event_loop_factory = match ccx.tcx.lang_items.event_loop_factory() {
         Some(did) => unsafe {
             if is_local(did) {
                 llvm::LLVMConstPointerCast(get_item_val(ccx, did.node),
                                            ccx.int_type.ptr_to().to_ref())
             } else {
-                let name = csearch::get_symbol(ccx.sess.cstore, did);
+                let name = csearch::get_symbol(&ccx.sess().cstore, did);
                 let global = name.with_c_str(|buf| {
                     llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type.to_ref(), buf)
                 });
@@ -2462,8 +2405,8 @@ pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) {
         None => C_null(ccx.int_type.ptr_to())
     };
     unsafe {
-        llvm::LLVMSetInitializer(map, C_struct(
-            [C_i32(2),
+        llvm::LLVMSetInitializer(map, C_struct(ccx,
+            [C_i32(ccx, 2),
             event_loop_factory,
         ], false));
     }
@@ -2472,17 +2415,17 @@ pub fn fill_crate_map(ccx: @CrateContext, map: ValueRef) {
 pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
     -> encoder::EncodeParams<'r> {
 
-        let diag = cx.sess.diagnostic();
+        let diag = cx.sess().diagnostic();
         let item_symbols = &cx.item_symbols;
         let link_meta = &cx.link_meta;
         encoder::EncodeParams {
             diag: diag,
-            tcx: cx.tcx,
+            tcx: cx.tcx(),
             reexports2: cx.exp_map2,
             item_symbols: item_symbols,
             non_inlineable_statics: &cx.non_inlineable_statics,
             link_meta: link_meta,
-            cstore: cx.sess.cstore,
+            cstore: &cx.sess().cstore,
             encode_inlined_item: ie,
         }
 }
@@ -2490,19 +2433,19 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeI
 pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
     use flate;
 
-    if !cx.sess.building_library.get() {
+    if !cx.sess().building_library.get() {
         return Vec::new()
     }
 
     let encode_inlined_item: encoder::EncodeInlinedItem =
-        |ecx, ebml_w, ii| astencode::encode_inlined_item(ecx, ebml_w, ii, cx.maps);
+        |ecx, ebml_w, ii| astencode::encode_inlined_item(ecx, ebml_w, ii, &cx.maps);
 
     let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
     let metadata = encoder::encode_metadata(encode_parms, krate);
     let compressed = encoder::metadata_encoding_version +
                         flate::deflate_bytes(metadata.as_slice()).as_slice();
-    let llmeta = C_bytes(compressed);
-    let llconst = C_struct([llmeta], false);
+    let llmeta = C_bytes(cx, compressed);
+    let llconst = C_struct(cx, [llmeta], false);
     let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.crateid.name,
                        cx.link_meta.crateid.version_or_default(), cx.link_meta.crate_hash);
     let llglobal = name.with_c_str(|buf| {
@@ -2512,17 +2455,18 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
     });
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
-        cx.sess.targ_cfg.target_strs.meta_sect_name.with_c_str(|buf| {
+        cx.sess().targ_cfg.target_strs.meta_sect_name.with_c_str(|buf| {
             llvm::LLVMSetSection(llglobal, buf)
         });
     }
     return metadata;
 }
 
-pub fn trans_crate(sess: session::Session,
-                   krate: ast::Crate,
-                   analysis: &CrateAnalysis,
-                   output: &OutputFilenames) -> CrateTranslation {
+pub fn trans_crate(krate: ast::Crate,
+                   analysis: CrateAnalysis,
+                   output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
+    let CrateAnalysis { ty_cx: tcx, exp_map2, maps, reachable, .. } = analysis;
+
     // Before we touch LLVM, make sure that multithreading is enabled.
     unsafe {
         use sync::one::{Once, ONCE_INIT};
@@ -2537,7 +2481,7 @@ pub fn trans_crate(sess: session::Session,
         });
 
         if POISONED {
-            sess.bug("couldn't enable multi-threaded LLVM");
+            tcx.sess.bug("couldn't enable multi-threaded LLVM");
         }
     }
 
@@ -2553,20 +2497,14 @@ pub fn trans_crate(sess: session::Session,
     // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
     let llmod_id = link_meta.crateid.name + ".rs";
 
-    let ccx = @CrateContext::new(sess,
-                                 llmod_id,
-                                 analysis.ty_cx,
-                                 analysis.exp_map2,
-                                 analysis.maps,
-                                 Sha256::new(),
-                                 link_meta,
-                                 analysis.reachable);
+    let ccx = CrateContext::new(llmod_id, tcx, exp_map2, maps,
+                                Sha256::new(), link_meta, reachable);
     {
         let _icx = push_ctxt("text");
-        trans_mod(ccx, &krate.module);
+        trans_mod(&ccx, &krate.module);
     }
 
-    fill_crate_map(ccx, ccx.crate_map);
+    fill_crate_map(&ccx, ccx.crate_map);
 
     // win32: wart with exporting crate_map symbol
     // We set the crate map (_rust_crate_map_toplevel) to use dll_export
@@ -2574,7 +2512,7 @@ pub fn trans_crate(sess: session::Session,
     // __rust_crate_map_toplevel symbol (extra underscore) which it will
     // subsequently fail to find. So to mitigate that we just introduce
     // an alias from the symbol it expects to the one that actually exists.
-    if ccx.sess.targ_cfg.os == OsWin32 && !ccx.sess.building_library.get() {
+    if ccx.sess().targ_cfg.os == OsWin32 && !ccx.sess().building_library.get() {
 
         let maptype = val_ty(ccx.crate_map).to_ref();
 
@@ -2586,14 +2524,14 @@ pub fn trans_crate(sess: session::Session,
         })
     }
 
-    glue::emit_tydescs(ccx);
-    if ccx.sess.opts.debuginfo != NoDebugInfo {
-        debuginfo::finalize(ccx);
+    glue::emit_tydescs(&ccx);
+    if ccx.sess().opts.debuginfo != NoDebugInfo {
+        debuginfo::finalize(&ccx);
     }
 
     // Translate the metadata.
-    let metadata = write_metadata(ccx, &krate);
-    if ccx.sess.trans_stats() {
+    let metadata = write_metadata(&ccx, &krate);
+    if ccx.sess().trans_stats() {
         println!("--- trans stats ---");
         println!("n_static_tydescs: {}", ccx.stats.n_static_tydescs.get());
         println!("n_glues_created: {}", ccx.stats.n_glues_created.get());
@@ -2605,21 +2543,19 @@ pub fn trans_crate(sess: session::Session,
         println!("n_inlines: {}", ccx.stats.n_inlines.get());
         println!("n_closures: {}", ccx.stats.n_closures.get());
         println!("fn stats:");
-        {
-            let mut fn_stats = ccx.stats.fn_stats.borrow_mut();
-            fn_stats.get().sort_by(|&(_, _, insns_a), &(_, _, insns_b)| {
-                insns_b.cmp(&insns_a)
-            });
-            for tuple in fn_stats.get().iter() {
-                match *tuple {
-                    (ref name, ms, insns) => {
-                        println!("{} insns, {} ms, {}", insns, ms, *name);
-                    }
+        let mut fn_stats = ccx.stats.fn_stats.borrow_mut();
+        fn_stats.get().sort_by(|&(_, _, insns_a), &(_, _, insns_b)| {
+            insns_b.cmp(&insns_a)
+        });
+        for tuple in fn_stats.get().iter() {
+            match *tuple {
+                (ref name, ms, insns) => {
+                    println!("{} insns, {} ms, {}", insns, ms, *name);
                 }
             }
         }
     }
-    if ccx.sess.count_llvm_insns() {
+    if ccx.sess().count_llvm_insns() {
         let llvm_insns = ccx.stats.llvm_insns.borrow();
         for (k, v) in llvm_insns.get().iter() {
             println!("{:7u} {}", *v, *k);
@@ -2630,13 +2566,9 @@ pub fn trans_crate(sess: session::Session,
     let link_meta = ccx.link_meta.clone();
     let llmod = ccx.llmod;
 
-    let mut reachable: Vec<~str> = {
-        let reachable_map = ccx.reachable.borrow();
-        reachable_map.get().iter().filter_map(|id| {
-            let item_symbols = ccx.item_symbols.borrow();
-            item_symbols.get().find(id).map(|s| s.to_owned())
-        }).collect()
-    };
+    let mut reachable: Vec<~str> = ccx.reachable.iter().filter_map(|id| {
+        ccx.item_symbols.borrow().get().find(id).map(|s| s.to_owned())
+    }).collect();
 
     // Make sure that some other crucial symbols are not eliminated from the
     // module. This includes the main function, the crate map (used for debug
@@ -2650,12 +2582,14 @@ pub fn trans_crate(sess: session::Session,
     reachable.push(~"rust_eh_personality"); // referenced from .eh_frame section on some platforms
     reachable.push(~"rust_eh_personality_catch"); // referenced from rt/rust_try.ll
 
-    return CrateTranslation {
+    let metadata_module = ccx.metadata_llmod;
+
+    (ccx.tcx, CrateTranslation {
         context: llcx,
         module: llmod,
         link: link_meta,
-        metadata_module: ccx.metadata_llmod,
+        metadata_module: metadata_module,
         metadata: metadata,
         reachable: reachable,
-    };
+    })
 }
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index d208394402c..79e22ea3455 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -115,7 +115,7 @@ pub fn Invoke(cx: &Block,
               attributes: &[(uint, lib::llvm::Attribute)])
               -> ValueRef {
     if cx.unreachable.get() {
-        return C_null(Type::i8());
+        return C_null(Type::i8(cx.ccx()));
     }
     check_not_terminated(cx);
     terminate(cx, "Invoke");
@@ -300,14 +300,18 @@ pub fn Not(cx: &Block, v: ValueRef) -> ValueRef {
 /* Memory */
 pub fn Malloc(cx: &Block, ty: Type) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref());
+        }
         B(cx).malloc(ty)
     }
 }
 
 pub fn ArrayMalloc(cx: &Block, ty: Type, val: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref());
+        }
         B(cx).array_malloc(ty, val)
     }
 }
@@ -357,7 +361,9 @@ pub fn Load(cx: &Block, pointer_val: ValueRef) -> ValueRef {
 
 pub fn VolatileLoad(cx: &Block, pointer_val: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).volatile_load(pointer_val)
     }
 }
@@ -408,7 +414,9 @@ pub fn AtomicStore(cx: &Block, val: ValueRef, ptr: ValueRef, order: AtomicOrderi
 
 pub fn GEP(cx: &Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref());
+        }
         B(cx).gep(pointer, indices)
     }
 }
@@ -418,35 +426,45 @@ pub fn GEP(cx: &Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef {
 #[inline]
 pub fn GEPi(cx: &Block, base: ValueRef, ixs: &[uint]) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref());
+        }
         B(cx).gepi(base, ixs)
     }
 }
 
 pub fn InBoundsGEP(cx: &Block, pointer: ValueRef, indices: &[ValueRef]) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref());
+        }
         B(cx).inbounds_gep(pointer, indices)
     }
 }
 
 pub fn StructGEP(cx: &Block, pointer: ValueRef, idx: uint) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).ptr_to().to_ref());
+        }
         B(cx).struct_gep(pointer, idx)
     }
 }
 
 pub fn GlobalString(cx: &Block, _str: *c_char) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref());
+        }
         B(cx).global_string(_str)
     }
 }
 
 pub fn GlobalStringPtr(cx: &Block, _str: *c_char) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i8p(cx.ccx()).to_ref());
+        }
         B(cx).global_string_ptr(_str)
     }
 }
@@ -591,7 +609,9 @@ pub fn FPCast(cx: &Block, val: ValueRef, dest_ty: Type) -> ValueRef {
 pub fn ICmp(cx: &Block, op: IntPredicate, lhs: ValueRef, rhs: ValueRef)
      -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref());
+        }
         B(cx).icmp(op, lhs, rhs)
     }
 }
@@ -599,7 +619,9 @@ pub fn ICmp(cx: &Block, op: IntPredicate, lhs: ValueRef, rhs: ValueRef)
 pub fn FCmp(cx: &Block, op: RealPredicate, lhs: ValueRef, rhs: ValueRef)
      -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref());
+        }
         B(cx).fcmp(op, lhs, rhs)
     }
 }
@@ -686,7 +708,9 @@ pub fn VAArg(cx: &Block, list: ValueRef, ty: Type) -> ValueRef {
 
 pub fn ExtractElement(cx: &Block, vec_val: ValueRef, index: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).extract_element(vec_val, index)
     }
 }
@@ -694,7 +718,9 @@ pub fn ExtractElement(cx: &Block, vec_val: ValueRef, index: ValueRef) -> ValueRe
 pub fn InsertElement(cx: &Block, vec_val: ValueRef, elt_val: ValueRef,
                      index: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).insert_element(vec_val, elt_val, index)
     }
 }
@@ -702,42 +728,54 @@ pub fn InsertElement(cx: &Block, vec_val: ValueRef, elt_val: ValueRef,
 pub fn ShuffleVector(cx: &Block, v1: ValueRef, v2: ValueRef,
                      mask: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).shuffle_vector(v1, v2, mask)
     }
 }
 
 pub fn VectorSplat(cx: &Block, num_elts: uint, elt_val: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).vector_splat(num_elts, elt_val)
     }
 }
 
 pub fn ExtractValue(cx: &Block, agg_val: ValueRef, index: uint) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).extract_value(agg_val, index)
     }
 }
 
 pub fn InsertValue(cx: &Block, agg_val: ValueRef, elt_val: ValueRef, index: uint) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::nil(cx.ccx()).to_ref());
+        }
         B(cx).insert_value(agg_val, elt_val, index)
     }
 }
 
 pub fn IsNull(cx: &Block, val: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref());
+        }
         B(cx).is_null(val)
     }
 }
 
 pub fn IsNotNull(cx: &Block, val: ValueRef) -> ValueRef {
     unsafe {
-        if cx.unreachable.get() { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
+        if cx.unreachable.get() {
+            return llvm::LLVMGetUndef(Type::i1(cx.ccx()).to_ref());
+        }
         B(cx).is_not_null(val)
     }
 }
diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs
index 15e74b1b55d..c403d323bf4 100644
--- a/src/librustc/middle/trans/builder.rs
+++ b/src/librustc/middle/trans/builder.rs
@@ -44,13 +44,13 @@ impl<'a> Builder<'a> {
     }
 
     pub fn count_insn(&self, category: &str) {
-        if self.ccx.sess.trans_stats() {
+        if self.ccx.sess().trans_stats() {
             self.ccx.stats.n_llvm_insns.set(self.ccx
                                                 .stats
                                                 .n_llvm_insns
                                                 .get() + 1);
         }
-        if self.ccx.sess.count_llvm_insns() {
+        if self.ccx.sess().count_llvm_insns() {
             base::with_insn_ctxt(|v| {
                 let mut h = self.ccx.stats.llvm_insns.borrow_mut();
 
@@ -536,13 +536,13 @@ impl<'a> Builder<'a> {
         // Small vector optimization. This should catch 100% of the cases that
         // we care about.
         if ixs.len() < 16 {
-            let mut small_vec = [ C_i32(0), ..16 ];
+            let mut small_vec = [ C_i32(self.ccx, 0), ..16 ];
             for (small_vec_e, &ix) in small_vec.mut_iter().zip(ixs.iter()) {
-                *small_vec_e = C_i32(ix as i32);
+                *small_vec_e = C_i32(self.ccx, ix as i32);
             }
             self.inbounds_gep(base, small_vec.slice(0, ixs.len()))
         } else {
-            let v = ixs.iter().map(|i| C_i32(*i as i32)).collect::<Vec<ValueRef> >();
+            let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
             self.count_insn("gepi");
             self.inbounds_gep(base, v.as_slice())
         }
@@ -748,21 +748,21 @@ impl<'a> Builder<'a> {
     }
 
     pub fn add_span_comment(&self, sp: Span, text: &str) {
-        if self.ccx.sess.asm_comments() {
-            let s = format!("{} ({})", text, self.ccx.sess.codemap.span_to_str(sp));
+        if self.ccx.sess().asm_comments() {
+            let s = format!("{} ({})", text, self.ccx.sess().codemap().span_to_str(sp));
             debug!("{}", s);
             self.add_comment(s);
         }
     }
 
     pub fn add_comment(&self, text: &str) {
-        if self.ccx.sess.asm_comments() {
+        if self.ccx.sess().asm_comments() {
             let sanitized = text.replace("$", "");
             let comment_text = format!("\\# {}", sanitized.replace("\n", "\n\t# "));
             self.count_insn("inlineasm");
             let asm = comment_text.with_c_str(|c| {
                 unsafe {
-                    llvm::LLVMConstInlineAsm(Type::func([], &Type::void()).to_ref(),
+                    llvm::LLVMConstInlineAsm(Type::func([], &Type::void(self.ccx)).to_ref(),
                                              c, noname(), False, False)
                 }
             });
@@ -860,8 +860,9 @@ impl<'a> Builder<'a> {
         unsafe {
             let elt_ty = val_ty(elt);
             let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref());
-            let vec = self.insert_element(undef, elt, C_i32(0));
-            self.shuffle_vector(vec, undef, C_null(Type::vector(&Type::i32(), num_elts as u64)))
+            let vec = self.insert_element(undef, elt, C_i32(self.ccx, 0));
+            let vec_i32_ty = Type::vector(&Type::i32(self.ccx), num_elts as u64);
+            self.shuffle_vector(vec, undef, C_null(vec_i32_ty))
         }
     }
 
diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs
index b8ab8d81d2f..d760c645441 100644
--- a/src/librustc/middle/trans/cabi.rs
+++ b/src/librustc/middle/trans/cabi.rs
@@ -94,7 +94,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
                         atys: &[Type],
                         rty: Type,
                         ret_def: bool) -> FnType {
-    match ccx.sess.targ_cfg.arch {
+    match ccx.sess().targ_cfg.arch {
         X86 => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def),
         X86_64 => cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def),
         Arm => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def),
diff --git a/src/librustc/middle/trans/cabi_arm.rs b/src/librustc/middle/trans/cabi_arm.rs
index 341844a3be0..83805cf844f 100644
--- a/src/librustc/middle/trans/cabi_arm.rs
+++ b/src/librustc/middle/trans/cabi_arm.rs
@@ -85,34 +85,34 @@ fn ty_size(ty: Type) -> uint {
     }
 }
 
-fn classify_ret_ty(ty: Type) -> ArgType {
+fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     if is_reg_ty(ty) {
         return ArgType::direct(ty, None, None, None);
     }
     let size = ty_size(ty);
     if size <= 4 {
         let llty = if size <= 1 {
-            Type::i8()
+            Type::i8(ccx)
         } else if size <= 2 {
-            Type::i16()
+            Type::i16(ccx)
         } else {
-            Type::i32()
+            Type::i32(ccx)
         };
         return ArgType::direct(ty, Some(llty), None, None);
     }
     ArgType::indirect(ty, Some(StructRetAttribute))
 }
 
-fn classify_arg_ty(ty: Type) -> ArgType {
+fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     if is_reg_ty(ty) {
         return ArgType::direct(ty, None, None, None);
     }
     let align = ty_align(ty);
     let size = ty_size(ty);
     let llty = if align <= 4 {
-        Type::array(&Type::i32(), ((size + 3) / 4) as u64)
+        Type::array(&Type::i32(ccx), ((size + 3) / 4) as u64)
     } else {
-        Type::array(&Type::i64(), ((size + 7) / 8) as u64)
+        Type::array(&Type::i64(ccx), ((size + 7) / 8) as u64)
     };
     ArgType::direct(ty, Some(llty), None, None)
 }
@@ -127,20 +127,20 @@ fn is_reg_ty(ty: Type) -> bool {
     }
 }
 
-pub fn compute_abi_info(_ccx: &CrateContext,
+pub fn compute_abi_info(ccx: &CrateContext,
                         atys: &[Type],
                         rty: Type,
                         ret_def: bool) -> FnType {
     let mut arg_tys = Vec::new();
     for &aty in atys.iter() {
-        let ty = classify_arg_ty(aty);
+        let ty = classify_arg_ty(ccx, aty);
         arg_tys.push(ty);
     }
 
     let ret_ty = if ret_def {
-        classify_ret_ty(rty)
+        classify_ret_ty(ccx, rty)
     } else {
-        ArgType::direct(Type::void(), None, None, None)
+        ArgType::direct(Type::void(ccx), None, None, None)
     };
 
     return FnType {
diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs
index 4bd695422a2..68d9bb82a6c 100644
--- a/src/librustc/middle/trans/cabi_mips.rs
+++ b/src/librustc/middle/trans/cabi_mips.rs
@@ -15,7 +15,6 @@ use std::cmp;
 use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
 use lib::llvm::StructRetAttribute;
 use middle::trans::context::CrateContext;
-use middle::trans::context::task_llcx;
 use middle::trans::cabi::*;
 use middle::trans::type_::Type;
 
@@ -94,7 +93,7 @@ fn classify_ret_ty(ty: Type) -> ArgType {
     }
 }
 
-fn classify_arg_ty(ty: Type, offset: &mut uint) -> ArgType {
+fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType {
     let orig_offset = *offset;
     let size = ty_size(ty) * 8;
     let mut align = ty_align(ty);
@@ -108,8 +107,8 @@ fn classify_arg_ty(ty: Type, offset: &mut uint) -> ArgType {
     } else {
         ArgType::direct(
             ty,
-            Some(struct_ty(ty)),
-            padding_ty(align, orig_offset),
+            Some(struct_ty(ccx, ty)),
+            padding_ty(ccx, align, orig_offset),
             None
         )
     }
@@ -125,16 +124,16 @@ fn is_reg_ty(ty: Type) -> bool {
     };
 }
 
-fn padding_ty(align: uint, offset: uint) -> Option<Type> {
+fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option<Type> {
     if ((align - 1 ) & offset) > 0 {
-        return Some(Type::i32());
+        Some(Type::i32(ccx))
+    } else {
+        None
     }
-
-    return None;
 }
 
-fn coerce_to_int(size: uint) -> Vec<Type> {
-    let int_ty = Type::i32();
+fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec<Type> {
+    let int_ty = Type::i32(ccx);
     let mut args = Vec::new();
 
     let mut n = size / 32;
@@ -146,27 +145,26 @@ fn coerce_to_int(size: uint) -> Vec<Type> {
     let r = size % 32;
     if r > 0 {
         unsafe {
-            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)));
+            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx, r as c_uint)));
         }
     }
 
     args
 }
 
-fn struct_ty(ty: Type) -> Type {
+fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
     let size = ty_size(ty) * 8;
-    let fields = coerce_to_int(size);
-    return Type::struct_(fields.as_slice(), false);
+    Type::struct_(ccx, coerce_to_int(ccx, size).as_slice(), false)
 }
 
-pub fn compute_abi_info(_ccx: &CrateContext,
+pub fn compute_abi_info(ccx: &CrateContext,
                         atys: &[Type],
                         rty: Type,
                         ret_def: bool) -> FnType {
     let ret_ty = if ret_def {
         classify_ret_ty(rty)
     } else {
-        ArgType::direct(Type::void(), None, None, None)
+        ArgType::direct(Type::void(ccx), None, None, None)
     };
 
     let sret = ret_ty.is_indirect();
@@ -174,7 +172,7 @@ pub fn compute_abi_info(_ccx: &CrateContext,
     let mut offset = if sret { 4 } else { 0 };
 
     for aty in atys.iter() {
-        let ty = classify_arg_ty(*aty, &mut offset);
+        let ty = classify_arg_ty(ccx, *aty, &mut offset);
         arg_tys.push(ty);
     };
 
diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs
index 194197e5011..b2cb6970597 100644
--- a/src/librustc/middle/trans/cabi_x86.rs
+++ b/src/librustc/middle/trans/cabi_x86.rs
@@ -25,7 +25,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
 
     let ret_ty;
     if !ret_def {
-        ret_ty = ArgType::direct(Type::void(), None, None, None);
+        ret_ty = ArgType::direct(Type::void(ccx), None, None, None);
     } else if rty.kind() == Struct {
         // Returning a structure. Most often, this will use
         // a hidden first argument. On some platforms, though,
@@ -36,13 +36,13 @@ pub fn compute_abi_info(ccx: &CrateContext,
         // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
 
         enum Strategy { RetValue(Type), RetPointer }
-        let strategy = match ccx.sess.targ_cfg.os {
+        let strategy = match ccx.sess().targ_cfg.os {
             OsWin32 | OsMacos => {
                 match llsize_of_alloc(ccx, rty) {
-                    1 => RetValue(Type::i8()),
-                    2 => RetValue(Type::i16()),
-                    4 => RetValue(Type::i32()),
-                    8 => RetValue(Type::i64()),
+                    1 => RetValue(Type::i8(ccx)),
+                    2 => RetValue(Type::i16(ccx)),
+                    4 => RetValue(Type::i32(ccx)),
+                    8 => RetValue(Type::i64(ccx)),
                     _ => RetPointer
                 }
             }
diff --git a/src/librustc/middle/trans/cabi_x86_64.rs b/src/librustc/middle/trans/cabi_x86_64.rs
index d3ffa7865a2..c1ae28005d9 100644
--- a/src/librustc/middle/trans/cabi_x86_64.rs
+++ b/src/librustc/middle/trans/cabi_x86_64.rs
@@ -291,7 +291,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
     return cls;
 }
 
-fn llreg_ty(cls: &[RegClass]) -> Type {
+fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
     fn llvec_len(cls: &[RegClass]) -> uint {
         let mut len = 1u;
         for c in cls.iter() {
@@ -309,33 +309,34 @@ fn llreg_ty(cls: &[RegClass]) -> Type {
     while i < e {
         match cls[i] {
             Int => {
-                tys.push(Type::i64());
+                tys.push(Type::i64(ccx));
             }
             SSEFv => {
                 let vec_len = llvec_len(cls.tailn(i + 1u));
-                let vec_ty = Type::vector(&Type::f32(), (vec_len * 2u) as u64);
+                let vec_ty = Type::vector(&Type::f32(ccx), (vec_len * 2u) as u64);
                 tys.push(vec_ty);
                 i += vec_len;
                 continue;
             }
             SSEFs => {
-                tys.push(Type::f32());
+                tys.push(Type::f32(ccx));
             }
             SSEDs => {
-                tys.push(Type::f64());
+                tys.push(Type::f64(ccx));
             }
             _ => fail!("llregtype: unhandled class")
         }
         i += 1u;
     }
-    return Type::struct_(tys.as_slice(), false);
+    return Type::struct_(ccx, tys.as_slice(), false);
 }
 
-pub fn compute_abi_info(_ccx: &CrateContext,
+pub fn compute_abi_info(ccx: &CrateContext,
                         atys: &[Type],
                         rty: Type,
                         ret_def: bool) -> FnType {
-    fn x86_64_ty(ty: Type,
+    fn x86_64_ty(ccx: &CrateContext,
+                 ty: Type,
                  is_mem_cls: |cls: &[RegClass]| -> bool,
                  attr: Attribute)
                  -> ArgType {
@@ -345,7 +346,7 @@ pub fn compute_abi_info(_ccx: &CrateContext,
                 ArgType::indirect(ty, Some(attr))
             } else {
                 ArgType::direct(ty,
-                                Some(llreg_ty(cls.as_slice())),
+                                Some(llreg_ty(ccx, cls.as_slice())),
                                 None,
                                 None)
             }
@@ -356,14 +357,14 @@ pub fn compute_abi_info(_ccx: &CrateContext,
 
     let mut arg_tys = Vec::new();
     for t in atys.iter() {
-        let ty = x86_64_ty(*t, |cls| cls.is_pass_byval(), ByValAttribute);
+        let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), ByValAttribute);
         arg_tys.push(ty);
     }
 
     let ret_ty = if ret_def {
-        x86_64_ty(rty, |cls| cls.is_ret_bysret(), StructRetAttribute)
+        x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), StructRetAttribute)
     } else {
-        ArgType::direct(Type::void(), None, None, None)
+        ArgType::direct(Type::void(ccx), None, None, None)
     };
 
     return FnType {
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index ff63b74444c..61a855a7f09 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -267,15 +267,15 @@ pub fn trans_fn_ref_with_vtables(
 
     let _icx = push_ctxt("trans_fn_ref_with_vtables");
     let ccx = bcx.ccx();
-    let tcx = ccx.tcx;
+    let tcx = bcx.tcx();
 
     debug!("trans_fn_ref_with_vtables(bcx={}, def_id={}, node={:?}, \
             type_params={}, vtables={})",
            bcx.to_str(),
-           def_id.repr(bcx.tcx()),
+           def_id.repr(tcx),
            node,
-           type_params.repr(bcx.tcx()),
-           vtables.repr(bcx.tcx()));
+           type_params.repr(tcx),
+           vtables.repr(tcx));
 
     assert!(type_params.iter().all(|t| !ty::type_needs_infer(*t)));
 
@@ -365,13 +365,13 @@ pub fn trans_fn_ref_with_vtables(
         true
     } else if def_id.krate == ast::LOCAL_CRATE {
         let map_node = session::expect(
-            ccx.sess,
-            ccx.tcx.map.find(def_id.node),
+            ccx.sess(),
+            tcx.map.find(def_id.node),
             || format!("local item should be in ast map"));
 
         match map_node {
             ast_map::NodeForeignItem(_) => {
-                ccx.tcx.map.get_foreign_abis(def_id.node).is_intrinsic()
+                tcx.map.get_foreign_abis(def_id.node).is_intrinsic()
             }
             _ => false
         }
@@ -502,9 +502,9 @@ pub fn trans_lang_call<'a>(
                        dest: Option<expr::Dest>)
                        -> Result<'a> {
     let fty = if did.krate == ast::LOCAL_CRATE {
-        ty::node_id_to_type(bcx.ccx().tcx, did.node)
+        ty::node_id_to_type(bcx.tcx(), did.node)
     } else {
-        csearch::get_type(bcx.ccx().tcx, did).ty
+        csearch::get_type(bcx.tcx(), did).ty
     };
     callee::trans_call_inner(bcx,
                              None,
@@ -649,7 +649,7 @@ pub fn trans_call_inner<'a>(
     };
 
     let mut llresult = unsafe {
-        llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
+        llvm::LLVMGetUndef(Type::nil(ccx).ptr_to().to_ref())
     };
 
     // The code below invokes the function, using either the Rust
diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs
index d249bd8a894..1acc746b197 100644
--- a/src/librustc/middle/trans/cleanup.rs
+++ b/src/librustc/middle/trans/cleanup.rs
@@ -205,7 +205,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
                 _ => {}
             }
         }
-        self.ccx.tcx.sess.bug("no loop scope found");
+        self.ccx.sess().bug("no loop scope found");
     }
 
     fn normal_exit_block(&'a self,
@@ -238,10 +238,10 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
          * instance of `ty`
          */
 
-        if !ty::type_needs_drop(self.ccx.tcx, ty) { return; }
+        if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = ~DropValue {
             is_immediate: false,
-            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx, ty),
+            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
             val: val,
             ty: ty
         };
@@ -249,7 +249,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
         debug!("schedule_drop_mem({:?}, val={}, ty={})",
                cleanup_scope,
                self.ccx.tn.val_to_str(val),
-               ty.repr(self.ccx.tcx));
+               ty.repr(self.ccx.tcx()));
 
         self.schedule_clean(cleanup_scope, drop as ~Cleanup);
     }
@@ -262,10 +262,10 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
          * Schedules a (deep) drop of `val`, which is an instance of `ty`
          */
 
-        if !ty::type_needs_drop(self.ccx.tcx, ty) { return; }
+        if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
         let drop = ~DropValue {
             is_immediate: true,
-            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx, ty),
+            on_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
             val: val,
             ty: ty
         };
@@ -273,7 +273,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
         debug!("schedule_drop_immediate({:?}, val={}, ty={})",
                cleanup_scope,
                self.ccx.tn.val_to_str(val),
-               ty.repr(self.ccx.tcx));
+               ty.repr(self.ccx.tcx()));
 
         self.schedule_clean(cleanup_scope, drop as ~Cleanup);
     }
@@ -330,7 +330,7 @@ impl<'a> CleanupMethods<'a> for FunctionContext<'a> {
             }
         }
 
-        self.ccx.tcx.sess.bug(
+        self.ccx.sess().bug(
             format!("no cleanup scope {} found",
                     self.ccx.tcx.map.node_to_str(cleanup_scope)));
     }
@@ -540,7 +540,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
                     }
 
                     LoopExit(id, _) => {
-                        self.ccx.tcx.sess.bug(format!(
+                        self.ccx.sess().bug(format!(
                                 "cannot exit from scope {:?}, \
                                 not in scope", id));
                     }
@@ -669,7 +669,9 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
         // The landing pad return type (the type being propagated). Not sure what
         // this represents but it's determined by the personality function and
         // this is what the EH proposal example uses.
-        let llretty = Type::struct_([Type::i8p(), Type::i32()], false);
+        let llretty = Type::struct_(self.ccx,
+                                    [Type::i8p(self.ccx), Type::i32(self.ccx)],
+                                    false);
 
         // The exception handling personality function.
         let def_id = common::langcall(pad_bcx, None, "", EhPersonalityLangItem);
@@ -846,7 +848,7 @@ impl Cleanup for FreeValue {
     }
 }
 
-pub fn temporary_scope(tcx: ty::ctxt,
+pub fn temporary_scope(tcx: &ty::ctxt,
                        id: ast::NodeId)
                        -> ScopeId {
     match tcx.region_maps.temporary_scope(id) {
@@ -861,7 +863,7 @@ pub fn temporary_scope(tcx: ty::ctxt,
     }
 }
 
-pub fn var_scope(tcx: ty::ctxt,
+pub fn var_scope(tcx: &ty::ctxt,
                  id: ast::NodeId)
                  -> ScopeId {
     let r = AstScope(tcx.region_maps.var_scope(id));
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index bfc9d8d2d6d..05375ebeb31 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -133,7 +133,7 @@ impl EnvValue {
 }
 
 // Given a closure ty, emits a corresponding tuple ty
-pub fn mk_closure_tys(tcx: ty::ctxt,
+pub fn mk_closure_tys(tcx: &ty::ctxt,
                       bound_values: &[EnvValue])
                    -> ty::t {
     // determine the types of the values in the env.  Note that this
@@ -151,7 +151,7 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
     return cdata_ty;
 }
 
-fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
+fn tuplify_box_ty(tcx: &ty::ctxt, t: ty::t) -> ty::t {
     let ptr = ty::mk_imm_ptr(tcx, ty::mk_i8());
     ty::mk_tup(tcx, vec!(ty::mk_uint(), ty::mk_nil_ptr(tcx), ptr, ptr, t))
 }
@@ -161,8 +161,7 @@ fn allocate_cbox<'a>(bcx: &'a Block<'a>,
                      cdata_ty: ty::t)
                      -> Result<'a> {
     let _icx = push_ctxt("closure::allocate_cbox");
-    let ccx = bcx.ccx();
-    let tcx = ccx.tcx;
+    let tcx = bcx.tcx();
 
     // Allocate and initialize the box:
     match sigil {
@@ -197,7 +196,7 @@ pub fn store_environment<'a>(
                          -> ClosureResult<'a> {
     let _icx = push_ctxt("closure::store_environment");
     let ccx = bcx.ccx();
-    let tcx = ccx.tcx;
+    let tcx = ccx.tcx();
 
     // compute the type of the closure
     let cdata_ty = mk_closure_tys(tcx, bound_values.as_slice());
@@ -227,7 +226,7 @@ pub fn store_environment<'a>(
     for (i, bv) in bound_values.move_iter().enumerate() {
         debug!("Copy {} into closure", bv.to_str(ccx));
 
-        if ccx.sess.asm_comments() {
+        if ccx.sess().asm_comments() {
             add_comment(bcx, format!("Copy {} into closure",
                                   bv.to_str(ccx)));
         }
@@ -301,7 +300,7 @@ fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t,
 
     // Store the pointer to closure data in an alloca for debug info because that's what the
     // llvm.dbg.declare intrinsic expects
-    let env_pointer_alloca = if bcx.ccx().sess.opts.debuginfo == FullDebugInfo {
+    let env_pointer_alloca = if bcx.sess().opts.debuginfo == FullDebugInfo {
         let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr");
         Store(bcx, llcdata, alloc);
         Some(alloc)
@@ -343,7 +342,7 @@ fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t,
 
 fn fill_fn_pair(bcx: &Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) {
     Store(bcx, llfn, GEPi(bcx, pair, [0u, abi::fn_field_code]));
-    let llenvptr = PointerCast(bcx, llenvptr, Type::i8p());
+    let llenvptr = PointerCast(bcx, llenvptr, Type::i8p(bcx.ccx()));
     Store(bcx, llenvptr, GEPi(bcx, pair, [0u, abi::fn_field_box]));
 }
 
@@ -409,7 +408,7 @@ pub fn trans_expr_fn<'a>(
     bcx
 }
 
-pub fn get_wrapper_for_bare_fn(ccx: @CrateContext,
+pub fn get_wrapper_for_bare_fn(ccx: &CrateContext,
                                closure_ty: ty::t,
                                def: ast::Def,
                                fn_ptr: ValueRef,
@@ -419,9 +418,9 @@ pub fn get_wrapper_for_bare_fn(ccx: @CrateContext,
         ast::DefFn(did, _) | ast::DefStaticMethod(did, _, _) |
         ast::DefVariant(_, did, _) | ast::DefStruct(did) => did,
         _ => {
-            ccx.sess.bug(format!("get_wrapper_for_bare_fn: \
-                                  expected a statically resolved fn, got {:?}",
-                                  def));
+            ccx.sess().bug(format!("get_wrapper_for_bare_fn: \
+                                    expected a statically resolved fn, got {:?}",
+                                    def));
         }
     };
 
@@ -433,16 +432,16 @@ pub fn get_wrapper_for_bare_fn(ccx: @CrateContext,
         }
     }
 
-    let tcx = ccx.tcx;
+    let tcx = ccx.tcx();
 
     debug!("get_wrapper_for_bare_fn(closure_ty={})", closure_ty.repr(tcx));
 
     let f = match ty::get(closure_ty).sty {
         ty::ty_closure(ref f) => f,
         _ => {
-            ccx.sess.bug(format!("get_wrapper_for_bare_fn: \
-                                  expected a closure ty, got {}",
-                                  closure_ty.repr(tcx)));
+            ccx.sess().bug(format!("get_wrapper_for_bare_fn: \
+                                    expected a closure ty, got {}",
+                                    closure_ty.repr(tcx)));
         }
     };
 
@@ -510,7 +509,7 @@ pub fn make_closure_from_bare_fn<'a>(bcx: &'a Block<'a>,
                                      -> DatumBlock<'a, Expr>  {
     let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
     let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true);
-    fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p()));
+    fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p(bcx.ccx())));
 
     DatumBlock(bcx, scratch.to_expr_datum())
 }
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index bfe5d5187d7..e812f36e85d 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -18,7 +18,6 @@ use lib::llvm::{True, False, Bool};
 use lib::llvm::llvm;
 use lib;
 use middle::lang_items::LangItem;
-use middle::trans::base;
 use middle::trans::build;
 use middle::trans::cleanup;
 use middle::trans::datum;
@@ -49,7 +48,7 @@ pub use middle::trans::context::CrateContext;
 fn type_is_newtype_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
     match ty::get(ty).sty {
         ty::ty_struct(def_id, ref substs) => {
-            let fields = ty::struct_fields(ccx.tcx, def_id, substs);
+            let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
             fields.len() == 1 &&
                 fields.get(0).ident.name ==
                     token::special_idents::unnamed_field.name &&
@@ -62,7 +61,7 @@ fn type_is_newtype_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
 pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
     use middle::trans::machine::llsize_of_alloc;
     use middle::trans::type_of::sizing_type_of;
-    let tcx = ccx.tcx;
+    let tcx = ccx.tcx();
     let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
         type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
@@ -100,7 +99,7 @@ pub fn return_type_is_void(ccx: &CrateContext, ty: ty::t) -> bool {
      * return type (in order to aid with C ABI compatibility).
      */
 
-    ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx, ty)
+    ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx(), ty)
 }
 
 /// Generates a unique symbol based off the name given. This is used to create
@@ -207,14 +206,14 @@ impl param_substs {
     }
 }
 
-fn param_substs_to_str(this: &param_substs, tcx: ty::ctxt) -> ~str {
+fn param_substs_to_str(this: &param_substs, tcx: &ty::ctxt) -> ~str {
     format!("param_substs \\{tys:{}, vtables:{}\\}",
          this.tys.repr(tcx),
          this.vtables.repr(tcx))
 }
 
 impl Repr for param_substs {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         param_substs_to_str(self, tcx)
     }
 }
@@ -286,7 +285,7 @@ pub struct FunctionContext<'a> {
     block_arena: &'a TypedArena<Block<'a>>,
 
     // This function's enclosing crate context.
-    ccx: @CrateContext,
+    ccx: &'a CrateContext,
 
     // Used and maintained by the debuginfo module.
     debug_context: debuginfo::FunctionDebugContext,
@@ -330,7 +329,12 @@ impl<'a> FunctionContext<'a> {
 
     pub fn get_llreturn(&self) -> BasicBlockRef {
         if self.llreturn.get().is_none() {
-            self.llreturn.set(Some(base::mk_return_basic_block(self.llfn)));
+
+            self.llreturn.set(Some(unsafe {
+                "return".with_c_str(|buf| {
+                    llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx, self.llfn, buf)
+                })
+            }))
         }
 
         self.llreturn.get().unwrap()
@@ -383,13 +387,6 @@ impl<'a> FunctionContext<'a> {
     }
 }
 
-pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) {
-    if !ccx.do_not_commit_warning_issued.get() {
-        ccx.do_not_commit_warning_issued.set(true);
-        ccx.sess.warn(msg.to_str() + " -- do not commit like this!");
-    }
-}
-
 // Heap selectors. Indicate which heap something should go on.
 #[deriving(Eq)]
 pub enum heap {
@@ -442,11 +439,11 @@ impl<'a> Block<'a> {
         })
     }
 
-    pub fn ccx(&self) -> @CrateContext { self.fcx.ccx }
-    pub fn tcx(&self) -> ty::ctxt {
-        self.fcx.ccx.tcx
+    pub fn ccx(&self) -> &'a CrateContext { self.fcx.ccx }
+    pub fn tcx(&self) -> &'a ty::ctxt {
+        &self.fcx.ccx.tcx
     }
-    pub fn sess(&self) -> Session { self.fcx.ccx.sess }
+    pub fn sess(&self) -> &'a Session { self.fcx.ccx.sess() }
 
     pub fn ident(&self, ident: Ident) -> ~str {
         token::get_ident(ident).get().to_str()
@@ -547,40 +544,40 @@ pub fn C_floating(s: &str, t: Type) -> ValueRef {
     }
 }
 
-pub fn C_nil() -> ValueRef {
-    C_struct([], false)
+pub fn C_nil(ccx: &CrateContext) -> ValueRef {
+    C_struct(ccx, [], false)
 }
 
-pub fn C_bool(val: bool) -> ValueRef {
-    C_integral(Type::bool(), val as u64, false)
+pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
+    C_integral(Type::bool(ccx), val as u64, false)
 }
 
-pub fn C_i1(val: bool) -> ValueRef {
-    C_integral(Type::i1(), val as u64, false)
+pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef {
+    C_integral(Type::i1(ccx), val as u64, false)
 }
 
-pub fn C_i32(i: i32) -> ValueRef {
-    return C_integral(Type::i32(), i as u64, true);
+pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
+    C_integral(Type::i32(ccx), i as u64, true)
 }
 
-pub fn C_i64(i: i64) -> ValueRef {
-    return C_integral(Type::i64(), i as u64, true);
+pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
+    C_integral(Type::i64(ccx), i as u64, true)
 }
 
-pub fn C_u64(i: u64) -> ValueRef {
-    return C_integral(Type::i64(), i, false);
+pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
+    C_integral(Type::i64(ccx), i, false)
 }
 
-pub fn C_int(cx: &CrateContext, i: int) -> ValueRef {
-    return C_integral(cx.int_type, i as u64, true);
+pub fn C_int(ccx: &CrateContext, i: int) -> ValueRef {
+    C_integral(ccx.int_type, i as u64, true)
 }
 
-pub fn C_uint(cx: &CrateContext, i: uint) -> ValueRef {
-    return C_integral(cx.int_type, i as u64, false);
+pub fn C_uint(ccx: &CrateContext, i: uint) -> ValueRef {
+    C_integral(ccx.int_type, i as u64, false)
 }
 
-pub fn C_u8(i: uint) -> ValueRef {
-    return C_integral(Type::i8(), i as u64, false);
+pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef {
+    C_integral(Type::i8(ccx), i as u64, false)
 }
 
 
@@ -620,15 +617,15 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString) -> ValueRef {
 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
     unsafe {
         let len = s.get().len();
-        let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
-        C_struct([cs, C_uint(cx, len)], false)
+        let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p(cx).to_ref());
+        C_struct(cx, [cs, C_uint(cx, len)], false)
     }
 }
 
 pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
     unsafe {
         let len = data.len();
-        let lldata = C_bytes(data);
+        let lldata = C_bytes(cx, data);
 
         let gsym = token::gensym("binary");
         let g = format!("binary{}", gsym).with_c_str(|buf| {
@@ -638,25 +635,14 @@ pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
         llvm::LLVMSetGlobalConstant(g, True);
         lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
 
-        let cs = llvm::LLVMConstPointerCast(g, Type::i8p().to_ref());
-        C_struct([cs, C_uint(cx, len)], false)
+        let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+        C_struct(cx, [cs, C_uint(cx, len)], false)
     }
 }
 
-pub fn C_zero_byte_arr(size: uint) -> ValueRef {
+pub fn C_struct(ccx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
     unsafe {
-        let mut i = 0u;
-        let mut elts: Vec<ValueRef> = Vec::new();
-        while i < size { elts.push(C_u8(0u)); i += 1u; }
-        return llvm::LLVMConstArray(Type::i8().to_ref(),
-                                    elts.as_ptr(), elts.len() as c_uint);
-    }
-}
-
-pub fn C_struct(elts: &[ValueRef], packed: bool) -> ValueRef {
-    unsafe {
-
-        llvm::LLVMConstStructInContext(base::task_llcx(),
+        llvm::LLVMConstStructInContext(ccx.llcx,
                                        elts.as_ptr(), elts.len() as c_uint,
                                        packed as Bool)
     }
@@ -674,10 +660,10 @@ pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
     }
 }
 
-pub fn C_bytes(bytes: &[u8]) -> ValueRef {
+pub fn C_bytes(ccx: &CrateContext, bytes: &[u8]) -> ValueRef {
     unsafe {
         let ptr = bytes.as_ptr() as *c_char;
-        return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint, True);
+        return llvm::LLVMConstStringInContext(ccx.llcx, ptr, bytes.len() as c_uint, True);
     }
 }
 
@@ -860,12 +846,12 @@ pub fn node_vtables(bcx: &Block, id: ast::NodeId)
 // vtables. This should eliminate any vtable_params.
 pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
     -> typeck::vtable_res {
-    resolve_vtables_under_param_substs(fcx.ccx.tcx,
+    resolve_vtables_under_param_substs(fcx.ccx.tcx(),
                                        fcx.param_substs,
                                        vts)
 }
 
-pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
+pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
                                           param_substs: Option<@param_substs>,
                                           vts: typeck::vtable_res)
     -> typeck::vtable_res {
@@ -877,7 +863,7 @@ pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
 }
 
 pub fn resolve_param_vtables_under_param_substs(
-    tcx: ty::ctxt,
+    tcx: &ty::ctxt,
     param_substs: Option<@param_substs>,
     ds: typeck::vtable_param_res)
     -> typeck::vtable_param_res {
@@ -890,7 +876,7 @@ pub fn resolve_param_vtables_under_param_substs(
 
 
 
-pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
+pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
                                          param_substs: Option<@param_substs>,
                                          vt: &typeck::vtable_origin)
                                          -> typeck::vtable_origin {
@@ -926,7 +912,7 @@ pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
     }
 }
 
-pub fn find_vtable(tcx: ty::ctxt,
+pub fn find_vtable(tcx: &ty::ctxt,
                    ps: &param_substs,
                    n_param: typeck::param_index,
                    n_bound: uint)
@@ -955,17 +941,17 @@ pub fn dummy_substs(tps: Vec<ty::t> ) -> ty::substs {
 
 pub fn filename_and_line_num_from_span(bcx: &Block, span: Span)
                                        -> (ValueRef, ValueRef) {
-    let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
+    let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
     let filename_cstr = C_cstr(bcx.ccx(),
-                               token::intern_and_get_ident(loc.file.name));
-    let filename = build::PointerCast(bcx, filename_cstr, Type::i8p());
+                               token::intern_and_get_ident(loc.file.deref().name));
+    let filename = build::PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx()));
     let line = C_int(bcx.ccx(), loc.line as int);
     (filename, line)
 }
 
 // Casts a Rust bool value to an i1.
 pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
-    build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
+    build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false))
 }
 
 pub fn langcall(bcx: &Block,
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 9d55084c7f4..d9868637b8f 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -41,11 +41,11 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: ast::Lit)
     -> ValueRef {
     let _icx = push_ctxt("trans_lit");
     match lit.node {
-        ast::LitChar(i) => C_integral(Type::char(), i as u64, false),
+        ast::LitChar(i) => C_integral(Type::char(cx), i as u64, false),
         ast::LitInt(i, t) => C_integral(Type::int_from_ty(cx, t), i as u64, true),
         ast::LitUint(u, t) => C_integral(Type::uint_from_ty(cx, t), u, false),
         ast::LitIntUnsuffixed(i) => {
-            let lit_int_ty = ty::node_id_to_type(cx.tcx, e.id);
+            let lit_int_ty = ty::node_id_to_type(cx.tcx(), e.id);
             match ty::get(lit_int_ty).sty {
                 ty::ty_int(t) => {
                     C_integral(Type::int_from_ty(cx, t), i as u64, true)
@@ -53,28 +53,28 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: ast::Lit)
                 ty::ty_uint(t) => {
                     C_integral(Type::uint_from_ty(cx, t), i as u64, false)
                 }
-                _ => cx.sess.span_bug(lit.span,
+                _ => cx.sess().span_bug(lit.span,
                         format!("integer literal has type {} (expected int or uint)",
-                                ty_to_str(cx.tcx, lit_int_ty)))
+                                ty_to_str(cx.tcx(), lit_int_ty)))
             }
         }
         ast::LitFloat(ref fs, t) => {
-            C_floating(fs.get(), Type::float_from_ty(t))
+            C_floating(fs.get(), Type::float_from_ty(cx, t))
         }
         ast::LitFloatUnsuffixed(ref fs) => {
-            let lit_float_ty = ty::node_id_to_type(cx.tcx, e.id);
+            let lit_float_ty = ty::node_id_to_type(cx.tcx(), e.id);
             match ty::get(lit_float_ty).sty {
                 ty::ty_float(t) => {
-                    C_floating(fs.get(), Type::float_from_ty(t))
+                    C_floating(fs.get(), Type::float_from_ty(cx, t))
                 }
                 _ => {
-                    cx.sess.span_bug(lit.span,
+                    cx.sess().span_bug(lit.span,
                         "floating point literal doesn't have the right type");
                 }
             }
         }
-        ast::LitBool(b) => C_bool(b),
-        ast::LitNil => C_nil(),
+        ast::LitBool(b) => C_bool(cx, b),
+        ast::LitNil => C_nil(cx),
         ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
         ast::LitBinary(ref data) => C_binary_slice(cx, data.deref().as_slice()),
     }
@@ -89,15 +89,15 @@ pub fn const_ptrcast(cx: &CrateContext, a: ValueRef, t: Type) -> ValueRef {
     }
 }
 
-fn const_vec(cx: @CrateContext, e: &ast::Expr,
+fn const_vec(cx: &CrateContext, e: &ast::Expr,
              es: &[@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 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);
     let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e, is_local)));
     // If the vector contains enums, an LLVM array won't work.
     let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
-        C_struct(vs, false)
+        C_struct(cx, vs, false)
     } else {
         C_array(llunitty, vs)
     };
@@ -147,20 +147,20 @@ fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool)
                     const_deref_newtype(cx, v, t)
                 }
                 _ => {
-                    cx.sess.bug(format!("unexpected dereferenceable type {}",
-                                     ty_to_str(cx.tcx, t)))
+                    cx.sess().bug(format!("unexpected dereferenceable type {}",
+                                          ty_to_str(cx.tcx(), t)))
                 }
             };
             (dv, mt.ty)
         }
         None => {
-            cx.sess.bug(format!("can't dereference const of type {}",
-                             ty_to_str(cx.tcx, t)))
+            cx.sess().bug(format!("can't dereference const of type {}",
+                                  ty_to_str(cx.tcx(), t)))
         }
     }
 }
 
-pub fn get_const_val(cx: @CrateContext,
+pub fn get_const_val(cx: &CrateContext,
                      mut def_id: ast::DefId) -> (ValueRef, bool) {
     let contains_key = {
         let const_values = cx.const_values.borrow();
@@ -185,12 +185,12 @@ pub fn get_const_val(cx: @CrateContext,
      !non_inlineable_statics.get().contains(&def_id.node))
 }
 
-pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef, bool) {
+pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef, bool) {
     let (llconst, inlineable) = const_expr_unadjusted(cx, e, is_local);
     let mut llconst = llconst;
     let mut inlineable = inlineable;
-    let ety = ty::expr_ty(cx.tcx, e);
-    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx, e,
+    let ety = ty::expr_ty(cx.tcx(), e);
+    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e,
                                             cx.maps.method_map.borrow().get());
     let adjustment = {
         let adjustments = cx.tcx.adjustments.borrow();
@@ -201,16 +201,16 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
         Some(adj) => {
             match *adj {
                 ty::AutoAddEnv(ty::ReStatic, ast::BorrowedSigil) => {
-                    let def = ty::resolve_expr(cx.tcx, e);
+                    let def = ty::resolve_expr(cx.tcx(), e);
                     let wrapper = closure::get_wrapper_for_bare_fn(cx,
                                                                    ety_adjusted,
                                                                    def,
                                                                    llconst,
                                                                    is_local);
-                    llconst = C_struct([wrapper, C_null(Type::i8p())], false)
+                    llconst = C_struct(cx, [wrapper, C_null(Type::i8p(cx))], false)
                 }
                 ty::AutoAddEnv(ref r, ref s) => {
-                    cx.sess
+                    cx.sess()
                       .span_bug(e.span,
                                 format!("unexpected static function: region \
                                          {:?} sigil {:?}",
@@ -218,7 +218,7 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
                                         *s))
                 }
                 ty::AutoObject(..) => {
-                    cx.sess
+                    cx.sess()
                       .span_unimpl(e.span,
                                    "unimplemented const coercion to trait \
                                     object");
@@ -255,9 +255,8 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
                                     assert_eq!(abi::slice_elt_base, 0);
                                     assert_eq!(abi::slice_elt_len, 1);
                                     match ty::get(ty).sty {
-                                        ty::ty_vec(_,
-                                                   ty::vstore_fixed(len)) => {
-                                            llconst = C_struct([
+                                        ty::ty_vec(_, ty::vstore_fixed(len)) => {
+                                            llconst = C_struct(cx, [
                                                 llptr,
                                                 C_uint(cx, len)
                                             ], false);
@@ -266,11 +265,11 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
                                     }
                                 }
                                 _ => {
-                                    cx.sess.span_bug(e.span,
-                                                     format!("unimplemented \
-                                                              const autoref \
-                                                              {:?}",
-                                                             autoref))
+                                    cx.sess().span_bug(e.span,
+                                                       format!("unimplemented \
+                                                                const autoref \
+                                                                {:?}",
+                                                               autoref))
                                 }
                             }
                         }
@@ -289,8 +288,8 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
             llvm::LLVMDumpValue(llconst);
             llvm::LLVMDumpValue(C_undef(llty));
         }
-        cx.sess.bug(format!("const {} of type {} has size {} instead of {}",
-                         e.repr(cx.tcx), ty_to_str(cx.tcx, ety),
+        cx.sess().bug(format!("const {} of type {} has size {} instead of {}",
+                         e.repr(cx.tcx()), ty_to_str(cx.tcx(), ety),
                          csize, tsize));
     }
     (llconst, inlineable)
@@ -298,7 +297,7 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
 
 // the bool returned is whether this expression can be inlined into other crates
 // if it's assigned to a static.
-fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
+fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                          is_local: bool) -> (ValueRef, bool) {
     let map_list = |exprs: &[@ast::Expr]| {
         exprs.iter().map(|&e| const_expr(cx, e, is_local))
@@ -321,7 +320,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
 
             /* Neither type is bottom, and we expect them to be unified
              * already, so the following is safe. */
-            let ty = ty::expr_ty(cx.tcx, e1);
+            let ty = ty::expr_ty(cx.tcx(), e1);
             let is_float = ty::type_is_fp(ty);
             let signed = ty::type_is_signed(ty);
             return (match b {
@@ -397,7 +396,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
           },
           ast::ExprUnary(u, e) => {
             let (te, _) = const_expr(cx, e, is_local);
-            let ty = ty::expr_ty(cx.tcx, e);
+            let ty = ty::expr_ty(cx.tcx(), e);
             let is_float = ty::type_is_fp(ty);
             return (match u {
               ast::UnBox | ast::UnUniq | ast::UnDeref => {
@@ -409,9 +408,9 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                     ty::ty_bool => {
                         // Somewhat questionable, but I believe this is
                         // correct.
-                        let te = llvm::LLVMConstTrunc(te, Type::i1().to_ref());
+                        let te = llvm::LLVMConstTrunc(te, Type::i1(cx).to_ref());
                         let te = llvm::LLVMConstNot(te);
-                        llvm::LLVMConstZExt(te, Type::bool().to_ref())
+                        llvm::LLVMConstZExt(te, Type::bool(cx).to_ref())
                     }
                     _ => llvm::LLVMConstNot(te),
                 }
@@ -423,25 +422,25 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
             }, true)
           }
           ast::ExprField(base, field, _) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx, base,
+              let bt = ty::expr_ty_adjusted(cx.tcx(), base,
                                             cx.maps.method_map.borrow().get());
               let brepr = adt::represent_type(cx, bt);
               let (bv, inlineable) = const_expr(cx, base, is_local);
-              expr::with_field_tys(cx.tcx, bt, None, |discr, field_tys| {
-                  let ix = ty::field_idx_strict(cx.tcx, field.name, field_tys);
+              expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
+                  let ix = ty::field_idx_strict(cx.tcx(), field.name, field_tys);
                   (adt::const_get_field(cx, brepr, bv, discr, ix), inlineable)
               })
           }
 
           ast::ExprIndex(base, index) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx, base,
+              let bt = ty::expr_ty_adjusted(cx.tcx(), base,
                                             cx.maps.method_map.borrow().get());
               let (bv, inlineable) = const_expr(cx, base, is_local);
-              let iv = match const_eval::eval_const_expr(cx.tcx, index) {
+              let iv = match const_eval::eval_const_expr(cx.tcx(), index) {
                   const_eval::const_int(i) => i as u64,
                   const_eval::const_uint(u) => u,
-                  _ => cx.sess.span_bug(index.span,
-                                        "index is not an integer-constant expression")
+                  _ => cx.sess().span_bug(index.span,
+                                          "index is not an integer-constant expression")
               };
               let (arr, len) = match ty::get(bt).sty {
                   ty::ty_vec(_, vstore) | ty::ty_str(vstore) =>
@@ -453,11 +452,11 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                           let e1 = const_get_elt(cx, bv, [0]);
                           (const_deref_ptr(cx, e1), const_get_elt(cx, bv, [1]))
                       },
-                      _ => cx.sess.span_bug(base.span,
-                                            "index-expr base must be fixed-size or slice")
+                      _ => cx.sess().span_bug(base.span,
+                                              "index-expr base must be fixed-size or slice")
                   },
-                  _ =>  cx.sess.span_bug(base.span,
-                                         "index-expr base must be a vector or string type")
+                  _ =>  cx.sess().span_bug(base.span,
+                                           "index-expr base must be a vector or string type")
               };
 
               let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
@@ -468,15 +467,15 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
               if iv >= len {
                   // FIXME #3170: report this earlier on in the const-eval
                   // pass. Reporting here is a bit late.
-                  cx.sess.span_err(e.span,
-                                   "const index-expr is out of bounds");
+                  cx.sess().span_err(e.span,
+                                     "const index-expr is out of bounds");
               }
               (const_get_elt(cx, arr, [iv as c_uint]), inlineable)
           }
           ast::ExprCast(base, _) => {
-            let ety = ty::expr_ty(cx.tcx, e);
+            let ety = ty::expr_ty(cx.tcx(), e);
             let llty = type_of::type_of(cx, ety);
-            let basety = ty::expr_ty(cx.tcx, base);
+            let basety = ty::expr_ty(cx.tcx(), base);
             let (v, inlineable) = const_expr(cx, base, is_local);
             return (match (expr::cast_type_kind(basety),
                            expr::cast_type_kind(ety)) {
@@ -511,8 +510,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                         llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
                     }
                     expr::cast_float => llvm::LLVMConstUIToFP(iv, llty.to_ref()),
-                    _ => cx.sess.bug("enum cast destination is not \
-                                      integral or float")
+                    _ => cx.sess().bug("enum cast destination is not \
+                                        integral or float")
                 }
               }
               (expr::cast_pointer, expr::cast_pointer) => {
@@ -522,8 +521,8 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                 llvm::LLVMConstIntToPtr(v, llty.to_ref())
               }
               _ => {
-                cx.sess.impossible_case(e.span,
-                                        "bad combination of types for cast")
+                cx.sess().impossible_case(e.span,
+                                          "bad combination of types for cast")
               }
             }, inlineable)
           }
@@ -532,15 +531,15 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
               (const_addr_of(cx, e), false)
           }
           ast::ExprTup(ref es) => {
-              let ety = ty::expr_ty(cx.tcx, e);
+              let ety = ty::expr_ty(cx.tcx(), e);
               let repr = adt::represent_type(cx, ety);
               let (vals, inlineable) = map_list(es.as_slice());
               (adt::trans_const(cx, repr, 0, vals.as_slice()), inlineable)
           }
           ast::ExprStruct(_, ref fs, ref base_opt) => {
-              let ety = ty::expr_ty(cx.tcx, e);
+              let ety = ty::expr_ty(cx.tcx(), e);
               let repr = adt::represent_type(cx, ety);
-              let tcx = cx.tcx;
+              let tcx = cx.tcx();
 
               let base_val = match *base_opt {
                 Some(base) => Some(const_expr(cx, base, is_local)),
@@ -558,7 +557,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                                     (adt::const_get_field(cx, repr, bv, discr, ix),
                                      inlineable)
                                 }
-                                None => cx.tcx.sess.span_bug(e.span, "missing struct field")
+                                None => cx.sess().span_bug(e.span, "missing struct field")
                               }
                           }
                       }
@@ -580,7 +579,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
               ast::ExprLit(ref lit) => {
                 match lit.node {
                     ast::LitStr(..) => { const_expr(cx, sub, is_local) }
-                    _ => { cx.sess.span_bug(e.span, "bad const-slice lit") }
+                    _ => { cx.sess().span_bug(e.span, "bad const-slice lit") }
                 }
               }
               ast::ExprVec(ref es, ast::MutImmutable) => {
@@ -596,23 +595,23 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                 llvm::LLVMSetGlobalConstant(gv, True);
                 SetLinkage(gv, PrivateLinkage);
                 let p = const_ptrcast(cx, gv, llunitty);
-                (C_struct([p, C_uint(cx, es.len())], false), false)
+                (C_struct(cx, [p, C_uint(cx, es.len())], false), false)
               }
-              _ => cx.sess.span_bug(e.span, "bad const-slice expr")
+              _ => cx.sess().span_bug(e.span, "bad const-slice expr")
             }
           }
           ast::ExprRepeat(elem, count, _) => {
-            let vec_ty = ty::expr_ty(cx.tcx, e);
-            let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
+            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);
-            let n = match const_eval::eval_const_expr(cx.tcx, count) {
+            let n = match const_eval::eval_const_expr(cx.tcx(), count) {
                 const_eval::const_int(i)  => i as uint,
                 const_eval::const_uint(i) => i as uint,
-                _ => cx.sess.span_bug(count.span, "count must be integral const expression.")
+                _ => cx.sess().span_bug(count.span, "count must be integral const expression.")
             };
             let vs = vec::from_elem(n, const_expr(cx, elem, is_local).val0());
             let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
-                C_struct(vs, false)
+                C_struct(cx, vs, false)
             } else {
                 C_array(llunitty, vs)
             };
@@ -622,7 +621,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
             // Assert that there are no type parameters in this path.
             assert!(pth.segments.iter().all(|seg| seg.types.is_empty()));
 
-            let tcx = cx.tcx;
+            let tcx = cx.tcx();
             let opt_def = {
                 let def_map = tcx.def_map.borrow();
                 def_map.get().find_copy(&e.id)
@@ -630,7 +629,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
             match opt_def {
                 Some(ast::DefFn(def_id, _purity)) => {
                     if !ast_util::is_local(def_id) {
-                        let ty = csearch::get_type(cx.tcx, def_id).ty;
+                        let ty = csearch::get_type(cx.tcx(), def_id).ty;
                         (base::trans_external_path(cx, def_id, ty), true)
                     } else {
                         assert!(ast_util::is_local(def_id));
@@ -641,41 +640,41 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                     get_const_val(cx, def_id)
                 }
                 Some(ast::DefVariant(enum_did, variant_did, _)) => {
-                    let ety = ty::expr_ty(cx.tcx, e);
+                    let ety = ty::expr_ty(cx.tcx(), e);
                     let repr = adt::represent_type(cx, ety);
-                    let vinfo = ty::enum_variant_with_id(cx.tcx,
+                    let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                          enum_did,
                                                          variant_did);
                     (adt::trans_const(cx, repr, vinfo.disr_val, []), true)
                 }
                 Some(ast::DefStruct(_)) => {
-                    let ety = ty::expr_ty(cx.tcx, e);
+                    let ety = ty::expr_ty(cx.tcx(), e);
                     let llty = type_of::type_of(cx, ety);
                     (C_null(llty), true)
                 }
                 _ => {
-                    cx.sess.span_bug(e.span, "expected a const, fn, struct, or variant def")
+                    cx.sess().span_bug(e.span, "expected a const, fn, struct, or variant def")
                 }
             }
           }
           ast::ExprCall(callee, ref args) => {
-              let tcx = cx.tcx;
+              let tcx = cx.tcx();
               let opt_def = {
                   let def_map = tcx.def_map.borrow();
                   def_map.get().find_copy(&callee.id)
               };
               match opt_def {
                   Some(ast::DefStruct(_)) => {
-                      let ety = ty::expr_ty(cx.tcx, e);
+                      let ety = ty::expr_ty(cx.tcx(), e);
                       let repr = adt::represent_type(cx, ety);
                       let (arg_vals, inlineable) = map_list(args.as_slice());
                       (adt::trans_const(cx, repr, 0, arg_vals.as_slice()),
                        inlineable)
                   }
                   Some(ast::DefVariant(enum_did, variant_did, _)) => {
-                      let ety = ty::expr_ty(cx.tcx, e);
+                      let ety = ty::expr_ty(cx.tcx(), e);
                       let repr = adt::represent_type(cx, ety);
-                      let vinfo = ty::enum_variant_with_id(cx.tcx,
+                      let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                            enum_did,
                                                            variant_did);
                       let (arg_vals, inlineable) = map_list(args.as_slice());
@@ -684,17 +683,17 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
                                         vinfo.disr_val,
                                         arg_vals.as_slice()), inlineable)
                   }
-                  _ => cx.sess.span_bug(e.span, "expected a struct or variant def")
+                  _ => cx.sess().span_bug(e.span, "expected a struct or variant def")
               }
           }
           ast::ExprParen(e) => { const_expr(cx, e, is_local) }
-          _ => cx.sess.span_bug(e.span,
+          _ => cx.sess().span_bug(e.span,
                   "bad constant expression type in consts::const_expr")
         };
     }
 }
 
-pub fn trans_const(ccx: @CrateContext, m: ast::Mutability, id: ast::NodeId) {
+pub fn trans_const(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
     unsafe {
         let _icx = push_ctxt("trans_const");
         let g = base::get_item_val(ccx, id);
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index 80dcfc90287..4ed4f0fb310 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 
-use driver::session;
 use driver::session::NoDebugInfo;
+use driver::session::Session;
 use lib::llvm::{ContextRef, ModuleRef, ValueRef};
 use lib::llvm::{llvm, TargetData, TypeNames};
 use lib::llvm::mk_target_data;
@@ -31,15 +31,14 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap};
 
 use std::cell::{Cell, RefCell};
 use std::c_str::ToCStr;
-use std::local_data;
 use std::libc::c_uint;
+use std::ptr;
 use std::vec_ng::Vec;
 use collections::{HashMap, HashSet};
 use syntax::ast;
 use syntax::parse::token::InternedString;
 
 pub struct CrateContext {
-    sess: session::Session,
     llmod: ModuleRef,
     llcx: ContextRef,
     metadata_llmod: ModuleRef,
@@ -49,7 +48,7 @@ pub struct CrateContext {
     intrinsics: HashMap<&'static str, ValueRef>,
     item_vals: RefCell<NodeMap<ValueRef>>,
     exp_map2: resolve::ExportMap2,
-    reachable: @RefCell<NodeSet>,
+    reachable: NodeSet,
     item_symbols: RefCell<NodeMap<~str>>,
     link_meta: LinkMeta,
     drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
@@ -104,7 +103,6 @@ pub struct CrateContext {
     tcx: ty::ctxt,
     maps: astencode::Maps,
     stats: @Stats,
-    tydesc_type: Type,
     int_type: Type,
     opaque_vec_type: Type,
     builder: BuilderRef_res,
@@ -115,131 +113,129 @@ pub struct CrateContext {
     // is not emitted by LLVM's GC pass when no functions use GC.
     uses_gc: bool,
     dbg_cx: Option<debuginfo::CrateDebugContext>,
-    do_not_commit_warning_issued: Cell<bool>,
 }
 
 impl CrateContext {
-    pub fn new(sess: session::Session,
-               name: &str,
+    pub fn new(name: &str,
                tcx: ty::ctxt,
                emap2: resolve::ExportMap2,
                maps: astencode::Maps,
                symbol_hasher: Sha256,
                link_meta: LinkMeta,
-               reachable: @RefCell<NodeSet>)
+               reachable: NodeSet)
                -> CrateContext {
         unsafe {
             let llcx = llvm::LLVMContextCreate();
-            set_task_llcx(llcx);
             let llmod = name.with_c_str(|buf| {
                 llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
             });
             let metadata_llmod = format!("{}_metadata", name).with_c_str(|buf| {
                 llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
             });
-            let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
-            let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
-            data_layout.with_c_str(|buf| {
+            tcx.sess.targ_cfg.target_strs.data_layout.with_c_str(|buf| {
                 llvm::LLVMSetDataLayout(llmod, buf);
                 llvm::LLVMSetDataLayout(metadata_llmod, buf);
             });
-            targ_triple.with_c_str(|buf| {
+            tcx.sess.targ_cfg.target_strs.target_triple.with_c_str(|buf| {
                 llvm::LLVMRustSetNormalizedTarget(llmod, buf);
                 llvm::LLVMRustSetNormalizedTarget(metadata_llmod, buf);
             });
-            let targ_cfg = sess.targ_cfg;
 
-            let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
-            let tn = TypeNames::new();
+            let td = mk_target_data(tcx.sess.targ_cfg.target_strs.data_layout);
 
-            let mut intrinsics = base::declare_intrinsics(llmod);
-            if sess.opts.debuginfo != NoDebugInfo {
-                base::declare_dbg_intrinsics(llmod, &mut intrinsics);
-            }
-            let int_type = Type::int(targ_cfg.arch);
-            let tydesc_type = Type::tydesc(targ_cfg.arch);
-            let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
-
-            let mut str_slice_ty = Type::named_struct("str_slice");
-            str_slice_ty.set_struct_body([Type::i8p(), int_type], false);
-
-            tn.associate_type("tydesc", &tydesc_type);
-            tn.associate_type("str_slice", &str_slice_ty);
-
-            let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod);
-            let dbg_cx = if sess.opts.debuginfo != NoDebugInfo {
+            let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
                 Some(debuginfo::CrateDebugContext::new(llmod))
             } else {
                 None
             };
 
-            if sess.count_llvm_insns() {
+            let mut ccx = CrateContext {
+                llmod: llmod,
+                llcx: llcx,
+                metadata_llmod: metadata_llmod,
+                td: td,
+                tn: TypeNames::new(),
+                externs: RefCell::new(HashMap::new()),
+                intrinsics: HashMap::new(),
+                item_vals: RefCell::new(NodeMap::new()),
+                exp_map2: emap2,
+                reachable: reachable,
+                item_symbols: RefCell::new(NodeMap::new()),
+                link_meta: link_meta,
+                drop_glues: RefCell::new(HashMap::new()),
+                tydescs: RefCell::new(HashMap::new()),
+                finished_tydescs: Cell::new(false),
+                external: RefCell::new(DefIdMap::new()),
+                external_srcs: RefCell::new(NodeMap::new()),
+                non_inlineable_statics: RefCell::new(NodeSet::new()),
+                monomorphized: RefCell::new(HashMap::new()),
+                monomorphizing: RefCell::new(DefIdMap::new()),
+                vtables: RefCell::new(HashMap::new()),
+                const_cstr_cache: RefCell::new(HashMap::new()),
+                const_globals: RefCell::new(HashMap::new()),
+                const_values: RefCell::new(NodeMap::new()),
+                extern_const_values: RefCell::new(DefIdMap::new()),
+                impl_method_cache: RefCell::new(HashMap::new()),
+                closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
+                lltypes: RefCell::new(HashMap::new()),
+                llsizingtypes: RefCell::new(HashMap::new()),
+                adt_reprs: RefCell::new(HashMap::new()),
+                symbol_hasher: RefCell::new(symbol_hasher),
+                type_hashcodes: RefCell::new(HashMap::new()),
+                all_llvm_symbols: RefCell::new(HashSet::new()),
+                tcx: tcx,
+                maps: maps,
+                stats: @Stats {
+                    n_static_tydescs: Cell::new(0u),
+                    n_glues_created: Cell::new(0u),
+                    n_null_glues: Cell::new(0u),
+                    n_real_glues: Cell::new(0u),
+                    n_fns: Cell::new(0u),
+                    n_monos: Cell::new(0u),
+                    n_inlines: Cell::new(0u),
+                    n_closures: Cell::new(0u),
+                    n_llvm_insns: Cell::new(0u),
+                    llvm_insns: RefCell::new(HashMap::new()),
+                    fn_stats: RefCell::new(Vec::new()),
+                },
+                int_type: Type::from_ref(ptr::null()),
+                opaque_vec_type: Type::from_ref(ptr::null()),
+                builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
+                crate_map: ptr::null(),
+                crate_map_name: ~"",
+                uses_gc: false,
+                dbg_cx: dbg_cx,
+            };
+
+            ccx.int_type = Type::int(&ccx);
+            ccx.opaque_vec_type = Type::opaque_vec(&ccx);
+
+            ccx.tn.associate_type("tydesc", &Type::tydesc(&ccx));
+
+            let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
+            str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type], false);
+            ccx.tn.associate_type("str_slice", &str_slice_ty);
+
+            decl_crate_map(&mut ccx);
+
+            base::declare_intrinsics(&mut ccx);
+
+            if ccx.sess().count_llvm_insns() {
                 base::init_insn_ctxt()
             }
 
-            CrateContext {
-                 sess: sess,
-                 llmod: llmod,
-                 llcx: llcx,
-                 metadata_llmod: metadata_llmod,
-                 td: td,
-                 tn: tn,
-                 externs: RefCell::new(HashMap::new()),
-                 intrinsics: intrinsics,
-                 item_vals: RefCell::new(NodeMap::new()),
-                 exp_map2: emap2,
-                 reachable: reachable,
-                 item_symbols: RefCell::new(NodeMap::new()),
-                 link_meta: link_meta,
-                 drop_glues: RefCell::new(HashMap::new()),
-                 tydescs: RefCell::new(HashMap::new()),
-                 finished_tydescs: Cell::new(false),
-                 external: RefCell::new(DefIdMap::new()),
-                 external_srcs: RefCell::new(NodeMap::new()),
-                 non_inlineable_statics: RefCell::new(NodeSet::new()),
-                 monomorphized: RefCell::new(HashMap::new()),
-                 monomorphizing: RefCell::new(DefIdMap::new()),
-                 vtables: RefCell::new(HashMap::new()),
-                 const_cstr_cache: RefCell::new(HashMap::new()),
-                 const_globals: RefCell::new(HashMap::new()),
-                 const_values: RefCell::new(NodeMap::new()),
-                 extern_const_values: RefCell::new(DefIdMap::new()),
-                 impl_method_cache: RefCell::new(HashMap::new()),
-                 closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
-                 lltypes: RefCell::new(HashMap::new()),
-                 llsizingtypes: RefCell::new(HashMap::new()),
-                 adt_reprs: RefCell::new(HashMap::new()),
-                 symbol_hasher: RefCell::new(symbol_hasher),
-                 type_hashcodes: RefCell::new(HashMap::new()),
-                 all_llvm_symbols: RefCell::new(HashSet::new()),
-                 tcx: tcx,
-                 maps: maps,
-                 stats: @Stats {
-                   n_static_tydescs: Cell::new(0u),
-                   n_glues_created: Cell::new(0u),
-                   n_null_glues: Cell::new(0u),
-                   n_real_glues: Cell::new(0u),
-                   n_fns: Cell::new(0u),
-                   n_monos: Cell::new(0u),
-                   n_inlines: Cell::new(0u),
-                   n_closures: Cell::new(0u),
-                   n_llvm_insns: Cell::new(0u),
-                   llvm_insns: RefCell::new(HashMap::new()),
-                   fn_stats: RefCell::new(Vec::new()),
-                 },
-                 tydesc_type: tydesc_type,
-                 int_type: int_type,
-                 opaque_vec_type: opaque_vec_type,
-                 builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
-                 crate_map: crate_map,
-                 crate_map_name: crate_map_name,
-                 uses_gc: false,
-                 dbg_cx: dbg_cx,
-                 do_not_commit_warning_issued: Cell::new(false),
-            }
+            ccx
         }
     }
 
+    pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
+        &self.tcx
+    }
+
+    pub fn sess<'a>(&'a self) -> &'a Session {
+        &self.tcx.sess
+    }
+
     pub fn builder<'a>(&'a self) -> Builder<'a> {
         Builder::new(self)
     }
@@ -250,7 +246,7 @@ impl CrateContext {
         debug!("const_inbounds_gepi: pointer={} indices={:?}",
                self.tn.val_to_str(pointer), indices);
         let v: Vec<ValueRef> =
-            indices.iter().map(|i| C_i32(*i as i32)).collect();
+            indices.iter().map(|i| C_i32(self, *i as i32)).collect();
         unsafe {
             llvm::LLVMConstInBoundsGEP(pointer,
                                        v.as_ptr(),
@@ -273,26 +269,8 @@ impl CrateContext {
                                     self.int_type.to_ref())
         }
     }
-}
 
-#[unsafe_destructor]
-impl Drop for CrateContext {
-    fn drop(&mut self) {
-        unset_task_llcx();
+    pub fn tydesc_type(&self) -> Type {
+        self.tn.find_type("tydesc").unwrap()
     }
 }
-
-local_data_key!(task_local_llcx_key: @ContextRef)
-
-pub fn task_llcx() -> ContextRef {
-    let opt = local_data::get(task_local_llcx_key, |k| k.map(|k| *k));
-    *opt.expect("task-local LLVMContextRef wasn't ever set!")
-}
-
-fn set_task_llcx(c: ContextRef) {
-    local_data::set(task_local_llcx_key, @c);
-}
-
-fn unset_task_llcx() {
-    local_data::pop(task_local_llcx_key);
-}
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 261660c13bb..2796eaeb129 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -331,16 +331,14 @@ pub fn trans_fail<'a>(
                   sp: Span,
                   fail_str: InternedString)
                   -> &'a Block<'a> {
-    let v_fail_str = C_cstr(bcx.ccx(), fail_str);
-    let _icx = push_ctxt("trans_fail_value");
     let ccx = bcx.ccx();
-    let sess = bcx.sess();
-    let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo);
-    let v_filename = C_cstr(bcx.ccx(),
-                            token::intern_and_get_ident(loc.file.name));
+    let v_fail_str = C_cstr(ccx, fail_str);
+    let _icx = push_ctxt("trans_fail_value");
+    let loc = bcx.sess().codemap().lookup_char_pos(sp.lo);
+    let v_filename = C_cstr(ccx, token::intern_and_get_ident(loc.file.deref().name));
     let v_line = loc.line as int;
-    let v_str = PointerCast(bcx, v_fail_str, Type::i8p());
-    let v_filename = PointerCast(bcx, v_filename, Type::i8p());
+    let v_str = PointerCast(bcx, v_fail_str, Type::i8p(ccx));
+    let v_filename = PointerCast(bcx, v_filename, Type::i8p(ccx));
     let args = vec!(v_str, v_filename, C_int(ccx, v_line));
     let did = langcall(bcx, Some(sp), "", FailFnLangItem);
     let bcx = callee::trans_lang_call(bcx,
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index fe848c429ae..c334971db59 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -635,7 +635,7 @@ impl<K:KindOps> Datum<K> {
     pub fn to_str(&self, ccx: &CrateContext) -> ~str {
         format!("Datum({}, {}, {:?})",
              ccx.tn.val_to_str(self.val),
-             ty_to_str(ccx.tcx, self.ty),
+             ty_to_str(ccx.tcx(), self.ty),
              self.kind)
     }
 
@@ -709,11 +709,11 @@ impl<'a> DatumBlock<'a, Expr> {
         self.datum.shallow_copy(self.bcx, dst)
     }
 
-    pub fn ccx(&self) -> @CrateContext {
+    pub fn ccx(&self) -> &'a CrateContext {
         self.bcx.ccx()
     }
 
-    pub fn tcx(&self) -> ty::ctxt {
+    pub fn tcx(&self) -> &'a ty::ctxt {
         self.bcx.tcx()
     }
 
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index dd6a3e61b69..b044ee15b3b 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -213,10 +213,10 @@ impl FunctionDebugContext {
         match *self {
             FunctionDebugContext(~ref data) => data,
             DebugInfoDisabled => {
-                cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
+                cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
             }
             FunctionWithoutDebugInfo => {
-                cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message());
+                cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
             }
         }
     }
@@ -253,7 +253,7 @@ enum VariableKind {
 }
 
 /// Create any deferred debug metadata nodes
-pub fn finalize(cx: @CrateContext) {
+pub fn finalize(cx: &CrateContext) {
     if cx.dbg_cx.is_none() {
         return;
     }
@@ -268,7 +268,7 @@ pub fn finalize(cx: @CrateContext) {
         // instruct LLVM to emit an older version of dwarf, however,
         // for OS X to understand. For more info see #11352
         // This can be overridden using --llvm-opts -dwarf-version,N.
-        if cx.sess.targ_cfg.os == abi::OsMacos {
+        if cx.sess().targ_cfg.os == abi::OsMacos {
             "Dwarf Version".with_c_str(
                 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
         }
@@ -299,7 +299,7 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
             match lllocals.get().find_copy(&node_id) {
                 Some(datum) => datum,
                 None => {
-                    bcx.tcx().sess.span_bug(span,
+                    bcx.sess().span_bug(span,
                         format!("no entry in lllocals table for {:?}",
                                 node_id));
                 }
@@ -338,7 +338,7 @@ pub fn create_captured_var_metadata(bcx: &Block,
 
     let variable_ident = match ast_item {
         None => {
-            cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
+            cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
         }
         Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
             match pat.node {
@@ -346,7 +346,7 @@ pub fn create_captured_var_metadata(bcx: &Block,
                     ast_util::path_to_ident(path)
                 }
                 _ => {
-                    cx.sess
+                    cx.sess()
                       .span_bug(span,
                                 format!(
                                 "debuginfo::create_captured_var_metadata() - \
@@ -357,7 +357,7 @@ pub fn create_captured_var_metadata(bcx: &Block,
             }
         }
         _ => {
-            cx.sess.span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
+            cx.sess().span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
                 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
         }
     };
@@ -369,10 +369,10 @@ pub fn create_captured_var_metadata(bcx: &Block,
     let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
 
     let address_operations = unsafe {
-        [llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref()),
-         llvm::LLVMDIBuilderCreateOpPlus(Type::i64().to_ref()),
-         C_i64(byte_offset_of_var_in_env as i64),
-         llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref())]
+        [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
+         llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
+         C_i64(cx, byte_offset_of_var_in_env as i64),
+         llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
     };
 
     let address_op_count = match closure_sigil {
@@ -441,7 +441,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
             match llargs.get().find_copy(&node_id) {
                 Some(v) => v,
                 None => {
-                    bcx.tcx().sess.span_bug(span,
+                    bcx.sess().span_bug(span,
                         format!("no entry in llargs table for {:?}",
                                 node_id));
                 }
@@ -449,7 +449,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
         };
 
         if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
-            cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \
+            cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
                                     Referenced variable location is not an alloca!");
         }
 
@@ -485,7 +485,7 @@ pub fn set_source_location(fcx: &FunctionContext,
 
     let cx = fcx.ccx;
 
-    debug!("set_source_location: {}", cx.sess.codemap.span_to_str(span));
+    debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
 
     if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
         let loc = span_start(cx, span);
@@ -532,7 +532,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                                      fn_ast_id: ast::NodeId,
                                      param_substs: Option<@param_substs>,
                                      llfn: ValueRef) -> FunctionDebugContext {
-    if cx.sess.opts.debuginfo == NoDebugInfo {
+    if cx.sess().opts.debuginfo == NoDebugInfo {
         return DebugInfoDisabled;
     }
 
@@ -551,7 +551,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                     (item.ident, fn_decl, generics, top_level_block, item.span, true)
                 }
                 _ => {
-                    cx.sess.span_bug(item.span,
+                    cx.sess().span_bug(item.span,
                         "create_function_debug_context: item bound to non-function");
                 }
             }
@@ -579,7 +579,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                         // Don't try to lookup the item path:
                         false)
                 }
-                _ => cx.sess.span_bug(expr.span,
+                _ => cx.sess().span_bug(expr.span,
                         "create_function_debug_context: expected an expr_fn_block here")
             }
         }
@@ -594,7 +594,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                      true)
                 }
                 _ => {
-                    cx.sess
+                    cx.sess()
                       .bug(format!("create_function_debug_context: \
                                     unexpected sort of node: {:?}",
                                     fnitem))
@@ -606,8 +606,8 @@ pub fn create_function_debug_context(cx: &CrateContext,
         ast_map::NodeStructCtor(..) => {
             return FunctionWithoutDebugInfo;
         }
-        _ => cx.sess.bug(format!("create_function_debug_context: \
-                                  unexpected sort of node: {:?}", fnitem))
+        _ => cx.sess().bug(format!("create_function_debug_context: \
+                                    unexpected sort of node: {:?}", fnitem))
     };
 
     // This can be the case for functions inlined from another crate
@@ -616,7 +616,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
     }
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
     let function_type_metadata = unsafe {
         let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
@@ -652,10 +652,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
     // (by being externally visible or by being inlined into something externally visible). It might
     // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
     // this set is not available in the translation pass.
-    let is_local_to_unit = {
-        let reachable = cx.reachable.borrow();
-        !reachable.get().contains(&fn_ast_id)
-    };
+    let is_local_to_unit = !cx.reachable.contains(&fn_ast_id);
 
     let fn_metadata = function_name.with_c_str(|function_name| {
                           linkage_name.with_c_str(|linkage_name| {
@@ -672,7 +669,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                     true,
                     scope_line as c_uint,
                     FlagPrototyped as c_uint,
-                    cx.sess.opts.optimize != session::No,
+                    cx.sess().opts.optimize != session::No,
                     llfn,
                     template_parameters,
                     ptr::null())
@@ -708,7 +705,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                               fn_decl: &ast::FnDecl,
                               param_substs: Option<@param_substs>,
                               error_span: Span) -> DIArray {
-        if cx.sess.opts.debuginfo == LimitedDebugInfo {
+        if cx.sess().opts.debuginfo == LimitedDebugInfo {
             return create_DIArray(DIB(cx), []);
         }
 
@@ -722,11 +719,11 @@ pub fn create_function_debug_context(cx: &CrateContext,
             _ => {
                 assert_type_for_node_id(cx, fn_ast_id, error_span);
 
-                let return_type = ty::node_id_to_type(cx.tcx, fn_ast_id);
+                let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
                 let return_type = match param_substs {
                     None => return_type,
                     Some(substs) => {
-                        ty::subst_tps(cx.tcx,
+                        ty::subst_tps(cx.tcx(),
                                       substs.tys.as_slice(),
                                       substs.self_ty,
                                       return_type)
@@ -740,11 +737,11 @@ pub fn create_function_debug_context(cx: &CrateContext,
         // Arguments types
         for arg in fn_decl.inputs.iter() {
             assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
-            let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id);
+            let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
             let arg_type = match param_substs {
                 None => arg_type,
                 Some(substs) => {
-                    ty::subst_tps(cx.tcx,
+                    ty::subst_tps(cx.tcx(),
                                   substs.tys.as_slice(),
                                   substs.self_ty,
                                   arg_type)
@@ -785,7 +782,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
         if has_self_type {
             let actual_self_type = self_type.unwrap();
             // Add self type name to <...> clause of function name
-            let actual_self_type_name = ppaux::ty_to_str(cx.tcx, actual_self_type);
+            let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
             name_to_append_suffix_to.push_str(actual_self_type_name);
 
             if generics.is_type_parameterized() {
@@ -793,7 +790,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
             }
 
             // Only create type information if full debuginfo is enabled
-            if cx.sess.opts.debuginfo == FullDebugInfo {
+            if cx.sess().opts.debuginfo == FullDebugInfo {
                 let actual_self_type_metadata = type_metadata(cx,
                                                               actual_self_type,
                                                               codemap::DUMMY_SP);
@@ -829,7 +826,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
         for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
             let actual_type = *actual_types.get(index);
             // Add actual type name to <...> clause of function name
-            let actual_type_name = ppaux::ty_to_str(cx.tcx, actual_type);
+            let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
             name_to_append_suffix_to.push_str(actual_type_name);
 
             if index != generics.ty_params.len() - 1 {
@@ -837,7 +834,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
             }
 
             // Again, only create type information if full debuginfo is enabled
-            if cx.sess.opts.debuginfo == FullDebugInfo {
+            if cx.sess().opts.debuginfo == FullDebugInfo {
                 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
                 let param_metadata = token::get_ident(ident).get()
                                                             .with_c_str(|name| {
@@ -873,12 +870,12 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
 }
 
 fn compile_unit_metadata(cx: &CrateContext) {
-    let work_dir = &cx.sess.working_dir;
-    let compile_unit_name = match cx.sess.local_crate_source_file {
+    let work_dir = &cx.sess().working_dir;
+    let compile_unit_name = match cx.sess().local_crate_source_file {
         None => fallback_path(cx),
         Some(ref abs_path) => {
             if abs_path.is_relative() {
-                cx.sess.warn("debuginfo: Invalid path to crate's local root source file!");
+                cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
                 fallback_path(cx)
             } else {
                 match abs_path.path_relative_from(work_dir) {
@@ -917,7 +914,7 @@ fn compile_unit_metadata(cx: &CrateContext) {
                                 compile_unit_name,
                                 work_dir,
                                 producer,
-                                cx.sess.opts.optimize != session::No,
+                                cx.sess().opts.optimize != session::No,
                                 flags,
                                 0,
                                 split_name);
@@ -942,7 +939,7 @@ fn declare_local(bcx: &Block,
                  span: Span) {
     let cx: &CrateContext = bcx.ccx();
 
-    let filename = span_start(cx, span).file.name.clone();
+    let filename = span_start(cx, span).file.deref().name.clone();
     let file_metadata = file_metadata(cx, filename);
 
     let name = token::get_ident(variable_ident);
@@ -968,7 +965,7 @@ fn declare_local(bcx: &Block,
                         file_metadata,
                         loc.line as c_uint,
                         type_metadata,
-                        cx.sess.opts.optimize != session::No,
+                        cx.sess().opts.optimize != session::No,
                         0,
                         argument_index)
                 }
@@ -1028,7 +1025,7 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
     debug!("file_metadata: {}", full_path);
 
     // FIXME (#9639): This needs to handle non-utf8 paths
-    let work_dir = cx.sess.working_dir.as_str().unwrap();
+    let work_dir = cx.sess().working_dir.as_str().unwrap();
     let file_name =
         if full_path.starts_with(work_dir) {
             full_path.slice(work_dir.len() + 1u, full_path.len())
@@ -1063,7 +1060,7 @@ fn scope_metadata(fcx: &FunctionContext,
         None => {
             let node = fcx.ccx.tcx.map.get(node_id);
 
-            fcx.ccx.sess.span_bug(span,
+            fcx.ccx.sess().span_bug(span,
                 format!("debuginfo: Could not find scope info for node {:?}", node));
         }
     }
@@ -1096,7 +1093,7 @@ fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
             ast::TyF32 => (~"f32", DW_ATE_float),
             ast::TyF64 => (~"f64", DW_ATE_float)
         },
-        _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type")
+        _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
     };
 
     let llvm_type = type_of::type_of(cx, t);
@@ -1121,7 +1118,7 @@ fn pointer_type_metadata(cx: &CrateContext,
                       -> DIType {
     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
-    let name = ppaux::ty_to_str(cx.tcx, pointer_type);
+    let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
     let ptr_metadata = name.with_c_str(|name| {
         unsafe {
             llvm::LLVMDIBuilderCreatePointerType(
@@ -1193,12 +1190,12 @@ fn prepare_struct_metadata(cx: &CrateContext,
                            substs: &ty::substs,
                            span: Span)
                         -> RecursiveTypeDescription {
-    let struct_name = ppaux::ty_to_str(cx.tcx, struct_type);
+    let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
     let struct_llvm_type = type_of::type_of(cx, struct_type);
 
     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
 
-    let file_name = span_start(cx, definition_span).file.name.clone();
+    let file_name = span_start(cx, definition_span).file.deref().name.clone();
     let file_metadata = file_metadata(cx, file_name);
 
     let struct_metadata_stub = create_struct_stub(cx,
@@ -1208,7 +1205,7 @@ fn prepare_struct_metadata(cx: &CrateContext,
                                                   file_metadata,
                                                   definition_span);
 
-    let fields = ty::struct_fields(cx.tcx, def_id, substs);
+    let fields = ty::struct_fields(cx.tcx(), def_id, substs);
 
     UnfinishedMetadata {
         cache_id: cache_id_for_type(struct_type),
@@ -1291,11 +1288,11 @@ fn prepare_tuple_metadata(cx: &CrateContext,
                           component_types: &[ty::t],
                           span: Span)
                        -> RecursiveTypeDescription {
-    let tuple_name = ppaux::ty_to_str(cx.tcx, tuple_type);
+    let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
     let tuple_llvm_type = type_of::type_of(cx, tuple_type);
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
     UnfinishedMetadata {
         cache_id: cache_id_for_type(tuple_type),
@@ -1329,7 +1326,7 @@ impl GeneralMemberDescriptionFactory {
         // Capture type_rep, so we don't have to copy the struct_defs array
         let struct_defs = match *self.type_rep {
             adt::General(_, ref struct_defs) => struct_defs,
-            _ => cx.sess.bug("unreachable")
+            _ => cx.sess().bug("unreachable")
         };
 
         struct_defs
@@ -1396,9 +1393,9 @@ fn describe_enum_variant(cx: &CrateContext,
                          span: Span)
                       -> (DICompositeType, Type, MemberDescriptionFactory) {
     let variant_llvm_type =
-        Type::struct_(struct_def.fields
-                                .map(|&t| type_of::type_of(cx, t))
-                                .as_slice(),
+        Type::struct_(cx, struct_def.fields
+                                    .map(|&t| type_of::type_of(cx, t))
+                                    .as_slice(),
                       struct_def.packed);
     // Could some consistency checks here: size, align, field count, discr type
 
@@ -1451,17 +1448,17 @@ fn prepare_enum_metadata(cx: &CrateContext,
                          enum_def_id: ast::DefId,
                          span: Span)
                       -> RecursiveTypeDescription {
-    let enum_name = ppaux::ty_to_str(cx.tcx, enum_type);
+    let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
 
     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
     let loc = span_start(cx, definition_span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
     // For empty enums there is an early exit. Just describe it as an empty struct with the
     // appropriate type name
-    if ty::type_is_empty(cx.tcx, enum_type) {
+    if ty::type_is_empty(cx.tcx(), enum_type) {
         let empty_type_metadata = composite_type_metadata(cx,
-                                                          Type::nil(),
+                                                          Type::nil(cx),
                                                           enum_name,
                                                           [],
                                                           containing_scope,
@@ -1471,7 +1468,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
         return FinalMetadata(empty_type_metadata);
     }
 
-    let variants = ty::enum_variants(cx.tcx, enum_def_id);
+    let variants = ty::enum_variants(cx.tcx(), enum_def_id);
 
     let enumerators_metadata: Vec<DIDescriptor> = variants
         .iter()
@@ -1653,9 +1650,9 @@ fn set_members_of_composite_type(cx: &CrateContext,
         let mut composite_types_completed =
             debug_context(cx).composite_types_completed.borrow_mut();
         if composite_types_completed.get().contains(&composite_type_metadata) {
-            cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
-                                               Already completed forward declaration \
-                                               re-encountered.");
+            cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
+                                                 Already completed forward declaration \
+                                                 re-encountered.");
         } else {
             composite_types_completed.get().insert(composite_type_metadata);
         }
@@ -1757,7 +1754,7 @@ fn boxed_type_metadata(cx: &CrateContext,
                                   content_llvm_type));
 
     let int_type = ty::mk_int();
-    let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
+    let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
     let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
 
     let member_descriptions = [
@@ -1794,7 +1791,7 @@ fn boxed_type_metadata(cx: &CrateContext,
     ];
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
     return composite_type_metadata(
         cx,
@@ -1814,8 +1811,8 @@ fn boxed_type_metadata(cx: &CrateContext,
         member_llvm_types.len() == 5 &&
         member_llvm_types[0] == cx.int_type &&
         member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
-        member_llvm_types[2] == Type::i8().ptr_to() &&
-        member_llvm_types[3] == Type::i8().ptr_to() &&
+        member_llvm_types[2] == Type::i8(cx).ptr_to() &&
+        member_llvm_types[3] == Type::i8(cx).ptr_to() &&
         member_llvm_types[4] == content_llvm_type
     }
 }
@@ -1856,8 +1853,8 @@ fn vec_metadata(cx: &CrateContext,
     let element_llvm_type = type_of::type_of(cx, element_type);
     let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
 
-    let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
-    let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
+    let vec_llvm_type = Type::vec(cx, &element_llvm_type);
+    let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx(), element_type));
 
     let member_llvm_types = vec_llvm_type.field_types();
 
@@ -1895,16 +1892,16 @@ fn vec_metadata(cx: &CrateContext,
     assert!(member_descriptions.len() == member_llvm_types.len());
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
-    return composite_type_metadata(
+    composite_type_metadata(
         cx,
         vec_llvm_type,
         vec_type_name,
         member_descriptions,
         file_metadata,
         file_metadata,
-        span);
+        span)
 }
 
 fn vec_slice_metadata(cx: &CrateContext,
@@ -1916,14 +1913,17 @@ fn vec_slice_metadata(cx: &CrateContext,
     debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
 
     let slice_llvm_type = type_of::type_of(cx, vec_type);
-    let slice_type_name = ppaux::ty_to_str(cx.tcx, vec_type);
+    let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
 
     let member_llvm_types = slice_llvm_type.field_types();
     assert!(slice_layout_is_correct(cx,
                                     member_llvm_types.as_slice(),
                                     element_type));
 
-    let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::MutImmutable });
+    let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
+        ty: element_type,
+        mutbl: ast::MutImmutable
+    });
 
     let member_descriptions = [
         MemberDescription {
@@ -1943,7 +1943,7 @@ fn vec_slice_metadata(cx: &CrateContext,
     assert!(member_descriptions.len() == member_llvm_types.len());
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
     return composite_type_metadata(
         cx,
@@ -1969,7 +1969,7 @@ fn subroutine_type_metadata(cx: &CrateContext,
                             span: Span)
                          -> DICompositeType {
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.deref().name);
 
     let mut signature_metadata: Vec<DIType> =
         Vec::with_capacity(signature.inputs.len() + 1);
@@ -2004,18 +2004,18 @@ fn trait_metadata(cx: &CrateContext,
     // The implementation provided here is a stub. It makes sure that the trait type is
     // assigned the correct name, size, namespace, and source location. But it does not describe
     // the trait's methods.
-    let last = ty::with_path(cx.tcx, def_id, |mut path| path.last().unwrap());
+    let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
     let ident_string = token::get_name(last.name());
-    let name = ppaux::trait_store_to_str(cx.tcx, trait_store) +
+    let name = ppaux::trait_store_to_str(cx.tcx(), trait_store) +
                ppaux::mutability_to_str(mutability) +
                ident_string.get();
     // Add type and region parameters
-    let name = ppaux::parameterized(cx.tcx, name, &substs.regions,
+    let name = ppaux::parameterized(cx.tcx(), name, &substs.regions,
                                     substs.tps.as_slice(), def_id, true);
 
     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
 
-    let file_name = span_start(cx, definition_span).file.name.clone();
+    let file_name = span_start(cx, definition_span).file.deref().name.clone();
     let file_metadata = file_metadata(cx, file_name);
 
     let trait_llvm_type = type_of::type_of(cx, trait_type);
@@ -2047,7 +2047,7 @@ fn type_metadata(cx: &CrateContext,
                                       pointer_type: ty::t,
                                       type_in_box: ty::t)
                                    -> DIType {
-        let content_type_name: &str = ppaux::ty_to_str(cx.tcx, type_in_box);
+        let content_type_name: &str = ppaux::ty_to_str(cx.tcx(), type_in_box);
         let content_llvm_type = type_of::type_of(cx, type_in_box);
         let content_type_metadata = type_metadata(
             cx,
@@ -2130,9 +2130,9 @@ fn type_metadata(cx: &CrateContext,
             trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
         },
         ty::ty_struct(def_id, ref substs) => {
-            if ty::type_is_simd(cx.tcx, t) {
-                let element_type = ty::simd_type(cx.tcx, t);
-                let len = ty::simd_size(cx.tcx, t);
+            if ty::type_is_simd(cx.tcx(), t) {
+                let element_type = ty::simd_type(cx.tcx(), t);
+                let len = ty::simd_size(cx.tcx(), t);
                 fixed_vec_metadata(cx, element_type, len, usage_site_span)
             } else {
                 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
@@ -2144,7 +2144,7 @@ fn type_metadata(cx: &CrateContext,
                                    elements.as_slice(),
                                    usage_site_span).finalize(cx)
         }
-        _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
+        _ => cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
     };
 
     let mut created_types = debug_context(cx).created_types.borrow_mut();
@@ -2179,7 +2179,7 @@ fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
         KnownLocation { scope, line, .. } => {
             let col = 0; // Always set the column to zero like Clang and GCC
             debug!("setting debug location to {} {}", line, col);
-            let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
+            let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
             unsafe {
                 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
                                                           elements.as_ptr(),
@@ -2218,7 +2218,7 @@ fn generate_unique_type_id(prefix: &'static str) -> ~str {
 
 /// Return codemap::Loc corresponding to the beginning of the span
 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
-    cx.sess.codemap.lookup_char_pos(span.lo)
+    cx.sess().codemap().lookup_char_pos(span.lo)
 }
 
 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
@@ -2250,7 +2250,7 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
     let node_types = cx.tcx.node_types.borrow();
     if !node_types.get().contains_key(&(node_id as uint)) {
-        cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!");
+        cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
     }
 }
 
@@ -2315,8 +2315,8 @@ fn populate_scope_map(cx: &CrateContext,
                                    &mut Vec<ScopeStackEntry> ,
                                    &mut HashMap<ast::NodeId, DIScope>|) {
         // Create a new lexical scope and push it onto the stack
-        let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
-        let file_metadata = file_metadata(cx, loc.file.name);
+        let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
+        let file_metadata = file_metadata(cx, loc.file.deref().name);
         let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
         let scope_metadata = unsafe {
@@ -2338,7 +2338,7 @@ fn populate_scope_map(cx: &CrateContext,
         }
 
         if scope_stack.last().unwrap().scope_metadata != scope_metadata {
-            cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
+            cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
         }
 
         scope_stack.pop();
@@ -2432,8 +2432,8 @@ fn populate_scope_map(cx: &CrateContext,
 
                     if need_new_scope {
                         // Create a new lexical scope and push it onto the stack
-                        let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
-                        let file_metadata = file_metadata(cx, loc.file.name);
+                        let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
+                        let file_metadata = file_metadata(cx, loc.file.deref().name);
                         let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
                         let scope_metadata = unsafe {
@@ -2614,13 +2614,13 @@ fn populate_scope_map(cx: &CrateContext,
             }
 
             ast::ExprForLoop(_, _, _, _) => {
-                cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
-                                            Found unexpanded for-loop.");
+                cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
+                                              Found unexpanded for-loop.");
             }
 
             ast::ExprMac(_) => {
-                cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
-                                            Found unexpanded macro.");
+                cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
+                                              Found unexpanded macro.");
             }
 
             ast::ExprLoop(block, _) |
@@ -2751,7 +2751,7 @@ impl NamespaceTreeNode {
 }
 
 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
-    ty::with_path(cx.tcx, def_id, |path| {
+    ty::with_path(cx.tcx(), def_id, |path| {
         // prepend crate name if not already present
         let krate = if def_id.krate == ast::LOCAL_CRATE {
             let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
@@ -2827,7 +2827,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
         match parent_node {
             Some(node) => node,
             None => {
-                cx.sess.bug(format!("debuginfo::namespace_for_item(): \
+                cx.sess().bug(format!("debuginfo::namespace_for_item(): \
                     path too short for {:?}", def_id));
             }
         }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index bf2d192d0de..a38322ef0dc 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -523,7 +523,7 @@ fn trans_index<'a>(bcx: &'a Block<'a>,
 
     let bounds_check = ICmp(bcx, lib::llvm::IntUGE, ix_val, len);
     let expect = ccx.intrinsics.get_copy(&("llvm.expect.i1"));
-    let expected = Call(bcx, expect, [bounds_check, C_i1(false)], []);
+    let expected = Call(bcx, expect, [bounds_check, C_i1(ccx, false)], []);
     let bcx = with_cond(bcx, expected, |bcx| {
             controlflow::trans_fail_bounds_check(bcx, index_expr.span, ix_val, len)
         });
@@ -548,7 +548,7 @@ fn trans_def<'a>(bcx: &'a Block<'a>,
         ast::DefStatic(did, _) => {
             let const_ty = expr_ty(bcx, ref_expr);
 
-            fn get_did(ccx: @CrateContext, did: ast::DefId)
+            fn get_did(ccx: &CrateContext, did: ast::DefId)
                        -> ast::DefId {
                 if did.krate != ast::LOCAL_CRATE {
                     inline::maybe_instantiate_inline(ccx, did)
@@ -581,7 +581,7 @@ fn trans_def<'a>(bcx: &'a Block<'a>,
                     unsafe {
                         let llty = type_of::type_of(bcx.ccx(), const_ty);
                         let symbol = csearch::get_symbol(
-                            bcx.ccx().sess.cstore,
+                            &bcx.ccx().sess().cstore,
                             did);
                         let llval = symbol.with_c_str(|buf| {
                                 llvm::LLVMAddGlobal(bcx.ccx().llmod,
@@ -816,7 +816,6 @@ fn trans_def_dps_unadjusted<'a>(
                             dest: Dest)
                             -> &'a Block<'a> {
     let _icx = push_ctxt("trans_def_dps_unadjusted");
-    let ccx = bcx.ccx();
 
     let lldest = match dest {
         SaveIn(lldest) => lldest,
@@ -825,7 +824,7 @@ fn trans_def_dps_unadjusted<'a>(
 
     match def {
         ast::DefVariant(tid, vid, _) => {
-            let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
+            let variant_info = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
             if variant_info.args.len() > 0u {
                 // N-ary variant.
                 let llfn = callee::trans_fn_ref(bcx, vid, ExprId(ref_expr.id));
@@ -834,7 +833,7 @@ fn trans_def_dps_unadjusted<'a>(
             } else {
                 // Nullary variant.
                 let ty = expr_ty(bcx, ref_expr);
-                let repr = adt::represent_type(ccx, ty);
+                let repr = adt::represent_type(bcx.ccx(), ty);
                 adt::trans_start_init(bcx, repr, lldest,
                                       variant_info.disr_val);
                 return bcx;
@@ -843,8 +842,8 @@ fn trans_def_dps_unadjusted<'a>(
         ast::DefStruct(_) => {
             let ty = expr_ty(bcx, ref_expr);
             match ty::get(ty).sty {
-                ty::ty_struct(did, _) if ty::has_dtor(ccx.tcx, did) => {
-                    let repr = adt::represent_type(ccx, ty);
+                ty::ty_struct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
+                    let repr = adt::represent_type(bcx.ccx(), ty);
                     adt::trans_start_init(bcx, repr, lldest, 0);
                 }
                 _ => {}
@@ -940,7 +939,7 @@ pub fn trans_local_var<'a>(bcx: &'a Block<'a>,
     }
 }
 
-pub fn with_field_tys<R>(tcx: ty::ctxt,
+pub fn with_field_tys<R>(tcx: &ty::ctxt,
                          ty: ty::t,
                          node_id_opt: Option<ast::NodeId>,
                          op: |ty::Disr, (&[ty::field])| -> R)
@@ -1150,6 +1149,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
                    op: ast::UnOp,
                    sub_expr: &ast::Expr)
                    -> DatumBlock<'a, Expr> {
+    let ccx = bcx.ccx();
     let mut bcx = bcx;
     let _icx = push_ctxt("trans_unary_datum");
 
@@ -1160,7 +1160,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
     // Otherwise, we should be in the RvalueDpsExpr path.
     assert!(
         op == ast::UnDeref ||
-        !bcx.ccx().maps.method_map.borrow().get().contains_key(&method_call));
+        !ccx.maps.method_map.borrow().get().contains_key(&method_call));
 
     let un_ty = expr_ty(bcx, expr);
 
@@ -1172,8 +1172,8 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
                 let llcond = ICmp(bcx,
                                   lib::llvm::IntEQ,
                                   val,
-                                  C_bool(false));
-                Select(bcx, llcond, C_bool(true), C_bool(false))
+                                  C_bool(ccx, false));
+                Select(bcx, llcond, C_bool(ccx, true), C_bool(ccx, false))
             } else {
                 // Note: `Not` is bitwise, not suitable for logical not.
                 Not(bcx, datum.to_llscalarish(bcx))
@@ -1361,7 +1361,7 @@ fn trans_eager_binop<'a>(
       }
       ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
         if ty::type_is_bot(rhs_t) {
-            C_bool(false)
+            C_bool(bcx.ccx(), false)
         } else {
             if !ty::type_is_scalar(rhs_t) {
                 bcx.tcx().sess.span_bug(binop_expr.span,
@@ -1369,7 +1369,7 @@ fn trans_eager_binop<'a>(
             }
             let cmpr = base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op);
             bcx = cmpr.bcx;
-            ZExt(bcx, cmpr.val, Type::i8())
+            ZExt(bcx, cmpr.val, Type::i8(bcx.ccx()))
         }
       }
       _ => {
@@ -1421,8 +1421,8 @@ fn trans_lazy_binop<'a>(
     }
 
     Br(past_rhs, join.llbb);
-    let phi = Phi(join, Type::bool(), [lhs, rhs], [past_lhs.llbb,
-                                                   past_rhs.llbb]);
+    let phi = Phi(join, Type::bool(bcx.ccx()), [lhs, rhs],
+                  [past_lhs.llbb, past_rhs.llbb]);
 
     return immediate_rvalue_bcx(join, phi, binop_ty).to_expr_datumblock();
 }
@@ -1612,22 +1612,22 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
                 bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
             let llexpr_ptr = datum.to_llref();
             let lldiscrim_a =
-                adt::trans_get_discr(bcx, repr, llexpr_ptr, Some(Type::i64()));
+                adt::trans_get_discr(bcx, repr, llexpr_ptr, Some(Type::i64(ccx)));
             match k_out {
                 cast_integral => int_cast(bcx, ll_t_out,
                                           val_ty(lldiscrim_a),
                                           lldiscrim_a, true),
                 cast_float => SIToFP(bcx, lldiscrim_a, ll_t_out),
-                _ => ccx.sess.bug(format!("translating unsupported cast: \
-                                          {} ({:?}) -> {} ({:?})",
-                                          t_in.repr(ccx.tcx), k_in,
-                                          t_out.repr(ccx.tcx), k_out))
+                _ => ccx.sess().bug(format!("translating unsupported cast: \
+                                            {} ({:?}) -> {} ({:?})",
+                                            t_in.repr(bcx.tcx()), k_in,
+                                            t_out.repr(bcx.tcx()), k_out))
             }
         }
-        _ => ccx.sess.bug(format!("translating unsupported cast: \
-                                  {} ({:?}) -> {} ({:?})",
-                                  t_in.repr(ccx.tcx), k_in,
-                                  t_out.repr(ccx.tcx), k_out))
+        _ => ccx.sess().bug(format!("translating unsupported cast: \
+                                    {} ({:?}) -> {} ({:?})",
+                                    t_in.repr(bcx.tcx()), k_in,
+                                    t_out.repr(bcx.tcx()), k_out))
     };
     return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock();
 }
@@ -1665,7 +1665,6 @@ fn trans_assign_op<'a>(
     return result_datum.store_to(bcx, dst_datum.val);
 }
 
-
 fn auto_ref<'a>(bcx: &'a Block<'a>,
                 datum: Datum<Expr>,
                 expr: &ast::Expr)
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index f37d4b9859d..fdc33666e8a 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -75,23 +75,23 @@ struct LlvmSignature {
 
 pub fn llvm_calling_convention(ccx: &CrateContext,
                                abis: AbiSet) -> Option<CallConv> {
-    let os = ccx.sess.targ_cfg.os;
-    let arch = ccx.sess.targ_cfg.arch;
+    let os = ccx.sess().targ_cfg.os;
+    let arch = ccx.sess().targ_cfg.arch;
     abis.for_target(os, arch).map(|abi| {
         match abi {
             RustIntrinsic => {
                 // Intrinsics are emitted by monomorphic fn
-                ccx.sess.bug(format!("asked to register intrinsic fn"));
+                ccx.sess().bug(format!("asked to register intrinsic fn"));
             }
 
             Rust => {
                 // FIXME(#3678) Implement linking to foreign fns with Rust ABI
-                ccx.sess.unimpl(
+                ccx.sess().unimpl(
                     format!("foreign functions with Rust ABI"));
             }
 
             // It's the ABI's job to select this, not us.
-            System => ccx.sess.bug("system abi should be selected elsewhere"),
+            System => ccx.sess().bug("system abi should be selected elsewhere"),
 
             Stdcall => lib::llvm::X86StdcallCallConv,
             Fastcall => lib::llvm::X86FastcallCallConv,
@@ -132,9 +132,9 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
     }
 }
 
-pub fn register_static(ccx: @CrateContext,
-                       foreign_item: @ast::ForeignItem) -> ValueRef {
-    let ty = ty::node_id_to_type(ccx.tcx, foreign_item.id);
+pub fn register_static(ccx: &CrateContext,
+                       foreign_item: &ast::ForeignItem) -> ValueRef {
+    let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
     let llty = type_of::type_of(ccx, ty);
 
     // Treat the crate map static specially in order to
@@ -145,7 +145,7 @@ pub fn register_static(ccx: @CrateContext,
     // library then we've already declared the crate map
     // so use that instead.
     if attr::contains_name(foreign_item.attrs.as_slice(), "crate_map") {
-        return if ccx.sess.building_library.get() {
+        return if ccx.sess().building_library.get() {
             let s = "_rust_crate_map_toplevel";
             let g = unsafe {
                 s.with_c_str(|buf| {
@@ -171,15 +171,15 @@ pub fn register_static(ccx: @CrateContext,
             let linkage = match llvm_linkage_by_name(name.get()) {
                 Some(linkage) => linkage,
                 None => {
-                    ccx.sess.span_fatal(foreign_item.span,
-                                        "invalid linkage specified");
+                    ccx.sess().span_fatal(foreign_item.span,
+                                          "invalid linkage specified");
                 }
             };
             let llty2 = match ty::get(ty).sty {
                 ty::ty_ptr(ref mt) => type_of::type_of(ccx, mt.ty),
                 _ => {
-                    ccx.sess.span_fatal(foreign_item.span,
-                                        "must have type `*T` or `*mut T`");
+                    ccx.sess().span_fatal(foreign_item.span,
+                                          "must have type `*T` or `*mut T`");
                 }
             };
             unsafe {
@@ -205,8 +205,8 @@ pub fn register_static(ccx: @CrateContext,
     }
 }
 
-pub fn register_foreign_item_fn(ccx: @CrateContext, abis: AbiSet,
-                                foreign_item: @ast::ForeignItem) -> ValueRef {
+pub fn register_foreign_item_fn(ccx: &CrateContext, abis: AbiSet,
+                                foreign_item: &ast::ForeignItem) -> ValueRef {
     /*!
      * Registers a foreign function found in a library.
      * Just adds a LLVM global.
@@ -215,17 +215,17 @@ pub fn register_foreign_item_fn(ccx: @CrateContext, abis: AbiSet,
     debug!("register_foreign_item_fn(abis={}, \
             path={}, \
             foreign_item.id={})",
-           abis.repr(ccx.tcx),
+           abis.repr(ccx.tcx()),
            ccx.tcx.map.path_to_str(foreign_item.id),
            foreign_item.id);
 
     let cc = match llvm_calling_convention(ccx, abis) {
         Some(cc) => cc,
         None => {
-            ccx.sess.span_fatal(foreign_item.span,
+            ccx.sess().span_fatal(foreign_item.span,
                 format!("ABI `{}` has no suitable calling convention \
                       for target architecture",
-                      abis.user_string(ccx.tcx)));
+                      abis.user_string(ccx.tcx())));
         }
     };
 
@@ -240,7 +240,7 @@ pub fn register_foreign_item_fn(ccx: @CrateContext, abis: AbiSet,
     }
 
     // Create the LLVM value for the C extern fn
-    let llfn_ty = lltype_for_fn_from_foreign_types(&tys);
+    let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
 
     let llfn;
     {
@@ -294,7 +294,7 @@ pub fn trans_native_call<'a>(
 
     let (fn_abis, fn_sig) = match ty::get(callee_ty).sty {
         ty::ty_bare_fn(ref fn_ty) => (fn_ty.abis, fn_ty.sig.clone()),
-        _ => ccx.sess.bug("trans_native_call called on non-function type")
+        _ => ccx.sess().bug("trans_native_call called on non-function type")
     };
     let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice());
     let ret_def = !return_type_is_void(bcx.ccx(), fn_sig.output);
@@ -383,10 +383,10 @@ pub fn trans_native_call<'a>(
         Some(cc) => cc,
         None => {
             // FIXME(#8357) We really ought to report a span here
-            ccx.sess.fatal(
+            ccx.sess().fatal(
                 format!("ABI string `{}` has no suitable ABI \
                         for target architecture",
-                        fn_abis.user_string(ccx.tcx)));
+                        fn_abis.user_string(ccx.tcx())));
         }
     };
 
@@ -440,8 +440,8 @@ pub fn trans_native_call<'a>(
             //   bitcasting to the struct type yields invalid cast errors.
             let llscratch = base::alloca(bcx, llforeign_ret_ty, "__cast");
             Store(bcx, llforeign_retval, llscratch);
-            let llscratch_i8 = BitCast(bcx, llscratch, Type::i8().ptr_to());
-            let llretptr_i8 = BitCast(bcx, llretptr, Type::i8().ptr_to());
+            let llscratch_i8 = BitCast(bcx, llscratch, Type::i8(ccx).ptr_to());
+            let llretptr_i8 = BitCast(bcx, llretptr, Type::i8(ccx).ptr_to());
             let llrust_size = machine::llsize_of_store(ccx, llrust_ret_ty);
             let llforeign_align = machine::llalign_of_min(ccx, llforeign_ret_ty);
             let llrust_align = machine::llalign_of_min(ccx, llrust_ret_ty);
@@ -455,7 +455,7 @@ pub fn trans_native_call<'a>(
     return bcx;
 }
 
-pub fn trans_foreign_mod(ccx: @CrateContext, foreign_mod: &ast::ForeignMod) {
+pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
     let _icx = push_ctxt("foreign::trans_foreign_mod");
     for &foreign_item in foreign_mod.items.iter() {
         match foreign_item.node {
@@ -499,7 +499,7 @@ pub fn trans_foreign_mod(ccx: @CrateContext, foreign_mod: &ast::ForeignMod) {
 // inline the one into the other. Of course we could just generate the
 // correct code in the first place, but this is much simpler.
 
-pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext,
+pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
                                          sp: Span,
                                          sym: ~str,
                                          node_id: ast::NodeId)
@@ -507,8 +507,8 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext,
     let _icx = push_ctxt("foreign::register_foreign_fn");
 
     let tys = foreign_types_for_id(ccx, node_id);
-    let llfn_ty = lltype_for_fn_from_foreign_types(&tys);
-    let t = ty::node_id_to_type(ccx.tcx, node_id);
+    let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
+    let t = ty::node_id_to_type(ccx.tcx(), node_id);
     let (cconv, output) = match ty::get(t).sty {
         ty::ty_bare_fn(ref fn_ty) => {
             let c = llvm_calling_convention(ccx, fn_ty.abis);
@@ -523,7 +523,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext,
     llfn
 }
 
-pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
+pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext,
                                       decl: &ast::FnDecl,
                                       body: &ast::Block,
                                       attrs: &[ast::Attribute],
@@ -540,14 +540,14 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
         return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys);
     }
 
-    fn build_rust_fn(ccx: @CrateContext,
+    fn build_rust_fn(ccx: &CrateContext,
                      decl: &ast::FnDecl,
                      body: &ast::Block,
                      attrs: &[ast::Attribute],
                      id: ast::NodeId)
                      -> ValueRef {
         let _icx = push_ctxt("foreign::foreign::build_rust_fn");
-        let tcx = ccx.tcx;
+        let tcx = ccx.tcx();
         let t = ty::node_id_to_type(tcx, id);
 
         let ps = ccx.tcx.map.with_path(id, |path| {
@@ -563,10 +563,10 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
                 f
             }
             _ => {
-                ccx.sess.bug(format!("build_rust_fn: extern fn {} has ty {}, \
-                                  expected a bare fn ty",
-                                  ccx.tcx.map.path_to_str(id),
-                                  t.repr(tcx)));
+                ccx.sess().bug(format!("build_rust_fn: extern fn {} has ty {}, \
+                                       expected a bare fn ty",
+                                       ccx.tcx.map.path_to_str(id),
+                                       t.repr(tcx)));
             }
         };
 
@@ -584,13 +584,13 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
         llfn
     }
 
-    unsafe fn build_wrap_fn(ccx: @CrateContext,
+    unsafe fn build_wrap_fn(ccx: &CrateContext,
                             llrustfn: ValueRef,
                             llwrapfn: ValueRef,
                             tys: &ForeignTypes) {
         let _icx = push_ctxt(
             "foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
-        let tcx = ccx.tcx;
+        let tcx = ccx.tcx();
 
         debug!("build_wrap_fn(llrustfn={}, llwrapfn={})",
                ccx.tn.val_to_str(llrustfn),
@@ -824,7 +824,7 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: @CrateContext,
 // This code is kind of a confused mess and needs to be reworked given
 // the massive simplifications that have occurred.
 
-pub fn link_name(i: @ast::ForeignItem) -> InternedString {
+pub fn link_name(i: &ast::ForeignItem) -> InternedString {
      match attr::first_attr_value_str_by_name(i.attrs.as_slice(),
                                               "link_name") {
         None => token::get_ident(i.ident),
@@ -853,14 +853,14 @@ fn foreign_signature(ccx: &CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty::t])
 
 fn foreign_types_for_id(ccx: &CrateContext,
                         id: ast::NodeId) -> ForeignTypes {
-    foreign_types_for_fn_ty(ccx, ty::node_id_to_type(ccx.tcx, id))
+    foreign_types_for_fn_ty(ccx, ty::node_id_to_type(ccx.tcx(), id))
 }
 
 fn foreign_types_for_fn_ty(ccx: &CrateContext,
                            ty: ty::t) -> ForeignTypes {
     let fn_sig = match ty::get(ty).sty {
         ty::ty_bare_fn(ref fn_ty) => fn_ty.sig.clone(),
-        _ => ccx.sess.bug("foreign_types_for_fn_ty called on non-function type")
+        _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
     };
     let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs.as_slice());
     let ret_def = !return_type_is_void(ccx, fn_sig.output);
@@ -873,7 +873,7 @@ fn foreign_types_for_fn_ty(ccx: &CrateContext,
            llsig={} -> {}, \
            fn_ty={} -> {}, \
            ret_def={}",
-           ty.repr(ccx.tcx),
+           ty.repr(ccx.tcx()),
            ccx.tn.types_to_str(llsig.llarg_tys.as_slice()),
            ccx.tn.type_to_str(llsig.llret_ty),
            ccx.tn.types_to_str(fn_ty.arg_tys.map(|t| t.ty).as_slice()),
@@ -888,13 +888,13 @@ fn foreign_types_for_fn_ty(ccx: &CrateContext,
     }
 }
 
-fn lltype_for_fn_from_foreign_types(tys: &ForeignTypes) -> Type {
+fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> Type {
     let mut llargument_tys = Vec::new();
 
     let ret_ty = tys.fn_ty.ret_ty;
     let llreturn_ty = if ret_ty.is_indirect() {
         llargument_tys.push(ret_ty.ty.ptr_to());
-        Type::void()
+        Type::void(ccx)
     } else {
         match ret_ty.cast {
             Some(ty) => ty,
@@ -929,8 +929,7 @@ fn lltype_for_fn_from_foreign_types(tys: &ForeignTypes) -> Type {
 }
 
 pub fn lltype_for_foreign_fn(ccx: &CrateContext, ty: ty::t) -> Type {
-    let fn_types = foreign_types_for_fn_ty(ccx, ty);
-    lltype_for_fn_from_foreign_types(&fn_types)
+    lltype_for_fn_from_foreign_types(ccx, &foreign_types_for_fn_ty(ccx, ty))
 }
 
 fn add_argument_attributes(tys: &ForeignTypes,
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 6d4737eeff1..3a1572559dd 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -46,7 +46,7 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> {
     let _icx = push_ctxt("trans_free");
     callee::trans_lang_call(cx,
         langcall(cx, None, "", FreeFnLangItem),
-        [PointerCast(cx, v, Type::i8p())],
+        [PointerCast(cx, v, Type::i8p(cx.ccx()))],
         Some(expr::Ignore)).bcx
 }
 
@@ -55,7 +55,7 @@ pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef)
     let _icx = push_ctxt("trans_exchange_free");
     callee::trans_lang_call(cx,
         langcall(cx, None, "", ExchangeFreeFnLangItem),
-        [PointerCast(cx, v, Type::i8p())],
+        [PointerCast(cx, v, Type::i8p(cx.ccx()))],
         Some(expr::Ignore)).bcx
 }
 
@@ -74,7 +74,7 @@ pub fn take_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
 }
 
 fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
-    let tcx = ccx.tcx;
+    let tcx = ccx.tcx();
     if !ty::type_needs_drop(tcx, t) {
         return ty::mk_i8();
     }
@@ -126,42 +126,36 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
     drop_ty(bcx, vp, t)
 }
 
-pub fn get_drop_glue(ccx: @CrateContext, t: ty::t) -> ValueRef {
+pub fn get_drop_glue(ccx: &CrateContext, t: ty::t) -> ValueRef {
     let t = get_drop_glue_type(ccx, t);
-    {
-        let drop_glues = ccx.drop_glues.borrow();
-        match drop_glues.get().find(&t) {
-            Some(&glue) => return glue,
-            _ => { }
-        }
+    match ccx.drop_glues.borrow().get().find(&t) {
+        Some(&glue) => return glue,
+        _ => { }
     }
 
-    let llfnty = Type::glue_fn(type_of(ccx, t).ptr_to());
+    let llfnty = Type::glue_fn(ccx, type_of(ccx, t).ptr_to());
     let glue = declare_generic_glue(ccx, t, llfnty, "drop");
 
-    {
-        let mut drop_glues = ccx.drop_glues.borrow_mut();
-        drop_glues.get().insert(t, glue);
-    }
+    ccx.drop_glues.borrow_mut().get().insert(t, glue);
 
     make_generic_glue(ccx, t, glue, make_drop_glue, "drop");
 
     glue
 }
 
-pub fn lazily_emit_visit_glue(ccx: @CrateContext, ti: @tydesc_info) {
+pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: @tydesc_info) {
     let _icx = push_ctxt("lazily_emit_visit_glue");
 
-    let llfnty = Type::glue_fn(type_of(ccx, ti.ty).ptr_to());
+    let llfnty = Type::glue_fn(ccx, type_of(ccx, ti.ty).ptr_to());
 
     match ti.visit_glue.get() {
         Some(_) => (),
         None => {
-            debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx, ti.ty));
+            debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
             let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
             ti.visit_glue.set(Some(glue_fn));
             make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
-            debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx, ti.ty));
+            debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
         }
     }
 }
@@ -173,7 +167,7 @@ pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef,
     let ccx = bcx.ccx();
     // NB: Don't short-circuit even if this block is unreachable because
     // GC-based cleanup needs to the see that the roots are live.
-    if bcx.unreachable.get() && !ccx.sess.no_landing_pads() { return; }
+    if bcx.unreachable.get() && !ccx.sess().no_landing_pads() { return; }
 
     let static_glue_fn = match static_ti {
         None => None,
@@ -185,7 +179,7 @@ pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef,
 
     // When static type info is available, avoid casting to a generic pointer.
     let llrawptr = if static_glue_fn.is_none() {
-        PointerCast(bcx, v, Type::i8p())
+        PointerCast(bcx, v, Type::i8p(ccx))
     } else {
         v
     };
@@ -283,7 +277,6 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
 fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'a> {
     // NB: v0 is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("make_drop_glue");
-    let ccx = bcx.ccx();
     match ty::get(t).sty {
         ty::ty_box(body_ty) => {
             decr_refcnt_maybe_free(bcx, v0, body_ty)
@@ -323,27 +316,27 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
             with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
                 let dtor_ptr = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
                 let dtor = Load(bcx, dtor_ptr);
-                Call(bcx, dtor, [PointerCast(bcx, lluniquevalue, Type::i8p())], []);
+                Call(bcx, dtor, [PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))], []);
                 bcx
             })
         }
         ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => {
             let box_cell_v = GEPi(bcx, v0, [0u, abi::fn_field_box]);
             let env = Load(bcx, box_cell_v);
-            let env_ptr_ty = Type::at_box(ccx, Type::i8()).ptr_to();
+            let env_ptr_ty = Type::at_box(bcx.ccx(), Type::i8(bcx.ccx())).ptr_to();
             let env = PointerCast(bcx, env, env_ptr_ty);
             with_cond(bcx, IsNotNull(bcx, env), |bcx| {
                 let dtor_ptr = GEPi(bcx, env, [0u, abi::box_field_tydesc]);
                 let dtor = Load(bcx, dtor_ptr);
                 let cdata = GEPi(bcx, env, [0u, abi::box_field_body]);
-                Call(bcx, dtor, [PointerCast(bcx, cdata, Type::i8p())], []);
+                Call(bcx, dtor, [PointerCast(bcx, cdata, Type::i8p(bcx.ccx()))], []);
 
                 // Free the environment itself
                 trans_exchange_free(bcx, env)
             })
         }
         _ => {
-            if ty::type_needs_drop(ccx.tcx, t) &&
+            if ty::type_needs_drop(bcx.tcx(), t) &&
                 ty::type_is_structural(t) {
                 iter_structural_ty(bcx, v0, t, drop_ty)
             } else {
@@ -403,23 +396,23 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
 
     let llty = type_of(ccx, t);
 
-    if ccx.sess.count_type_sizes() {
+    if ccx.sess().count_type_sizes() {
         println!("{}\t{}", llsize_of_real(ccx, llty),
-                 ppaux::ty_to_str(ccx.tcx, t));
+                 ppaux::ty_to_str(ccx.tcx(), t));
     }
 
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
-    debug!("+++ declare_tydesc {} {}", ppaux::ty_to_str(ccx.tcx, t), name);
+    debug!("+++ declare_tydesc {} {}", ppaux::ty_to_str(ccx.tcx(), t), name);
     let gvar = name.with_c_str(|buf| {
         unsafe {
-            llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
+            llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type().to_ref(), buf)
         }
     });
     note_unique_llvm_symbol(ccx, name);
 
-    let ty_name = token::intern_and_get_ident(ppaux::ty_to_str(ccx.tcx, t));
+    let ty_name = token::intern_and_get_ident(ppaux::ty_to_str(ccx.tcx(), t));
     let ty_name = C_str_slice(ccx, ty_name);
 
     let inf = @tydesc_info {
@@ -430,7 +423,7 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
         name: ty_name,
         visit_glue: Cell::new(None),
     };
-    debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx, t));
+    debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx(), t));
     return inf;
 }
 
@@ -438,13 +431,13 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
                         name: &str) -> ValueRef {
     let _icx = push_ctxt("declare_generic_glue");
     let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, ~"glue_" + name);
-    debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
+    debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx(), t));
     let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty, ty::mk_nil());
     note_unique_llvm_symbol(ccx, fn_nm);
     return llfn;
 }
 
-fn make_generic_glue(ccx: @CrateContext,
+fn make_generic_glue(ccx: &CrateContext,
                      t: ty::t,
                      llfn: ValueRef,
                      helper: <'a> |&'a Block<'a>, ValueRef, ty::t|
@@ -452,7 +445,7 @@ fn make_generic_glue(ccx: @CrateContext,
                      name: &str)
                      -> ValueRef {
     let _icx = push_ctxt("make_generic_glue");
-    let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx, t));
+    let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx(), t));
     let _s = StatRecorder::new(ccx, glue_name);
 
     let arena = TypedArena::new();
@@ -478,7 +471,7 @@ fn make_generic_glue(ccx: @CrateContext,
     llfn
 }
 
-pub fn emit_tydescs(ccx: @CrateContext) {
+pub fn emit_tydescs(ccx: &CrateContext) {
     let _icx = push_ctxt("emit_tydescs");
     // As of this point, allow no more tydescs to be created.
     ccx.finished_tydescs.set(true);
@@ -511,7 +504,7 @@ pub fn emit_tydescs(ccx: @CrateContext) {
               }
             };
 
-        let tydesc = C_named_struct(ccx.tydesc_type,
+        let tydesc = C_named_struct(ccx.tydesc_type(),
                                     [ti.size, // size
                                      ti.align, // align
                                      drop_glue, // drop_glue
diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs
index 896d97f0374..ee810a652dc 100644
--- a/src/librustc/middle/trans/inline.rs
+++ b/src/librustc/middle/trans/inline.rs
@@ -19,7 +19,7 @@ use syntax::ast;
 use syntax::ast_util::local_def;
 use syntax::attr;
 
-pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
+pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
     -> ast::DefId {
     let _icx = push_ctxt("maybe_instantiate_inline");
     {
@@ -28,7 +28,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
             Some(&Some(node_id)) => {
                 // Already inline
                 debug!("maybe_instantiate_inline({}): already inline as node id {}",
-                       ty::item_path_str(ccx.tcx, fn_id), node_id);
+                       ty::item_path_str(ccx.tcx(), fn_id), node_id);
                 return local_def(node_id);
             }
             Some(&None) => {
@@ -42,8 +42,8 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
 
     let csearch_result =
         csearch::maybe_get_item_ast(
-            ccx.tcx, fn_id,
-            |a,b,c,d| astencode::decode_inlined_item(a, b, ccx.maps, c, d));
+            ccx.tcx(), fn_id,
+            |a,b,c,d| astencode::decode_inlined_item(a, b, &ccx.maps, c, d));
     return match csearch_result {
         csearch::not_found => {
             let mut external = ccx.external.borrow_mut();
@@ -104,8 +104,8 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
           let mut my_id = 0;
           match item.node {
             ast::ItemEnum(_, _) => {
-              let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
-              let vs_there = ty::enum_variants(ccx.tcx, parent_id);
+              let vs_here = ty::enum_variants(ccx.tcx(), local_def(item.id));
+              let vs_there = ty::enum_variants(ccx.tcx(), parent_id);
               for (here, there) in vs_here.iter().zip(vs_there.iter()) {
                   if there.id == fn_id { my_id = here.id.node; }
                   let mut external = ccx.external.borrow_mut();
@@ -122,14 +122,14 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
                 }
               }
             }
-            _ => ccx.sess.bug("maybe_instantiate_inline: item has a \
-                               non-enum, non-struct parent")
+            _ => ccx.sess().bug("maybe_instantiate_inline: item has a \
+                                 non-enum, non-struct parent")
           }
           trans_item(ccx, item);
           local_def(my_id)
         }
         csearch::found_parent(_, _) => {
-            ccx.sess.bug("maybe_get_item_ast returned a found_parent \
+            ccx.sess().bug("maybe_get_item_ast returned a found_parent \
              with a non-item parent");
         }
         csearch::found(ast::IIMethod(impl_did, is_provided, mth)) => {
@@ -146,7 +146,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
           // impl type. But we aren't going to translate anyways, so don't.
           if is_provided { return local_def(mth.id); }
 
-            let impl_tpt = ty::lookup_item_type(ccx.tcx, impl_did);
+            let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
             let num_type_params =
                 impl_tpt.generics.type_param_defs().len() +
                 mth.generics.ty_params.len();
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index 1a5d794c1a4..98e63641c12 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -31,7 +31,7 @@ use syntax::ast_map;
 use syntax::parse::token;
 use util::ppaux::ty_to_str;
 
-pub fn get_simple_intrinsic(ccx: @CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
+pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
     let name = match token::get_ident(item.ident).get() {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
@@ -83,7 +83,7 @@ pub fn get_simple_intrinsic(ccx: @CrateContext, item: &ast::ForeignItem) -> Opti
     Some(ccx.intrinsics.get_copy(&name))
 }
 
-pub fn trans_intrinsic(ccx: @CrateContext,
+pub fn trans_intrinsic(ccx: &CrateContext,
                        decl: ValueRef,
                        item: &ast::ForeignItem,
                        substs: @param_substs,
@@ -99,7 +99,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         // convert `i1` to a `bool`, and write to the out parameter
         let val = Call(bcx, llfn, [a, b], []);
         let result = ExtractValue(bcx, val, 0);
-        let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool());
+        let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool(bcx.ccx()));
         let ret = C_undef(type_of::type_of(bcx.ccx(), t));
         let ret = InsertValue(bcx, ret, result, 0);
         let ret = InsertValue(bcx, ret, overflow, 1);
@@ -133,7 +133,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
     fn copy_intrinsic(bcx: &Block, allow_overlap: bool, tp_ty: ty::t) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
-        let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
+        let align = C_i32(ccx, machine::llalign_of_min(ccx, lltp_ty) as i32);
         let size = machine::llsize_of(ccx, lltp_ty);
         let int_size = machine::llbitsize_of_real(ccx, ccx.int_type);
         let name = if allow_overlap {
@@ -152,11 +152,11 @@ pub fn trans_intrinsic(ccx: @CrateContext,
 
         let decl = bcx.fcx.llfn;
         let first_real_arg = bcx.fcx.arg_pos(0u);
-        let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
-        let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
+        let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p(ccx));
+        let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p(ccx));
         let count = get_param(decl, first_real_arg + 2);
-        let volatile = C_i1(false);
-        let llfn = bcx.ccx().intrinsics.get_copy(&name);
+        let volatile = C_i1(ccx, false);
+        let llfn = ccx.intrinsics.get_copy(&name);
         Call(bcx, llfn, [dst_ptr, src_ptr, Mul(bcx, size, count), align, volatile], []);
         RetVoid(bcx);
     }
@@ -164,7 +164,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
     fn memset_intrinsic(bcx: &Block, tp_ty: ty::t) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
-        let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
+        let align = C_i32(ccx, machine::llalign_of_min(ccx, lltp_ty) as i32);
         let size = machine::llsize_of(ccx, lltp_ty);
         let name = if machine::llbitsize_of_real(ccx, ccx.int_type) == 32 {
             "llvm.memset.p0i8.i32"
@@ -174,24 +174,24 @@ pub fn trans_intrinsic(ccx: @CrateContext,
 
         let decl = bcx.fcx.llfn;
         let first_real_arg = bcx.fcx.arg_pos(0u);
-        let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
+        let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p(ccx));
         let val = get_param(decl, first_real_arg + 1);
         let count = get_param(decl, first_real_arg + 2);
-        let volatile = C_i1(false);
-        let llfn = bcx.ccx().intrinsics.get_copy(&name);
+        let volatile = C_i1(ccx, false);
+        let llfn = ccx.intrinsics.get_copy(&name);
         Call(bcx, llfn, [dst_ptr, val, Mul(bcx, size, count), align, volatile], []);
         RetVoid(bcx);
     }
 
     fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
         let x = get_param(bcx.fcx.llfn, bcx.fcx.arg_pos(0u));
-        let y = C_i1(false);
+        let y = C_i1(bcx.ccx(), false);
         let llfn = bcx.ccx().intrinsics.get_copy(&name);
         let llcall = Call(bcx, llfn, [x, y], []);
         Ret(bcx, llcall);
     }
 
-    let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id));
+    let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), item.id));
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, decl, item.id, false, output_type,
@@ -218,7 +218,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                 "acq"     => lib::llvm::Acquire,
                 "rel"     => lib::llvm::Release,
                 "acqrel"  => lib::llvm::AcquireRelease,
-                _ => ccx.sess.fatal("unknown ordering in atomic intrinsic")
+                _ => ccx.sess().fatal("unknown ordering in atomic intrinsic")
             }
         };
 
@@ -259,7 +259,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                     "min"   => lib::llvm::Min,
                     "umax"  => lib::llvm::UMax,
                     "umin"  => lib::llvm::UMin,
-                    _ => ccx.sess.fatal("unknown atomic operation")
+                    _ => ccx.sess().fatal("unknown atomic operation")
                 };
 
                 let old = AtomicRMW(bcx, atom_op, get_param(decl, first_real_arg),
@@ -328,12 +328,13 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         }
         "type_id" => {
             let hash = ty::hash_crate_independent(
-                ccx.tcx,
+                ccx.tcx(),
                 *substs.tys.get(0),
                 &ccx.link_meta.crate_hash);
             // NB: This needs to be kept in lockstep with the TypeId struct in
             //     libstd/unstable/intrinsics.rs
-            let val = C_named_struct(type_of::type_of(ccx, output_type), [C_u64(hash)]);
+            let val = C_named_struct(type_of::type_of(ccx, output_type),
+                                     [C_u64(ccx, hash)]);
             match bcx.fcx.llretptr.get() {
                 Some(ptr) => {
                     Store(bcx, val, ptr);
@@ -377,13 +378,13 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                     ast_map::NodeExpr(e) => e.span,
                     _ => fail!("transmute has non-expr arg"),
                 };
-                ccx.sess.span_fatal(sp,
+                ccx.sess().span_fatal(sp,
                     format!("transmute called on types with different sizes: \
                              {intype} ({insize, plural, =1{# bit} other{# bits}}) to \
                              {outtype} ({outsize, plural, =1{# bit} other{# bits}})",
-                            intype = ty_to_str(ccx.tcx, in_type),
+                            intype = ty_to_str(ccx.tcx(), in_type),
                             insize = in_type_size as uint,
-                            outtype = ty_to_str(ccx.tcx, out_type),
+                            outtype = ty_to_str(ccx.tcx(), out_type),
                             outsize = out_type_size as uint));
             }
 
@@ -421,8 +422,8 @@ pub fn trans_intrinsic(ccx: @CrateContext,
                     // code bloat when `transmute` is used on large structural
                     // types.
                     let lldestptr = fcx.llretptr.get().unwrap();
-                    let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
-                    let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p());
+                    let lldestptr = PointerCast(bcx, lldestptr, Type::i8p(ccx));
+                    let llsrcptr = PointerCast(bcx, llsrcval, Type::i8p(ccx));
 
                     let llsize = llsize_of(ccx, llintype);
                     call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);
@@ -434,16 +435,16 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         }
         "needs_drop" => {
             let tp_ty = *substs.tys.get(0);
-            Ret(bcx, C_bool(ty::type_needs_drop(ccx.tcx, tp_ty)));
+            Ret(bcx, C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)));
         }
         "owns_managed" => {
             let tp_ty = *substs.tys.get(0);
-            Ret(bcx, C_bool(ty::type_contents(ccx.tcx, tp_ty).owns_managed()));
+            Ret(bcx, C_bool(ccx, ty::type_contents(ccx.tcx(), tp_ty).owns_managed()));
         }
         "visit_tydesc" => {
             let td = get_param(decl, first_real_arg);
             let visitor = get_param(decl, first_real_arg + 1u);
-            let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to());
+            let td = PointerCast(bcx, td, ccx.tydesc_type().ptr_to());
             glue::call_visit_glue(bcx, visitor, td, None);
             RetVoid(bcx);
         }
@@ -527,7 +528,7 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         _ => {
             // Could we make this an enum rather than a string? does it get
             // checked earlier?
-            ccx.sess.span_bug(item.span, "unknown intrinsic");
+            ccx.sess().span_bug(item.span, "unknown intrinsic");
         }
     }
     fcx.cleanup();
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 89f33776431..cd33bcf6031 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -45,13 +45,13 @@ for non-monomorphized methods only.  Other methods will
 be generated once they are invoked with specific type parameters,
 see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
 */
-pub fn trans_impl(ccx: @CrateContext,
+pub fn trans_impl(ccx: &CrateContext,
                   name: ast::Ident,
                   methods: &[@ast::Method],
                   generics: &ast::Generics,
                   id: ast::NodeId) {
     let _icx = push_ctxt("meth::trans_impl");
-    let tcx = ccx.tcx;
+    let tcx = ccx.tcx();
 
     debug!("trans_impl(name={}, id={:?})", name.repr(tcx), id);
 
@@ -84,7 +84,7 @@ pub fn trans_impl(ccx: @CrateContext,
 ///   type parameters and so forth, else None
 /// * `llfn`: the LLVM ValueRef for the method
 ///
-pub fn trans_method(ccx: @CrateContext, method: &ast::Method,
+pub fn trans_method(ccx: &CrateContext, method: &ast::Method,
                     param_substs: Option<@param_substs>,
                     llfn: ValueRef) -> ValueRef {
     trans_fn(ccx, method.decl, method.body,
@@ -108,8 +108,8 @@ pub fn trans_method_callee<'a>(
             (method.origin, method.ty)
         }
         None => {
-            bcx.tcx().sess.span_bug(bcx.tcx().map.span(method_call.expr_id),
-                                    "method call expr wasn't in method map")
+            bcx.sess().span_bug(bcx.tcx().map.span(method_call.expr_id),
+                                "method call expr wasn't in method map")
         }
     };
 
@@ -145,9 +145,9 @@ pub fn trans_method_callee<'a>(
             let self_expr = match self_expr {
                 Some(self_expr) => self_expr,
                 None => {
-                    bcx.tcx().sess.span_bug(bcx.tcx().map.span(method_call.expr_id),
-                                            "self expr wasn't provided for trait object \
-                                            callee (trying to call overloaded op?)")
+                    bcx.sess().span_bug(bcx.tcx().map.span(method_call.expr_id),
+                                        "self expr wasn't provided for trait object \
+                                         callee (trying to call overloaded op?)")
                 }
             };
             trans_trait_callee(bcx,
@@ -270,7 +270,7 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
     match vtbl {
       typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
-          let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
+          let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
           let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
 
           // create a concatenated set of substitutions which includes
@@ -319,16 +319,16 @@ fn combine_impl_and_methods_tps(bcx: &Block,
     * mapped to. */
 
     let ccx = bcx.ccx();
-    let method = ty::method(ccx.tcx, mth_did);
+    let method = ty::method(ccx.tcx(), mth_did);
     let n_m_tps = method.generics.type_param_defs().len();
     let node_substs = node_id_type_params(bcx, node);
-    debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx));
+    debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
     let ty_substs
         = vec_ng::append(Vec::from_slice(rcvr_substs),
                          node_substs.tailn(node_substs.len() - n_m_tps));
     debug!("n_m_tps={:?}", n_m_tps);
-    debug!("node_substs={:?}", node_substs.repr(ccx.tcx));
-    debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx));
+    debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
+    debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx()));
 
 
     // Now, do the same work for the vtables.  The vtables might not
@@ -415,7 +415,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
     debug!("(translating trait callee) loading second index from pair");
     let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]);
     let llbox = Load(bcx, llboxptr);
-    let llself = PointerCast(bcx, llbox, Type::i8p());
+    let llself = PointerCast(bcx, llbox, Type::i8p(ccx));
 
     // Load the function from the vtable and cast it to the expected type.
     debug!("(translating trait callee) loading method");
@@ -425,14 +425,14 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
             type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output)
         }
         _ => {
-            ccx.sess.bug("meth::trans_trait_callee given non-bare-rust-fn");
+            ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn");
         }
     };
     let llvtable = Load(bcx,
                         PointerCast(bcx,
                                     GEPi(bcx, llpair,
                                          [0u, abi::trt_field_vtable]),
-                                    Type::vtable().ptr_to().ptr_to()));
+                                    Type::vtable(ccx).ptr_to().ptr_to()));
     let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
     let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
 
@@ -445,7 +445,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
     };
 }
 
-pub fn vtable_id(ccx: @CrateContext,
+pub fn vtable_id(ccx: &CrateContext,
                  origin: &typeck::vtable_origin)
               -> mono_id {
     match origin {
@@ -500,7 +500,7 @@ pub fn get_vtable(bcx: &Block,
                     methods.push(vtable_method)
                 }
             }
-            _ => ccx.sess.bug("get_vtable: expected a static origin"),
+            _ => ccx.sess().bug("get_vtable: expected a static origin"),
         }
     }
 
@@ -526,7 +526,7 @@ pub fn make_vtable(ccx: &CrateContext,
             components.push(ptr)
         }
 
-        let tbl = C_struct(components.as_slice(), false);
+        let tbl = C_struct(ccx, components.as_slice(), false);
         let sym = token::gensym("vtable");
         let vt_gvar = format!("vtable{}", sym).with_c_str(|buf| {
             llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
@@ -544,12 +544,12 @@ fn emit_vtable_methods(bcx: &Block,
                        vtables: typeck::vtable_res)
                        -> Vec<ValueRef> {
     let ccx = bcx.ccx();
-    let tcx = ccx.tcx;
+    let tcx = ccx.tcx();
 
     let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
         Some(t_id) => t_id.def_id,
-        None       => ccx.sess.bug("make_impl_vtable: don't know how to \
-                                    make a vtable for a type impl!")
+        None       => ccx.sess().bug("make_impl_vtable: don't know how to \
+                                      make a vtable for a type impl!")
     };
 
     ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trt_id);
@@ -568,7 +568,7 @@ fn emit_vtable_methods(bcx: &Block,
            ty::type_has_self(ty::mk_bare_fn(tcx, m.fty.clone())) {
             debug!("(making impl vtable) method has self or type params: {}",
                    token::get_ident(ident));
-            C_null(Type::nil().ptr_to())
+            C_null(Type::nil(ccx).ptr_to())
         } else {
             trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), substs, Some(vtables))
         }
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index b39bcfb075f..0d9b6a087f9 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -28,7 +28,7 @@ use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::local_def;
 
-pub fn monomorphic_fn(ccx: @CrateContext,
+pub fn monomorphic_fn(ccx: &CrateContext,
                       fn_id: ast::DefId,
                       real_substs: &ty::substs,
                       vtables: Option<typeck::vtable_res>,
@@ -41,10 +41,10 @@ pub fn monomorphic_fn(ccx: @CrateContext,
             vtables={}, \
             self_vtable={}, \
             ref_id={:?})",
-           fn_id.repr(ccx.tcx),
-           real_substs.repr(ccx.tcx),
-           vtables.repr(ccx.tcx),
-           self_vtables.repr(ccx.tcx),
+           fn_id.repr(ccx.tcx()),
+           real_substs.repr(ccx.tcx()),
+           vtables.repr(ccx.tcx()),
+           self_vtables.repr(ccx.tcx()),
            ref_id);
 
     assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
@@ -71,8 +71,8 @@ pub fn monomorphic_fn(ccx: @CrateContext,
             fn_id={}, \
             psubsts={}, \
             hash_id={:?})",
-           fn_id.repr(ccx.tcx),
-           psubsts.repr(ccx.tcx),
+           fn_id.repr(ccx.tcx()),
+           psubsts.repr(ccx.tcx()),
            hash_id);
 
     {
@@ -80,14 +80,14 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         match monomorphized.get().find(&hash_id) {
           Some(&val) => {
             debug!("leaving monomorphic fn {}",
-                   ty::item_path_str(ccx.tcx, fn_id));
+                   ty::item_path_str(ccx.tcx(), fn_id));
             return (val, must_cast);
           }
           None => ()
         }
     }
 
-    let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
+    let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
     let llitem_ty = tpt.ty;
 
     // We need to do special handling of the substitutions if we are
@@ -95,7 +95,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
     let mut is_static_provided = None;
 
     let map_node = session::expect(
-        ccx.sess,
+        ccx.sess(),
         ccx.tcx.map.find(fn_id.node),
         || format!("while monomorphizing {:?}, couldn't find it in the \
                     item map (may have attempted to monomorphize an item \
@@ -123,9 +123,9 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         _ => {}
     }
 
-    debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx));
+    debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
     let mono_ty = match is_static_provided {
-        None => ty::subst_tps(ccx.tcx, psubsts.tys.as_slice(),
+        None => ty::subst_tps(ccx.tcx(), psubsts.tys.as_slice(),
                               psubsts.self_ty, llitem_ty),
         Some(num_method_ty_params) => {
             // Static default methods are a little unfortunate, in
@@ -146,9 +146,9 @@ pub fn monomorphic_fn(ccx: @CrateContext,
             let substs = psubsts.tys.slice(0, idx) +
                 &[psubsts.self_ty.unwrap()] + psubsts.tys.tailn(idx);
             debug!("static default: changed substitution to {}",
-                   substs.repr(ccx.tcx));
+                   substs.repr(ccx.tcx()));
 
-            ty::subst_tps(ccx.tcx, substs, None, llitem_ty)
+            ty::subst_tps(ccx.tcx(), substs, None, llitem_ty)
         }
     };
 
@@ -172,8 +172,8 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         // Random cut-off -- code that needs to instantiate the same function
         // recursively more than thirty times can probably safely be assumed
         // to be causing an infinite expansion.
-        if depth > ccx.sess.recursion_limit.get() {
-            ccx.sess.span_fatal(ccx.tcx.map.span(fn_id.node),
+        if depth > ccx.sess().recursion_limit.get() {
+            ccx.sess().span_fatal(ccx.tcx.map.span(fn_id.node),
                 "reached the recursion limit during monomorphization");
         }
 
@@ -207,7 +207,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
                   d
               }
               _ => {
-                ccx.tcx.sess.bug("Can't monomorphize this kind of item")
+                ccx.sess().bug("Can't monomorphize this kind of item")
               }
             }
         }
@@ -224,7 +224,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         }
         ast_map::NodeVariant(v) => {
             let parent = ccx.tcx.map.get_parent(fn_id.node);
-            let tvs = ty::enum_variants(ccx.tcx, local_def(parent));
+            let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
             let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
             let d = mk_lldecl();
             set_inline_hint(d);
@@ -239,7 +239,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
                                        d);
                 }
                 ast::StructVariantKind(_) =>
-                    ccx.tcx.sess.bug("can't monomorphize struct variants"),
+                    ccx.sess().bug("can't monomorphize struct variants"),
             }
             d
         }
@@ -258,8 +258,8 @@ pub fn monomorphic_fn(ccx: @CrateContext,
                     d
                 }
                 _ => {
-                    ccx.tcx.sess.bug(format!("can't monomorphize a {:?}",
-                                             map_node))
+                    ccx.sess().bug(format!("can't monomorphize a {:?}",
+                                           map_node))
                 }
             }
         }
@@ -281,7 +281,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         ast_map::NodeArg(..) |
         ast_map::NodeBlock(..) |
         ast_map::NodeLocal(..) => {
-            ccx.tcx.sess.bug(format!("can't monomorphize a {:?}", map_node))
+            ccx.sess().bug(format!("can't monomorphize a {:?}", map_node))
         }
     };
 
@@ -290,11 +290,11 @@ pub fn monomorphic_fn(ccx: @CrateContext,
         monomorphizing.get().insert(fn_id, depth);
     }
 
-    debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx, fn_id));
+    debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
     (lldecl, must_cast)
 }
 
-pub fn make_mono_id(ccx: @CrateContext,
+pub fn make_mono_id(ccx: &CrateContext,
                     item: ast::DefId,
                     substs: &param_substs) -> mono_id {
     // FIXME (possibly #5801): Need a lot of type hints to get
@@ -303,7 +303,7 @@ pub fn make_mono_id(ccx: @CrateContext,
     let precise_param_ids: Vec<(ty::t, Option<@Vec<mono_id> >)> = match substs.vtables {
       Some(vts) => {
         debug!("make_mono_id vtables={} substs={}",
-               vts.repr(ccx.tcx), substs.tys.repr(ccx.tcx));
+               vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx()));
         let vts_iter = substs.self_vtables.iter().chain(vts.iter());
         vts_iter.zip(substs_iter).map(|(vtable, subst)| {
             let v = vtable.map(|vt| meth::vtable_id(ccx, vt));
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 6c87ae94ba4..397361b83e0 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -54,7 +54,7 @@ impl<'a> Reflector<'a> {
     }
 
     pub fn c_bool(&mut self, b: bool) -> ValueRef {
-        C_bool(b)
+        C_bool(self.bcx.ccx(), b)
     }
 
     pub fn c_slice(&mut self, s: InternedString) -> ValueRef {
@@ -65,7 +65,7 @@ impl<'a> Reflector<'a> {
         let str_ty = ty::mk_str(bcx.tcx(), str_vstore);
         let scratch = rvalue_scratch_datum(bcx, str_ty, "");
         let len = C_uint(bcx.ccx(), s.get().len());
-        let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
+        let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p(bcx.ccx()));
         Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
         Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
         scratch.val
@@ -151,8 +151,8 @@ impl<'a> Reflector<'a> {
     // Entrypoint
     pub fn visit_ty(&mut self, t: ty::t) {
         let bcx = self.bcx;
-        let tcx = bcx.ccx().tcx;
-        debug!("reflect::visit_ty {}", ty_to_str(bcx.ccx().tcx, t));
+        let tcx = bcx.tcx();
+        debug!("reflect::visit_ty {}", ty_to_str(bcx.tcx(), t));
 
         match ty::get(t).sty {
           ty::ty_bot => self.leaf("bot"),
@@ -285,10 +285,10 @@ impl<'a> Reflector<'a> {
           ty::ty_enum(did, ref substs) => {
             let ccx = bcx.ccx();
             let repr = adt::represent_type(bcx.ccx(), t);
-            let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
+            let variants = ty::substd_enum_variants(ccx.tcx(), did, substs);
             let llptrty = type_of(ccx, t).ptr_to();
-            let opaquety = ty::get_opaque_ty(ccx.tcx).unwrap();
-            let opaqueptrty = ty::mk_ptr(ccx.tcx, ty::mt { ty: opaquety,
+            let opaquety = ty::get_opaque_ty(ccx.tcx()).unwrap();
+            let opaqueptrty = ty::mk_ptr(ccx.tcx(), ty::mt { ty: opaquety,
                                                            mutbl: ast::MutImmutable });
 
             let make_get_disr = || {
@@ -311,7 +311,7 @@ impl<'a> Reflector<'a> {
                 };
                 let bcx = fcx.entry_bcx.get().unwrap();
                 let arg = BitCast(bcx, arg, llptrty);
-                let ret = adt::trans_get_discr(bcx, repr, arg, Some(Type::i64()));
+                let ret = adt::trans_get_discr(bcx, repr, arg, Some(Type::i64(ccx)));
                 Store(bcx, ret, fcx.llretptr.get().unwrap());
                 match fcx.llreturn.get() {
                     Some(llreturn) => Br(bcx, llreturn),
@@ -328,23 +328,23 @@ impl<'a> Reflector<'a> {
             self.bracketed("enum", enum_args.as_slice(), |this| {
                 for (i, v) in variants.iter().enumerate() {
                     let name = token::get_ident(v.name);
-                    let variant_args = vec!(this.c_uint(i),
-                                         C_u64(v.disr_val),
+                    let variant_args = [this.c_uint(i),
+                                         C_u64(ccx, v.disr_val),
                                          this.c_uint(v.args.len()),
-                                         this.c_slice(name));
+                                         this.c_slice(name)];
                     this.bracketed("enum_variant",
-                                   variant_args.as_slice(),
+                                   variant_args,
                                    |this| {
                         for (j, a) in v.args.iter().enumerate() {
                             let bcx = this.bcx;
                             let null = C_null(llptrty);
                             let ptr = adt::trans_field_ptr(bcx, repr, null, v.disr_val, j);
                             let offset = p2i(ccx, ptr);
-                            let field_args = vec!(this.c_uint(j),
+                            let field_args = [this.c_uint(j),
                                                offset,
-                                               this.c_tydesc(*a));
+                                               this.c_tydesc(*a)];
                             this.visit("enum_variant_field",
-                                       field_args.as_slice());
+                                       field_args);
                         }
                     })
                 }
@@ -393,7 +393,7 @@ pub fn emit_calls_to_trait_visit_ty<'a>(
                                     -> &'a Block<'a> {
     let fcx = bcx.fcx;
     let final = fcx.new_temp_block("final");
-    let tydesc_ty = ty::get_tydesc_ty(bcx.ccx().tcx).unwrap();
+    let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
     let mut r = Reflector {
         visitor_val: visitor_val,
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 43498727566..1a54c25e364 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -38,7 +38,7 @@ use syntax::parse::token::InternedString;
 // containing an unboxed vector. This expands a boxed vector type into such an
 // expanded type. It doesn't respect mutability, but that doesn't matter at
 // this point.
-pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
+pub fn expand_boxed_vec_ty(tcx: &ty::ctxt, t: ty::t) -> ty::t {
     let unit_ty = ty::sequence_element_type(tcx, t);
     let unboxed_vec_ty = ty::mk_mut_unboxed_vec(tcx, unit_ty);
     match ty::get(t).sty {
@@ -71,7 +71,7 @@ pub fn get_dataptr(bcx: &Block, vptr: ValueRef) -> ValueRef {
 pub fn pointer_add_byte(bcx: &Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
     let _icx = push_ctxt("tvec::pointer_add_byte");
     let old_ty = val_ty(ptr);
-    let bptr = PointerCast(bcx, ptr, Type::i8p());
+    let bptr = PointerCast(bcx, ptr, Type::i8p(bcx.ccx()));
     return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
 }
 
@@ -154,8 +154,8 @@ impl VecTypes {
     pub fn to_str(&self, ccx: &CrateContext) -> ~str {
         format!("VecTypes \\{vec_ty={}, unit_ty={}, llunit_ty={}, llunit_size={}, \
                  llunit_alloc_size={}\\}",
-             ty_to_str(ccx.tcx, self.vec_ty),
-             ty_to_str(ccx.tcx, self.unit_ty),
+             ty_to_str(ccx.tcx(), self.vec_ty),
+             ty_to_str(ccx.tcx(), self.unit_ty),
              ccx.tn.type_to_str(self.llunit_ty),
              ccx.tn.val_to_str(self.llunit_size),
              self.llunit_alloc_size)
@@ -290,7 +290,7 @@ pub fn trans_lit_str<'a>(
                 let bytes = str_lit.get().len();
                 let llbytes = C_uint(bcx.ccx(), bytes);
                 let llcstr = C_cstr(bcx.ccx(), str_lit);
-                let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p().to_ref());
+                let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p(bcx.ccx()).to_ref());
                 Store(bcx, llcstr,
                       GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
                 Store(bcx, llbytes,
@@ -322,7 +322,7 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,
                     let llptrval = C_cstr(bcx.ccx(), (*s).clone());
                     let llptrval = PointerCast(bcx,
                                                llptrval,
-                                               Type::i8p());
+                                               Type::i8p(bcx.ccx()));
                     let llsizeval = C_uint(bcx.ccx(), s.get().len());
                     let typ = ty::mk_str(bcx.tcx(), ty::vstore_uniq);
                     let lldestval = rvalue_scratch_datum(bcx,
@@ -441,7 +441,7 @@ pub fn write_content<'a>(
                     return expr::trans_into(bcx, element, Ignore);
                 }
                 SaveIn(lldest) => {
-                    let count = ty::eval_repeat_count(&bcx.tcx(), count_expr);
+                    let count = ty::eval_repeat_count(bcx.tcx(), count_expr);
                     if count == 0 {
                         return bcx;
                     }
@@ -505,7 +505,7 @@ pub fn elements_required(bcx: &Block, content_expr: &ast::Expr) -> uint {
         },
         ast::ExprVec(ref es, _) => es.len(),
         ast::ExprRepeat(_, count_expr, _) => {
-            ty::eval_repeat_count(&bcx.tcx(), count_expr)
+            ty::eval_repeat_count(bcx.tcx(), count_expr)
         }
         _ => bcx.tcx().sess.span_bug(content_expr.span,
                                      "unexpected vec content")
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 3127231259d..bd1a7498d21 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -14,10 +14,9 @@ use lib::llvm::{llvm, TypeRef, Bool, False, True, TypeKind};
 use lib::llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 
 use middle::trans::context::CrateContext;
-use middle::trans::base;
 
 use syntax::ast;
-use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
+use syntax::abi::{X86, X86_64, Arm, Mips};
 
 use std::c_str::ToCStr;
 use std::cast;
@@ -51,100 +50,94 @@ impl Type {
         self.rf
     }
 
-    pub fn void() -> Type {
-        ty!(llvm::LLVMVoidTypeInContext(base::task_llcx()))
+    pub fn void(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMVoidTypeInContext(ccx.llcx))
     }
 
-    pub fn nil() -> Type {
-        Type::empty_struct()
+    pub fn nil(ccx: &CrateContext) -> Type {
+        Type::empty_struct(ccx)
     }
 
-    pub fn metadata() -> Type {
-        ty!(llvm::LLVMMetadataTypeInContext(base::task_llcx()))
+    pub fn metadata(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMMetadataTypeInContext(ccx.llcx))
     }
 
-    pub fn i1() -> Type {
-        ty!(llvm::LLVMInt1TypeInContext(base::task_llcx()))
+    pub fn i1(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMInt1TypeInContext(ccx.llcx))
     }
 
-    pub fn i8() -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(base::task_llcx()))
+    pub fn i8(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMInt8TypeInContext(ccx.llcx))
     }
 
-    pub fn i16() -> Type {
-        ty!(llvm::LLVMInt16TypeInContext(base::task_llcx()))
+    pub fn i16(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMInt16TypeInContext(ccx.llcx))
     }
 
-    pub fn i32() -> Type {
-        ty!(llvm::LLVMInt32TypeInContext(base::task_llcx()))
+    pub fn i32(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMInt32TypeInContext(ccx.llcx))
     }
 
-    pub fn i64() -> Type {
-        ty!(llvm::LLVMInt64TypeInContext(base::task_llcx()))
+    pub fn i64(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMInt64TypeInContext(ccx.llcx))
     }
 
-    pub fn f32() -> Type {
-        ty!(llvm::LLVMFloatTypeInContext(base::task_llcx()))
+    pub fn f32(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMFloatTypeInContext(ccx.llcx))
     }
 
-    pub fn f64() -> Type {
-        ty!(llvm::LLVMDoubleTypeInContext(base::task_llcx()))
+    pub fn f64(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx))
     }
 
-    pub fn bool() -> Type {
-        Type::i8()
+    pub fn bool(ccx: &CrateContext) -> Type {
+        Type::i8(ccx)
     }
 
-    pub fn char() -> Type {
-        Type::i32()
+    pub fn char(ccx: &CrateContext) -> Type {
+        Type::i32(ccx)
     }
 
-    pub fn i8p() -> Type {
-        Type::i8().ptr_to()
+    pub fn i8p(ccx: &CrateContext) -> Type {
+        Type::i8(ccx).ptr_to()
     }
 
-    pub fn int(arch: Architecture) -> Type {
-        match arch {
-            X86 | Arm | Mips => Type::i32(),
-            X86_64 => Type::i64()
+    pub fn int(ccx: &CrateContext) -> Type {
+        match ccx.tcx.sess.targ_cfg.arch {
+            X86 | Arm | Mips => Type::i32(ccx),
+            X86_64 => Type::i64(ccx)
         }
     }
 
-    pub fn float(_: Architecture) -> Type {
-        // All architectures currently just use doubles as the default
-        // float size
-        Type::f64()
-    }
-
-    pub fn int_from_ty(ctx: &CrateContext, t: ast::IntTy) -> Type {
+    pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type {
         match t {
-            ast::TyI => ctx.int_type,
-            ast::TyI8 => Type::i8(),
-            ast::TyI16 => Type::i16(),
-            ast::TyI32 => Type::i32(),
-            ast::TyI64 => Type::i64()
+            ast::TyI => ccx.int_type,
+            ast::TyI8 => Type::i8(ccx),
+            ast::TyI16 => Type::i16(ccx),
+            ast::TyI32 => Type::i32(ccx),
+            ast::TyI64 => Type::i64(ccx)
         }
     }
 
-    pub fn uint_from_ty(ctx: &CrateContext, t: ast::UintTy) -> Type {
+    pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type {
         match t {
-            ast::TyU => ctx.int_type,
-            ast::TyU8 => Type::i8(),
-            ast::TyU16 => Type::i16(),
-            ast::TyU32 => Type::i32(),
-            ast::TyU64 => Type::i64()
+            ast::TyU => ccx.int_type,
+            ast::TyU8 => Type::i8(ccx),
+            ast::TyU16 => Type::i16(ccx),
+            ast::TyU32 => Type::i32(ccx),
+            ast::TyU64 => Type::i64(ccx)
         }
     }
 
-    pub fn float_from_ty(t: ast::FloatTy) -> Type {
+    pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
         match t {
-            ast::TyF32 => Type::f32(),
-            ast::TyF64 => Type::f64()
+            ast::TyF32 => Type::f32(ccx),
+            ast::TyF64 => Type::f64(ccx)
         }
     }
 
-    pub fn size_t(arch: Architecture) -> Type {
-        Type::int(arch)
+    pub fn size_t(ccx: &CrateContext) -> Type {
+        Type::int(ccx)
     }
 
     pub fn func(args: &[Type], ret: &Type) -> Type {
@@ -163,23 +156,23 @@ impl Type {
         ty!(llvm::LLVMPointerType(ty.to_ref(), 0 as c_uint))
     }
 
-    pub fn struct_(els: &[Type], packed: bool) -> Type {
+    pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
         let els : &[TypeRef] = unsafe { cast::transmute(els) };
-        ty!(llvm::LLVMStructTypeInContext(base::task_llcx(), els.as_ptr(),
-                                          els.len() as c_uint, packed as Bool))
+        ty!(llvm::LLVMStructTypeInContext(ccx.llcx, els.as_ptr(),
+                                          els.len() as c_uint,
+                                          packed as Bool))
     }
 
-    pub fn named_struct(name: &str) -> Type {
-        let ctx = base::task_llcx();
-        ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ctx, s)))
+    pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
+        ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx, s)))
     }
 
-    pub fn empty_struct() -> Type {
-        Type::struct_([], false)
+    pub fn empty_struct(ccx: &CrateContext) -> Type {
+        Type::struct_(ccx, [], false)
     }
 
-    pub fn vtable() -> Type {
-        Type::array(&Type::i8p().ptr_to(), 1)
+    pub fn vtable(ccx: &CrateContext) -> Type {
+        Type::array(&Type::i8p(ccx).ptr_to(), 1)
     }
 
     pub fn generic_glue_fn(cx: &CrateContext) -> Type {
@@ -188,21 +181,21 @@ impl Type {
             None => ()
         }
 
-        let ty = Type::glue_fn(Type::i8p());
+        let ty = Type::glue_fn(cx, Type::i8p(cx));
         cx.tn.associate_type("glue_fn", &ty);
 
-        return ty;
+        ty
     }
 
-    pub fn glue_fn(t: Type) -> Type {
-        Type::func([t], &Type::void())
+    pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type {
+        Type::func([t], &Type::void(ccx))
     }
 
-    pub fn tydesc(arch: Architecture) -> Type {
-        let mut tydesc = Type::named_struct("tydesc");
-        let glue_fn_ty = Type::glue_fn(Type::i8p()).ptr_to();
+    pub fn tydesc(ccx: &CrateContext) -> Type {
+        let mut tydesc = Type::named_struct(ccx, "tydesc");
+        let glue_fn_ty = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to();
 
-        let int_ty = Type::int(arch);
+        let int_ty = Type::int(ccx);
 
         // Must mirror:
         //
@@ -212,10 +205,10 @@ impl Type {
                      int_ty,     // align
                      glue_fn_ty, // drop
                      glue_fn_ty, // visit
-                     Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name
+                     Type::struct_(ccx, [Type::i8p(ccx), Type::int(ccx)], false)]; // name
         tydesc.set_struct_body(elems, false);
 
-        return tydesc;
+        tydesc
     }
 
     pub fn array(ty: &Type, len: u64) -> Type {
@@ -226,27 +219,27 @@ impl Type {
         ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
     }
 
-    pub fn vec(arch: Architecture, ty: &Type) -> Type {
-        Type::struct_(
-            [ Type::int(arch), Type::int(arch), Type::array(ty, 0) ],
+    pub fn vec(ccx: &CrateContext, ty: &Type) -> Type {
+        Type::struct_(ccx,
+            [Type::int(ccx), Type::int(ccx), Type::array(ty, 0)],
         false)
     }
 
-    pub fn opaque_vec(arch: Architecture) -> Type {
-        Type::vec(arch, &Type::i8())
+    pub fn opaque_vec(ccx: &CrateContext) -> Type {
+        Type::vec(ccx, &Type::i8(ccx))
     }
 
     // The box pointed to by @T.
-    pub fn at_box(ctx: &CrateContext, ty: Type) -> Type {
-        Type::struct_([
-            ctx.int_type, Type::glue_fn(Type::i8p()).ptr_to(),
-            Type::i8p(), Type::i8p(), ty
+    pub fn at_box(ccx: &CrateContext, ty: Type) -> Type {
+        Type::struct_(ccx, [
+            ccx.int_type, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to(),
+            Type::i8p(ccx), Type::i8p(ccx), ty
         ], false)
     }
 
-    pub fn opaque_trait() -> Type {
-        let vtable = Type::glue_fn(Type::i8p()).ptr_to().ptr_to();
-        Type::struct_([vtable, Type::i8p()], false)
+    pub fn opaque_trait(ccx: &CrateContext) -> Type {
+        let vtable = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to();
+        Type::struct_(ccx, [vtable, Type::i8p(ccx)], false)
     }
 
     pub fn kind(&self) -> TypeKind {
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index de3aff0fff6..32821f32df5 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -54,7 +54,7 @@ pub fn type_of_rust_fn(cx: &CrateContext, has_env: bool,
 
     // Arg 1: Environment
     if has_env {
-        atys.push(Type::i8p());
+        atys.push(Type::i8p(cx));
     }
 
     // ... then explicit args.
@@ -63,7 +63,7 @@ pub fn type_of_rust_fn(cx: &CrateContext, has_env: bool,
 
     // Use the output as the actual return value if it's immediate.
     if use_out_pointer || return_type_is_void(cx, output) {
-        Type::func(atys.as_slice(), &Type::void())
+        Type::func(atys.as_slice(), &Type::void(cx))
     } else {
         Type::func(atys.as_slice(), &lloutputtype)
     }
@@ -86,7 +86,7 @@ pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type {
             }
         }
         _ => {
-            cx.sess.bug("type_of_fn_from_ty given non-closure, non-bare-fn")
+            cx.sess().bug("type_of_fn_from_ty given non-closure, non-bare-fn")
         }
     }
 }
@@ -112,37 +112,36 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
     }
 
     let llsizingty = match ty::get(t).sty {
-        ty::ty_nil | ty::ty_bot => Type::nil(),
-        ty::ty_bool => Type::bool(),
-        ty::ty_char => Type::char(),
+        ty::ty_nil | ty::ty_bot => Type::nil(cx),
+        ty::ty_bool => Type::bool(cx),
+        ty::ty_char => Type::char(cx),
         ty::ty_int(t) => Type::int_from_ty(cx, t),
         ty::ty_uint(t) => Type::uint_from_ty(cx, t),
-        ty::ty_float(t) => Type::float_from_ty(t),
+        ty::ty_float(t) => Type::float_from_ty(cx, t),
 
         ty::ty_str(ty::vstore_uniq) |
         ty::ty_vec(_, ty::vstore_uniq) |
         ty::ty_box(..) |
         ty::ty_uniq(..) |
         ty::ty_ptr(..) |
-        ty::ty_rptr(..) => Type::i8p(),
+        ty::ty_rptr(..) => Type::i8p(cx),
 
         ty::ty_str(ty::vstore_slice(..)) |
         ty::ty_vec(_, ty::vstore_slice(..)) => {
-            Type::struct_([Type::i8p(), Type::i8p()], false)
+            Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
         }
 
-        ty::ty_bare_fn(..) => Type::i8p(),
-        ty::ty_closure(..) => Type::struct_([Type::i8p(), Type::i8p()], false),
-        ty::ty_trait(..) => Type::opaque_trait(),
+        ty::ty_bare_fn(..) => Type::i8p(cx),
+        ty::ty_closure(..) => Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false),
+        ty::ty_trait(..) => Type::opaque_trait(cx),
 
-        ty::ty_str(ty::vstore_fixed(size)) => Type::array(&Type::i8(), size as u64),
+        ty::ty_str(ty::vstore_fixed(size)) => Type::array(&Type::i8(cx), size as u64),
         ty::ty_vec(mt, ty::vstore_fixed(size)) => {
             Type::array(&sizing_type_of(cx, mt.ty), size as u64)
         }
 
         ty::ty_unboxed_vec(mt) => {
-            let sz_ty = sizing_type_of(cx, mt.ty);
-            Type::vec(cx.sess.targ_cfg.arch, &sz_ty)
+            Type::vec(cx, &sizing_type_of(cx, mt.ty))
         }
 
         ty::ty_tup(..) | ty::ty_enum(..) => {
@@ -151,9 +150,9 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
         }
 
         ty::ty_struct(..) => {
-            if ty::type_is_simd(cx.tcx, t) {
-                let et = ty::simd_type(cx.tcx, t);
-                let n = ty::simd_size(cx.tcx, t);
+            if ty::type_is_simd(cx.tcx(), t) {
+                let et = ty::simd_type(cx.tcx(), t);
+                let n = ty::simd_size(cx.tcx(), t);
                 Type::vector(&type_of(cx, et), n as u64)
             } else {
                 let repr = adt::represent_type(cx, t);
@@ -162,7 +161,8 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
         }
 
         ty::ty_self(_) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
-            cx.tcx.sess.bug(format!("fictitious type {:?} in sizing_type_of()", ty::get(t).sty))
+            cx.sess().bug(format!("fictitious type {:?} in sizing_type_of()",
+                                  ty::get(t).sty))
         }
     };
 
@@ -182,21 +182,21 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
         }
     }
 
-    debug!("type_of {} {:?}", t.repr(cx.tcx), t);
+    debug!("type_of {} {:?}", t.repr(cx.tcx()), t);
 
     // Replace any typedef'd types with their equivalent non-typedef
     // type. This ensures that all LLVM nominal types that contain
     // Rust types are defined as the same LLVM types.  If we don't do
     // this then, e.g. `Option<{myfield: bool}>` would be a different
     // type than `Option<myrec>`.
-    let t_norm = ty::normalize_ty(cx.tcx, t);
+    let t_norm = ty::normalize_ty(cx.tcx(), t);
 
     if t != t_norm {
         let llty = type_of(cx, t_norm);
         debug!("--> normalized {} {:?} to {} {:?} llty={}",
-                t.repr(cx.tcx),
+                t.repr(cx.tcx()),
                 t,
-                t_norm.repr(cx.tcx),
+                t_norm.repr(cx.tcx()),
                 t_norm,
                 cx.tn.type_to_str(llty));
         let mut lltypes = cx.lltypes.borrow_mut();
@@ -205,14 +205,14 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
     }
 
     let mut llty = match ty::get(t).sty {
-      ty::ty_nil | ty::ty_bot => Type::nil(),
-      ty::ty_bool => Type::bool(),
-      ty::ty_char => Type::char(),
+      ty::ty_nil | ty::ty_bot => Type::nil(cx),
+      ty::ty_bool => Type::bool(cx),
+      ty::ty_char => Type::char(cx),
       ty::ty_int(t) => Type::int_from_ty(cx, t),
       ty::ty_uint(t) => Type::uint_from_ty(cx, t),
-      ty::ty_float(t) => Type::float_from_ty(t),
+      ty::ty_float(t) => Type::float_from_ty(cx, t),
       ty::ty_str(ty::vstore_uniq) => {
-        Type::vec(cx.sess.targ_cfg.arch, &Type::i8()).ptr_to()
+        Type::vec(cx, &Type::i8(cx)).ptr_to()
       }
       ty::ty_enum(did, ref substs) => {
         // Only create the named struct, but don't fill it in. We
@@ -230,12 +230,10 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
           type_of(cx, typ).ptr_to()
       }
       ty::ty_vec(ref mt, ty::vstore_uniq) => {
-          let ty = type_of(cx, mt.ty);
-          Type::vec(cx.sess.targ_cfg.arch, &ty).ptr_to()
+          Type::vec(cx, &type_of(cx, mt.ty)).ptr_to()
       }
       ty::ty_unboxed_vec(ref mt) => {
-          let ty = type_of(cx, mt.ty);
-          Type::vec(cx.sess.targ_cfg.arch, &ty)
+          Type::vec(cx, &type_of(cx, mt.ty))
       }
       ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
       ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
@@ -243,7 +241,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       ty::ty_vec(ref mt, ty::vstore_slice(_)) => {
           let p_ty = type_of(cx, mt.ty).ptr_to();
           let u_ty = Type::uint_from_ty(cx, ast::TyU);
-          Type::struct_([p_ty, u_ty], false)
+          Type::struct_(cx, [p_ty, u_ty], false)
       }
 
       ty::ty_str(ty::vstore_slice(_)) => {
@@ -252,7 +250,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       }
 
       ty::ty_str(ty::vstore_fixed(n)) => {
-          Type::array(&Type::i8(), (n + 1u) as u64)
+          Type::array(&Type::i8(cx), (n + 1u) as u64)
       }
 
       ty::ty_vec(ref mt, ty::vstore_fixed(n)) => {
@@ -264,17 +262,17 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       }
       ty::ty_closure(_) => {
           let fn_ty = type_of_fn_from_ty(cx, t).ptr_to();
-          Type::struct_([fn_ty, Type::i8p()], false)
+          Type::struct_(cx, [fn_ty, Type::i8p(cx)], false)
       }
-      ty::ty_trait(..) => Type::opaque_trait(),
+      ty::ty_trait(..) => Type::opaque_trait(cx),
       ty::ty_tup(..) => {
           let repr = adt::represent_type(cx, t);
           adt::type_of(cx, repr)
       }
       ty::ty_struct(did, ref substs) => {
-          if ty::type_is_simd(cx.tcx, t) {
-              let et = ty::simd_type(cx.tcx, t);
-              let n = ty::simd_size(cx.tcx, t);
+          if ty::type_is_simd(cx.tcx(), t) {
+              let et = ty::simd_type(cx.tcx(), t);
+              let n = ty::simd_size(cx.tcx(), t);
               Type::vector(&type_of(cx, et), n as u64)
           } else {
               // Only create the named struct, but don't fill it in. We fill it
@@ -288,14 +286,14 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
               adt::incomplete_type_of(cx, repr, name)
           }
       }
-      ty::ty_self(..) => cx.tcx.sess.unimpl("type_of: ty_self"),
-      ty::ty_infer(..) => cx.tcx.sess.bug("type_of with ty_infer"),
-      ty::ty_param(..) => cx.tcx.sess.bug("type_of with ty_param"),
-      ty::ty_err(..) => cx.tcx.sess.bug("type_of with ty_err")
+      ty::ty_self(..) => cx.sess().unimpl("type_of: ty_self"),
+      ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
+      ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
+      ty::ty_err(..) => cx.sess().bug("type_of with ty_err")
     };
 
     debug!("--> mapped t={} {:?} to llty={}",
-            t.repr(cx.tcx),
+            t.repr(cx.tcx()),
             t,
             cx.tn.type_to_str(llty));
     {
@@ -305,7 +303,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
 
     // If this was an enum or struct, fill in the type now.
     match ty::get(t).sty {
-        ty::ty_enum(..) | ty::ty_struct(..) if !ty::type_is_simd(cx.tcx, t) => {
+        ty::ty_enum(..) | ty::ty_struct(..) if !ty::type_is_simd(cx.tcx(), t) => {
             let repr = adt::represent_type(cx, t);
             adt::finish_type_of(cx, repr, &mut llty);
         }
@@ -326,7 +324,7 @@ pub fn llvm_type_name(cx: &CrateContext,
         a_struct => { "struct" }
         an_enum => { "enum" }
     };
-    let tstr = ppaux::parameterized(cx.tcx, ty::item_path_str(cx.tcx, did),
+    let tstr = ppaux::parameterized(cx.tcx(), ty::item_path_str(cx.tcx(), did),
                                     &ty::NonerasedRegions(opt_vec::Empty),
                                     tps, did, false);
     if did.krate == 0 {
@@ -338,5 +336,5 @@ pub fn llvm_type_name(cx: &CrateContext,
 
 pub fn type_of_dtor(ccx: &CrateContext, self_ty: ty::t) -> Type {
     let self_ty = type_of(ccx, self_ty).ptr_to();
-    Type::func([self_ty], &Type::void())
+    Type::func([self_ty], &Type::void(ccx))
 }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index e1dddda01f7..ae940ebeef2 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -11,9 +11,8 @@
 #[allow(non_camel_case_types)];
 
 use back::svh::Svh;
-use driver::session;
+use driver::session::Session;
 use metadata::csearch;
-use metadata;
 use middle::const_eval;
 use middle::lang_items::{ExchangeHeapLangItem, OpaqueStructLangItem};
 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
@@ -250,22 +249,18 @@ pub enum AutoRef {
     AutoBorrowObj(Region, ast::Mutability),
 }
 
-pub type ctxt = @ctxt_;
-
 /// The data structure to keep track of all the information that typechecker
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
-pub struct ctxt_ {
-    diag: @syntax::diagnostic::SpanHandler,
+pub struct ctxt {
     // Specifically use a speedy hash algorithm for this hash map, it's used
     // quite often.
     interner: RefCell<FnvHashMap<intern_key, ~t_box_>>,
     next_id: Cell<uint>,
-    cstore: @metadata::cstore::CStore,
-    sess: session::Session,
+    sess: Session,
     def_map: resolve::DefMap,
 
-    named_region_map: @RefCell<resolve_lifetime::NamedRegionMap>,
+    named_region_map: resolve_lifetime::NamedRegionMap,
 
     region_maps: middle::region::RegionMaps,
 
@@ -1081,21 +1076,19 @@ pub type type_cache = RefCell<DefIdMap<ty_param_bounds_and_ty>>;
 
 pub type node_type_table = RefCell<HashMap<uint,t>>;
 
-pub fn mk_ctxt(s: session::Session,
+pub fn mk_ctxt(s: Session,
                dm: resolve::DefMap,
-               named_region_map: @RefCell<resolve_lifetime::NamedRegionMap>,
+               named_region_map: resolve_lifetime::NamedRegionMap,
                map: ast_map::Map,
                freevars: freevars::freevar_map,
                region_maps: middle::region::RegionMaps,
                lang_items: @middle::lang_items::LanguageItems)
             -> ctxt {
-    @ctxt_ {
+    ctxt {
         named_region_map: named_region_map,
         item_variance_map: RefCell::new(DefIdMap::new()),
-        diag: s.diagnostic(),
         interner: RefCell::new(FnvHashMap::new()),
         next_id: Cell::new(primitives::LAST_PRIMITIVE_ID),
-        cstore: s.cstore,
         sess: s,
         def_map: dm,
         region_maps: region_maps,
@@ -1143,7 +1136,7 @@ pub fn mk_ctxt(s: session::Session,
 
 // Interns a type/name combination, stores the resulting box in cx.interner,
 // and returns the box as cast to an unsafe ptr (see comments for t above).
-pub fn mk_t(cx: ctxt, st: sty) -> t {
+pub fn mk_t(cx: &ctxt, st: sty) -> t {
     // Check for primitive types.
     match st {
         ty_nil => return mk_nil(),
@@ -1355,64 +1348,64 @@ pub fn mk_mach_float(tm: ast::FloatTy) -> t {
 #[inline]
 pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
 
-pub fn mk_str(cx: ctxt, t: vstore) -> t {
+pub fn mk_str(cx: &ctxt, t: vstore) -> t {
     mk_t(cx, ty_str(t))
 }
 
-pub fn mk_enum(cx: ctxt, did: ast::DefId, substs: substs) -> t {
+pub fn mk_enum(cx: &ctxt, did: ast::DefId, substs: substs) -> t {
     // take a copy of substs so that we own the vectors inside
     mk_t(cx, ty_enum(did, substs))
 }
 
-pub fn mk_box(cx: ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
+pub fn mk_box(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
 
-pub fn mk_uniq(cx: ctxt, ty: t) -> t { mk_t(cx, ty_uniq(ty)) }
+pub fn mk_uniq(cx: &ctxt, ty: t) -> t { mk_t(cx, ty_uniq(ty)) }
 
-pub fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
+pub fn mk_ptr(cx: &ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
 
-pub fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
+pub fn mk_rptr(cx: &ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
 
-pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
+pub fn mk_mut_rptr(cx: &ctxt, r: Region, ty: t) -> t {
     mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable})
 }
-pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
+pub fn mk_imm_rptr(cx: &ctxt, r: Region, ty: t) -> t {
     mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable})
 }
 
-pub fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
+pub fn mk_mut_ptr(cx: &ctxt, ty: t) -> t {
     mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable})
 }
 
-pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
+pub fn mk_imm_ptr(cx: &ctxt, ty: t) -> t {
     mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable})
 }
 
-pub fn mk_nil_ptr(cx: ctxt) -> t {
+pub fn mk_nil_ptr(cx: &ctxt) -> t {
     mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
 }
 
-pub fn mk_vec(cx: ctxt, tm: mt, t: vstore) -> t {
+pub fn mk_vec(cx: &ctxt, tm: mt, t: vstore) -> t {
     mk_t(cx, ty_vec(tm, t))
 }
 
-pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
+pub fn mk_unboxed_vec(cx: &ctxt, tm: mt) -> t {
     mk_t(cx, ty_unboxed_vec(tm))
 }
-pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
+pub fn mk_mut_unboxed_vec(cx: &ctxt, ty: t) -> t {
     mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::MutImmutable}))
 }
 
-pub fn mk_tup(cx: ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
+pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
 
-pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t {
+pub fn mk_closure(cx: &ctxt, fty: ClosureTy) -> t {
     mk_t(cx, ty_closure(fty))
 }
 
-pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
+pub fn mk_bare_fn(cx: &ctxt, fty: BareFnTy) -> t {
     mk_t(cx, ty_bare_fn(fty))
 }
 
-pub fn mk_ctor_fn(cx: ctxt,
+pub fn mk_ctor_fn(cx: &ctxt,
                   binder_id: ast::NodeId,
                   input_tys: &[ty::t],
                   output: ty::t) -> t {
@@ -1431,7 +1424,7 @@ pub fn mk_ctor_fn(cx: ctxt,
 }
 
 
-pub fn mk_trait(cx: ctxt,
+pub fn mk_trait(cx: &ctxt,
                 did: ast::DefId,
                 substs: substs,
                 store: TraitStore,
@@ -1442,22 +1435,22 @@ pub fn mk_trait(cx: ctxt,
     mk_t(cx, ty_trait(did, substs, store, mutability, bounds))
 }
 
-pub fn mk_struct(cx: ctxt, struct_id: ast::DefId, substs: substs) -> t {
+pub fn mk_struct(cx: &ctxt, struct_id: ast::DefId, substs: substs) -> t {
     // take a copy of substs so that we own the vectors inside
     mk_t(cx, ty_struct(struct_id, substs))
 }
 
-pub fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
+pub fn mk_var(cx: &ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
 
-pub fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
+pub fn mk_int_var(cx: &ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
 
-pub fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
+pub fn mk_float_var(cx: &ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
 
-pub fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
+pub fn mk_infer(cx: &ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
 
-pub fn mk_self(cx: ctxt, did: ast::DefId) -> t { mk_t(cx, ty_self(did)) }
+pub fn mk_self(cx: &ctxt, did: ast::DefId) -> t { mk_t(cx, ty_self(did)) }
 
-pub fn mk_param(cx: ctxt, n: uint, k: DefId) -> t {
+pub fn mk_param(cx: &ctxt, n: uint, k: DefId) -> t {
     mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
 }
 
@@ -1495,35 +1488,35 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
 }
 
 // Folds types from the bottom up.
-pub fn fold_ty(cx: ctxt, t0: t, fldop: |t| -> t) -> t {
+pub fn fold_ty(cx: &ctxt, t0: t, fldop: |t| -> t) -> t {
     let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
     f.fold_ty(t0)
 }
 
-pub fn walk_regions_and_ty(cx: ctxt, ty: t, fldr: |r: Region|, fldt: |t: t|)
+pub fn walk_regions_and_ty(cx: &ctxt, ty: t, fldr: |r: Region|, fldt: |t: t|)
                            -> t {
     ty_fold::RegionFolder::general(cx,
                                    |r| { fldr(r); r },
                                    |t| { fldt(t); t }).fold_ty(ty)
 }
 
-pub fn fold_regions(cx: ctxt, ty: t, fldr: |r: Region| -> Region) -> t {
+pub fn fold_regions(cx: &ctxt, ty: t, fldr: |r: Region| -> Region) -> t {
     ty_fold::RegionFolder::regions(cx, fldr).fold_ty(ty)
 }
 
 // Substitute *only* type parameters.  Used in trans where regions are erased.
-pub fn subst_tps(tcx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
+pub fn subst_tps(tcx: &ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
     let mut subst = TpsSubst { tcx: tcx, self_ty_opt: self_ty_opt, tps: tps };
     return subst.fold_ty(typ);
 
     struct TpsSubst<'a> {
-        tcx: ctxt,
+        tcx: &'a ctxt,
         self_ty_opt: Option<t>,
         tps: &'a [t],
     }
 
     impl<'a> TypeFolder for TpsSubst<'a> {
-        fn tcx(&self) -> ty::ctxt { self.tcx }
+        fn tcx<'a>(&'a self) -> &'a ctxt { self.tcx }
 
         fn fold_ty(&mut self, t: ty::t) -> ty::t {
             if self.tps.len() == 0u && self.self_ty_opt.is_none() {
@@ -1566,11 +1559,11 @@ pub fn substs_is_noop(substs: &substs) -> bool {
         substs.self_ty.is_none()
 }
 
-pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
+pub fn substs_to_str(cx: &ctxt, substs: &substs) -> ~str {
     substs.repr(cx)
 }
 
-pub fn subst(cx: ctxt,
+pub fn subst(cx: &ctxt,
              substs: &substs,
              typ: t)
           -> t {
@@ -1631,7 +1624,7 @@ pub fn type_is_sequence(ty: t) -> bool {
     }
 }
 
-pub fn type_is_simd(cx: ctxt, ty: t) -> bool {
+pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
     match get(ty).sty {
         ty_struct(did, _) => lookup_simd(cx, did),
         _ => false
@@ -1645,7 +1638,7 @@ pub fn type_is_str(ty: t) -> bool {
     }
 }
 
-pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
+pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
     match get(ty).sty {
       ty_str(_) => return mk_mach_uint(ast::TyU8),
       ty_vec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
@@ -1653,7 +1646,7 @@ pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
     }
 }
 
-pub fn simd_type(cx: ctxt, ty: t) -> t {
+pub fn simd_type(cx: &ctxt, ty: t) -> t {
     match get(ty).sty {
         ty_struct(did, ref substs) => {
             let fields = lookup_struct_fields(cx, did);
@@ -1663,7 +1656,7 @@ pub fn simd_type(cx: ctxt, ty: t) -> t {
     }
 }
 
-pub fn simd_size(cx: ctxt, ty: t) -> uint {
+pub fn simd_size(cx: &ctxt, ty: t) -> uint {
     match get(ty).sty {
         ty_struct(did, _) => {
             let fields = lookup_struct_fields(cx, did);
@@ -1751,7 +1744,7 @@ pub fn type_is_scalar(ty: t) -> bool {
     }
 }
 
-pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
+pub fn type_needs_drop(cx: &ctxt, ty: t) -> bool {
     type_contents(cx, ty).needs_drop(cx)
 }
 
@@ -1759,7 +1752,7 @@ pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
 // task can free them all at once later. Currently only things
 // that only contain scalars and shared boxes can avoid unwind
 // cleanups.
-pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
+pub fn type_needs_unwind_cleanup(cx: &ctxt, ty: t) -> bool {
     {
         let needs_unwind_cleanup_cache = cx.needs_unwind_cleanup_cache
                                            .borrow();
@@ -1778,7 +1771,7 @@ pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
     return needs_unwind_cleanup;
 }
 
-fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
+fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
                               tycache: &mut HashSet<t>,
                               encountered_box: bool) -> bool {
 
@@ -1925,11 +1918,11 @@ def_type_content_sets!(
 )
 
 impl TypeContents {
-    pub fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
+    pub fn meets_bounds(&self, cx: &ctxt, bbs: BuiltinBounds) -> bool {
         bbs.iter().all(|bb| self.meets_bound(cx, bb))
     }
 
-    pub fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
+    pub fn meets_bound(&self, cx: &ctxt, bb: BuiltinBound) -> bool {
         match bb {
             BoundStatic => self.is_static(cx),
             BoundFreeze => self.is_freezable(cx),
@@ -1947,11 +1940,11 @@ impl TypeContents {
         (self.bits & tc.bits) != 0
     }
 
-    pub fn is_static(&self, _: ctxt) -> bool {
+    pub fn is_static(&self, _: &ctxt) -> bool {
         !self.intersects(TC::Nonstatic)
     }
 
-    pub fn is_sendable(&self, _: ctxt) -> bool {
+    pub fn is_sendable(&self, _: &ctxt) -> bool {
         !self.intersects(TC::Nonsendable)
     }
 
@@ -1963,23 +1956,23 @@ impl TypeContents {
         self.intersects(TC::OwnsOwned)
     }
 
-    pub fn is_freezable(&self, _: ctxt) -> bool {
+    pub fn is_freezable(&self, _: &ctxt) -> bool {
         !self.intersects(TC::Nonfreezable)
     }
 
-    pub fn is_sized(&self, _: ctxt) -> bool {
+    pub fn is_sized(&self, _: &ctxt) -> bool {
         !self.intersects(TC::Nonsized)
     }
 
-    pub fn is_pod(&self, _: ctxt) -> bool {
+    pub fn is_pod(&self, _: &ctxt) -> bool {
         !self.intersects(TC::Nonpod)
     }
 
-    pub fn moves_by_default(&self, _: ctxt) -> bool {
+    pub fn moves_by_default(&self, _: &ctxt) -> bool {
         self.intersects(TC::Moves)
     }
 
-    pub fn needs_drop(&self, _: ctxt) -> bool {
+    pub fn needs_drop(&self, _: &ctxt) -> bool {
         self.intersects(TC::NeedsDrop)
     }
 
@@ -2055,23 +2048,23 @@ impl fmt::Show for TypeContents {
     }
 }
 
-pub fn type_has_dtor(cx: ctxt, t: ty::t) -> bool {
+pub fn type_has_dtor(cx: &ctxt, t: ty::t) -> bool {
     type_contents(cx, t).has_dtor()
 }
 
-pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
+pub fn type_is_static(cx: &ctxt, t: ty::t) -> bool {
     type_contents(cx, t).is_static(cx)
 }
 
-pub fn type_is_sendable(cx: ctxt, t: ty::t) -> bool {
+pub fn type_is_sendable(cx: &ctxt, t: ty::t) -> bool {
     type_contents(cx, t).is_sendable(cx)
 }
 
-pub fn type_is_freezable(cx: ctxt, t: ty::t) -> bool {
+pub fn type_is_freezable(cx: &ctxt, t: ty::t) -> bool {
     type_contents(cx, t).is_freezable(cx)
 }
 
-pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
+pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
     let ty_id = type_id(ty);
 
     {
@@ -2089,7 +2082,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
     tc_cache.get().insert(ty_id, result);
     return result;
 
-    fn tc_ty(cx: ctxt,
+    fn tc_ty(cx: &ctxt,
              ty: t,
              cache: &mut HashMap<uint, TypeContents>) -> TypeContents
     {
@@ -2255,7 +2248,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         return result;
     }
 
-    fn tc_mt(cx: ctxt,
+    fn tc_mt(cx: &ctxt,
              mt: mt,
              cache: &mut HashMap<uint, TypeContents>) -> TypeContents
     {
@@ -2263,7 +2256,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         mc | tc_ty(cx, mt.ty, cache)
     }
 
-    fn apply_lang_items(cx: ctxt,
+    fn apply_lang_items(cx: &ctxt,
                         did: ast::DefId,
                         tc: TypeContents)
                         -> TypeContents {
@@ -2295,7 +2288,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
     }
 
-    fn closure_contents(cx: ctxt, cty: &ClosureTy) -> TypeContents {
+    fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
         // Closure contents are just like trait contents, but with potentially
         // even more stuff.
         let st = match cty.sigil {
@@ -2321,7 +2314,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         st | rt | ot
     }
 
-    fn object_contents(cx: ctxt,
+    fn object_contents(cx: &ctxt,
                        store: TraitStore,
                        mutbl: ast::Mutability,
                        bounds: BuiltinBounds)
@@ -2340,7 +2333,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
         }
     }
 
-    fn kind_bounds_to_contents(cx: ctxt,
+    fn kind_bounds_to_contents(cx: &ctxt,
                                bounds: BuiltinBounds,
                                traits: &[@TraitRef])
                                -> TypeContents {
@@ -2359,7 +2352,7 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
 
         // Iterates over all builtin bounds on the type parameter def, including
         // those inherited from traits with builtin-kind-supertraits.
-        fn each_inherited_builtin_bound(cx: ctxt,
+        fn each_inherited_builtin_bound(cx: &ctxt,
                                         bounds: BuiltinBounds,
                                         traits: &[@TraitRef],
                                         f: |BuiltinBound|) {
@@ -2378,13 +2371,13 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
     }
 }
 
-pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
+pub fn type_moves_by_default(cx: &ctxt, ty: t) -> bool {
     type_contents(cx, ty).moves_by_default(cx)
 }
 
 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
-pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
-    fn type_requires(cx: ctxt, seen: &mut Vec<DefId> ,
+pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
+    fn type_requires(cx: &ctxt, seen: &mut Vec<DefId>,
                      r_ty: t, ty: t) -> bool {
         debug!("type_requires({}, {})?",
                ::util::ppaux::ty_to_str(cx, r_ty),
@@ -2402,7 +2395,7 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
         return r;
     }
 
-    fn subtypes_require(cx: ctxt, seen: &mut Vec<DefId> ,
+    fn subtypes_require(cx: &ctxt, seen: &mut Vec<DefId>,
                         r_ty: t, ty: t) -> bool {
         debug!("subtypes_require({}, {})?",
                ::util::ppaux::ty_to_str(cx, r_ty),
@@ -2508,10 +2501,10 @@ pub enum Representability {
 
 /// Check whether a type is representable. This means it cannot contain unboxed
 /// structural recursion. This check is needed for structs and enums.
-pub fn is_type_representable(cx: ctxt, ty: t) -> Representability {
+pub fn is_type_representable(cx: &ctxt, ty: t) -> Representability {
 
     // Iterate until something non-representable is found
-    fn find_nonrepresentable<It: Iterator<t>>(cx: ctxt, seen: &mut Vec<DefId> ,
+    fn find_nonrepresentable<It: Iterator<t>>(cx: &ctxt, seen: &mut Vec<DefId>,
                                               mut iter: It) -> Representability {
         for ty in iter {
             let r = type_structurally_recursive(cx, seen, ty);
@@ -2524,7 +2517,7 @@ pub fn is_type_representable(cx: ctxt, ty: t) -> Representability {
 
     // Does the type `ty` directly (without indirection through a pointer)
     // contain any types on stack `seen`?
-    fn type_structurally_recursive(cx: ctxt, seen: &mut Vec<DefId> ,
+    fn type_structurally_recursive(cx: &ctxt, seen: &mut Vec<DefId>,
                                    ty: t) -> Representability {
         debug!("type_structurally_recursive: {}",
                ::util::ppaux::ty_to_str(cx, ty));
@@ -2656,7 +2649,7 @@ pub fn type_is_enum(ty: t) -> bool {
 }
 
 // Is the type's representation size known at compile time?
-pub fn type_is_sized(cx: ctxt, ty: ty::t) -> bool {
+pub fn type_is_sized(cx: &ctxt, ty: ty::t) -> bool {
     match get(ty).sty {
         // FIXME(#6308) add trait, vec, str, etc here.
         ty_param(p) => {
@@ -2673,7 +2666,7 @@ pub fn type_is_sized(cx: ctxt, ty: ty::t) -> bool {
 
 // Whether a type is enum like, that is an enum type with only nullary
 // constructors
-pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
+pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
     match get(ty).sty {
         ty_enum(did, _) => {
             let variants = enum_variants(cx, did);
@@ -2720,7 +2713,7 @@ pub fn index(t: t) -> Option<mt> {
     }
 }
 
-pub fn node_id_to_trait_ref(cx: ctxt, id: ast::NodeId) -> @ty::TraitRef {
+pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> @ty::TraitRef {
     let trait_refs = cx.trait_refs.borrow();
     match trait_refs.get().find(&id) {
        Some(&t) => t,
@@ -2730,12 +2723,12 @@ pub fn node_id_to_trait_ref(cx: ctxt, id: ast::NodeId) -> @ty::TraitRef {
     }
 }
 
-pub fn try_node_id_to_type(cx: ctxt, id: ast::NodeId) -> Option<t> {
+pub fn try_node_id_to_type(cx: &ctxt, id: ast::NodeId) -> Option<t> {
     let node_types = cx.node_types.borrow();
     node_types.get().find_copy(&(id as uint))
 }
 
-pub fn node_id_to_type(cx: ctxt, id: ast::NodeId) -> t {
+pub fn node_id_to_type(cx: &ctxt, id: ast::NodeId) -> t {
     match try_node_id_to_type(cx, id) {
        Some(t) => t,
        None => cx.sess.bug(
@@ -2744,7 +2737,7 @@ pub fn node_id_to_type(cx: ctxt, id: ast::NodeId) -> t {
     }
 }
 
-pub fn node_id_to_type_opt(cx: ctxt, id: ast::NodeId) -> Option<t> {
+pub fn node_id_to_type_opt(cx: &ctxt, id: ast::NodeId) -> Option<t> {
     let node_types = cx.node_types.borrow();
     debug!("id: {:?}, node_types: {:?}", id, node_types);
     match node_types.get().find(&(id as uint)) {
@@ -2754,7 +2747,7 @@ pub fn node_id_to_type_opt(cx: ctxt, id: ast::NodeId) -> Option<t> {
 }
 
 // FIXME(pcwalton): Makes a copy, bleh. Probably better to not do that.
-pub fn node_id_to_type_params(cx: ctxt, id: ast::NodeId) -> Vec<t> {
+pub fn node_id_to_type_params(cx: &ctxt, id: ast::NodeId) -> Vec<t> {
     let node_type_substs = cx.node_type_substs.borrow();
     match node_type_substs.get().find(&id) {
       None => return Vec::new(),
@@ -2762,7 +2755,7 @@ pub fn node_id_to_type_params(cx: ctxt, id: ast::NodeId) -> Vec<t> {
     }
 }
 
-fn node_id_has_type_params(cx: ctxt, id: ast::NodeId) -> bool {
+fn node_id_has_type_params(cx: &ctxt, id: ast::NodeId) -> bool {
     let node_type_substs = cx.node_type_substs.borrow();
     node_type_substs.get().contains_key(&id)
 }
@@ -2843,7 +2836,7 @@ pub fn ty_vstore(ty: t) -> vstore {
     }
 }
 
-pub fn ty_region(tcx: ctxt,
+pub fn ty_region(tcx: &ctxt,
                  span: Span,
                  ty: t) -> Region {
     match get(ty).sty {
@@ -2858,7 +2851,7 @@ pub fn ty_region(tcx: ctxt,
     }
 }
 
-pub fn replace_fn_sig(cx: ctxt, fsty: &sty, new_sig: FnSig) -> t {
+pub fn replace_fn_sig(cx: &ctxt, fsty: &sty, new_sig: FnSig) -> t {
     match *fsty {
         ty_bare_fn(ref f) => mk_bare_fn(cx, BareFnTy {sig: new_sig, ..*f}),
         ty_closure(ref f) => mk_closure(cx, ClosureTy {sig: new_sig, ..*f}),
@@ -2869,7 +2862,7 @@ pub fn replace_fn_sig(cx: ctxt, fsty: &sty, new_sig: FnSig) -> t {
     }
 }
 
-pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
+pub fn replace_closure_return_type(tcx: &ctxt, fn_type: t, ret_type: t) -> t {
     /*!
      *
      * Returns a new function type based on `fn_type` but returning a value of
@@ -2896,14 +2889,14 @@ pub fn tys_in_fn_sig(sig: &FnSig) -> Vec<t> {
 }
 
 // Type accessors for AST nodes
-pub fn block_ty(cx: ctxt, b: &ast::Block) -> t {
+pub fn block_ty(cx: &ctxt, b: &ast::Block) -> t {
     return node_id_to_type(cx, b.id);
 }
 
 
 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
 // doesn't provide type parameter substitutions.
-pub fn pat_ty(cx: ctxt, pat: &ast::Pat) -> t {
+pub fn pat_ty(cx: &ctxt, pat: &ast::Pat) -> t {
     return node_id_to_type(cx, pat.id);
 }
 
@@ -2919,15 +2912,15 @@ pub fn pat_ty(cx: ctxt, pat: &ast::Pat) -> t {
 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
 // instead of "fn(t) -> T with T = int". If this isn't what you want, see
 // expr_ty_params_and_ty() below.
-pub fn expr_ty(cx: ctxt, expr: &ast::Expr) -> t {
+pub fn expr_ty(cx: &ctxt, expr: &ast::Expr) -> t {
     return node_id_to_type(cx, expr.id);
 }
 
-pub fn expr_ty_opt(cx: ctxt, expr: &ast::Expr) -> Option<t> {
+pub fn expr_ty_opt(cx: &ctxt, expr: &ast::Expr) -> Option<t> {
     return node_id_to_type_opt(cx, expr.id);
 }
 
-pub fn expr_ty_adjusted(cx: ctxt,
+pub fn expr_ty_adjusted(cx: &ctxt,
                         expr: &ast::Expr,
                         method_map: &FnvHashMap<MethodCall, MethodCallee>)
                         -> t {
@@ -2951,7 +2944,7 @@ pub fn expr_ty_adjusted(cx: ctxt,
     })
 }
 
-pub fn expr_span(cx: ctxt, id: NodeId) -> Span {
+pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
     match cx.map.find(id) {
         Some(ast_map::NodeExpr(e)) => {
             e.span
@@ -2967,7 +2960,7 @@ pub fn expr_span(cx: ctxt, id: NodeId) -> Span {
     }
 }
 
-pub fn local_var_name_str(cx: ctxt, id: NodeId) -> InternedString {
+pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
     match cx.map.find(id) {
         Some(ast_map::NodeLocal(pat)) => {
             match pat.node {
@@ -2989,7 +2982,7 @@ pub fn local_var_name_str(cx: ctxt, id: NodeId) -> InternedString {
     }
 }
 
-pub fn adjust_ty(cx: ctxt,
+pub fn adjust_ty(cx: &ctxt,
                  span: Span,
                  expr_id: ast::NodeId,
                  unadjusted_ty: ty::t,
@@ -3104,7 +3097,7 @@ pub fn adjust_ty(cx: ctxt,
         None => unadjusted_ty
     };
 
-    fn borrow_vec(cx: ctxt, span: Span,
+    fn borrow_vec(cx: &ctxt, span: Span,
                   r: Region, m: ast::Mutability,
                   ty: ty::t) -> ty::t {
         match get(ty).sty {
@@ -3125,7 +3118,7 @@ pub fn adjust_ty(cx: ctxt,
         }
     }
 
-    fn borrow_fn(cx: ctxt, span: Span, r: Region, ty: ty::t) -> ty::t {
+    fn borrow_fn(cx: &ctxt, span: Span, r: Region, ty: ty::t) -> ty::t {
         match get(ty).sty {
             ty_closure(ref fty) => {
                 ty::mk_closure(cx, ClosureTy {
@@ -3144,7 +3137,7 @@ pub fn adjust_ty(cx: ctxt,
         }
     }
 
-    fn borrow_obj(cx: ctxt, span: Span, r: Region,
+    fn borrow_obj(cx: &ctxt, span: Span, r: Region,
                   m: ast::Mutability, ty: ty::t) -> ty::t {
         match get(ty).sty {
             ty_trait(trt_did, ref trt_substs, _, _, b) => {
@@ -3161,7 +3154,7 @@ pub fn adjust_ty(cx: ctxt,
     }
 }
 
-pub fn trait_adjustment_to_ty(cx: ctxt, sigil: &ast::Sigil, region: &Option<Region>,
+pub fn trait_adjustment_to_ty(cx: &ctxt, sigil: &ast::Sigil, region: &Option<Region>,
                               def_id: ast::DefId, substs: &substs, m: ast::Mutability,
                               bounds: BuiltinBounds) -> t {
 
@@ -3192,7 +3185,7 @@ pub struct ParamsTy {
     ty: t
 }
 
-pub fn expr_ty_params_and_ty(cx: ctxt,
+pub fn expr_ty_params_and_ty(cx: &ctxt,
                              expr: &ast::Expr)
                           -> ParamsTy {
     ParamsTy {
@@ -3201,12 +3194,12 @@ pub fn expr_ty_params_and_ty(cx: ctxt,
     }
 }
 
-pub fn expr_has_ty_params(cx: ctxt, expr: &ast::Expr) -> bool {
+pub fn expr_has_ty_params(cx: &ctxt, expr: &ast::Expr) -> bool {
     return node_id_has_type_params(cx, expr.id);
 }
 
-pub fn method_call_type_param_defs(tcx: ctxt, origin: typeck::MethodOrigin)
-                                   -> Rc<Vec<TypeParameterDef> > {
+pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
+                                   -> Rc<Vec<TypeParameterDef>> {
     match origin {
         typeck::MethodStatic(did) => {
             // n.b.: When we encode impl methods, the bounds
@@ -3234,7 +3227,7 @@ pub fn method_call_type_param_defs(tcx: ctxt, origin: typeck::MethodOrigin)
     }
 }
 
-pub fn resolve_expr(tcx: ctxt, expr: &ast::Expr) -> ast::Def {
+pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> ast::Def {
     let def_map = tcx.def_map.borrow();
     match def_map.get().find(&expr.id) {
         Some(&def) => def,
@@ -3245,7 +3238,7 @@ pub fn resolve_expr(tcx: ctxt, expr: &ast::Expr) -> ast::Def {
     }
 }
 
-pub fn expr_is_lval(tcx: ctxt,
+pub fn expr_is_lval(tcx: &ctxt,
                     method_map: MethodMap,
                     e: &ast::Expr) -> bool {
     match expr_kind(tcx, method_map, e) {
@@ -3266,7 +3259,7 @@ pub enum ExprKind {
     RvalueStmtExpr
 }
 
-pub fn expr_kind(tcx: ctxt,
+pub fn expr_kind(tcx: &ctxt,
                  method_map: MethodMap,
                  expr: &ast::Expr) -> ExprKind {
     if method_map.borrow().get().contains_key(&MethodCall::expr(expr.id)) {
@@ -3440,7 +3433,7 @@ pub fn field_idx(name: ast::Name, fields: &[field]) -> Option<uint> {
     return None;
 }
 
-pub fn field_idx_strict(tcx: ty::ctxt, name: ast::Name, fields: &[field])
+pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
                      -> uint {
     let mut i = 0u;
     for f in fields.iter() { if f.ident.name == name { return i; } i += 1u; }
@@ -3470,7 +3463,7 @@ pub fn param_tys_in_type(ty: t) -> Vec<param_ty> {
     rslt
 }
 
-pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
+pub fn ty_sort_str(cx: &ctxt, t: t) -> ~str {
     match get(t).sty {
         ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
         ty_uint(_) | ty_float(_) | ty_str(_) => {
@@ -3498,7 +3491,7 @@ pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
     }
 }
 
-pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
+pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~str {
     /*!
      *
      * Explains the source of a type err in a short,
@@ -3644,7 +3637,7 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
     }
 }
 
-pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
+pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
     match *err {
         terr_regions_does_not_outlive(subregion, superregion) => {
             note_and_explain_region(cx, "", subregion, "...");
@@ -3683,12 +3676,12 @@ pub fn def_has_ty_params(def: ast::Def) -> bool {
     }
 }
 
-pub fn provided_source(cx: ctxt, id: ast::DefId) -> Option<ast::DefId> {
+pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
     let provided_method_sources = cx.provided_method_sources.borrow();
     provided_method_sources.get().find(&id).map(|x| *x)
 }
 
-pub fn provided_trait_methods(cx: ctxt, id: ast::DefId) -> Vec<@Method> {
+pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<@Method> {
     if is_local(id) {
         {
             match cx.map.find(id.node) {
@@ -3720,7 +3713,7 @@ pub fn provided_trait_methods(cx: ctxt, id: ast::DefId) -> Vec<@Method> {
     }
 }
 
-pub fn trait_supertraits(cx: ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
+pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
     // Check the cache.
     {
         let supertraits = cx.supertraits.borrow();
@@ -3742,7 +3735,7 @@ pub fn trait_supertraits(cx: ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
     return result;
 }
 
-pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> Vec<@TraitRef> {
+pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec<@TraitRef> {
     let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
     supertrait_refs.map(
         |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
@@ -3776,13 +3769,13 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
     v
 }
 
-pub fn trait_method(cx: ctxt, trait_did: ast::DefId, idx: uint) -> @Method {
+pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> @Method {
     let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
     ty::method(cx, method_def_id)
 }
 
 
-pub fn trait_methods(cx: ctxt, trait_did: ast::DefId) -> @Vec<@Method> {
+pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> @Vec<@Method> {
     let mut trait_methods_cache = cx.trait_methods_cache.borrow_mut();
     match trait_methods_cache.get().find(&trait_did) {
         Some(&methods) => methods,
@@ -3795,24 +3788,24 @@ pub fn trait_methods(cx: ctxt, trait_did: ast::DefId) -> @Vec<@Method> {
     }
 }
 
-pub fn method(cx: ctxt, id: ast::DefId) -> @Method {
+pub fn method(cx: &ctxt, id: ast::DefId) -> @Method {
     let mut methods = cx.methods.borrow_mut();
     lookup_locally_or_in_crate_store("methods", id, methods.get(), || {
         @csearch::get_method(cx, id)
     })
 }
 
-pub fn trait_method_def_ids(cx: ctxt, id: ast::DefId) -> @Vec<DefId> {
+pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> @Vec<DefId> {
     let mut trait_method_def_ids = cx.trait_method_def_ids.borrow_mut();
     lookup_locally_or_in_crate_store("trait_method_def_ids",
                                      id,
                                      trait_method_def_ids.get(),
                                      || {
-        @csearch::get_trait_method_def_ids(cx.cstore, id)
+        @csearch::get_trait_method_def_ids(&cx.sess.cstore, id)
     })
 }
 
-pub fn impl_trait_ref(cx: ctxt, id: ast::DefId) -> Option<@TraitRef> {
+pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<@TraitRef> {
     {
         let mut impl_trait_cache = cx.impl_trait_cache.borrow_mut();
         match impl_trait_cache.get().find(&id) {
@@ -3848,7 +3841,7 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::DefId) -> Option<@TraitRef> {
     return ret;
 }
 
-pub fn trait_ref_to_def_id(tcx: ctxt, tr: &ast::TraitRef) -> ast::DefId {
+pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
     let def_map = tcx.def_map.borrow();
     let def = def_map.get()
                      .find(&tr.ref_id)
@@ -3856,7 +3849,7 @@ pub fn trait_ref_to_def_id(tcx: ctxt, tr: &ast::TraitRef) -> ast::DefId {
     ast_util::def_id_of_def(*def)
 }
 
-pub fn try_add_builtin_trait(tcx: ctxt,
+pub fn try_add_builtin_trait(tcx: &ctxt,
                              trait_def_id: ast::DefId,
                              builtin_bounds: &mut BuiltinBounds) -> bool {
     //! Checks whether `trait_ref` refers to one of the builtin
@@ -3894,7 +3887,7 @@ impl VariantInfo {
     /// Creates a new VariantInfo from the corresponding ast representation.
     ///
     /// Does not do any caching of the value in the type context.
-    pub fn from_ast_variant(cx: ctxt,
+    pub fn from_ast_variant(cx: &ctxt,
                             ast_variant: &ast::Variant,
                             discriminant: Disr) -> VariantInfo {
         let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
@@ -3946,7 +3939,7 @@ impl VariantInfo {
     }
 }
 
-pub fn substd_enum_variants(cx: ctxt,
+pub fn substd_enum_variants(cx: &ctxt,
                             id: ast::DefId,
                             substs: &substs)
                          -> Vec<@VariantInfo> {
@@ -3964,7 +3957,7 @@ pub fn substd_enum_variants(cx: ctxt,
     }).collect()
 }
 
-pub fn item_path_str(cx: ctxt, id: ast::DefId) -> ~str {
+pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> ~str {
     with_path(cx, id, |path| ast_map::path_to_str(path))
 }
 
@@ -3995,7 +3988,7 @@ impl DtorKind {
 
 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
    Otherwise return none. */
-pub fn ty_dtor(cx: ctxt, struct_id: DefId) -> DtorKind {
+pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind {
     let destructor_for_type = cx.destructor_for_type.borrow();
     match destructor_for_type.get().find(&struct_id) {
         Some(&method_def_id) => {
@@ -4007,11 +4000,11 @@ pub fn ty_dtor(cx: ctxt, struct_id: DefId) -> DtorKind {
     }
 }
 
-pub fn has_dtor(cx: ctxt, struct_id: DefId) -> bool {
+pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool {
     ty_dtor(cx, struct_id).is_present()
 }
 
-pub fn with_path<T>(cx: ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T {
+pub fn with_path<T>(cx: &ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T {
     if id.krate == ast::LOCAL_CRATE {
         cx.map.with_path(id.node, f)
     } else {
@@ -4019,18 +4012,18 @@ pub fn with_path<T>(cx: ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T
     }
 }
 
-pub fn enum_is_univariant(cx: ctxt, id: ast::DefId) -> bool {
+pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
     enum_variants(cx, id).len() == 1
 }
 
-pub fn type_is_empty(cx: ctxt, t: t) -> bool {
+pub fn type_is_empty(cx: &ctxt, t: t) -> bool {
     match ty::get(t).sty {
        ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
        _ => false
      }
 }
 
-pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
+pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
     {
         let enum_var_cache = cx.enum_var_cache.borrow();
         match enum_var_cache.get().find(&id) {
@@ -4061,7 +4054,7 @@ pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
                             };
 
                             match variant.node.disr_expr {
-                                Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
+                                Some(e) => match const_eval::eval_const_expr_partial(cx, e) {
                                     Ok(const_eval::const_int(val)) => {
                                         discriminant = val as Disr
                                     }
@@ -4113,7 +4106,7 @@ pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
 
 
 // Returns information about the enum variant with the given ID:
-pub fn enum_variant_with_id(cx: ctxt,
+pub fn enum_variant_with_id(cx: &ctxt,
                             enum_id: ast::DefId,
                             variant_id: ast::DefId)
                          -> @VariantInfo {
@@ -4132,7 +4125,7 @@ pub fn enum_variant_with_id(cx: ctxt,
 
 // If the given item is in an external crate, looks up its type and adds it to
 // the type cache. Returns the type parameters and type.
-pub fn lookup_item_type(cx: ctxt,
+pub fn lookup_item_type(cx: &ctxt,
                         did: ast::DefId)
                      -> ty_param_bounds_and_ty {
     let mut tcache = cx.tcache.borrow_mut();
@@ -4141,7 +4134,7 @@ pub fn lookup_item_type(cx: ctxt,
         || csearch::get_type(cx, did))
 }
 
-pub fn lookup_impl_vtables(cx: ctxt,
+pub fn lookup_impl_vtables(cx: &ctxt,
                            did: ast::DefId)
                      -> typeck::impl_res {
     let mut impl_vtables = cx.impl_vtables.borrow_mut();
@@ -4151,7 +4144,7 @@ pub fn lookup_impl_vtables(cx: ctxt,
 }
 
 /// Given the did of a trait, returns its canonical trait ref.
-pub fn lookup_trait_def(cx: ctxt, did: ast::DefId) -> @ty::TraitDef {
+pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> @ty::TraitDef {
     let mut trait_defs = cx.trait_defs.borrow_mut();
     match trait_defs.get().find(&did) {
         Some(&trait_def) => {
@@ -4171,13 +4164,13 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::DefId) -> @ty::TraitDef {
 /// Iterate over meta_items of a definition.
 // (This should really be an iterator, but that would require csearch and
 // decoder to use iterators instead of higher-order functions.)
-pub fn each_attr(tcx: ctxt, did: DefId, f: |@MetaItem| -> bool) -> bool {
+pub fn each_attr(tcx: &ctxt, did: DefId, f: |@MetaItem| -> bool) -> bool {
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
         item.attrs.iter().advance(|attr| f(attr.node.value))
     } else {
         let mut cont = true;
-        csearch::get_item_attrs(tcx.cstore, did, |meta_items| {
+        csearch::get_item_attrs(&tcx.sess.cstore, did, |meta_items| {
             if cont {
                 cont = meta_items.iter().advance(|ptrptr| f(*ptrptr));
             }
@@ -4187,7 +4180,7 @@ pub fn each_attr(tcx: ctxt, did: DefId, f: |@MetaItem| -> bool) -> bool {
 }
 
 /// Determine whether an item is annotated with an attribute
-pub fn has_attr(tcx: ctxt, did: DefId, attr: &str) -> bool {
+pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
     let mut found = false;
     each_attr(tcx, did, |item| {
         if item.name().equiv(&attr) {
@@ -4201,17 +4194,17 @@ pub fn has_attr(tcx: ctxt, did: DefId, attr: &str) -> bool {
 }
 
 /// Determine whether an item is annotated with `#[packed]`
-pub fn lookup_packed(tcx: ctxt, did: DefId) -> bool {
+pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
     has_attr(tcx, did, "packed")
 }
 
 /// Determine whether an item is annotated with `#[simd]`
-pub fn lookup_simd(tcx: ctxt, did: DefId) -> bool {
+pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
     has_attr(tcx, did, "simd")
 }
 
 // Obtain the representation annotation for a definition.
-pub fn lookup_repr_hint(tcx: ctxt, did: DefId) -> attr::ReprAttr {
+pub fn lookup_repr_hint(tcx: &ctxt, did: DefId) -> attr::ReprAttr {
     let mut acc = attr::ReprAny;
     ty::each_attr(tcx, did, |meta| {
         acc = attr::find_repr_attr(tcx.sess.diagnostic(), meta, acc);
@@ -4222,7 +4215,7 @@ pub fn lookup_repr_hint(tcx: ctxt, did: DefId) -> attr::ReprAttr {
 
 // Look up a field ID, whether or not it's local
 // Takes a list of type substs in case the struct is generic
-pub fn lookup_field_type(tcx: ctxt,
+pub fn lookup_field_type(tcx: &ctxt,
                          struct_id: DefId,
                          id: DefId,
                          substs: &substs)
@@ -4247,42 +4240,40 @@ pub fn lookup_field_type(tcx: ctxt,
 
 // Look up the list of field names and IDs for a given struct
 // Fails if the id is not bound to a struct.
-pub fn lookup_struct_fields(cx: ctxt, did: ast::DefId) -> Vec<field_ty> {
-  if did.krate == ast::LOCAL_CRATE {
-      {
-          match cx.map.find(did.node) {
-           Some(ast_map::NodeItem(i)) => {
-             match i.node {
-                ast::ItemStruct(struct_def, _) => {
-                   struct_field_tys(struct_def.fields.as_slice())
-                }
-                _ => cx.sess.bug("struct ID bound to non-struct")
-             }
-           }
-           Some(ast_map::NodeVariant(ref variant)) => {
-              match (*variant).node.kind {
-                ast::StructVariantKind(struct_def) => {
-                  struct_field_tys(struct_def.fields.as_slice())
+pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
+    if did.krate == ast::LOCAL_CRATE {
+        match cx.map.find(did.node) {
+            Some(ast_map::NodeItem(i)) => {
+                match i.node {
+                    ast::ItemStruct(struct_def, _) => {
+                        struct_field_tys(struct_def.fields.as_slice())
+                    }
+                    _ => cx.sess.bug("struct ID bound to non-struct")
                 }
-                _ => {
-                  cx.sess.bug("struct ID bound to enum variant that isn't \
-                               struct-like")
+            }
+            Some(ast_map::NodeVariant(ref variant)) => {
+                match (*variant).node.kind {
+                    ast::StructVariantKind(struct_def) => {
+                        struct_field_tys(struct_def.fields.as_slice())
+                    }
+                    _ => {
+                        cx.sess.bug("struct ID bound to enum variant that \
+                                    isn't struct-like")
+                    }
                 }
-              }
-           }
-           _ => {
-               cx.sess.bug(
-                   format!("struct ID not bound to an item: {}",
+            }
+            _ => {
+                cx.sess.bug(
+                    format!("struct ID not bound to an item: {}",
                         cx.map.node_to_str(did.node)));
-           }
-          }
-      }
-  } else {
-    return csearch::get_struct_fields(cx.sess.cstore, did);
-  }
+            }
+        }
+    } else {
+        csearch::get_struct_fields(&cx.sess.cstore, did)
+    }
 }
 
-pub fn lookup_struct_field(cx: ctxt,
+pub fn lookup_struct_field(cx: &ctxt,
                            parent: ast::DefId,
                            field_id: ast::DefId)
                         -> field_ty {
@@ -4317,7 +4308,7 @@ fn struct_field_tys(fields: &[StructField]) -> Vec<field_ty> {
 
 // Returns a list of fields corresponding to the struct's items. trans uses
 // this. Takes a list of substs with which to instantiate field types.
-pub fn struct_fields(cx: ctxt, did: ast::DefId, substs: &substs)
+pub fn struct_fields(cx: &ctxt, did: ast::DefId, substs: &substs)
                      -> Vec<field> {
     lookup_struct_fields(cx, did).map(|f| {
        field {
@@ -4331,7 +4322,7 @@ pub fn struct_fields(cx: ctxt, did: ast::DefId, substs: &substs)
     })
 }
 
-pub fn is_binopable(cx: ctxt, ty: t, op: ast::BinOp) -> bool {
+pub fn is_binopable(cx: &ctxt, ty: t, op: ast::BinOp) -> bool {
     static tycat_other: int = 0;
     static tycat_bool: int = 1;
     static tycat_char: int = 2;
@@ -4372,7 +4363,7 @@ pub fn is_binopable(cx: ctxt, ty: t, op: ast::BinOp) -> bool {
         }
     }
 
-    fn tycat(cx: ctxt, ty: t) -> int {
+    fn tycat(cx: &ctxt, ty: t) -> int {
         if type_is_simd(cx, ty) {
             return tycat(cx, simd_type(cx, ty))
         }
@@ -4403,7 +4394,7 @@ pub fn is_binopable(cx: ctxt, ty: t, op: ast::BinOp) -> bool {
     return tbl[tycat(cx, ty)][opcat(op)];
 }
 
-pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> Vec<t> {
+pub fn ty_params_to_tys(tcx: &ctxt, generics: &ast::Generics) -> Vec<t> {
     Vec::from_fn(generics.ty_params.len(), |i| {
         let id = generics.ty_params.get(i).id;
         ty::mk_param(tcx, i, ast_util::local_def(id))
@@ -4411,14 +4402,14 @@ pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> Vec<t> {
 }
 
 /// Returns an equivalent type with all the typedefs and self regions removed.
-pub fn normalize_ty(cx: ctxt, t: t) -> t {
+pub fn normalize_ty(cx: &ctxt, t: t) -> t {
     let u = TypeNormalizer(cx).fold_ty(t);
     return u;
 
-    struct TypeNormalizer(ctxt);
+    struct TypeNormalizer<'a>(&'a ctxt);
 
-    impl TypeFolder for TypeNormalizer {
-        fn tcx(&self) -> ty::ctxt { let TypeNormalizer(c) = *self; c }
+    impl<'a> TypeFolder for TypeNormalizer<'a> {
+        fn tcx<'a>(&'a self) -> &'a ctxt { let TypeNormalizer(c) = *self; c }
 
         fn fold_ty(&mut self, t: ty::t) -> ty::t {
             let normalized_opt = {
@@ -4476,16 +4467,16 @@ pub fn normalize_ty(cx: ctxt, t: t) -> t {
 
 pub trait ExprTyProvider {
     fn expr_ty(&self, ex: &ast::Expr) -> t;
-    fn ty_ctxt(&self) -> ctxt;
+    fn ty_ctxt<'a>(&'a self) -> &'a ctxt;
 }
 
 impl ExprTyProvider for ctxt {
     fn expr_ty(&self, ex: &ast::Expr) -> t {
-        expr_ty(*self, ex)
+        expr_ty(self, ex)
     }
 
-    fn ty_ctxt(&self) -> ctxt {
-        *self
+    fn ty_ctxt<'a>(&'a self) -> &'a ctxt {
+        self
     }
 }
 
@@ -4555,7 +4546,7 @@ pub fn determine_inherited_purity(parent: (ast::Purity, ast::NodeId),
 // Here, the supertraits are the transitive closure of the supertrait
 // relation on the supertraits from each bounded trait's constraint
 // list.
-pub fn each_bound_trait_and_supertraits(tcx: ctxt,
+pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
                                         bounds: &[@TraitRef],
                                         f: |@TraitRef| -> bool)
                                         -> bool {
@@ -4598,7 +4589,7 @@ pub fn each_bound_trait_and_supertraits(tcx: ctxt,
     return true;
 }
 
-pub fn count_traits_and_supertraits(tcx: ctxt,
+pub fn count_traits_and_supertraits(tcx: &ctxt,
                                     type_param_defs: &[TypeParameterDef]) -> uint {
     let mut total = 0;
     for type_param_def in type_param_defs.iter() {
@@ -4611,7 +4602,7 @@ pub fn count_traits_and_supertraits(tcx: ctxt,
     return total;
 }
 
-pub fn get_tydesc_ty(tcx: ctxt) -> Result<t, ~str> {
+pub fn get_tydesc_ty(tcx: &ctxt) -> Result<t, ~str> {
     tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
         let intrinsic_defs = tcx.intrinsic_defs.borrow();
         intrinsic_defs.get().find_copy(&tydesc_lang_item)
@@ -4619,7 +4610,7 @@ pub fn get_tydesc_ty(tcx: ctxt) -> Result<t, ~str> {
     })
 }
 
-pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
+pub fn get_opaque_ty(tcx: &ctxt) -> Result<t, ~str> {
     tcx.lang_items.require(OpaqueStructLangItem).map(|opaque_lang_item| {
         let intrinsic_defs = tcx.intrinsic_defs.borrow();
         intrinsic_defs.get().find_copy(&opaque_lang_item)
@@ -4627,7 +4618,7 @@ pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
     })
 }
 
-pub fn visitor_object_ty(tcx: ctxt,
+pub fn visitor_object_ty(tcx: &ctxt,
                          region: ty::Region) -> Result<(@TraitRef, t), ~str> {
     let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
         Ok(id) => id,
@@ -4648,15 +4639,15 @@ pub fn visitor_object_ty(tcx: ctxt,
                  EmptyBuiltinBounds())))
 }
 
-pub fn item_variances(tcx: ctxt, item_id: ast::DefId) -> @ItemVariances {
+pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> @ItemVariances {
     let mut item_variance_map = tcx.item_variance_map.borrow_mut();
     lookup_locally_or_in_crate_store(
         "item_variance_map", item_id, item_variance_map.get(),
-        || @csearch::get_item_variances(tcx.cstore, item_id))
+        || @csearch::get_item_variances(&tcx.sess.cstore, item_id))
 }
 
 /// Records a trait-to-implementation mapping.
-fn record_trait_implementation(tcx: ctxt,
+fn record_trait_implementation(tcx: &ctxt,
                                trait_def_id: DefId,
                                implementation: @Impl) {
     let implementation_list;
@@ -4677,7 +4668,7 @@ fn record_trait_implementation(tcx: ctxt,
 
 /// Populates the type context with all the implementations for the given type
 /// if necessary.
-pub fn populate_implementations_for_type_if_necessary(tcx: ctxt,
+pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
                                                       type_id: ast::DefId) {
     if type_id.krate == LOCAL_CRATE {
         return
@@ -4689,7 +4680,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: ctxt,
         }
     }
 
-    csearch::each_implementation_for_type(tcx.sess.cstore, type_id,
+    csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
             |implementation_def_id| {
         let implementation = @csearch::get_impl(tcx, implementation_def_id);
 
@@ -4745,7 +4736,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: ctxt,
 /// Populates the type context with all the implementations for the given
 /// trait if necessary.
 pub fn populate_implementations_for_trait_if_necessary(
-        tcx: ctxt,
+        tcx: &ctxt,
         trait_id: ast::DefId) {
     if trait_id.krate == LOCAL_CRATE {
         return
@@ -4758,7 +4749,7 @@ pub fn populate_implementations_for_trait_if_necessary(
         }
     }
 
-    csearch::each_implementation_for_trait(tcx.sess.cstore, trait_id,
+    csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
             |implementation_def_id| {
         let implementation = @csearch::get_impl(tcx, implementation_def_id);
 
@@ -4787,7 +4778,7 @@ pub fn populate_implementations_for_trait_if_necessary(
 
 /// Given the def_id of an impl, return the def_id of the trait it implements.
 /// If it implements no trait, return `None`.
-pub fn trait_id_of_impl(tcx: ctxt,
+pub fn trait_id_of_impl(tcx: &ctxt,
                         def_id: ast::DefId) -> Option<ast::DefId> {
     let node = match tcx.map.find(def_id.node) {
         Some(node) => node,
@@ -4809,10 +4800,10 @@ pub fn trait_id_of_impl(tcx: ctxt,
 /// If the given def ID describes a method belonging to a trait (either a
 /// default method or an implementation of a trait method), return the ID of
 /// the trait that the method belongs to. Otherwise, return `None`.
-pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId)
+pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
                        -> Option<ast::DefId> {
     if def_id.krate != LOCAL_CRATE {
-        return csearch::get_trait_of_method(tcx.cstore, def_id, tcx);
+        return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
     }
     let method;
     {
@@ -4836,7 +4827,7 @@ pub fn trait_of_method(tcx: ctxt, def_id: ast::DefId)
 /// is already that of the original trait method, then the return value is
 /// the same).
 /// Otherwise, return `None`.
-pub fn trait_method_of_method(tcx: ctxt,
+pub fn trait_method_of_method(tcx: &ctxt,
                               def_id: ast::DefId) -> Option<ast::DefId> {
     let method;
     {
@@ -4860,7 +4851,7 @@ pub fn trait_method_of_method(tcx: ctxt,
 
 /// Creates a hash of the type `t` which will be the same no matter what crate
 /// context it's calculated within. This is used by the `type_id` intrinsic.
-pub fn hash_crate_independent(tcx: ctxt, t: t, svh: &Svh) -> u64 {
+pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
     let mut state = sip::SipState::new();
     macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
     macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );
@@ -5014,7 +5005,7 @@ impl Variance {
 }
 
 pub fn construct_parameter_environment(
-    tcx: ctxt,
+    tcx: &ctxt,
     self_bound: Option<@TraitRef>,
     item_type_params: &[TypeParameterDef],
     method_type_params: &[TypeParameterDef],
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 769924c02c8..2456c607317 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -16,7 +16,7 @@ use util::ppaux::Repr;
 use std::vec_ng::Vec;
 
 pub trait TypeFolder {
-    fn tcx(&self) -> ty::ctxt;
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt;
 
     fn fold_ty(&mut self, t: ty::t) -> ty::t {
         super_fold_ty(self, t)
@@ -93,7 +93,8 @@ pub fn fold_ty_vec<T:TypeFolder>(this: &mut T, tys: &[ty::t]) -> Vec<ty::t> {
 pub fn super_fold_ty<T:TypeFolder>(this: &mut T,
                                    t: ty::t)
                                    -> ty::t {
-    ty::mk_t(this.tcx(), this.fold_sty(&ty::get(t).sty))
+    let sty = this.fold_sty(&ty::get(t).sty);
+    ty::mk_t(this.tcx(), sty)
 }
 
 pub fn super_fold_substs<T:TypeFolder>(this: &mut T,
@@ -218,12 +219,12 @@ pub fn super_fold_trait_store<T:TypeFolder>(this: &mut T,
 // Some sample folders
 
 pub struct BottomUpFolder<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     fldop: 'a |ty::t| -> ty::t,
 }
 
 impl<'a> TypeFolder for BottomUpFolder<'a> {
-    fn tcx(&self) -> ty::ctxt { self.tcx }
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
 
     fn fold_ty(&mut self, ty: ty::t) -> ty::t {
         let t1 = super_fold_ty(self, ty);
@@ -235,13 +236,13 @@ impl<'a> TypeFolder for BottomUpFolder<'a> {
 // Region folder
 
 pub struct RegionFolder<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     fld_t: 'a |ty::t| -> ty::t,
     fld_r: 'a |ty::Region| -> ty::Region,
 }
 
 impl<'a> RegionFolder<'a> {
-    pub fn general(tcx: ty::ctxt,
+    pub fn general(tcx: &'a ty::ctxt,
                    fld_r: 'a |ty::Region| -> ty::Region,
                    fld_t: 'a |ty::t| -> ty::t)
                    -> RegionFolder<'a> {
@@ -252,7 +253,7 @@ impl<'a> RegionFolder<'a> {
         }
     }
 
-    pub fn regions(tcx: ty::ctxt, fld_r: 'a |ty::Region| -> ty::Region)
+    pub fn regions(tcx: &'a ty::ctxt, fld_r: 'a |ty::Region| -> ty::Region)
                    -> RegionFolder<'a> {
         fn noop(t: ty::t) -> ty::t { t }
 
@@ -265,7 +266,7 @@ impl<'a> RegionFolder<'a> {
 }
 
 impl<'a> TypeFolder for RegionFolder<'a> {
-    fn tcx(&self) -> ty::ctxt { self.tcx }
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
 
     fn fold_ty(&mut self, ty: ty::t) -> ty::t {
         debug!("RegionFolder.fold_ty({})", ty.repr(self.tcx()));
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 8336fa2d6b5..658538bcec8 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -20,7 +20,7 @@
  * `AstConv` instance; in this phase, the `get_item_ty()` function
  * triggers a recursive call to `ty_of_item()`  (note that
  * `ast_ty_to_ty()` will detect recursive types and report an error).
- * In the check phase, when the @FnCtxt is used as the `AstConv`,
+ * In the check phase, when the FnCtxt is used as the `AstConv`,
  * `get_item_ty()` just looks up the item type in `tcx.tcache`.
  *
  * The `RegionScope` trait controls what happens when the user does
@@ -69,7 +69,7 @@ use syntax::opt_vec;
 use syntax::print::pprust::{lifetime_to_str, path_to_str};
 
 pub trait AstConv {
-    fn tcx(&self) -> ty::ctxt;
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt;
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
     fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef;
 
@@ -77,10 +77,9 @@ pub trait AstConv {
     fn ty_infer(&self, span: Span) -> ty::t;
 }
 
-pub fn ast_region_to_region(tcx: ty::ctxt, lifetime: &ast::Lifetime)
+pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
                             -> ty::Region {
-    let named_region_map = tcx.named_region_map.borrow();
-    let r = match named_region_map.get().find(&lifetime.id) {
+    let r = match tcx.named_region_map.find(&lifetime.id) {
         None => {
             // should have been recorded by the `resolve_lifetime` pass
             tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
@@ -304,7 +303,7 @@ pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
 pub static NO_REGIONS: uint = 1;
 pub static NO_TPS: uint = 2;
 
-fn check_path_args(tcx: ty::ctxt,
+fn check_path_args(tcx: &ty::ctxt,
                    path: &ast::Path,
                    flags: uint) {
     if (flags & NO_TPS) != 0u {
@@ -324,7 +323,7 @@ fn check_path_args(tcx: ty::ctxt,
     }
 }
 
-pub fn ast_ty_to_prim_ty(tcx: ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
+pub fn ast_ty_to_prim_ty(tcx: &ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
     match ast_ty.node {
         ast::TyPath(ref path, _, id) => {
             let def_map = tcx.def_map.borrow();
@@ -393,7 +392,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
         VStore(ty::vstore)
     }
     impl PointerTy {
-        fn expect_vstore(&self, tcx: ty::ctxt, span: Span, ty: &str) -> ty::vstore {
+        fn expect_vstore(&self, tcx: &ty::ctxt, span: Span, ty: &str) -> ty::vstore {
             match *self {
                 Box => {
                     tcx.sess.span_err(span, format!("managed {} are not supported", ty));
@@ -614,7 +613,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
                 }
             }
             ast::TyFixedLengthVec(ty, e) => {
-                match const_eval::eval_const_expr_partial(&tcx, e) {
+                match const_eval::eval_const_expr_partial(tcx, e) {
                     Ok(ref r) => {
                         match *r {
                             const_eval::const_int(i) =>
@@ -818,7 +817,7 @@ pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
     }
 }
 
-fn conv_builtin_bounds(tcx: ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBound>>,
+fn conv_builtin_bounds(tcx: &ty::ctxt, ast_bounds: &Option<OptVec<ast::TyParamBound>>,
                        store: ty::TraitStore)
                        -> ty::BuiltinBounds {
     //! Converts a list of bounds from the AST into a `BuiltinBounds`
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 6c59ce09e05..bfb0ab6400d 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -27,7 +27,7 @@ use syntax::parse::token;
 use syntax::codemap::Span;
 use syntax::print::pprust;
 
-pub fn check_match(fcx: @FnCtxt,
+pub fn check_match(fcx: &FnCtxt,
                    expr: &ast::Expr,
                    discrim: &ast::Expr,
                    arms: &[ast::Arm]) {
@@ -103,8 +103,8 @@ pub fn check_match(fcx: @FnCtxt,
     fcx.write_ty(expr.id, result_ty);
 }
 
-pub struct pat_ctxt {
-    fcx: @FnCtxt,
+pub struct pat_ctxt<'a> {
+    fcx: &'a FnCtxt<'a>,
     map: PatIdMap,
 }
 
diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs
index 1c7ad292877..dc9aa1b7e8c 100644
--- a/src/librustc/middle/typeck/check/demand.rs
+++ b/src/librustc/middle/typeck/check/demand.rs
@@ -46,7 +46,7 @@ pub fn suptype_with_fn(fcx: &FnCtxt,
     }
 }
 
-pub fn eqtype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
+pub fn eqtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
     match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) {
         Ok(()) => { /* ok */ }
         Err(ref err) => {
@@ -56,7 +56,7 @@ pub fn eqtype(fcx: @FnCtxt, sp: Span, expected: ty::t, actual: ty::t) {
 }
 
 // Checks that the type `actual` can be coerced to `expected`.
-pub fn coerce(fcx: @FnCtxt, sp: Span, expected: ty::t, expr: &ast::Expr) {
+pub fn coerce(fcx: &FnCtxt, sp: Span, expected: ty::t, expr: &ast::Expr) {
     let expr_ty = fcx.expr_ty(expr);
     match fcx.mk_assignty(expr, expr_ty, expected) {
       result::Ok(()) => { /* ok */ }
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 0d37904445f..5d232b488a6 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -95,7 +95,6 @@ use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
 use util::common::indenter;
 use util::ppaux::Repr;
 
-use std::cell::RefCell;
 use collections::HashSet;
 use std::result;
 use std::vec_ng::Vec;
@@ -120,7 +119,7 @@ pub enum AutoderefReceiverFlag {
 }
 
 pub fn lookup<'a>(
-        fcx: @FnCtxt,
+        fcx: &'a FnCtxt<'a>,
 
         // In a call `a.b::<X, Y, ...>(...)`:
         expr: &ast::Expr,                   // The expression `a.b(...)`.
@@ -132,15 +131,15 @@ pub fn lookup<'a>(
         check_traits: CheckTraitsFlag,      // Whether we check traits only.
         autoderef_receiver: AutoderefReceiverFlag)
      -> Option<MethodCallee> {
-    let lcx = LookupContext {
+    let mut lcx = LookupContext {
         fcx: fcx,
         span: expr.span,
         self_expr: Some(self_expr),
         m_name: m_name,
         supplied_tps: supplied_tps,
-        impl_dups: @RefCell::new(HashSet::new()),
-        inherent_candidates: @RefCell::new(Vec::new()),
-        extension_candidates: @RefCell::new(Vec::new()),
+        impl_dups: HashSet::new(),
+        inherent_candidates: Vec::new(),
+        extension_candidates: Vec::new(),
         deref_args: deref_args,
         check_traits: check_traits,
         autoderef_receiver: autoderef_receiver,
@@ -161,11 +160,11 @@ pub fn lookup<'a>(
     lcx.reset_candidates();
     lcx.push_bound_candidates(self_ty, None);
     lcx.push_extension_candidates(expr.id);
-    return lcx.search(self_ty);
+    lcx.search(self_ty)
 }
 
 pub fn lookup_in_trait<'a>(
-        fcx: @FnCtxt,
+        fcx: &'a FnCtxt<'a>,
 
         // In a call `a.b::<X, Y, ...>(...)`:
         span: Span,                         // The expression `a.b(...)`'s span.
@@ -176,15 +175,15 @@ pub fn lookup_in_trait<'a>(
         supplied_tps: &'a [ty::t],          // The list of types X, Y, ... .
         autoderef_receiver: AutoderefReceiverFlag)
      -> Option<MethodCallee> {
-    let lcx = LookupContext {
+    let mut lcx = LookupContext {
         fcx: fcx,
         span: span,
         self_expr: self_expr,
         m_name: m_name,
         supplied_tps: supplied_tps,
-        impl_dups: @RefCell::new(HashSet::new()),
-        inherent_candidates: @RefCell::new(Vec::new()),
-        extension_candidates: @RefCell::new(Vec::new()),
+        impl_dups: HashSet::new(),
+        inherent_candidates: Vec::new(),
+        extension_candidates: Vec::new(),
         deref_args: check::DoDerefArgs,
         check_traits: CheckTraitsOnly,
         autoderef_receiver: autoderef_receiver,
@@ -198,8 +197,93 @@ pub fn lookup_in_trait<'a>(
     lcx.search(self_ty)
 }
 
+
+
+// Determine the index of a method in the list of all methods belonging
+// to a trait and its supertraits.
+fn get_method_index(tcx: &ty::ctxt,
+                    trait_ref: &TraitRef,
+                    subtrait: @TraitRef,
+                    n_method: uint) -> uint {
+    // We need to figure the "real index" of the method in a
+    // listing of all the methods of an object. We do this by
+    // iterating down the supertraits of the object's trait until
+    // we find the trait the method came from, counting up the
+    // methods from them.
+    let mut method_count = 0;
+    ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
+        if bound_ref.def_id == trait_ref.def_id { false }
+            else {
+            method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
+            true
+        }
+    });
+    method_count + n_method
+}
+
+fn construct_transformed_self_ty_for_object(
+    tcx: &ty::ctxt,
+    span: Span,
+    trait_def_id: ast::DefId,
+    rcvr_substs: &ty::substs,
+    method_ty: &ty::Method)
+    -> ty::t {
+    /*!
+        * This is a bit tricky. We have a match against a trait method
+        * being invoked on an object, and we want to generate the
+        * self-type. As an example, consider a trait
+        *
+        *     trait Foo {
+        *         fn r_method<'a>(&'a self);
+        *         fn u_method(~self);
+        *     }
+        *
+        * Now, assuming that `r_method` is being called, we want the
+        * result to be `&'a Foo`. Assuming that `u_method` is being
+        * called, we want the result to be `~Foo`. Of course,
+        * this transformation has already been done as part of
+        * `method_ty.fty.sig.inputs[0]`, but there the type
+        * is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
+        * Because objects are not standalone types, we can't just substitute
+        * `s/Self/Foo/`, so we must instead perform this kind of hokey
+        * match below.
+        */
+
+    let substs = ty::substs {regions: rcvr_substs.regions.clone(),
+                                self_ty: None,
+                                tps: rcvr_substs.tps.clone()};
+    match method_ty.explicit_self {
+        ast::SelfStatic => {
+            tcx.sess.span_bug(span, "static method for object type receiver");
+        }
+        ast::SelfValue => {
+            ty::mk_err() // error reported in `enforce_object_limitations()`
+        }
+        ast::SelfRegion(..) | ast::SelfUniq => {
+            let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
+            match ty::get(transformed_self_ty).sty {
+                ty::ty_rptr(r, mt) => { // must be SelfRegion
+                    ty::mk_trait(tcx, trait_def_id, substs,
+                                 RegionTraitStore(r), mt.mutbl,
+                                 ty::EmptyBuiltinBounds())
+                }
+                ty::ty_uniq(_) => { // must be SelfUniq
+                    ty::mk_trait(tcx, trait_def_id, substs,
+                                 UniqTraitStore, ast::MutImmutable,
+                                 ty::EmptyBuiltinBounds())
+                }
+                _ => {
+                    tcx.sess.span_bug(span,
+                        format!("'impossible' transformed_self_ty: {}",
+                                transformed_self_ty.repr(tcx)));
+                }
+            }
+        }
+    }
+}
+
 struct LookupContext<'a> {
-    fcx: @FnCtxt,
+    fcx: &'a FnCtxt<'a>,
     span: Span,
 
     // The receiver to the method call. Only `None` in the case of
@@ -210,9 +294,9 @@ struct LookupContext<'a> {
 
     m_name: ast::Name,
     supplied_tps: &'a [ty::t],
-    impl_dups: @RefCell<HashSet<DefId>>,
-    inherent_candidates: @RefCell<Vec<Candidate> >,
-    extension_candidates: @RefCell<Vec<Candidate> >,
+    impl_dups: HashSet<DefId>,
+    inherent_candidates: Vec<Candidate>,
+    extension_candidates: Vec<Candidate>,
     deref_args: check::DerefArgs,
     check_traits: CheckTraitsFlag,
     autoderef_receiver: AutoderefReceiverFlag,
@@ -315,12 +399,12 @@ impl<'a> LookupContext<'a> {
     // ______________________________________________________________________
     // Candidate collection (see comment at start of file)
 
-    fn reset_candidates(&self) {
-        self.inherent_candidates.set(Vec::new());
-        self.extension_candidates.set(Vec::new());
+    fn reset_candidates(&mut self) {
+        self.inherent_candidates = Vec::new();
+        self.extension_candidates = Vec::new();
     }
 
-    fn push_inherent_candidates(&self, self_ty: ty::t) {
+    fn push_inherent_candidates(&mut self, self_ty: ty::t) {
         /*!
          * Collect all inherent candidates into
          * `self.inherent_candidates`.  See comment at the start of
@@ -354,7 +438,7 @@ impl<'a> LookupContext<'a> {
         });
     }
 
-    fn push_bound_candidates(&self, self_ty: ty::t, restrict_to: Option<DefId>) {
+    fn push_bound_candidates(&mut self, self_ty: ty::t, restrict_to: Option<DefId>) {
         let span = self.self_expr.map_or(self.span, |e| e.span);
         check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
             match get(self_ty).sty {
@@ -378,20 +462,18 @@ impl<'a> LookupContext<'a> {
         });
     }
 
-    fn push_extension_candidate(&self, trait_did: DefId) {
+    fn push_extension_candidate(&mut self, trait_did: DefId) {
         ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
 
         // Look for explicit implementations.
-        let trait_impls = self.tcx().trait_impls.borrow();
-        for impl_infos in trait_impls.get().find(&trait_did).iter() {
+        for impl_infos in self.tcx().trait_impls.borrow().get().find(&trait_did).iter() {
             for impl_info in impl_infos.borrow().get().iter() {
-                self.push_candidates_from_impl(
-                    self.extension_candidates.borrow_mut().get(), *impl_info);
+                self.push_candidates_from_impl(*impl_info, true);
             }
         }
     }
 
-    fn push_extension_candidates(&self, expr_id: ast::NodeId) {
+    fn push_extension_candidates(&mut self, expr_id: ast::NodeId) {
         // If the method being called is associated with a trait, then
         // find all the impls of that trait.  Each of those are
         // candidates.
@@ -403,38 +485,15 @@ impl<'a> LookupContext<'a> {
         }
     }
 
-    // Determine the index of a method in the list of all methods belonging
-    // to a trait and its supertraits.
-    fn get_method_index(&self,
-                        trait_ref: @TraitRef,
-                        subtrait: @TraitRef,
-                        n_method: uint) -> uint {
-        let tcx = self.tcx();
-
-        // We need to figure the "real index" of the method in a
-        // listing of all the methods of an object. We do this by
-        // iterating down the supertraits of the object's trait until
-        // we find the trait the method came from, counting up the
-        // methods from them.
-        let mut method_count = 0;
-        ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| {
-            if bound_ref.def_id == trait_ref.def_id { false }
-                else {
-                method_count += ty::trait_methods(tcx, bound_ref.def_id).len();
-                true
-            }
-        });
-        return method_count + n_method;
-    }
-
-
-    fn push_inherent_candidates_from_object(&self,
+    fn push_inherent_candidates_from_object(&mut self,
                                             did: DefId,
                                             substs: &ty::substs) {
         debug!("push_inherent_candidates_from_object(did={}, substs={})",
                self.did_to_str(did),
                substs.repr(self.tcx()));
         let _indenter = indenter();
+        let tcx = self.tcx();
+        let span = self.span;
 
         // It is illegal to invoke a method on a trait instance that
         // refers to the `self` type. An error will be reported by
@@ -452,13 +511,13 @@ impl<'a> LookupContext<'a> {
 
         self.push_inherent_candidates_from_bounds_inner(&[trait_ref],
             |new_trait_ref, m, method_num, _bound_num| {
-            let vtable_index =
-                self.get_method_index(new_trait_ref, trait_ref, method_num);
+            let vtable_index = get_method_index(tcx, new_trait_ref,
+                                                trait_ref, method_num);
             let mut m = (*m).clone();
             // We need to fix up the transformed self type.
             *m.fty.sig.inputs.get_mut(0) =
-                self.construct_transformed_self_ty_for_object(
-                    did, &rcvr_substs, &m);
+                construct_transformed_self_ty_for_object(
+                    tcx, span, did, &rcvr_substs, &m);
 
             Some(Candidate {
                 rcvr_match_condition: RcvrMatchesIfObject(did),
@@ -474,7 +533,7 @@ impl<'a> LookupContext<'a> {
         });
     }
 
-    fn push_inherent_candidates_from_param(&self,
+    fn push_inherent_candidates_from_param(&mut self,
                                            rcvr_ty: ty::t,
                                            restrict_to: Option<DefId>,
                                            param_ty: param_ty) {
@@ -494,7 +553,7 @@ impl<'a> LookupContext<'a> {
     }
 
 
-    fn push_inherent_candidates_from_self(&self,
+    fn push_inherent_candidates_from_self(&mut self,
                                           rcvr_ty: ty::t,
                                           restrict_to: Option<DefId>) {
         debug!("push_inherent_candidates_from_self()");
@@ -505,7 +564,7 @@ impl<'a> LookupContext<'a> {
             param_self)
     }
 
-    fn push_inherent_candidates_from_bounds(&self,
+    fn push_inherent_candidates_from_bounds(&mut self,
                                             self_ty: ty::t,
                                             bounds: &[@TraitRef],
                                             restrict_to: Option<DefId>,
@@ -536,7 +595,7 @@ impl<'a> LookupContext<'a> {
 
     // Do a search through a list of bounds, using a callback to actually
     // create the candidates.
-    fn push_inherent_candidates_from_bounds_inner(&self,
+    fn push_inherent_candidates_from_bounds_inner(&mut self,
                                                   bounds: &[@TraitRef],
                                                   mk_cand: |tr: @TraitRef,
                                                             m: @ty::Method,
@@ -561,7 +620,7 @@ impl<'a> LookupContext<'a> {
                         Some(cand) => {
                             debug!("pushing inherent candidate for param: {}",
                                    cand.repr(self.tcx()));
-                            self.inherent_candidates.borrow_mut().get().push(cand);
+                            self.inherent_candidates.push(cand);
                         }
                         None => {}
                     }
@@ -577,32 +636,23 @@ impl<'a> LookupContext<'a> {
     }
 
 
-    fn push_inherent_impl_candidates_for_type(&self, did: DefId) {
+    fn push_inherent_impl_candidates_for_type(&mut self, did: DefId) {
         // Read the inherent implementation candidates for this type from the
         // metadata if necessary.
         ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
 
-        let inherent_impls = self.tcx().inherent_impls.borrow();
-        let opt_impl_infos = inherent_impls.get().find(&did);
-        for impl_infos in opt_impl_infos.iter() {
-            let impl_infos = impl_infos.borrow();
-            for impl_info in impl_infos.get().iter() {
-                let mut inherent_candidates = self.inherent_candidates
-                                                  .borrow_mut();
-                self.push_candidates_from_impl(inherent_candidates.get(),
-                                               *impl_info);
+        for impl_infos in self.tcx().inherent_impls.borrow().get().find(&did).iter() {
+            for impl_info in impl_infos.borrow().get().iter() {
+                self.push_candidates_from_impl(*impl_info, false);
             }
         }
     }
 
-    fn push_candidates_from_impl(&self,
-                                 candidates: &mut Vec<Candidate>,
-                                 impl_info: &ty::Impl) {
-        {
-            let mut impl_dups = self.impl_dups.borrow_mut();
-            if !impl_dups.get().insert(impl_info.did) {
-                return; // already visited
-            }
+    fn push_candidates_from_impl(&mut self,
+                                 impl_info: &ty::Impl,
+                                 is_extension: bool) {
+        if !self.impl_dups.insert(impl_info.did) {
+            return; // already visited
         }
 
         debug!("push_candidates_from_impl: {} {} {}",
@@ -631,6 +681,12 @@ impl<'a> LookupContext<'a> {
             ty: impl_ty
         } = impl_self_ty(&vcx, span, impl_info.did);
 
+        let candidates = if is_extension {
+            &mut self.extension_candidates
+        } else {
+            &mut self.inherent_candidates
+        };
+
         candidates.push(Candidate {
             rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
             rcvr_substs: impl_substs,
@@ -913,8 +969,7 @@ impl<'a> LookupContext<'a> {
         // existing code.
 
         debug!("searching inherent candidates");
-        let mut inherent_candidates = self.inherent_candidates.borrow_mut();
-        match self.consider_candidates(rcvr_ty, inherent_candidates.get()) {
+        match self.consider_candidates(rcvr_ty, self.inherent_candidates.as_slice()) {
             None => {}
             Some(mme) => {
                 return Some(mme);
@@ -922,19 +977,11 @@ impl<'a> LookupContext<'a> {
         }
 
         debug!("searching extension candidates");
-        let mut extension_candidates = self.extension_candidates.borrow_mut();
-        match self.consider_candidates(rcvr_ty, extension_candidates.get()) {
-            None => {
-                return None;
-            }
-            Some(mme) => {
-                return Some(mme);
-            }
-        }
+        self.consider_candidates(rcvr_ty, self.extension_candidates.as_slice())
     }
 
     fn consider_candidates(&self, rcvr_ty: ty::t,
-                           candidates: &mut Vec<Candidate>)
+                           candidates: &[Candidate])
                            -> Option<MethodCallee> {
         // FIXME(pcwalton): Do we need to clone here?
         let relevant_candidates: Vec<Candidate> =
@@ -1140,66 +1187,6 @@ impl<'a> LookupContext<'a> {
         }
     }
 
-    fn construct_transformed_self_ty_for_object(
-        &self,
-        trait_def_id: ast::DefId,
-        rcvr_substs: &ty::substs,
-        method_ty: &ty::Method)
-        -> ty::t {
-        /*!
-         * This is a bit tricky. We have a match against a trait method
-         * being invoked on an object, and we want to generate the
-         * self-type. As an example, consider a trait
-         *
-         *     trait Foo {
-         *         fn r_method<'a>(&'a self);
-         *         fn u_method(~self);
-         *     }
-         *
-         * Now, assuming that `r_method` is being called, we want the
-         * result to be `&'a Foo`. Assuming that `u_method` is being
-         * called, we want the result to be `~Foo`. Of course,
-         * this transformation has already been done as part of
-         * `method_ty.fty.sig.inputs[0]`, but there the type
-         * is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
-         * Because objects are not standalone types, we can't just substitute
-         * `s/Self/Foo/`, so we must instead perform this kind of hokey
-         * match below.
-         */
-
-        let substs = ty::substs {regions: rcvr_substs.regions.clone(),
-                                 self_ty: None,
-                                 tps: rcvr_substs.tps.clone()};
-        match method_ty.explicit_self {
-            ast::SelfStatic => {
-                self.bug("static method for object type receiver");
-            }
-            ast::SelfValue => {
-                ty::mk_err() // error reported in `enforce_object_limitations()`
-            }
-            ast::SelfRegion(..) | ast::SelfUniq => {
-                let transformed_self_ty = *method_ty.fty.sig.inputs.get(0);
-                match ty::get(transformed_self_ty).sty {
-                    ty::ty_rptr(r, mt) => { // must be SelfRegion
-                        ty::mk_trait(self.tcx(), trait_def_id,
-                                     substs, RegionTraitStore(r), mt.mutbl,
-                                     ty::EmptyBuiltinBounds())
-                    }
-                    ty::ty_uniq(_) => { // must be SelfUniq
-                        ty::mk_trait(self.tcx(), trait_def_id,
-                                     substs, UniqTraitStore, ast::MutImmutable,
-                                     ty::EmptyBuiltinBounds())
-                    }
-                    _ => {
-                        self.bug(
-                            format!("'impossible' transformed_self_ty: {}",
-                                 transformed_self_ty.repr(self.tcx())));
-                    }
-                }
-            }
-        }
-    }
-
     fn enforce_object_limitations(&self, candidate: &Candidate) {
         /*!
          * There are some limitations to calling functions through an
@@ -1351,7 +1338,7 @@ impl<'a> LookupContext<'a> {
             }
         }
 
-        fn rcvr_matches_ty(fcx: @FnCtxt,
+        fn rcvr_matches_ty(fcx: &FnCtxt,
                            rcvr_ty: ty::t,
                            candidate: &Candidate) -> bool {
             match candidate.rcvr_match_condition {
@@ -1422,11 +1409,11 @@ impl<'a> LookupContext<'a> {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    fn infcx(&'a self) -> &'a infer::InferCtxt {
+    fn infcx(&'a self) -> &'a infer::InferCtxt<'a> {
         &self.fcx.inh.infcx
     }
 
-    fn tcx(&self) -> ty::ctxt {
+    fn tcx(&self) -> &'a ty::ctxt {
         self.fcx.tcx()
     }
 
@@ -1439,13 +1426,12 @@ impl<'a> LookupContext<'a> {
     }
 
     fn bug(&self, s: &str) -> ! {
-        let span = self.self_expr.map_or(self.span, |e| e.span);
-        self.tcx().sess.span_bug(span, s)
+        self.tcx().sess.span_bug(self.span, s)
     }
 }
 
 impl Repr for Candidate {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("Candidate(rcvr_ty={}, rcvr_substs={}, origin={:?})",
                 self.rcvr_match_condition.repr(tcx),
                 self.rcvr_substs.repr(tcx),
@@ -1454,7 +1440,7 @@ impl Repr for Candidate {
 }
 
 impl Repr for RcvrMatchCondition {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             RcvrMatchesIfObject(d) => {
                 format!("RcvrMatchesIfObject({})", d.repr(tcx))
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index f4a04d824ad..205c1c106dd 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -155,8 +155,8 @@ pub mod method;
 /// Here, the function `foo()` and the closure passed to
 /// `bar()` will each have their own `FnCtxt`, but they will
 /// share the inherited fields.
-pub struct Inherited {
-    infcx: infer::InferCtxt,
+pub struct Inherited<'a> {
+    infcx: infer::InferCtxt<'a>,
     locals: @RefCell<NodeMap<ty::t>>,
     param_env: ty::ParameterEnvironment,
 
@@ -221,7 +221,7 @@ enum IsBinopAssignment{
 }
 
 #[deriving(Clone)]
-pub struct FnCtxt {
+pub struct FnCtxt<'a> {
     // Number of errors that had been reported when we started
     // checking this function. On exit, if we find that *more* errors
     // have been reported, we will skip regionck and other work that
@@ -251,15 +251,15 @@ pub struct FnCtxt {
     // function return type.
     fn_kind: FnKind,
 
-    inh: @Inherited,
+    inh: &'a Inherited<'a>,
 
-    ccx: @CrateCtxt,
+    ccx: &'a CrateCtxt<'a>,
 }
 
-impl Inherited {
-    fn new(tcx: ty::ctxt,
+impl<'a> Inherited<'a> {
+    fn new(tcx: &'a ty::ctxt,
            param_env: ty::ParameterEnvironment)
-           -> Inherited {
+           -> Inherited<'a> {
         Inherited {
             infcx: infer::new_infer_ctxt(tcx),
             locals: @RefCell::new(NodeMap::new()),
@@ -275,51 +275,56 @@ impl Inherited {
 }
 
 // Used by check_const and check_enum_variants
-pub fn blank_fn_ctxt(ccx: @CrateCtxt,
+fn blank_fn_ctxt<'a>(ccx: &'a CrateCtxt<'a>,
+                     inh: &'a Inherited<'a>,
                      rty: ty::t,
                      region_bnd: ast::NodeId)
-                     -> @FnCtxt {
-    // It's kind of a kludge to manufacture a fake function context
-    // and statement context, but we might as well do write the code only once
-    let param_env = ty::ParameterEnvironment { free_substs: substs::empty(),
-                                               self_param_bound: None,
-                                               type_param_bounds: Vec::new() };
-    @FnCtxt {
+                     -> FnCtxt<'a> {
+    FnCtxt {
         err_count_on_creation: ccx.tcx.sess.err_count(),
         ret_ty: rty,
         ps: RefCell::new(PurityState::function(ast::ImpureFn, 0)),
         region_lb: Cell::new(region_bnd),
         fn_kind: Vanilla,
-        inh: @Inherited::new(ccx.tcx, param_env),
+        inh: inh,
         ccx: ccx
     }
 }
 
-impl ExprTyProvider for FnCtxt {
+fn blank_inherited_fields<'a>(ccx: &'a CrateCtxt<'a>) -> Inherited<'a> {
+    // It's kind of a kludge to manufacture a fake function context
+    // and statement context, but we might as well do write the code only once
+    let param_env = ty::ParameterEnvironment { free_substs: substs::empty(),
+                                               self_param_bound: None,
+                                               type_param_bounds: Vec::new() };
+    Inherited::new(ccx.tcx, param_env)
+}
+
+impl<'a> ExprTyProvider for FnCtxt<'a> {
     fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
         self.expr_ty(ex)
     }
 
-    fn ty_ctxt(&self) -> ty::ctxt {
+    fn ty_ctxt<'a>(&'a self) -> &'a ty::ctxt {
         self.ccx.tcx
     }
 }
 
-struct CheckItemTypesVisitor { ccx: @CrateCtxt }
+struct CheckItemTypesVisitor<'a> { ccx: &'a CrateCtxt<'a> }
 
-impl Visitor<()> for CheckItemTypesVisitor {
+impl<'a> Visitor<()> for CheckItemTypesVisitor<'a> {
     fn visit_item(&mut self, i: &ast::Item, _: ()) {
         check_item(self.ccx, i);
         visit::walk_item(self, i, ());
     }
 }
 
-pub fn check_item_types(ccx: @CrateCtxt, krate: &ast::Crate) {
+pub fn check_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
     let mut visit = CheckItemTypesVisitor { ccx: ccx };
     visit::walk_crate(&mut visit, krate, ());
 }
 
-fn check_bare_fn(ccx: @CrateCtxt,
+fn check_bare_fn(ccx: &CrateCtxt,
                  decl: &ast::FnDecl,
                  body: &ast::Block,
                  id: ast::NodeId,
@@ -327,25 +332,24 @@ fn check_bare_fn(ccx: @CrateCtxt,
                  param_env: ty::ParameterEnvironment) {
     match ty::get(fty).sty {
         ty::ty_bare_fn(ref fn_ty) => {
-            let fcx =
-                check_fn(ccx, fn_ty.purity, &fn_ty.sig, decl, id, body,
-                         Vanilla, @Inherited::new(ccx.tcx, param_env));
+            let inh = Inherited::new(ccx.tcx, param_env);
+            let fcx = check_fn(ccx, fn_ty.purity, &fn_ty.sig,
+                               decl, id, body, Vanilla, &inh);
 
-            vtable::resolve_in_block(fcx, body);
-            regionck::regionck_fn(fcx, body);
-            writeback::resolve_type_vars_in_fn(fcx, decl, body);
+            vtable::resolve_in_block(&fcx, body);
+            regionck::regionck_fn(&fcx, body);
+            writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
         _ => ccx.tcx.sess.impossible_case(body.span,
                                  "check_bare_fn: function type expected")
     }
 }
 
-struct GatherLocalsVisitor {
-                     fcx: @FnCtxt,
-                     tcx: ty::ctxt,
+struct GatherLocalsVisitor<'a> {
+    fcx: &'a FnCtxt<'a>
 }
 
-impl GatherLocalsVisitor {
+impl<'a> GatherLocalsVisitor<'a> {
     fn assign(&mut self, nid: ast::NodeId, ty_opt: Option<ty::t>) {
             match ty_opt {
                 None => {
@@ -364,7 +368,7 @@ impl GatherLocalsVisitor {
     }
 }
 
-impl Visitor<()> for GatherLocalsVisitor {
+impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
         // Add explicitly-declared locals.
     fn visit_local(&mut self, local: &ast::Local, _: ()) {
             let o_ty = match local.ty.node {
@@ -416,14 +420,14 @@ impl Visitor<()> for GatherLocalsVisitor {
 
 }
 
-fn check_fn(ccx: @CrateCtxt,
-            purity: ast::Purity,
-            fn_sig: &ty::FnSig,
-            decl: &ast::FnDecl,
-            id: ast::NodeId,
-            body: &ast::Block,
-            fn_kind: FnKind,
-            inherited: @Inherited) -> @FnCtxt
+fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
+                purity: ast::Purity,
+                fn_sig: &ty::FnSig,
+                decl: &ast::FnDecl,
+                id: ast::NodeId,
+                body: &ast::Block,
+                fn_kind: FnKind,
+                inherited: &'a Inherited<'a>) -> FnCtxt<'a>
 {
     /*!
      * Helper used by check_bare_fn and check_expr_fn.  Does the
@@ -455,7 +459,7 @@ fn check_fn(ccx: @CrateCtxt,
 
     // Create the function context.  This is either derived from scratch or,
     // in the case of function expressions, based on the outer context.
-    let fcx = @FnCtxt {
+    let fcx = FnCtxt {
         err_count_on_creation: err_count_on_creation,
         ret_ty: ret_ty,
         ps: RefCell::new(PurityState::function(purity, id)),
@@ -467,7 +471,7 @@ fn check_fn(ccx: @CrateCtxt,
 
     {
 
-        let mut visit = GatherLocalsVisitor { fcx: fcx, tcx: tcx, };
+        let mut visit = GatherLocalsVisitor { fcx: &fcx, };
         // Add formal parameters.
         for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
             // Create type variables for each argument.
@@ -479,7 +483,7 @@ fn check_fn(ccx: @CrateCtxt,
 
             // Check the pattern.
             let pcx = pat_ctxt {
-                fcx: fcx,
+                fcx: &fcx,
                 map: pat_id_map(tcx.def_map, input.pat),
             };
             _match::check_pat(&pcx, input.pat, *arg_ty);
@@ -488,7 +492,7 @@ fn check_fn(ccx: @CrateCtxt,
         visit.visit_block(body, ());
     }
 
-    check_block_with_expected(fcx, body, Some(ret_ty));
+    check_block_with_expected(&fcx, body, Some(ret_ty));
 
     // We unify the tail expr's type with the
     // function result type, if there is a tail expr.
@@ -496,7 +500,7 @@ fn check_fn(ccx: @CrateCtxt,
         Some(tail_expr) => {
             // Special case: we print a special error if there appears
             // to be do-block/for-loop confusion
-            demand::suptype_with_fn(fcx, tail_expr.span, false,
+            demand::suptype_with_fn(&fcx, tail_expr.span, false,
                 fcx.ret_ty, fcx.expr_ty(tail_expr),
                 |sp, e, a, s| {
                     fcx.report_mismatched_return_types(sp, e, a, s);
@@ -512,8 +516,8 @@ fn check_fn(ccx: @CrateCtxt,
     fcx
 }
 
-pub fn check_no_duplicate_fields(tcx: ty::ctxt,
-                                 fields: Vec<(ast::Ident, Span)> ) {
+pub fn check_no_duplicate_fields(tcx: &ty::ctxt,
+                                 fields: Vec<(ast::Ident, Span)>) {
     let mut field_names = HashMap::new();
 
     for p in fields.iter() {
@@ -533,7 +537,7 @@ pub fn check_no_duplicate_fields(tcx: ty::ctxt,
     }
 }
 
-pub fn check_struct(ccx: @CrateCtxt, id: ast::NodeId, span: Span) {
+pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
     let tcx = ccx.tcx;
 
     // Check that the struct is representable
@@ -547,7 +551,7 @@ pub fn check_struct(ccx: @CrateCtxt, id: ast::NodeId, span: Span) {
     }
 }
 
-pub fn check_item(ccx: @CrateCtxt, it: &ast::Item) {
+pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
     debug!("check_item(it.id={}, it.ident={})",
            it.id,
            ty::item_path_str(ccx.tcx, local_def(it.id)));
@@ -649,7 +653,7 @@ pub fn check_item(ccx: @CrateCtxt, it: &ast::Item) {
     }
 }
 
-fn check_method_body(ccx: @CrateCtxt,
+fn check_method_body(ccx: &CrateCtxt,
                      item_generics: &ty::Generics,
                      self_bound: Option<@ty::TraitRef>,
                      method: &ast::Method) {
@@ -690,7 +694,7 @@ fn check_method_body(ccx: @CrateCtxt,
     check_bare_fn(ccx, method.decl, method.body, method.id, fty, param_env);
 }
 
-fn check_impl_methods_against_trait(ccx: @CrateCtxt,
+fn check_impl_methods_against_trait(ccx: &CrateCtxt,
                                     impl_span: Span,
                                     impl_generics: &ty::Generics,
                                     ast_trait_ref: &ast::TraitRef,
@@ -769,7 +773,7 @@ fn check_impl_methods_against_trait(ccx: @CrateCtxt,
  * - trait_m: the method in the trait
  * - trait_substs: the substitutions used on the type of the trait
  */
-fn compare_impl_method(tcx: ty::ctxt,
+fn compare_impl_method(tcx: &ty::ctxt,
                        impl_generics: &ty::Generics,
                        impl_m: @ty::Method,
                        impl_m_span: Span,
@@ -796,7 +800,7 @@ fn compare_impl_method(tcx: ty::ctxt,
                 format!("method `{}` has a `{}` declaration in the impl, \
                         but not in the trait",
                         token::get_ident(trait_m.ident),
-                        pprust::explicit_self_to_str(&impl_m.explicit_self)));
+                        pprust::explicit_self_to_str(impl_m.explicit_self)));
             return;
         }
         (_, &ast::SelfStatic) => {
@@ -805,7 +809,7 @@ fn compare_impl_method(tcx: ty::ctxt,
                 format!("method `{}` has a `{}` declaration in the trait, \
                         but not in the impl",
                         token::get_ident(trait_m.ident),
-                        pprust::explicit_self_to_str(&trait_m.explicit_self)));
+                        pprust::explicit_self_to_str(trait_m.explicit_self)));
             return;
         }
         _ => {
@@ -956,8 +960,8 @@ fn compare_impl_method(tcx: ty::ctxt,
     }
 }
 
-impl AstConv for FnCtxt {
-    fn tcx(&self) -> ty::ctxt { self.ccx.tcx }
+impl<'a> AstConv for FnCtxt<'a> {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.ccx.tcx }
 
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
         ty::lookup_item_type(self.tcx(), id)
@@ -972,8 +976,8 @@ impl AstConv for FnCtxt {
     }
 }
 
-impl FnCtxt {
-    pub fn infcx<'a>(&'a self) -> &'a infer::InferCtxt {
+impl<'a> FnCtxt<'a> {
+    pub fn infcx<'b>(&'b self) -> &'b infer::InferCtxt<'a> {
         &self.inh.infcx
     }
 
@@ -989,7 +993,7 @@ impl FnCtxt {
     }
 }
 
-impl RegionScope for infer::InferCtxt {
+impl<'a> RegionScope for infer::InferCtxt<'a> {
     fn anon_regions(&self, span: Span, count: uint)
                     -> Result<Vec<ty::Region> , ()> {
         Ok(Vec::from_fn(count, |_| {
@@ -998,7 +1002,7 @@ impl RegionScope for infer::InferCtxt {
     }
 }
 
-impl FnCtxt {
+impl<'a> FnCtxt<'a> {
     pub fn tag(&self) -> ~str {
         format!("{}", self as *FnCtxt)
     }
@@ -1241,7 +1245,7 @@ pub enum LvaluePreference {
     NoPreference
 }
 
-pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, base_ty: ty::t,
+pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
                     expr_id: Option<ast::NodeId>,
                     mut lvalue_pref: LvaluePreference,
                     should_stop: |ty::t, uint| -> Option<T>)
@@ -1292,7 +1296,7 @@ pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, base_ty: ty::t,
     (ty::mk_err(), 0, None)
 }
 
-fn try_overloaded_deref(fcx: @FnCtxt,
+fn try_overloaded_deref(fcx: &FnCtxt,
                         span: Span,
                         method_call: Option<MethodCall>,
                         base_expr: Option<&ast::Expr>,
@@ -1335,7 +1339,7 @@ fn try_overloaded_deref(fcx: @FnCtxt,
 }
 
 // AST fragment checking
-pub fn check_lit(fcx: @FnCtxt, lit: &ast::Lit) -> ty::t {
+pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
     let tcx = fcx.ccx.tcx;
 
     match lit.node {
@@ -1363,7 +1367,7 @@ pub fn check_lit(fcx: @FnCtxt, lit: &ast::Lit) -> ty::t {
     }
 }
 
-pub fn valid_range_bounds(ccx: @CrateCtxt,
+pub fn valid_range_bounds(ccx: &CrateCtxt,
                           from: &ast::Expr,
                           to: &ast::Expr)
                        -> Option<bool> {
@@ -1374,40 +1378,40 @@ pub fn valid_range_bounds(ccx: @CrateCtxt,
 }
 
 pub fn check_expr_has_type(
-    fcx: @FnCtxt, expr: &ast::Expr,
+    fcx: &FnCtxt, expr: &ast::Expr,
     expected: ty::t) {
     check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
         demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr));
     });
 }
 
-fn check_expr_coercable_to_type(fcx: @FnCtxt, expr: &ast::Expr, expected: ty::t) {
+fn check_expr_coercable_to_type(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
     check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || {
         demand::coerce(fcx, expr.span, expected, expr)
     });
 }
 
-fn check_expr_with_hint(fcx: @FnCtxt, expr: &ast::Expr, expected: ty::t) {
+fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
     check_expr_with_unifier(fcx, expr, Some(expected), NoPreference, || ())
 }
 
-fn check_expr_with_opt_hint(fcx: @FnCtxt, expr: &ast::Expr,
+fn check_expr_with_opt_hint(fcx: &FnCtxt, expr: &ast::Expr,
                             expected: Option<ty::t>)  {
     check_expr_with_unifier(fcx, expr, expected, NoPreference, || ())
 }
 
-fn check_expr_with_opt_hint_and_lvalue_pref(fcx: @FnCtxt,
+fn check_expr_with_opt_hint_and_lvalue_pref(fcx: &FnCtxt,
                                             expr: &ast::Expr,
                                             expected: Option<ty::t>,
                                             lvalue_pref: LvaluePreference) {
     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
 }
 
-fn check_expr(fcx: @FnCtxt, expr: &ast::Expr)  {
+fn check_expr(fcx: &FnCtxt, expr: &ast::Expr)  {
     check_expr_with_unifier(fcx, expr, None, NoPreference, || ())
 }
 
-fn check_expr_with_lvalue_pref(fcx: @FnCtxt, expr: &ast::Expr,
+fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
                                lvalue_pref: LvaluePreference)  {
     check_expr_with_unifier(fcx, expr, None, lvalue_pref, || ())
 }
@@ -1444,7 +1448,7 @@ pub fn impl_self_ty(vcx: &VtableContext,
 
 // Only for fields! Returns <none> for methods>
 // Indifferent to privacy flags
-pub fn lookup_field_ty(tcx: ty::ctxt,
+pub fn lookup_field_ty(tcx: &ty::ctxt,
                        class_id: ast::DefId,
                        items: &[ty::field_ty],
                        fieldname: ast::Name,
@@ -1463,7 +1467,7 @@ pub enum DerefArgs {
 
 // Given the provenance of a static method, returns the generics of the static
 // method's container.
-fn generics_of_static_method_container(type_context: ty::ctxt,
+fn generics_of_static_method_container(type_context: &ty::ctxt,
                                        provenance: ast::MethodProvenance)
                                        -> ty::Generics {
     match provenance {
@@ -1478,7 +1482,7 @@ fn generics_of_static_method_container(type_context: ty::ctxt,
 
 // Verifies that type parameters supplied in paths are in the right
 // locations.
-fn check_type_parameter_positions_in_path(function_context: @FnCtxt,
+fn check_type_parameter_positions_in_path(function_context: &FnCtxt,
                                           path: &ast::Path,
                                           def: ast::Def) {
     // We only care about checking the case in which the path has two or
@@ -1635,7 +1639,7 @@ fn check_type_parameter_positions_in_path(function_context: @FnCtxt,
 /// Note that inspecting a type's structure *directly* may expose the fact
 /// that there are actually multiple representations for both `ty_err` and
 /// `ty_bot`, so avoid that when err and bot need to be handled differently.
-fn check_expr_with_unifier(fcx: @FnCtxt,
+fn check_expr_with_unifier(fcx: &FnCtxt,
                            expr: &ast::Expr,
                            expected: Option<ty::t>,
                            lvalue_pref: LvaluePreference,
@@ -1643,7 +1647,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
     debug!(">> typechecking");
 
     fn check_method_argument_types(
-        fcx: @FnCtxt,
+        fcx: &FnCtxt,
         sp: Span,
         method_fn_ty: ty::t,
         callee_expr: &ast::Expr,
@@ -1674,7 +1678,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         }
     }
 
-    fn check_argument_types(fcx: @FnCtxt,
+    fn check_argument_types(fcx: &FnCtxt,
                             sp: Span,
                             fn_inputs: &[ty::t],
                             callee_expr: &ast::Expr,
@@ -1825,12 +1829,12 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         Vec::from_fn(len, |_| ty::mk_err())
     }
 
-    fn write_call(fcx: @FnCtxt, call_expr: &ast::Expr, output: ty::t) {
+    fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
         fcx.write_ty(call_expr.id, output);
     }
 
     // A generic function for doing all of the checking for call expressions
-    fn check_call(fcx: @FnCtxt,
+    fn check_call(fcx: &FnCtxt,
                   call_expr: &ast::Expr,
                   f: &ast::Expr,
                   args: &[@ast::Expr]) {
@@ -1879,7 +1883,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
     }
 
     // Checks a method call.
-    fn check_method_call(fcx: @FnCtxt,
+    fn check_method_call(fcx: &FnCtxt,
                          expr: &ast::Expr,
                          method_name: ast::Ident,
                          args: &[@ast::Expr],
@@ -1936,7 +1940,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
 
     // A generic function for checking the then and else in an if
     // or if-check
-    fn check_then_else(fcx: @FnCtxt,
+    fn check_then_else(fcx: &FnCtxt,
                        cond_expr: &ast::Expr,
                        then_blk: &ast::Block,
                        opt_else_expr: Option<@ast::Expr>,
@@ -1975,7 +1979,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         fcx.write_ty(id, if_ty);
     }
 
-    fn lookup_op_method(fcx: @FnCtxt,
+    fn lookup_op_method(fcx: &FnCtxt,
                         op_ex: &ast::Expr,
                         self_t: ty::t,
                         opname: ast::Name,
@@ -2014,7 +2018,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
     }
 
     // could be either an expr_binop or an expr_assign_binop
-    fn check_binop(fcx: @FnCtxt,
+    fn check_binop(fcx: &FnCtxt,
                    expr: &ast::Expr,
                    op: ast::BinOp,
                    lhs: @ast::Expr,
@@ -2092,7 +2096,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         }
     }
 
-    fn check_user_binop(fcx: @FnCtxt,
+    fn check_user_binop(fcx: &FnCtxt,
                         ex: &ast::Expr,
                         lhs_expr: @ast::Expr,
                         lhs_resolved_t: ty::t,
@@ -2131,7 +2135,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         })
     }
 
-    fn check_user_unop(fcx: @FnCtxt,
+    fn check_user_unop(fcx: &FnCtxt,
                        op_str: &str,
                        mname: &str,
                        trait_did: Option<ast::DefId>,
@@ -2151,7 +2155,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
     // resolution is not possible (e.g., no constraints yet present), just
     // returns `none`.
     fn unpack_expected<O>(
-                       fcx: @FnCtxt,
+                       fcx: &FnCtxt,
                        expected: Option<ty::t>,
                        unpack: |&ty::sty| -> Option<O>)
                        -> Option<O> {
@@ -2166,7 +2170,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         }
     }
 
-    fn check_expr_fn(fcx: @FnCtxt,
+    fn check_expr_fn(fcx: &FnCtxt,
                      expr: &ast::Expr,
                      ast_sigil_opt: Option<ast::Sigil>,
                      decl: &ast::FnDecl,
@@ -2272,7 +2276,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
 
 
     // Check field access expressions
-    fn check_field(fcx: @FnCtxt,
+    fn check_field(fcx: &FnCtxt,
                    expr: &ast::Expr,
                    lvalue_pref: LvaluePreference,
                    base: &ast::Expr,
@@ -2341,7 +2345,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         fcx.write_error(expr.id);
     }
 
-    fn check_struct_or_variant_fields(fcx: @FnCtxt,
+    fn check_struct_or_variant_fields(fcx: &FnCtxt,
                                       struct_ty: ty::t,
                                       span: Span,
                                       class_id: ast::DefId,
@@ -2429,7 +2433,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         }
     }
 
-    fn check_struct_constructor(fcx: @FnCtxt,
+    fn check_struct_constructor(fcx: &FnCtxt,
                                 id: ast::NodeId,
                                 span: codemap::Span,
                                 class_id: ast::DefId,
@@ -2485,7 +2489,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
         fcx.write_ty(id, struct_type);
     }
 
-    fn check_struct_enum_variant(fcx: @FnCtxt,
+    fn check_struct_enum_variant(fcx: &FnCtxt,
                                  id: ast::NodeId,
                                  span: codemap::Span,
                                  enum_id: ast::DefId,
@@ -3021,7 +3025,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
                                 _ => false
                             }
                         }
-                        fn types_compatible(fcx: @FnCtxt, sp: Span,
+                        fn types_compatible(fcx: &FnCtxt, sp: Span,
                                             t1: ty::t, t2: ty::t) -> bool {
                             if !is_vec(t1) {
                                 false
@@ -3206,7 +3210,7 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
     unifier();
 }
 
-pub fn require_integral(fcx: @FnCtxt, sp: Span, t: ty::t) {
+pub fn require_integral(fcx: &FnCtxt, sp: Span, t: ty::t) {
     if !type_is_integral(fcx, sp, t) {
         fcx.type_error_message(sp, |actual| {
             format!("mismatched types: expected integral type but found `{}`",
@@ -3215,7 +3219,7 @@ pub fn require_integral(fcx: @FnCtxt, sp: Span, t: ty::t) {
     }
 }
 
-pub fn check_decl_initializer(fcx: @FnCtxt,
+pub fn check_decl_initializer(fcx: &FnCtxt,
                               nid: ast::NodeId,
                               init: &ast::Expr)
                             {
@@ -3223,7 +3227,7 @@ pub fn check_decl_initializer(fcx: @FnCtxt,
     check_expr_coercable_to_type(fcx, init, local_ty)
 }
 
-pub fn check_decl_local(fcx: @FnCtxt, local: &ast::Local)  {
+pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
     let tcx = fcx.ccx.tcx;
 
     let t = fcx.local_ty(local.span, local.id);
@@ -3251,7 +3255,7 @@ pub fn check_decl_local(fcx: @FnCtxt, local: &ast::Local)  {
     }
 }
 
-pub fn check_stmt(fcx: @FnCtxt, stmt: &ast::Stmt)  {
+pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
     let node_id;
     let mut saw_bot = false;
     let mut saw_err = false;
@@ -3296,7 +3300,7 @@ pub fn check_stmt(fcx: @FnCtxt, stmt: &ast::Stmt)  {
     }
 }
 
-pub fn check_block_no_value(fcx: @FnCtxt, blk: &ast::Block)  {
+pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
     check_block_with_expected(fcx, blk, Some(ty::mk_nil()));
     let blkty = fcx.node_ty(blk.id);
     if ty::type_is_error(blkty) {
@@ -3311,11 +3315,11 @@ pub fn check_block_no_value(fcx: @FnCtxt, blk: &ast::Block)  {
     }
 }
 
-pub fn check_block(fcx0: @FnCtxt, blk: &ast::Block)  {
+pub fn check_block(fcx0: &FnCtxt, blk: &ast::Block)  {
     check_block_with_expected(fcx0, blk, None)
 }
 
-pub fn check_block_with_expected(fcx: @FnCtxt,
+pub fn check_block_with_expected(fcx: &FnCtxt,
                                  blk: &ast::Block,
                                  expected: Option<ty::t>) {
     let prev = {
@@ -3384,20 +3388,21 @@ pub fn check_block_with_expected(fcx: @FnCtxt,
     fcx.ps.set(prev);
 }
 
-pub fn check_const(ccx: @CrateCtxt,
+pub fn check_const(ccx: &CrateCtxt,
                    sp: Span,
                    e: &ast::Expr,
                    id: ast::NodeId) {
+    let inh = blank_inherited_fields(ccx);
     let rty = ty::node_id_to_type(ccx.tcx, id);
-    let fcx = blank_fn_ctxt(ccx, rty, e.id);
+    let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
     let declty = {
         let tcache = fcx.ccx.tcx.tcache.borrow();
         tcache.get().get(&local_def(id)).ty
     };
-    check_const_with_ty(fcx, sp, e, declty);
+    check_const_with_ty(&fcx, sp, e, declty);
 }
 
-pub fn check_const_with_ty(fcx: @FnCtxt,
+pub fn check_const_with_ty(fcx: &FnCtxt,
                            _: Span,
                            e: &ast::Expr,
                            declty: ty::t) {
@@ -3413,7 +3418,7 @@ pub fn check_const_with_ty(fcx: @FnCtxt,
 /// pointer, which would mean their size is unbounded. This is different from
 /// the question of whether a type can be instantiated. See the definition of
 /// `check_instantiable`.
-pub fn check_representable(tcx: ty::ctxt,
+pub fn check_representable(tcx: &ty::ctxt,
                            sp: Span,
                            item_id: ast::NodeId,
                            designation: &str) {
@@ -3446,7 +3451,7 @@ pub fn check_representable(tcx: ty::ctxt,
 ///     enum foo { Some(@foo) }
 ///
 /// is representable, but not instantiable.
-pub fn check_instantiable(tcx: ty::ctxt,
+pub fn check_instantiable(tcx: &ty::ctxt,
                           sp: Span,
                           item_id: ast::NodeId) {
     let item_ty = ty::node_id_to_type(tcx, item_id);
@@ -3458,7 +3463,7 @@ pub fn check_instantiable(tcx: ty::ctxt,
     }
 }
 
-pub fn check_simd(tcx: ty::ctxt, sp: Span, id: ast::NodeId) {
+pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
     let t = ty::node_id_to_type(tcx, id);
     if ty::type_needs_subst(t) {
         tcx.sess.span_err(sp, "SIMD vector cannot be generic");
@@ -3487,15 +3492,15 @@ pub fn check_simd(tcx: ty::ctxt, sp: Span, id: ast::NodeId) {
     }
 }
 
-pub fn check_enum_variants(ccx: @CrateCtxt,
+pub fn check_enum_variants(ccx: &CrateCtxt,
                            sp: Span,
                            vs: &[ast::P<ast::Variant>],
                            id: ast::NodeId) {
 
-    fn disr_in_range(ccx: @CrateCtxt,
+    fn disr_in_range(ccx: &CrateCtxt,
                      ty: attr::IntType,
                      disr: ty::Disr) -> bool {
-        fn uint_in_range(ccx: @CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
+        fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
             match ty {
                 ast::TyU8 => disr as u8 as Disr == disr,
                 ast::TyU16 => disr as u16 as Disr == disr,
@@ -3504,7 +3509,7 @@ pub fn check_enum_variants(ccx: @CrateCtxt,
                 ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
             }
         }
-        fn int_in_range(ccx: @CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
+        fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
             match ty {
                 ast::TyI8 => disr as i8 as Disr == disr,
                 ast::TyI16 => disr as i16 as Disr == disr,
@@ -3519,7 +3524,7 @@ pub fn check_enum_variants(ccx: @CrateCtxt,
         }
     }
 
-    fn do_check(ccx: @CrateCtxt,
+    fn do_check(ccx: &CrateCtxt,
                 vs: &[ast::P<ast::Variant>],
                 id: ast::NodeId,
                 hint: attr::ReprAttr)
@@ -3543,14 +3548,15 @@ pub fn check_enum_variants(ccx: @CrateCtxt,
                 Some(e) => {
                     debug!("disr expr, checking {}", pprust::expr_to_str(e));
 
-                    let fcx = blank_fn_ctxt(ccx, rty, e.id);
+                    let inh = blank_inherited_fields(ccx);
+                    let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
                     let declty = ty::mk_int_var(ccx.tcx, fcx.infcx().next_int_var_id());
-                    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 an 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(_) => {
@@ -3618,12 +3624,12 @@ pub fn check_enum_variants(ccx: @CrateCtxt,
     check_instantiable(ccx.tcx, sp, id);
 }
 
-pub fn lookup_def(fcx: @FnCtxt, sp: Span, id: ast::NodeId) -> ast::Def {
+pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> ast::Def {
     lookup_def_ccx(fcx.ccx, sp, id)
 }
 
 // Returns the type parameter count and the type for the given definition.
-pub fn ty_param_bounds_and_ty_for_def(fcx: @FnCtxt,
+pub fn ty_param_bounds_and_ty_for_def(fcx: &FnCtxt,
                                       sp: Span,
                                       defn: ast::Def)
                                    -> ty_param_bounds_and_ty {
@@ -3673,7 +3679,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @FnCtxt,
 
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
-pub fn instantiate_path(fcx: @FnCtxt,
+pub fn instantiate_path(fcx: &FnCtxt,
                         pth: &ast::Path,
                         tpt: ty_param_bounds_and_ty,
                         def: ast::Def,
@@ -3859,47 +3865,47 @@ pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
 }
 
 // Returns the one-level-deep structure of the given type.
-pub fn structure_of<'a>(fcx: @FnCtxt, sp: Span, typ: ty::t)
+pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
                         -> &'a ty::sty {
     &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
 }
 
-pub fn type_is_integral(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_integral(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_integral(typ_s);
 }
 
-pub fn type_is_scalar(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_scalar(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_scalar(typ_s);
 }
 
-pub fn type_is_char(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_char(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_char(typ_s);
 }
 
-pub fn type_is_bare_fn(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_bare_fn(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_bare_fn(typ_s);
 }
 
-pub fn type_is_unsafe_ptr(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_unsafe_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_unsafe_ptr(typ_s);
 }
 
-pub fn type_is_region_ptr(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_region_ptr(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_region_ptr(typ_s);
 }
 
-pub fn type_is_c_like_enum(fcx: @FnCtxt, sp: Span, typ: ty::t) -> bool {
+pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
     let typ_s = structurally_resolved_type(fcx, sp, typ);
     return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
 }
 
-pub fn ast_expr_vstore_to_vstore(fcx: @FnCtxt,
+pub fn ast_expr_vstore_to_vstore(fcx: &FnCtxt,
                                  e: &ast::Expr,
                                  v: ast::ExprVstore)
                               -> ty::vstore {
@@ -3939,7 +3945,7 @@ pub fn ast_expr_vstore_to_vstore(fcx: @FnCtxt,
 }
 
 // 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::P<ast::Block>) -> bool {
     // First: is there an unlabeled break immediately
     // inside the loop?
     (loop_query(b, |e| {
@@ -3963,7 +3969,7 @@ pub fn may_break(cx: ty::ctxt, id: ast::NodeId, b: ast::P<ast::Block>) -> bool {
         }}))
 }
 
-pub fn check_bounds_are_used(ccx: @CrateCtxt,
+pub fn check_bounds_are_used(ccx: &CrateCtxt,
                              span: Span,
                              tps: &OptVec<ast::TyParam>,
                              ty: ty::t) {
@@ -3993,8 +3999,8 @@ pub fn check_bounds_are_used(ccx: @CrateCtxt,
     }
 }
 
-pub fn check_intrinsic_type(ccx: @CrateCtxt, it: &ast::ForeignItem) {
-    fn param(ccx: @CrateCtxt, n: uint) -> ty::t {
+pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
+    fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
         ty::mk_param(ccx.tcx, n, local_def(0))
     }
 
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index 1278bfb2e16..4610305a70b 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -154,15 +154,15 @@ macro_rules! ignore_err(
     )
 )
 
-pub struct Rcx {
-    fcx: @FnCtxt,
+pub struct Rcx<'a> {
+    fcx: &'a FnCtxt<'a>,
     errors_reported: uint,
 
     // id of innermost fn or loop
     repeating_scope: ast::NodeId,
 }
 
-fn region_of_def(fcx: @FnCtxt, def: ast::Def) -> ty::Region {
+fn region_of_def(fcx: &FnCtxt, def: ast::Def) -> ty::Region {
     /*!
      * Returns the validity region of `def` -- that is, how long
      * is `def` valid?
@@ -187,8 +187,8 @@ fn region_of_def(fcx: @FnCtxt, def: ast::Def) -> ty::Region {
     }
 }
 
-impl Rcx {
-    pub fn tcx(&self) -> ty::ctxt {
+impl<'a> Rcx<'a> {
+    pub fn tcx(&self) -> &'a ty::ctxt {
         self.fcx.ccx.tcx
     }
 
@@ -198,7 +198,7 @@ impl Rcx {
         old_scope
     }
 
-    pub fn resolve_type(&mut self, unresolved_ty: ty::t) -> ty::t {
+    pub fn resolve_type(&self, unresolved_ty: ty::t) -> ty::t {
         /*!
          * Try to resolve the type for the given node, returning
          * t_err if an error results.  Note that we never care
@@ -240,7 +240,7 @@ impl Rcx {
         self.resolve_type(t)
     }
 
-    fn resolve_method_type(&mut self, method_call: MethodCall) -> Option<ty::t> {
+    fn resolve_method_type(&self, method_call: MethodCall) -> Option<ty::t> {
         let method_ty = self.fcx.inh.method_map.borrow().get()
                             .find(&method_call).map(|method| method.ty);
         method_ty.map(|method_ty| self.resolve_type(method_ty))
@@ -260,8 +260,8 @@ impl Rcx {
     }
 }
 
-impl<'a> mc::Typer for &'a mut Rcx {
-    fn tcx(&self) -> ty::ctxt {
+impl<'a, 'b> mc::Typer for &'a mut Rcx<'b> {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt {
         self.fcx.tcx()
     }
 
@@ -270,7 +270,7 @@ impl<'a> mc::Typer for &'a mut Rcx {
         if ty::type_is_error(t) {Err(())} else {Ok(t)}
     }
 
-    fn node_method_ty(&mut self, method_call: MethodCall) -> Option<ty::t> {
+    fn node_method_ty(&self, method_call: MethodCall) -> Option<ty::t> {
         self.resolve_method_type(method_call)
     }
 
@@ -293,7 +293,7 @@ impl<'a> mc::Typer for &'a mut Rcx {
     }
 }
 
-pub fn regionck_expr(fcx: @FnCtxt, e: &ast::Expr) {
+pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
     let mut rcx = Rcx { fcx: fcx, errors_reported: 0,
                          repeating_scope: e.id };
     let rcx = &mut rcx;
@@ -304,7 +304,7 @@ pub fn regionck_expr(fcx: @FnCtxt, e: &ast::Expr) {
     fcx.infcx().resolve_regions();
 }
 
-pub fn regionck_fn(fcx: @FnCtxt, blk: &ast::Block) {
+pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
     let mut rcx = Rcx { fcx: fcx, errors_reported: 0,
                          repeating_scope: blk.id };
     let rcx = &mut rcx;
@@ -315,7 +315,7 @@ pub fn regionck_fn(fcx: @FnCtxt, blk: &ast::Block) {
     fcx.infcx().resolve_regions();
 }
 
-impl Visitor<()> for Rcx {
+impl<'a> Visitor<()> for Rcx<'a> {
     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
     // However, right now we run into an issue whereby some free
     // regions are not properly related if they appear within the
diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs
index c8a126382f4..45eab7c7e62 100644
--- a/src/librustc/middle/typeck/check/regionmanip.rs
+++ b/src/librustc/middle/typeck/check/regionmanip.rs
@@ -22,7 +22,7 @@ use util::ppaux;
 // Helper functions related to manipulating region types.
 
 pub fn replace_late_bound_regions_in_fn_sig(
-        tcx: ty::ctxt,
+        tcx: &ty::ctxt,
         fn_sig: &ty::FnSig,
         mapf: |ty::BoundRegion| -> ty::Region)
         -> (HashMap<ty::BoundRegion,ty::Region>, ty::FnSig) {
@@ -45,7 +45,7 @@ pub fn replace_late_bound_regions_in_fn_sig(
     (map, fn_sig)
 }
 
-pub fn relate_nested_regions(tcx: ty::ctxt,
+pub fn relate_nested_regions(tcx: &ty::ctxt,
                              opt_region: Option<ty::Region>,
                              ty: ty::t,
                              relate_op: |ty::Region, ty::Region|) {
@@ -85,8 +85,8 @@ pub fn relate_nested_regions(tcx: ty::ctxt,
     rr.fold_ty(ty);
 
     struct RegionRelator<'a> {
-        tcx: ty::ctxt,
-        stack: Vec<ty::Region> ,
+        tcx: &'a ty::ctxt,
+        stack: Vec<ty::Region>,
         relate_op: 'a |ty::Region, ty::Region|,
     }
 
@@ -95,7 +95,7 @@ pub fn relate_nested_regions(tcx: ty::ctxt,
     // well.
 
     impl<'a> TypeFolder for RegionRelator<'a> {
-        fn tcx(&self) -> ty::ctxt {
+        fn tcx<'a>(&'a self) -> &'a ty::ctxt {
             self.tcx
         }
 
@@ -134,7 +134,7 @@ pub fn relate_nested_regions(tcx: ty::ctxt,
     }
 }
 
-pub fn relate_free_regions(tcx: ty::ctxt, fn_sig: &ty::FnSig) {
+pub fn relate_free_regions(tcx: &ty::ctxt, fn_sig: &ty::FnSig) {
     /*!
      * This function populates the region map's `free_region_map`.
      * It walks over the transformed self type and argument types
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 3fee30bc498..30bbdabbc71 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -66,12 +66,12 @@ use syntax::visit::Visitor;
 /// A vtable context includes an inference context, a crate context, and a
 /// callback function to call in case of type error.
 pub struct VtableContext<'a> {
-    infcx: &'a infer::InferCtxt,
+    infcx: &'a infer::InferCtxt<'a>,
     param_env: &'a ty::ParameterEnvironment,
 }
 
 impl<'a> VtableContext<'a> {
-    pub fn tcx(&self) -> ty::ctxt { self.infcx.tcx }
+    pub fn tcx(&self) -> &'a ty::ctxt { self.infcx.tcx }
 }
 
 fn has_trait_bounds(type_param_defs: &[ty::TypeParameterDef]) -> bool {
@@ -726,7 +726,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
     }
 }
 
-pub fn resolve_impl(tcx: ty::ctxt,
+pub fn resolve_impl(tcx: &ty::ctxt,
                     impl_item: &ast::Item,
                     impl_generics: &ty::Generics,
                     impl_trait_ref: &ty::TraitRef) {
@@ -783,7 +783,7 @@ pub fn resolve_impl(tcx: ty::ctxt,
 
 /// Resolve vtables for a method call after typeck has finished.
 /// Used by trans to monomorphize artificial method callees (e.g. drop).
-pub fn trans_resolve_method(tcx: ty::ctxt, id: ast::NodeId,
+pub fn trans_resolve_method(tcx: &ty::ctxt, id: ast::NodeId,
                             substs: &ty::substs) -> Option<vtable_res> {
     let generics = ty::lookup_item_type(tcx, ast_util::local_def(id)).generics;
     let type_param_defs = generics.type_param_defs.deref();
@@ -803,7 +803,7 @@ pub fn trans_resolve_method(tcx: ty::ctxt, id: ast::NodeId,
     }
 }
 
-impl<'a> visit::Visitor<()> for &'a FnCtxt {
+impl<'a, 'b> visit::Visitor<()> for &'a FnCtxt<'b> {
     fn visit_expr(&mut self, ex: &ast::Expr, _: ()) {
         early_resolve_expr(ex, *self, false);
         visit::walk_expr(self, ex, ());
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 7659842aff4..1c03328bcea 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -35,7 +35,7 @@ use syntax::print::pprust::pat_to_str;
 use syntax::visit;
 use syntax::visit::Visitor;
 
-fn resolve_type_vars_in_type(fcx: @FnCtxt, sp: Span, typ: ty::t)
+fn resolve_type_vars_in_type(fcx: &FnCtxt, sp: Span, typ: ty::t)
                           -> Option<ty::t> {
     if !ty::type_needs_infer(typ) { return Some(typ); }
     match resolve_type(fcx.infcx(), typ, resolve_all | force_all) {
@@ -53,7 +53,7 @@ fn resolve_type_vars_in_type(fcx: @FnCtxt, sp: Span, typ: ty::t)
     }
 }
 
-fn resolve_type_vars_in_types(fcx: @FnCtxt, sp: Span, tys: &[ty::t])
+fn resolve_type_vars_in_types(fcx: &FnCtxt, sp: Span, tys: &[ty::t])
                           -> Vec<ty::t> {
     tys.iter().map(|t| {
         match resolve_type_vars_in_type(fcx, sp, *t) {
@@ -101,7 +101,7 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall
     }
 }
 
-fn resolve_vtable_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
+fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, id: ast::NodeId) {
     // Resolve any vtable map entry
     match fcx.inh.vtable_map.borrow().get().find_copy(&id) {
         Some(origins) => {
@@ -113,12 +113,12 @@ fn resolve_vtable_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
         None => {}
     }
 
-    fn resolve_origins(fcx: @FnCtxt, sp: Span,
+    fn resolve_origins(fcx: &FnCtxt, sp: Span,
                        vtbls: vtable_res) -> vtable_res {
         @vtbls.map(|os| @os.map(|o| resolve_origin(fcx, sp, o)))
     }
 
-    fn resolve_origin(fcx: @FnCtxt,
+    fn resolve_origin(fcx: &FnCtxt,
                       sp: Span,
                       origin: &vtable_origin) -> vtable_origin {
         match origin {
@@ -254,8 +254,8 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
     }
 }
 
-struct WbCtxt {
-    fcx: @FnCtxt,
+struct WbCtxt<'a> {
+    fcx: &'a FnCtxt<'a>,
 
     // As soon as we hit an error we have to stop resolving
     // the entire function.
@@ -338,7 +338,7 @@ fn visit_item(_item: &ast::Item, _wbcx: &mut WbCtxt) {
     // Ignore items
 }
 
-impl Visitor<()> for WbCtxt {
+impl<'a> Visitor<()> for WbCtxt<'a> {
     fn visit_item(&mut self, i: &ast::Item, _: ()) { visit_item(i, self); }
     fn visit_stmt(&mut self, s: &ast::Stmt, _: ()) { visit_stmt(s, self); }
     fn visit_expr(&mut self, ex:&ast::Expr, _: ()) { visit_expr(ex, self); }
@@ -383,7 +383,7 @@ fn resolve_upvar_borrow_map(wbcx: &mut WbCtxt) {
     }
 }
 
-pub fn resolve_type_vars_in_expr(fcx: @FnCtxt, e: &ast::Expr) -> bool {
+pub fn resolve_type_vars_in_expr(fcx: &FnCtxt, e: &ast::Expr) -> bool {
     let mut wbcx = WbCtxt { fcx: fcx, success: true };
     let wbcx = &mut wbcx;
     wbcx.visit_expr(e, ());
@@ -391,7 +391,7 @@ pub fn resolve_type_vars_in_expr(fcx: @FnCtxt, e: &ast::Expr) -> bool {
     return wbcx.success;
 }
 
-pub fn resolve_type_vars_in_fn(fcx: @FnCtxt, decl: &ast::FnDecl,
+pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, decl: &ast::FnDecl,
                                blk: &ast::Block) -> bool {
     let mut wbcx = WbCtxt { fcx: fcx, success: true };
     let wbcx = &mut wbcx;
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index ca5befa8d4e..894c70c7b61 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -144,13 +144,13 @@ fn get_base_type_def_id(inference_context: &InferCtxt,
     }
 }
 
-struct CoherenceChecker {
-    crate_context: @CrateCtxt,
-    inference_context: InferCtxt,
+struct CoherenceChecker<'a> {
+    crate_context: &'a CrateCtxt<'a>,
+    inference_context: InferCtxt<'a>,
 }
 
 struct CoherenceCheckVisitor<'a> {
-    cc: &'a CoherenceChecker
+    cc: &'a CoherenceChecker<'a>
 }
 
 impl<'a> visit::Visitor<()> for CoherenceCheckVisitor<'a> {
@@ -176,7 +176,7 @@ impl<'a> visit::Visitor<()> for CoherenceCheckVisitor<'a> {
     }
 }
 
-struct PrivilegedScopeVisitor<'a> { cc: &'a CoherenceChecker }
+struct PrivilegedScopeVisitor<'a> { cc: &'a CoherenceChecker<'a> }
 
 impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> {
     fn visit_item(&mut self, item: &Item, _: ()) {
@@ -189,7 +189,7 @@ impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> {
             ItemImpl(_, None, ast_ty, _) => {
                 if !self.cc.ast_type_is_defined_in_local_crate(ast_ty) {
                     // This is an error.
-                    let session = self.cc.crate_context.tcx.sess;
+                    let session = &self.cc.crate_context.tcx.sess;
                     session.span_err(item.span,
                                      "cannot associate methods with a type outside the \
                                      crate the type is defined in; define and implement \
@@ -210,7 +210,7 @@ impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> {
                         self.cc.trait_ref_to_trait_def_id(trait_ref);
 
                     if trait_def_id.krate != LOCAL_CRATE {
-                        let session = self.cc.crate_context.tcx.sess;
+                        let session = &self.cc.crate_context.tcx.sess;
                         session.span_err(item.span,
                                 "cannot provide an extension implementation \
                                 where both trait and type are not defined in this crate");
@@ -226,14 +226,7 @@ impl<'a> visit::Visitor<()> for PrivilegedScopeVisitor<'a> {
     }
 }
 
-impl CoherenceChecker {
-    fn new(crate_context: @CrateCtxt) -> CoherenceChecker {
-        CoherenceChecker {
-            crate_context: crate_context,
-            inference_context: new_infer_ctxt(crate_context.tcx),
-        }
-    }
-
+impl<'a> CoherenceChecker<'a> {
     fn check(&self, krate: &Crate) {
         // Check implementations and traits. This populates the tables
         // containing the inherent methods and extension methods. It also
@@ -274,7 +267,7 @@ impl CoherenceChecker {
                                        item.span,
                                        self_type.ty) {
                 None => {
-                    let session = self.crate_context.tcx.sess;
+                    let session = &self.crate_context.tcx.sess;
                     session.span_err(item.span,
                                      "no base type found for inherent implementation; \
                                       implement a trait or new type instead");
@@ -447,7 +440,7 @@ impl CoherenceChecker {
                             implementation_b);
 
                     if self.polytypes_unify(polytype_a.clone(), polytype_b) {
-                        let session = self.crate_context.tcx.sess;
+                        let session = &self.crate_context.tcx.sess;
                         session.span_err(
                             self.span_of_impl(implementation_a),
                             format!("conflicting implementations for trait `{}`",
@@ -457,7 +450,7 @@ impl CoherenceChecker {
                             session.span_note(self.span_of_impl(implementation_b),
                                               "note conflicting implementation here");
                         } else {
-                            let crate_store = self.crate_context.tcx.sess.cstore;
+                            let crate_store = &self.crate_context.tcx.sess.cstore;
                             let cdata = crate_store.get_crate_data(implementation_b.did.krate);
                             session.note(
                                 "conflicting implementation in crate `" + cdata.name + "`");
@@ -475,7 +468,7 @@ impl CoherenceChecker {
             return;
         }
 
-        let crate_store = self.crate_context.tcx.sess.cstore;
+        let crate_store = &self.crate_context.tcx.sess.cstore;
         csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| {
             let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id);
             let _ = lookup_item_type(self.crate_context.tcx, implementation.did);
@@ -689,7 +682,7 @@ impl CoherenceChecker {
     fn add_external_crates(&self) {
         let mut impls_seen = HashSet::new();
 
-        let crate_store = self.crate_context.tcx.sess.cstore;
+        let crate_store = &self.crate_context.tcx.sess.cstore;
         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
             each_impl(crate_store, crate_number, |def_id| {
                 assert_eq!(crate_number, def_id.krate);
@@ -762,7 +755,7 @@ impl CoherenceChecker {
     }
 }
 
-pub fn make_substs_for_receiver_types(tcx: ty::ctxt,
+pub fn make_substs_for_receiver_types(tcx: &ty::ctxt,
                                       impl_id: ast::DefId,
                                       trait_ref: &ty::TraitRef,
                                       method: &ty::Method)
@@ -810,7 +803,7 @@ pub fn make_substs_for_receiver_types(tcx: ty::ctxt,
     };
 }
 
-fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
+fn subst_receiver_types_in_method_ty(tcx: &ty::ctxt,
                                      impl_id: ast::DefId,
                                      trait_ref: &ty::TraitRef,
                                      new_def_id: ast::DefId,
@@ -838,6 +831,9 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
     )
 }
 
-pub fn check_coherence(crate_context: @CrateCtxt, krate: &Crate) {
-    CoherenceChecker::new(crate_context).check(krate);
+pub fn check_coherence(crate_context: &CrateCtxt, krate: &Crate) {
+    CoherenceChecker {
+        crate_context: crate_context,
+        inference_context: new_infer_ctxt(crate_context.tcx),
+    }.check(krate);
 }
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 0c6aeda4258..fc6b4c91b4e 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -61,11 +61,11 @@ use syntax::print::pprust::{path_to_str};
 use syntax::visit;
 use syntax::opt_vec::OptVec;
 
-struct CollectItemTypesVisitor {
-    ccx: @CrateCtxt
+struct CollectItemTypesVisitor<'a> {
+    ccx: &'a CrateCtxt<'a>
 }
 
-impl visit::Visitor<()> for CollectItemTypesVisitor {
+impl<'a> visit::Visitor<()> for CollectItemTypesVisitor<'a> {
     fn visit_item(&mut self, i: &ast::Item, _: ()) {
         convert(self.ccx, i);
         visit::walk_item(self, i, ());
@@ -76,7 +76,7 @@ impl visit::Visitor<()> for CollectItemTypesVisitor {
     }
 }
 
-pub fn collect_item_types(ccx: @CrateCtxt, krate: &ast::Crate) {
+pub fn collect_item_types(ccx: &CrateCtxt, krate: &ast::Crate) {
     fn collect_intrinsic_type(ccx: &CrateCtxt,
                               lang_item: ast::DefId) {
         let ty::ty_param_bounds_and_ty { ty: ty, .. } =
@@ -100,14 +100,14 @@ pub trait ToTy {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
 }
 
-impl ToTy for CrateCtxt {
+impl<'a> ToTy for CrateCtxt<'a> {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
         ast_ty_to_ty(self, rs, ast_ty)
     }
 }
 
-impl AstConv for CrateCtxt {
-    fn tcx(&self) -> ty::ctxt { self.tcx }
+impl<'a> AstConv for CrateCtxt<'a> {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
 
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
         if id.krate != ast::LOCAL_CRATE {
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index 32b6da40b08..f6894f44099 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -70,7 +70,7 @@ use syntax::opt_vec;
 use syntax::abi::AbiSet;
 
 pub trait Combine {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt;
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a>;
     fn tag(&self) -> ~str;
     fn a_is_expected(&self) -> bool;
     fn trace(&self) -> TypeTrace;
@@ -331,7 +331,7 @@ pub trait Combine {
 }
 
 pub struct CombineFields<'a> {
-    infcx: &'a InferCtxt,
+    infcx: &'a InferCtxt<'a>,
     a_is_expected: bool,
     trace: TypeTrace,
 }
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index a01fd4d86ad..b0cd5e361e9 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -150,7 +150,7 @@ trait ErrorReportingHelpers {
                                 generics: ast::Generics);
 }
 
-impl ErrorReporting for InferCtxt {
+impl<'a> ErrorReporting for InferCtxt<'a> {
     fn report_region_errors(&self,
                             errors: &OptVec<RegionResolutionError>) {
         let p_errors = self.process_errors(errors);
@@ -255,7 +255,7 @@ impl ErrorReporting for InferCtxt {
             scope_id: ast::NodeId
         }
 
-        fn free_regions_from_same_fn(tcx: ty::ctxt,
+        fn free_regions_from_same_fn(tcx: &ty::ctxt,
                                      sub: Region,
                                      sup: Region)
                                      -> Option<FreeRegionsFromSameFn> {
@@ -672,7 +672,7 @@ impl ErrorReporting for InferCtxt {
 }
 
 struct Rebuilder<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     fn_decl: ast::P<ast::FnDecl>,
     generics: &'a ast::Generics,
     same_regions: &'a [SameRegions],
@@ -682,7 +682,7 @@ struct Rebuilder<'a> {
 }
 
 impl<'a> Rebuilder<'a> {
-    fn new(tcx: ty::ctxt,
+    fn new(tcx: &'a ty::ctxt,
            fn_decl: ast::P<ast::FnDecl>,
            generics: &'a ast::Generics,
            same_regions: &'a [SameRegions])
@@ -1006,7 +1006,7 @@ impl<'a> Rebuilder<'a> {
     }
 }
 
-impl ErrorReportingHelpers for InferCtxt {
+impl<'a> ErrorReportingHelpers for InferCtxt<'a> {
     fn give_expl_lifetime_param(&self,
                                 inputs: Vec<ast::Arg>,
                                 output: ast::P<ast::Ty>,
diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs
index ac73c308025..e846e3621bd 100644
--- a/src/librustc/middle/typeck/infer/glb.rs
+++ b/src/librustc/middle/typeck/infer/glb.rs
@@ -35,7 +35,7 @@ impl<'f> Glb<'f> {
 }
 
 impl<'f> Combine for Glb<'f> {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt { self.get_ref().infcx }
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { ~"glb" }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
     fn trace(&self) -> TypeTrace { self.get_ref().trace }
diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs
index 7d772065da6..e63ad7322b9 100644
--- a/src/librustc/middle/typeck/infer/lub.rs
+++ b/src/librustc/middle/typeck/infer/lub.rs
@@ -38,7 +38,7 @@ impl<'f> Lub<'f> {
 }
 
 impl<'f> Combine for Lub<'f> {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt { self.get_ref().infcx }
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { ~"lub" }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
     fn trace(&self) -> TypeTrace { self.get_ref().trace }
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index e10aa8159d0..07948477800 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -75,8 +75,8 @@ pub type ures = cres<()>; // "unify result"
 pub type fres<T> = Result<T, fixup_err>; // "fixup result"
 pub type CoerceResult = cres<Option<@ty::AutoAdjustment>>;
 
-pub struct InferCtxt {
-    tcx: ty::ctxt,
+pub struct InferCtxt<'a> {
+    tcx: &'a ty::ctxt,
 
     // We instantiate ValsAndBindings with bounds<ty::t> because the
     // types that might instantiate a general type variable have an
@@ -95,7 +95,7 @@ pub struct InferCtxt {
     float_var_counter: Cell<uint>,
 
     // For region variables.
-    region_vars: RegionVarBindings,
+    region_vars: RegionVarBindings<'a>,
 }
 
 /// Why did we require that the two types be related?
@@ -267,7 +267,7 @@ fn new_ValsAndBindings<V:Clone,T:Clone>() -> ValsAndBindings<V, T> {
     }
 }
 
-pub fn new_infer_ctxt(tcx: ty::ctxt) -> InferCtxt {
+pub fn new_infer_ctxt<'a>(tcx: &'a ty::ctxt) -> InferCtxt<'a> {
     InferCtxt {
         tcx: tcx,
 
@@ -510,7 +510,7 @@ pub struct Snapshot {
     region_vars_snapshot: uint,
 }
 
-impl InferCtxt {
+impl<'a> InferCtxt<'a> {
     pub fn combine_fields<'a>(&'a self, a_is_expected: bool, trace: TypeTrace)
                               -> CombineFields<'a> {
         CombineFields {infcx: self,
@@ -609,7 +609,7 @@ fn next_simple_var<V:Clone,T:Clone>(counter: &mut uint,
     return id;
 }
 
-impl InferCtxt {
+impl<'a> InferCtxt<'a> {
     pub fn next_ty_var_id(&self) -> TyVid {
         let id = self.ty_var_counter.get();
         self.ty_var_counter.set(id + 1);
@@ -840,7 +840,7 @@ impl InferCtxt {
     }
 }
 
-pub fn fold_regions_in_sig(tcx: ty::ctxt,
+pub fn fold_regions_in_sig(tcx: &ty::ctxt,
                            fn_sig: &ty::FnSig,
                            fldr: |r: ty::Region| -> ty::Region)
                            -> ty::FnSig {
@@ -854,7 +854,7 @@ impl TypeTrace {
 }
 
 impl Repr for TypeTrace {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("TypeTrace({})", self.origin.repr(tcx))
     }
 }
@@ -874,7 +874,7 @@ impl TypeOrigin {
 }
 
 impl Repr for TypeOrigin {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             MethodCompatCheck(a) => format!("MethodCompatCheck({})", a.repr(tcx)),
             ExprAssignable(a) => format!("ExprAssignable({})", a.repr(tcx)),
@@ -911,7 +911,7 @@ impl SubregionOrigin {
 }
 
 impl Repr for SubregionOrigin {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             Subtype(a) => format!("Subtype({})", a.repr(tcx)),
             InfStackClosure(a) => format!("InfStackClosure({})", a.repr(tcx)),
@@ -954,7 +954,7 @@ impl RegionVariableOrigin {
 }
 
 impl Repr for RegionVariableOrigin {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             MiscVariable(a) => format!("MiscVariable({})", a.repr(tcx)),
             PatternRegion(a) => format!("PatternRegion({})", a.repr(tcx)),
diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs
index a90c89db49f..415367eea62 100644
--- a/src/librustc/middle/typeck/infer/region_inference/mod.rs
+++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs
@@ -123,9 +123,9 @@ impl SameRegions {
 
 pub type CombineMap = HashMap<TwoRegions, RegionVid>;
 
-pub struct RegionVarBindings {
-    tcx: ty::ctxt,
-    var_origins: RefCell<Vec<RegionVariableOrigin> >,
+pub struct RegionVarBindings<'a> {
+    tcx: &'a ty::ctxt,
+    var_origins: RefCell<Vec<RegionVariableOrigin>>,
     constraints: RefCell<HashMap<Constraint, SubregionOrigin>>,
     lubs: RefCell<CombineMap>,
     glbs: RefCell<CombineMap>,
@@ -147,7 +147,7 @@ pub struct RegionVarBindings {
     values: RefCell<Option<Vec<VarValue> >>,
 }
 
-pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings {
+pub fn RegionVarBindings<'a>(tcx: &'a ty::ctxt) -> RegionVarBindings<'a> {
     RegionVarBindings {
         tcx: tcx,
         var_origins: RefCell::new(Vec::new()),
@@ -161,7 +161,7 @@ pub fn RegionVarBindings(tcx: ty::ctxt) -> RegionVarBindings {
     }
 }
 
-impl RegionVarBindings {
+impl<'a> RegionVarBindings<'a> {
     pub fn in_snapshot(&self) -> bool {
         let undo_log = self.undo_log.borrow();
         undo_log.get().len() > 0
@@ -572,7 +572,7 @@ impl RegionVarBindings {
     }
 }
 
-impl RegionVarBindings {
+impl<'a> RegionVarBindings<'a> {
     fn is_subregion_of(&self, sub: Region, sup: Region) -> bool {
         self.tcx.region_maps.is_subregion_of(sub, sup)
     }
@@ -814,7 +814,7 @@ struct RegionAndOrigin {
 
 type RegionGraph = graph::Graph<(), Constraint>;
 
-impl RegionVarBindings {
+impl<'a> RegionVarBindings<'a> {
     fn infer_variable_values(&self,
                              errors: &mut OptVec<RegionResolutionError>)
                              -> Vec<VarValue> {
@@ -1359,7 +1359,7 @@ impl RegionVarBindings {
 }
 
 impl Repr for Constraint {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             ConstrainVarSubVar(a, b) => format!("ConstrainVarSubVar({}, {})",
                                              a.repr(tcx), b.repr(tcx)),
diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs
index d4ee567ba41..f91e20a649b 100644
--- a/src/librustc/middle/typeck/infer/resolve.rs
+++ b/src/librustc/middle/typeck/infer/resolve.rs
@@ -81,7 +81,7 @@ pub static resolve_and_force_all_but_regions: uint =
     (resolve_all | force_all) & not_regions;
 
 pub struct ResolveState<'a> {
-    infcx: &'a InferCtxt,
+    infcx: &'a InferCtxt<'a>,
     modes: uint,
     err: Option<fixup_err>,
     v_seen: Vec<TyVid> ,
@@ -99,7 +99,7 @@ pub fn resolver<'a>(infcx: &'a InferCtxt, modes: uint) -> ResolveState<'a> {
 }
 
 impl<'a> ty_fold::TypeFolder for ResolveState<'a> {
-    fn tcx(&self) -> ty::ctxt {
+    fn tcx<'a>(&'a self) -> &'a ty::ctxt {
         self.infcx.tcx
     }
 
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 2233e680bc9..ef17a593654 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -34,7 +34,7 @@ impl<'f> Sub<'f> {
 }
 
 impl<'f> Combine for Sub<'f> {
-    fn infcx<'a>(&'a self) -> &'a InferCtxt { self.get_ref().infcx }
+    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { ~"sub" }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
     fn trace(&self) -> TypeTrace { self.get_ref().trace }
diff --git a/src/librustc/middle/typeck/infer/unify.rs b/src/librustc/middle/typeck/infer/unify.rs
index b58fa905ca4..57a08d211c7 100644
--- a/src/librustc/middle/typeck/infer/unify.rs
+++ b/src/librustc/middle/typeck/infer/unify.rs
@@ -61,7 +61,7 @@ pub trait UnifyInferCtxtMethods {
              -> (V, uint);
 }
 
-impl UnifyInferCtxtMethods for InferCtxt {
+impl<'a> UnifyInferCtxtMethods for InferCtxt<'a> {
     fn get<T:Clone,
            V:Clone + Eq + Vid + UnifyVid<T>>(
            &self,
@@ -80,7 +80,7 @@ impl UnifyInferCtxtMethods for InferCtxt {
         return helper(tcx, vb.get(), vid);
 
         fn helper<T:Clone, V:Clone+Eq+Vid>(
-            tcx: ty::ctxt,
+            tcx: &ty::ctxt,
             vb: &mut ValsAndBindings<V,T>,
             vid: V) -> Node<V, T>
         {
@@ -200,7 +200,7 @@ pub trait InferCtxtMethods {
                     -> ures;
 }
 
-impl InferCtxtMethods for InferCtxt {
+impl<'a> InferCtxtMethods for InferCtxt<'a> {
     fn simple_vars<T:Clone + Eq + InferStr + SimplyUnifiable,
                    V:Clone + Eq + Vid + ToStr + UnifyVid<Option<T>>>(
                    &self,
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 726f8904898..bf34e7c1351 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -200,7 +200,7 @@ pub enum vtable_origin {
 }
 
 impl Repr for vtable_origin {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
             vtable_static(def_id, ref tys, ref vtable_res) => {
                 format!("vtable_static({:?}:{}, {}, {})",
@@ -232,7 +232,7 @@ pub struct impl_res {
 }
 
 impl Repr for impl_res {
-    fn repr(&self, tcx: ty::ctxt) -> ~str {
+    fn repr(&self, tcx: &ty::ctxt) -> ~str {
         format!("impl_res \\{trait_vtables={}, self_vtables={}\\}",
              self.trait_vtables.repr(tcx),
              self.self_vtables.repr(tcx))
@@ -241,22 +241,22 @@ impl Repr for impl_res {
 
 pub type impl_vtable_map = RefCell<DefIdMap<impl_res>>;
 
-pub struct CrateCtxt {
+pub struct CrateCtxt<'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: resolve::TraitMap,
     method_map: MethodMap,
     vtable_map: vtable_map,
-    tcx: ty::ctxt
+    tcx: &'a ty::ctxt
 }
 
 // Functions that write types into the node type table
-pub fn write_ty_to_tcx(tcx: ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
+pub fn write_ty_to_tcx(tcx: &ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
     debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_str(tcx, ty));
     assert!(!ty::type_needs_infer(ty));
     let mut node_types = tcx.node_types.borrow_mut();
     node_types.get().insert(node_id as uint, ty);
 }
-pub fn write_substs_to_tcx(tcx: ty::ctxt,
+pub fn write_substs_to_tcx(tcx: &ty::ctxt,
                            node_id: ast::NodeId,
                            substs: Vec<ty::t> ) {
     if substs.len() > 0u {
@@ -268,7 +268,7 @@ pub fn write_substs_to_tcx(tcx: ty::ctxt,
         node_type_substs.get().insert(node_id, substs);
     }
 }
-pub fn write_tpt_to_tcx(tcx: ty::ctxt,
+pub fn write_tpt_to_tcx(tcx: &ty::ctxt,
                         node_id: ast::NodeId,
                         tpt: &ty::ty_param_substs_and_ty) {
     write_ty_to_tcx(tcx, node_id, tpt.ty);
@@ -277,7 +277,7 @@ pub fn write_tpt_to_tcx(tcx: ty::ctxt,
     }
 }
 
-pub fn lookup_def_tcx(tcx: ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
+pub fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
     let def_map = tcx.def_map.borrow();
     match def_map.get().find(&id) {
         Some(&x) => x,
@@ -300,7 +300,7 @@ pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
     }
 }
 
-pub fn require_same_types(tcx: ty::ctxt,
+pub fn require_same_types(tcx: &ty::ctxt,
                           maybe_infcx: Option<&infer::InferCtxt>,
                           t1_is_expected: bool,
                           span: Span,
@@ -457,12 +457,12 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
     }
 }
 
-pub fn check_crate(tcx: ty::ctxt,
+pub fn check_crate(tcx: &ty::ctxt,
                    trait_map: resolve::TraitMap,
                    krate: &ast::Crate)
                 -> (MethodMap, vtable_map) {
     let time_passes = tcx.sess.time_passes();
-    let ccx = @CrateCtxt {
+    let ccx = CrateCtxt {
         trait_map: trait_map,
         method_map: @RefCell::new(FnvHashMap::new()),
         vtable_map: @RefCell::new(NodeMap::new()),
@@ -470,7 +470,7 @@ pub fn check_crate(tcx: ty::ctxt,
     };
 
     time(time_passes, "type collecting", (), |_|
-        collect::collect_item_types(ccx, krate));
+        collect::collect_item_types(&ccx, krate));
 
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
@@ -480,12 +480,12 @@ pub fn check_crate(tcx: ty::ctxt,
          variance::infer_variance(tcx, krate));
 
     time(time_passes, "coherence checking", (), |_|
-        coherence::check_coherence(ccx, krate));
+        coherence::check_coherence(&ccx, krate));
 
     time(time_passes, "type checking", (), |_|
-        check::check_item_types(ccx, krate));
+        check::check_item_types(&ccx, krate));
 
-    check_for_entry_fn(ccx);
+    check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
     (ccx.method_map, ccx.vtable_map)
 }
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 3712f046358..468d97a8392 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -205,7 +205,7 @@ use syntax::visit;
 use syntax::visit::Visitor;
 use util::ppaux::Repr;
 
-pub fn infer_variance(tcx: ty::ctxt,
+pub fn infer_variance(tcx: &ty::ctxt,
                       krate: &ast::Crate) {
     let mut arena = arena::Arena::new();
     let terms_cx = determine_parameters_to_be_inferred(tcx, &mut arena, krate);
@@ -251,7 +251,7 @@ impl<'a> fmt::Show for VarianceTerm<'a> {
  */
 
 struct TermsContext<'a> {
-    tcx: ty::ctxt,
+    tcx: &'a ty::ctxt,
     arena: &'a Arena,
 
     empty_variances: @ty::ItemVariances,
@@ -274,7 +274,7 @@ struct InferredInfo<'a> {
     term: VarianceTermPtr<'a>,
 }
 
-fn determine_parameters_to_be_inferred<'a>(tcx: ty::ctxt,
+fn determine_parameters_to_be_inferred<'a>(tcx: &'a ty::ctxt,
                                            arena: &'a mut Arena,
                                            krate: &ast::Crate)
                                            -> TermsContext<'a> {
@@ -522,7 +522,7 @@ impl<'a> Visitor<()> for ConstraintContext<'a> {
 }
 
 impl<'a> ConstraintContext<'a> {
-    fn tcx(&self) -> ty::ctxt {
+    fn tcx(&self) -> &'a ty::ctxt {
         self.terms_cx.tcx
     }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 2f06ab67a3b..b3d3e59ea6b 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -35,15 +35,15 @@ use syntax::opt_vec::OptVec;
 
 /// Produces a string suitable for debugging output.
 pub trait Repr {
-    fn repr(&self, tcx: ctxt) -> ~str;
+    fn repr(&self, tcx: &ctxt) -> ~str;
 }
 
 /// Produces a string suitable for showing to the user.
 pub trait UserString {
-    fn user_string(&self, tcx: ctxt) -> ~str;
+    fn user_string(&self, tcx: &ctxt) -> ~str;
 }
 
-pub fn note_and_explain_region(cx: ctxt,
+pub fn note_and_explain_region(cx: &ctxt,
                                prefix: &str,
                                region: ty::Region,
                                suffix: &str) {
@@ -62,13 +62,13 @@ pub fn note_and_explain_region(cx: ctxt,
 
 /// Returns a string like "the block at 27:31" that attempts to explain a
 /// lifetime in a way it might plausibly be understood.
-pub fn explain_region(cx: ctxt, region: ty::Region) -> ~str {
+pub fn explain_region(cx: &ctxt, region: ty::Region) -> ~str {
   let (res, _) = explain_region_and_span(cx, region);
   return res;
 }
 
 
-pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
+pub fn explain_region_and_span(cx: &ctxt, region: ty::Region)
                             -> (~str, Option<Span>) {
     return match region {
       ReScope(node_id) => {
@@ -138,20 +138,19 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
       }
     };
 
-    fn explain_span(cx: ctxt, heading: &str, span: Span)
-        -> (~str, Option<Span>)
-    {
-        let lo = cx.sess.codemap.lookup_char_pos_adj(span.lo);
+    fn explain_span(cx: &ctxt, heading: &str, span: Span)
+        -> (~str, Option<Span>) {
+        let lo = cx.sess.codemap().lookup_char_pos_adj(span.lo);
         (format!("the {} at {}:{}", heading,
               lo.line, lo.col.to_uint()), Some(span))
     }
 }
 
-pub fn bound_region_ptr_to_str(cx: ctxt, br: BoundRegion) -> ~str {
+pub fn bound_region_ptr_to_str(cx: &ctxt, br: BoundRegion) -> ~str {
     bound_region_to_str(cx, "&", true, br)
 }
 
-pub fn bound_region_to_str(cx: ctxt,
+pub fn bound_region_to_str(cx: &ctxt,
                            prefix: &str, space: bool,
                            br: BoundRegion) -> ~str {
     let space_str = if space { " " } else { "" };
@@ -168,32 +167,32 @@ pub fn bound_region_to_str(cx: ctxt,
     }
 }
 
-pub fn ReScope_id_to_str(cx: ctxt, node_id: ast::NodeId) -> ~str {
+pub fn ReScope_id_to_str(cx: &ctxt, node_id: ast::NodeId) -> ~str {
     match cx.map.find(node_id) {
       Some(ast_map::NodeBlock(ref blk)) => {
         format!("<block at {}>",
-             cx.sess.codemap.span_to_str(blk.span))
+             cx.sess.codemap().span_to_str(blk.span))
       }
       Some(ast_map::NodeExpr(expr)) => {
         match expr.node {
           ast::ExprCall(..) => {
             format!("<call at {}>",
-                 cx.sess.codemap.span_to_str(expr.span))
+                 cx.sess.codemap().span_to_str(expr.span))
           }
           ast::ExprMatch(..) => {
             format!("<match at {}>",
-                 cx.sess.codemap.span_to_str(expr.span))
+                 cx.sess.codemap().span_to_str(expr.span))
           }
           ast::ExprAssignOp(..) |
           ast::ExprUnary(..) |
           ast::ExprBinary(..) |
           ast::ExprIndex(..) => {
             format!("<method at {}>",
-                 cx.sess.codemap.span_to_str(expr.span))
+                 cx.sess.codemap().span_to_str(expr.span))
           }
           _ => {
             format!("<expression at {}>",
-                 cx.sess.codemap.span_to_str(expr.span))
+                 cx.sess.codemap().span_to_str(expr.span))
           }
         }
       }
@@ -207,11 +206,11 @@ pub fn ReScope_id_to_str(cx: ctxt, node_id: ast::NodeId) -> ~str {
 // In general, if you are giving a region error message,
 // you should use `explain_region()` or, better yet,
 // `note_and_explain_region()`
-pub fn region_ptr_to_str(cx: ctxt, region: Region) -> ~str {
+pub fn region_ptr_to_str(cx: &ctxt, region: Region) -> ~str {
     region_to_str(cx, "&", true, region)
 }
 
-pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~str {
+pub fn region_to_str(cx: &ctxt, prefix: &str, space: bool, region: Region) -> ~str {
     let space_str = if space { " " } else { "" };
 
     if cx.sess.verbose() {
@@ -243,16 +242,16 @@ pub fn mutability_to_str(m: ast::Mutability) -> ~str {
     }
 }
 
-pub fn mt_to_str(cx: ctxt, m: &mt) -> ~str {
+pub fn mt_to_str(cx: &ctxt, m: &mt) -> ~str {
     mt_to_str_wrapped(cx, "", m, "")
 }
 
-pub fn mt_to_str_wrapped(cx: ctxt, before: &str, m: &mt, after: &str) -> ~str {
+pub fn mt_to_str_wrapped(cx: &ctxt, before: &str, m: &mt, after: &str) -> ~str {
     let mstr = mutability_to_str(m.mutbl);
     return format!("{}{}{}{}", mstr, before, ty_to_str(cx, m.ty), after);
 }
 
-pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
+pub fn vstore_to_str(cx: &ctxt, vs: ty::vstore) -> ~str {
     match vs {
       ty::vstore_fixed(n) => format!("{}", n),
       ty::vstore_uniq => ~"~",
@@ -260,14 +259,14 @@ pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
     }
 }
 
-pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str {
+pub fn trait_store_to_str(cx: &ctxt, s: ty::TraitStore) -> ~str {
     match s {
       ty::UniqTraitStore => ~"~",
       ty::RegionTraitStore(r) => region_ptr_to_str(cx, r)
     }
 }
 
-pub fn vstore_ty_to_str(cx: ctxt, mt: &mt, vs: ty::vstore) -> ~str {
+pub fn vstore_ty_to_str(cx: &ctxt, mt: &mt, vs: ty::vstore) -> ~str {
     match vs {
         ty::vstore_fixed(_) => {
             format!("[{}, .. {}]", mt_to_str(cx, mt), vstore_to_str(cx, vs))
@@ -283,26 +282,26 @@ pub fn vec_map_to_str<T>(ts: &[T], f: |t: &T| -> ~str) -> ~str {
     format!("[{}]", tstrs.connect(", "))
 }
 
-pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
+pub fn tys_to_str(cx: &ctxt, ts: &[t]) -> ~str {
     vec_map_to_str(ts, |t| ty_to_str(cx, *t))
 }
 
-pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
+pub fn fn_sig_to_str(cx: &ctxt, typ: &ty::FnSig) -> ~str {
     format!("fn{}{} -> {}",
             typ.binder_id,
             typ.inputs.repr(cx),
             typ.output.repr(cx))
 }
 
-pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
+pub fn trait_ref_to_str(cx: &ctxt, trait_ref: &ty::TraitRef) -> ~str {
     trait_ref.user_string(cx)
 }
 
-pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
-    fn fn_input_to_str(cx: ctxt, input: ty::t) -> ~str {
+pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str {
+    fn fn_input_to_str(cx: &ctxt, input: ty::t) -> ~str {
         ty_to_str(cx, input)
     }
-    fn bare_fn_to_str(cx: ctxt,
+    fn bare_fn_to_str(cx: &ctxt,
                       purity: ast::Purity,
                       abis: AbiSet,
                       ident: Option<ast::Ident>,
@@ -336,7 +335,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
 
         return s;
     }
-    fn closure_to_str(cx: ctxt, cty: &ty::ClosureTy) -> ~str {
+    fn closure_to_str(cx: &ctxt, cty: &ty::ClosureTy) -> ~str {
         let is_proc =
             (cty.sigil, cty.onceness) == (ast::OwnedSigil, ast::Once);
         let is_borrowed_closure = cty.sigil == ast::BorrowedSigil;
@@ -402,7 +401,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
 
         return s;
     }
-    fn push_sig_to_str(cx: ctxt,
+    fn push_sig_to_str(cx: &ctxt,
                        s: &mut ~str,
                        bra: char,
                        ket: char,
@@ -501,7 +500,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
     }
 }
 
-pub fn parameterized(cx: ctxt,
+pub fn parameterized(cx: &ctxt,
                      base: &str,
                      regions: &ty::RegionSubsts,
                      tps: &[ty::t],
@@ -554,14 +553,14 @@ pub fn parameterized(cx: ctxt,
     }
 }
 
-pub fn ty_to_short_str(cx: ctxt, typ: t) -> ~str {
+pub fn ty_to_short_str(cx: &ctxt, typ: t) -> ~str {
     let mut s = encoder::encoded_ty(cx, typ);
     if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); }
     return s;
 }
 
 impl<T:Repr> Repr for Option<T> {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match self {
             &None => ~"None",
             &Some(ref t) => t.repr(tcx),
@@ -570,7 +569,7 @@ impl<T:Repr> Repr for Option<T> {
 }
 
 impl<T:Repr,U:Repr> Repr for Result<T,U> {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match self {
             &Ok(ref t) => t.repr(tcx),
             &Err(ref u) => format!("Err({})", u.repr(tcx))
@@ -579,35 +578,35 @@ impl<T:Repr,U:Repr> Repr for Result<T,U> {
 }
 
 impl Repr for () {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         ~"()"
     }
 }
 
 impl<T:Repr> Repr for @T {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         (&**self).repr(tcx)
     }
 }
 
 impl<T:Repr> Repr for ~T {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         (&**self).repr(tcx)
     }
 }
 
-fn repr_vec<T:Repr>(tcx: ctxt, v: &[T]) -> ~str {
+fn repr_vec<T:Repr>(tcx: &ctxt, v: &[T]) -> ~str {
     vec_map_to_str(v, |t| t.repr(tcx))
 }
 
 impl<'a, T:Repr> Repr for &'a [T] {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         repr_vec(tcx, *self)
     }
 }
 
 impl<T:Repr> Repr for OptVec<T> {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match *self {
             opt_vec::Empty => ~"[]",
             opt_vec::Vec(ref v) => repr_vec(tcx, v.as_slice())
@@ -618,13 +617,13 @@ impl<T:Repr> Repr for OptVec<T> {
 // This is necessary to handle types like Option<~[T]>, for which
 // autoderef cannot convert the &[T] handler
 impl<T:Repr> Repr for Vec<T> {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         repr_vec(tcx, self.as_slice())
     }
 }
 
 impl Repr for ty::TypeParameterDef {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("TypeParameterDef({:?}, {})",
                 self.def_id,
                 self.bounds.repr(tcx))
@@ -632,7 +631,7 @@ impl Repr for ty::TypeParameterDef {
 }
 
 impl Repr for ty::RegionParameterDef {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("RegionParameterDef({}, {:?})",
                 token::get_name(self.name),
                 self.def_id)
@@ -640,13 +639,13 @@ impl Repr for ty::RegionParameterDef {
 }
 
 impl Repr for ty::t {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         ty_to_str(tcx, *self)
     }
 }
 
 impl Repr for ty::substs {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("substs(regions={}, self_ty={}, tps={})",
              self.regions.repr(tcx),
              self.self_ty.repr(tcx),
@@ -655,7 +654,7 @@ impl Repr for ty::substs {
 }
 
 impl Repr for ty::RegionSubsts {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match *self {
             ty::ErasedRegions => ~"erased",
             ty::NonerasedRegions(ref regions) => regions.repr(tcx)
@@ -664,7 +663,7 @@ impl Repr for ty::RegionSubsts {
 }
 
 impl Repr for ty::ParamBounds {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         let mut res = Vec::new();
         for b in self.builtin_bounds.iter() {
             res.push(match b {
@@ -683,25 +682,25 @@ impl Repr for ty::ParamBounds {
 }
 
 impl Repr for ty::TraitRef {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         trait_ref_to_str(tcx, self)
     }
 }
 
 impl Repr for ast::Expr {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("expr({}: {})", self.id, pprust::expr_to_str(self))
     }
 }
 
 impl Repr for ast::Item {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("item({})", tcx.map.node_to_str(self.id))
     }
 }
 
 impl Repr for ast::Stmt {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("stmt({}: {})",
                 ast_util::stmt_id(self),
                 pprust::stmt_to_str(self))
@@ -709,7 +708,7 @@ impl Repr for ast::Stmt {
 }
 
 impl Repr for ast::Pat {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("pat({}: {})",
              self.id,
              pprust::pat_to_str(self))
@@ -717,7 +716,7 @@ impl Repr for ast::Pat {
 }
 
 impl Repr for ty::BoundRegion {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match *self {
             ty::BrAnon(id) => format!("BrAnon({})", id),
             ty::BrNamed(id, name) => format!("BrNamed({}, {})",
@@ -729,7 +728,7 @@ impl Repr for ty::BoundRegion {
 }
 
 impl Repr for ty::Region {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match *self {
             ty::ReEarlyBound(id, index, name) => {
                 format!("ReEarlyBound({}, {}, {})",
@@ -772,7 +771,7 @@ impl Repr for ty::Region {
 }
 
 impl Repr for ast::DefId {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         // Unfortunately, there seems to be no way to attempt to print
         // 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
@@ -798,7 +797,7 @@ impl Repr for ast::DefId {
 }
 
 impl Repr for ty::ty_param_bounds_and_ty {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("ty_param_bounds_and_ty \\{generics: {}, ty: {}\\}",
              self.generics.repr(tcx),
              self.ty.repr(tcx))
@@ -806,7 +805,7 @@ impl Repr for ty::ty_param_bounds_and_ty {
 }
 
 impl Repr for ty::Generics {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("Generics(type_param_defs: {}, region_param_defs: {})",
                 self.type_param_defs().repr(tcx),
                 self.region_param_defs().repr(tcx))
@@ -814,7 +813,7 @@ impl Repr for ty::Generics {
 }
 
 impl Repr for ty::ItemVariances {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("IterVariances(self_param={}, type_params={}, region_params={})",
                 self.self_param.repr(tcx),
                 self.type_params.repr(tcx),
@@ -823,13 +822,13 @@ impl Repr for ty::ItemVariances {
 }
 
 impl Repr for ty::Variance {
-    fn repr(&self, _: ctxt) -> ~str {
+    fn repr(&self, _: &ctxt) -> ~str {
         self.to_str().to_owned()
     }
 }
 
 impl Repr for ty::Method {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("method(ident: {}, generics: {}, fty: {}, \
                 explicit_self: {}, vis: {}, def_id: {})",
                 self.ident.repr(tcx),
@@ -842,31 +841,31 @@ impl Repr for ty::Method {
 }
 
 impl Repr for ast::Name {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         token::get_name(*self).get().to_str()
     }
 }
 
 impl Repr for ast::Ident {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         token::get_ident(*self).get().to_str()
     }
 }
 
 impl Repr for ast::ExplicitSelf_ {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("{:?}", *self)
     }
 }
 
 impl Repr for ast::Visibility {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("{:?}", *self)
     }
 }
 
 impl Repr for ty::BareFnTy {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("BareFnTy \\{purity: {:?}, abis: {}, sig: {}\\}",
              self.purity,
              self.abis.to_str(),
@@ -875,13 +874,13 @@ impl Repr for ty::BareFnTy {
 }
 
 impl Repr for ty::FnSig {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         fn_sig_to_str(tcx, self)
     }
 }
 
 impl Repr for typeck::MethodCallee {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("MethodCallee \\{origin: {}, ty: {}, {}\\}",
             self.origin.repr(tcx),
             self.ty.repr(tcx),
@@ -890,7 +889,7 @@ impl Repr for typeck::MethodCallee {
 }
 
 impl Repr for typeck::MethodOrigin {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match self {
             &typeck::MethodStatic(def_id) => {
                 format!("MethodStatic({})", def_id.repr(tcx))
@@ -906,7 +905,7 @@ impl Repr for typeck::MethodOrigin {
 }
 
 impl Repr for typeck::MethodParam {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("MethodParam({},{:?},{:?},{:?})",
              self.trait_id.repr(tcx),
              self.method_num,
@@ -916,7 +915,7 @@ impl Repr for typeck::MethodParam {
 }
 
 impl Repr for typeck::MethodObject {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("MethodObject({},{:?},{:?})",
              self.trait_id.repr(tcx),
              self.method_num,
@@ -926,13 +925,13 @@ impl Repr for typeck::MethodObject {
 
 
 impl Repr for ty::RegionVid {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("{:?}", *self)
     }
 }
 
 impl Repr for ty::TraitStore {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         match self {
             &ty::UniqTraitStore => ~"~Trait",
             &ty::RegionTraitStore(r) => format!("&{} Trait", r.repr(tcx))
@@ -941,19 +940,19 @@ impl Repr for ty::TraitStore {
 }
 
 impl Repr for ty::vstore {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         vstore_to_str(tcx, *self)
     }
 }
 
 impl Repr for ty::BuiltinBound {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("{:?}", *self)
     }
 }
 
 impl UserString for ty::BuiltinBound {
-    fn user_string(&self, _tcx: ctxt) -> ~str {
+    fn user_string(&self, _tcx: &ctxt) -> ~str {
         match *self {
             ty::BoundStatic => ~"'static",
             ty::BoundSend => ~"Send",
@@ -965,26 +964,26 @@ impl UserString for ty::BuiltinBound {
 }
 
 impl Repr for ty::BuiltinBounds {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         self.user_string(tcx)
     }
 }
 
 impl Repr for Span {
-    fn repr(&self, tcx: ctxt) -> ~str {
-        tcx.sess.codemap.span_to_str(*self)
+    fn repr(&self, tcx: &ctxt) -> ~str {
+        tcx.sess.codemap().span_to_str(*self)
     }
 }
 
 impl<A:UserString> UserString for @A {
-    fn user_string(&self, tcx: ctxt) -> ~str {
+    fn user_string(&self, tcx: &ctxt) -> ~str {
         let this: &A = &**self;
         this.user_string(tcx)
     }
 }
 
 impl UserString for ty::BuiltinBounds {
-    fn user_string(&self, tcx: ctxt) -> ~str {
+    fn user_string(&self, tcx: &ctxt) -> ~str {
         if self.is_empty() { ~"<no-bounds>" } else {
             let mut result = Vec::new();
             for bb in self.iter() {
@@ -996,7 +995,7 @@ impl UserString for ty::BuiltinBounds {
 }
 
 impl UserString for ty::TraitRef {
-    fn user_string(&self, tcx: ctxt) -> ~str {
+    fn user_string(&self, tcx: &ctxt) -> ~str {
         let base = ty::item_path_str(tcx, self.def_id);
         if tcx.sess.verbose() && self.substs.self_ty.is_some() {
             let mut all_tps = self.substs.tps.clone();
@@ -1011,31 +1010,31 @@ impl UserString for ty::TraitRef {
 }
 
 impl UserString for ty::t {
-    fn user_string(&self, tcx: ctxt) -> ~str {
+    fn user_string(&self, tcx: &ctxt) -> ~str {
         ty_to_str(tcx, *self)
     }
 }
 
 impl UserString for ast::Ident {
-    fn user_string(&self, _tcx: ctxt) -> ~str {
+    fn user_string(&self, _tcx: &ctxt) -> ~str {
         token::get_name(self.name).get().to_owned()
     }
 }
 
 impl Repr for AbiSet {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         self.to_str()
     }
 }
 
 impl UserString for AbiSet {
-    fn user_string(&self, _tcx: ctxt) -> ~str {
+    fn user_string(&self, _tcx: &ctxt) -> ~str {
         self.to_str()
     }
 }
 
 impl Repr for ty::UpvarId {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("UpvarId({};`{}`;{})",
              self.var_id,
              ty::local_var_name_str(tcx, self.var_id),
@@ -1044,19 +1043,19 @@ impl Repr for ty::UpvarId {
 }
 
 impl Repr for ast::Mutability {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("{:?}", *self)
     }
 }
 
 impl Repr for ty::BorrowKind {
-    fn repr(&self, _tcx: ctxt) -> ~str {
+    fn repr(&self, _tcx: &ctxt) -> ~str {
         format!("{:?}", *self)
     }
 }
 
 impl Repr for ty::UpvarBorrow {
-    fn repr(&self, tcx: ctxt) -> ~str {
+    fn repr(&self, tcx: &ctxt) -> ~str {
         format!("UpvarBorrow({}, {})",
              self.kind.repr(tcx),
              self.region.repr(tcx))
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index c27725fd585..2ac3834ea49 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -26,6 +26,7 @@ use rustc::metadata::decoder;
 
 use std;
 
+use core;
 use doctree;
 use visit_ast;
 use std::local_data;
@@ -84,7 +85,7 @@ impl<'a> Clean<Crate> for visit_ast::RustdocVisitor<'a> {
         let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
 
         let mut externs = ~[];
-        cx.sess.cstore.iter_crate_data(|n, meta| {
+        cx.sess().cstore.iter_crate_data(|n, meta| {
             externs.push((n, meta.clean()));
         });
 
@@ -683,7 +684,7 @@ impl Clean<Type> for ast::Ty {
     fn clean(&self) -> Type {
         use syntax::ast::*;
         debug!("cleaning type `{:?}`", self);
-        let codemap = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess.codemap;
+        let codemap = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap();
         debug!("span corresponds to `{}`", codemap.span_to_str(self.span));
         match self.node {
             TyNil => Unit,
@@ -865,7 +866,7 @@ pub struct Span {
 
 impl Clean<Span> for syntax::codemap::Span {
     fn clean(&self) -> Span {
-        let cm = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess.codemap;
+        let cm = local_data::get(super::ctxtkey, |x| *x.unwrap()).sess().codemap();
         let filename = cm.span_to_filename(*self);
         let lo = cm.lookup_char_pos(self.lo);
         let hi = cm.lookup_char_pos(self.hi);
@@ -1179,7 +1180,7 @@ trait ToSource {
 impl ToSource for syntax::codemap::Span {
     fn to_src(&self) -> ~str {
         debug!("converting span {:?} to snippet", self.clean());
-        let cm = local_data::get(super::ctxtkey, |x| x.unwrap().clone()).sess.codemap.clone();
+        let cm = local_data::get(super::ctxtkey, |x| x.unwrap().clone()).sess().codemap().clone();
         let sn = match cm.span_to_snippet(*self) {
             Some(x) => x,
             None    => ~""
@@ -1234,10 +1235,10 @@ fn name_from_pat(p: &ast::Pat) -> ~str {
 fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
                 id: ast::NodeId) -> Type {
     let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
-    let tycx = match cx.tycx {
-        Some(tycx) => tycx,
+    let tycx = match cx.maybe_typed {
+        core::Typed(ref tycx) => tycx,
         // If we're extracting tests, this return value doesn't matter.
-        None => return Bool
+        core::NotTyped(_) => return Bool
     };
     debug!("searching for {:?} in defmap", id);
     let def_map = tycx.def_map.borrow();
@@ -1289,12 +1290,12 @@ fn resolve_use_source(path: Path, id: ast::NodeId) -> ImportSource {
 
 fn resolve_def(id: ast::NodeId) -> Option<ast::DefId> {
     let cx = local_data::get(super::ctxtkey, |x| *x.unwrap());
-    match cx.tycx {
-        Some(tcx) => {
+    match cx.maybe_typed {
+        core::Typed(ref tcx) => {
             let def_map = tcx.def_map.borrow();
             def_map.get().find(&id).map(|&d| ast_util::def_id_of_def(d))
         }
-        None => None
+        core::NotTyped(_) => None
     }
 }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index eda24fb6dc2..91c4311ff54 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -15,7 +15,6 @@ use rustc::middle::privacy;
 
 use syntax::ast;
 use syntax::parse::token;
-use syntax::parse;
 use syntax;
 
 use std::cell::RefCell;
@@ -27,10 +26,23 @@ use visit_ast::RustdocVisitor;
 use clean;
 use clean::Clean;
 
+pub enum MaybeTyped {
+    Typed(middle::ty::ctxt),
+    NotTyped(driver::session::Session)
+}
+
 pub struct DocContext {
     krate: ast::Crate,
-    tycx: Option<middle::ty::ctxt>,
-    sess: driver::session::Session
+    maybe_typed: MaybeTyped
+}
+
+impl DocContext {
+    pub fn sess<'a>(&'a self) -> &'a driver::session::Session {
+        match self.maybe_typed {
+            Typed(ref tcx) => &tcx.sess,
+            NotTyped(ref sess) => sess
+        }
+    }
 }
 
 pub struct CrateAnalysis {
@@ -47,47 +59,46 @@ fn get_ast_and_resolve(cpath: &Path,
                                 phase_2_configure_and_expand,
                                 phase_3_run_analysis_passes};
 
-    let parsesess = parse::new_parse_sess();
     let input = FileInput(cpath.clone());
 
-    let sessopts = @driver::session::Options {
-        maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
-        addl_lib_search_paths: @RefCell::new(libs),
+    let sessopts = driver::session::Options {
+        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
+        addl_lib_search_paths: RefCell::new(libs),
         crate_types: vec!(driver::session::CrateTypeDylib),
-        .. (*rustc::driver::session::basic_options()).clone()
+        ..rustc::driver::session::basic_options().clone()
     };
 
 
+    let codemap = syntax::codemap::CodeMap::new();
     let diagnostic_handler = syntax::diagnostic::default_handler();
     let span_diagnostic_handler =
-        syntax::diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
+        syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
     let sess = driver::driver::build_session_(sessopts,
                                               Some(cpath.clone()),
-                                              parsesess.cm,
                                               span_diagnostic_handler);
 
-    let mut cfg = build_configuration(sess);
+    let mut cfg = build_configuration(&sess);
     for cfg_ in cfgs.move_iter() {
         let cfg_ = token::intern_and_get_ident(cfg_);
         cfg.push(@dummy_spanned(ast::MetaWord(cfg_)));
     }
 
-    let krate = phase_1_parse_input(sess, cfg, &input);
-    let loader = &mut Loader::new(sess);
-    let id = from_str("rustdoc").unwrap();
-    let (krate, ast_map) = phase_2_configure_and_expand(sess, loader,
-                                                        krate, &id);
+    let krate = phase_1_parse_input(&sess, cfg, &input);
+    let (krate, ast_map) = phase_2_configure_and_expand(&sess, &mut Loader::new(&sess),
+                                                        krate, &from_str("rustdoc").unwrap());
     let driver::driver::CrateAnalysis {
         exported_items, public_items, ty_cx, ..
     } = phase_3_run_analysis_passes(sess, &krate, ast_map);
 
     debug!("crate: {:?}", krate);
-    return (DocContext { krate: krate, tycx: Some(ty_cx), sess: sess },
-            CrateAnalysis {
-                exported_items: exported_items,
-                public_items: public_items,
-            });
+    (DocContext {
+        krate: krate,
+        maybe_typed: Typed(ty_cx)
+    }, CrateAnalysis {
+        exported_items: exported_items,
+        public_items: public_items,
+    })
 }
 
 pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Crate, CrateAnalysis) {
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 07c4903585b..d67c7ea6505 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -18,7 +18,6 @@ use std::io;
 
 use syntax::parse;
 use syntax::parse::lexer;
-use syntax::diagnostic;
 use syntax::codemap::{BytePos, Span};
 
 use html::escape::Escape;
@@ -28,13 +27,11 @@ use t = syntax::parse::token;
 /// Highlights some source code, returning the HTML output.
 pub fn highlight(src: &str, class: Option<&str>) -> ~str {
     let sess = parse::new_parse_sess();
-    let handler = diagnostic::default_handler();
-    let span_handler = diagnostic::mk_span_handler(handler, sess.cm);
-    let fm = parse::string_to_filemap(sess, src.to_owned(), ~"<stdin>");
+    let fm = parse::string_to_filemap(&sess, src.to_owned(), ~"<stdin>");
 
     let mut out = io::MemWriter::new();
-    doit(sess,
-         lexer::new_string_reader(span_handler, fm),
+    doit(&sess,
+         lexer::new_string_reader(&sess.span_diagnostic, fm),
          class,
          &mut out).unwrap();
     str::from_utf8_lossy(out.unwrap()).into_owned()
@@ -47,7 +44,7 @@ pub fn highlight(src: &str, class: Option<&str>) -> ~str {
 /// it's used. All source code emission is done as slices from the source map,
 /// not from the tokens themselves, in order to stay true to the original
 /// source.
-fn doit(sess: @parse::ParseSess, lexer: lexer::StringReader, class: Option<&str>,
+fn doit(sess: &parse::ParseSess, lexer: lexer::StringReader, class: Option<&str>,
         out: &mut Writer) -> io::IoResult<()> {
     use syntax::parse::lexer::Reader;
 
@@ -68,7 +65,7 @@ fn doit(sess: @parse::ParseSess, lexer: lexer::StringReader, class: Option<&str>
         // comment. This will classify some whitespace as a comment, but that
         // doesn't matter too much for syntax highlighting purposes.
         if test > last {
-            let snip = sess.cm.span_to_snippet(Span {
+            let snip = sess.span_diagnostic.cm.span_to_snippet(Span {
                 lo: last,
                 hi: test,
                 expn_info: None,
@@ -172,7 +169,7 @@ fn doit(sess: @parse::ParseSess, lexer: lexer::StringReader, class: Option<&str>
 
         // as mentioned above, use the original source code instead of
         // stringifying this token
-        let snip = sess.cm.span_to_snippet(next.sp).unwrap();
+        let snip = sess.span_diagnostic.cm.span_to_snippet(next.sp).unwrap();
         if klass == "" {
             try!(write!(out, "{}", Escape(snip)));
         } else {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index fff6e4dafb3..e64292285d0 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -28,7 +28,6 @@ extern crate time;
 #[phase(syntax, link)]
 extern crate log;
 
-use std::cell::RefCell;
 use std::local_data;
 use std::io;
 use std::io::{File, MemWriter};
@@ -155,8 +154,7 @@ pub fn main_args(args: &[~str]) -> int {
     }
     let input = matches.free[0].as_slice();
 
-    let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice()));
-    let libs = @RefCell::new(libs.move_iter().collect());
+    let libs = matches.opt_strs("L").map(|s| Path::new(s.as_slice())).move_iter().collect();
 
     let test_args = matches.opt_strs("test-args");
     let test_args = test_args.iter().flat_map(|s| s.words()).map(|s| s.to_owned()).to_owned_vec();
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 7ab3fe017b9..bd15d1b1331 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use std::{str, io};
-use std::cell::RefCell;
 use std::vec_ng::Vec;
 
 use collections::HashSet;
@@ -160,7 +159,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches) -> int
 }
 
 /// Run any tests/code examples in the markdown file `input`.
-pub fn test(input: &str, libs: @RefCell<HashSet<Path>>, mut test_args: ~[~str]) -> int {
+pub fn test(input: &str, libs: HashSet<Path>, mut test_args: ~[~str]) -> int {
     let input_str = load_or_return!(input, 1, 2);
 
     let mut collector = Collector::new(input.to_owned(), libs, true, true);
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index d8b7c525538..0a472a0ccaf 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -23,7 +23,6 @@ use rustc::driver::driver;
 use rustc::driver::session;
 use rustc::metadata::creader::Loader;
 use syntax::diagnostic;
-use syntax::parse;
 use syntax::codemap::CodeMap;
 
 use core;
@@ -34,41 +33,35 @@ use html::markdown;
 use passes;
 use visit_ast::RustdocVisitor;
 
-pub fn run(input: &str, libs: @RefCell<HashSet<Path>>, mut test_args: ~[~str]) -> int {
+pub fn run(input: &str, libs: HashSet<Path>, mut test_args: ~[~str]) -> int {
     let input_path = Path::new(input);
     let input = driver::FileInput(input_path.clone());
 
-    let sessopts = @session::Options {
-        maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
-        addl_lib_search_paths: libs,
+    let sessopts = session::Options {
+        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
+        addl_lib_search_paths: RefCell::new(libs.clone()),
         crate_types: vec!(session::CrateTypeDylib),
-        .. (*session::basic_options()).clone()
+        ..session::basic_options().clone()
     };
 
 
-    let cm = @CodeMap::new();
+    let codemap = CodeMap::new();
     let diagnostic_handler = diagnostic::default_handler();
     let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, cm);
-    let parsesess = parse::new_parse_sess_special_handler(span_diagnostic_handler,
-                                                          cm);
+    diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
     let sess = driver::build_session_(sessopts,
                                       Some(input_path),
-                                      parsesess.cm,
                                       span_diagnostic_handler);
 
-    let cfg = driver::build_configuration(sess);
-    let krate = driver::phase_1_parse_input(sess, cfg, &input);
-    let loader = &mut Loader::new(sess);
-    let id = from_str("rustdoc-test").unwrap();
-    let (krate, _) = driver::phase_2_configure_and_expand(sess, loader, krate,
-                                                          &id);
+    let cfg = driver::build_configuration(&sess);
+    let krate = driver::phase_1_parse_input(&sess, cfg, &input);
+    let (krate, _) = driver::phase_2_configure_and_expand(&sess, &mut Loader::new(&sess), krate,
+                                                          &from_str("rustdoc-test").unwrap());
 
     let ctx = @core::DocContext {
         krate: krate,
-        tycx: None,
-        sess: sess,
+        maybe_typed: core::NotTyped(sess),
     };
     local_data::set(super::ctxtkey, ctx);
 
@@ -91,19 +84,18 @@ pub fn run(input: &str, libs: @RefCell<HashSet<Path>>, mut test_args: ~[~str]) -
 fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
            no_run: bool, loose_feature_gating: bool) {
     let test = maketest(test, cratename, loose_feature_gating);
-    let parsesess = parse::new_parse_sess();
     let input = driver::StrInput(test);
 
-    let sessopts = @session::Options {
-        maybe_sysroot: Some(@os::self_exe_path().unwrap().dir_path()),
-        addl_lib_search_paths: @RefCell::new(libs),
+    let sessopts = session::Options {
+        maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
+        addl_lib_search_paths: RefCell::new(libs),
         crate_types: vec!(session::CrateTypeExecutable),
         output_types: vec!(link::OutputTypeExe),
         cg: session::CodegenOptions {
             prefer_dynamic: true,
             .. session::basic_codegen_options()
         },
-        .. (*session::basic_options()).clone()
+        ..session::basic_options().clone()
     };
 
     // Shuffle around a few input and output handles here. We're going to pass
@@ -129,18 +121,18 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool,
     let emitter = diagnostic::EmitterWriter::new(~w2);
 
     // Compile the code
+    let codemap = CodeMap::new();
     let diagnostic_handler = diagnostic::mk_handler(~emitter);
     let span_diagnostic_handler =
-        diagnostic::mk_span_handler(diagnostic_handler, parsesess.cm);
+        diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
     let sess = driver::build_session_(sessopts,
                                       None,
-                                      parsesess.cm,
                                       span_diagnostic_handler);
 
     let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
     let out = Some(outdir.path().clone());
-    let cfg = driver::build_configuration(sess);
+    let cfg = driver::build_configuration(&sess);
     driver::compile_input(sess, cfg, &input, &out, &None);
 
     if no_run { return }
@@ -197,7 +189,7 @@ fn maketest(s: &str, cratename: &str, loose_feature_gating: bool) -> ~str {
 pub struct Collector {
     tests: ~[testing::TestDescAndFn],
     priv names: ~[~str],
-    priv libs: @RefCell<HashSet<Path>>,
+    priv libs: HashSet<Path>,
     priv cnt: uint,
     priv use_headers: bool,
     priv current_header: Option<~str>,
@@ -207,7 +199,7 @@ pub struct Collector {
 }
 
 impl Collector {
-    pub fn new(cratename: ~str, libs: @RefCell<HashSet<Path>>,
+    pub fn new(cratename: ~str, libs: HashSet<Path>,
                use_headers: bool, loose_feature_gating: bool) -> Collector {
         Collector {
             tests: ~[],
@@ -230,8 +222,7 @@ impl Collector {
             format!("{}_{}", self.names.connect("::"), self.cnt)
         };
         self.cnt += 1;
-        let libs = self.libs.borrow();
-        let libs = (*libs.get()).clone();
+        let libs = self.libs.clone();
         let cratename = self.cratename.to_owned();
         let loose_feature_gating = self.loose_feature_gating;
         debug!("Creating test {}: {}", name, test);
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 5ac623af37a..c0a39112b69 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -183,21 +183,18 @@ impl<'a> RustdocVisitor<'a> {
 
     fn resolve_id(&mut self, id: ast::NodeId, glob: bool,
                   om: &mut Module) -> bool {
-        let def = {
-            let dm = match self.cx.tycx {
-                Some(tcx) => tcx.def_map.borrow(),
-                None => return false,
-            };
-            ast_util::def_id_of_def(*dm.get().get(&id))
+        let tcx = match self.cx.maybe_typed {
+            core::Typed(ref tcx) => tcx,
+            core::NotTyped(_) => return false
         };
+        let def = ast_util::def_id_of_def(*tcx.def_map.borrow().get().get(&id));
         if !ast_util::is_local(def) { return false }
         let analysis = match self.analysis {
             Some(analysis) => analysis, None => return false
         };
         if analysis.public_items.contains(&def.node) { return false }
 
-        let item = self.cx.tycx.unwrap().map.get(def.node);
-        match item {
+        match tcx.map.get(def.node) {
             ast_map::NodeItem(it) => {
                 if glob {
                     match it.node {
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 7ff9a73f29d..65a0f473db2 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -375,7 +375,7 @@ pub fn find_stability<AM: AttrMetaMethods, It: Iterator<AM>>(mut metas: It)
     None
 }
 
-pub fn require_unique_names(diagnostic: @SpanHandler, metas: &[@MetaItem]) {
+pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[@MetaItem]) {
     let mut set = HashSet::new();
     for meta in metas.iter() {
         let name = meta.name();
@@ -400,7 +400,7 @@ pub fn require_unique_names(diagnostic: @SpanHandler, metas: &[@MetaItem]) {
  * present (before fields, if any) with that type; reprensentation
  * optimizations which would remove it will not be done.
  */
-pub fn find_repr_attr(diagnostic: @SpanHandler, attr: @ast::MetaItem, acc: ReprAttr)
+pub fn find_repr_attr(diagnostic: &SpanHandler, attr: @ast::MetaItem, acc: ReprAttr)
     -> ReprAttr {
     let mut acc = acc;
     match attr.node {
@@ -438,7 +438,7 @@ pub fn find_repr_attr(diagnostic: @SpanHandler, attr: @ast::MetaItem, acc: ReprA
         // Not a "repr" hint: ignore.
         _ => { }
     }
-    return acc;
+    acc
 }
 
 fn int_type_of_word(s: &str) -> Option<IntType> {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 5be03317b77..4bfd5391a8f 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -23,6 +23,7 @@ source code snippets, etc.
 
 use std::cell::RefCell;
 use std::cmp;
+use std::rc::Rc;
 use std::vec_ng::Vec;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -140,7 +141,7 @@ pub fn mk_sp(lo: BytePos, hi: BytePos) -> Span {
 /// A source code location used for error reporting
 pub struct Loc {
     /// Information about the original source
-    file: @FileMap,
+    file: Rc<FileMap>,
     /// The (1-based) line number
     line: uint,
     /// The (0-based) column offset
@@ -154,12 +155,12 @@ pub struct LocWithOpt {
     filename: FileName,
     line: uint,
     col: CharPos,
-    file: Option<@FileMap>,
+    file: Option<Rc<FileMap>>,
 }
 
 // used to be structural records. Better names, anyone?
-pub struct FileMapAndLine {fm: @FileMap, line: uint}
-pub struct FileMapAndBytePos {fm: @FileMap, pos: BytePos}
+pub struct FileMapAndLine {fm: Rc<FileMap>, line: uint}
+pub struct FileMapAndBytePos {fm: Rc<FileMap>, pos: BytePos}
 
 #[deriving(Clone, Hash, Show)]
 pub enum MacroFormat {
@@ -186,10 +187,10 @@ pub struct ExpnInfo {
 
 pub type FileName = ~str;
 
-pub struct FileLines
-{
-    file: @FileMap,
-    lines: Vec<uint> }
+pub struct FileLines {
+    file: Rc<FileMap>,
+    lines: Vec<uint>
+}
 
 /// Identifies an offset of a multi-byte character in a FileMap
 pub struct MultiByteChar {
@@ -251,8 +252,7 @@ impl FileMap {
             pos: pos,
             bytes: bytes,
         };
-        let mut multibyte_chars = self.multibyte_chars.borrow_mut();
-        multibyte_chars.get().push(mbc);
+        self.multibyte_chars.borrow_mut().get().push(mbc);
     }
 
     pub fn is_real_file(&self) -> bool {
@@ -261,7 +261,7 @@ impl FileMap {
 }
 
 pub struct CodeMap {
-    files: RefCell<Vec<@FileMap> >
+    files: RefCell<Vec<Rc<FileMap>>>
 }
 
 impl CodeMap {
@@ -271,11 +271,11 @@ impl CodeMap {
         }
     }
 
-    pub fn new_filemap(&self, filename: FileName, mut src: ~str) -> @FileMap {
+    pub fn new_filemap(&self, filename: FileName, mut src: ~str) -> Rc<FileMap> {
         let mut files = self.files.borrow_mut();
         let start_pos = match files.get().last() {
             None => 0,
-            Some(last) => last.start_pos.to_uint() + last.src.len(),
+            Some(last) => last.deref().start_pos.to_uint() + last.deref().src.len(),
         };
 
         // Append '\n' in case it's not already there.
@@ -286,34 +286,33 @@ impl CodeMap {
             src.push_char('\n');
         }
 
-        let filemap = @FileMap {
+        let filemap = Rc::new(FileMap {
             name: filename,
             src: src,
             start_pos: Pos::from_uint(start_pos),
             lines: RefCell::new(Vec::new()),
             multibyte_chars: RefCell::new(Vec::new()),
-        };
+        });
 
-        files.get().push(filemap);
+        files.get().push(filemap.clone());
 
-        return filemap;
+        filemap
     }
 
     pub fn mk_substr_filename(&self, sp: Span) -> ~str {
         let pos = self.lookup_char_pos(sp.lo);
-        return format!("<{}:{}:{}>", pos.file.name,
-                       pos.line, pos.col.to_uint() + 1)
+        format!("<{}:{}:{}>", pos.file.deref().name, pos.line, pos.col.to_uint() + 1)
     }
 
     /// Lookup source information about a BytePos
     pub fn lookup_char_pos(&self, pos: BytePos) -> Loc {
-        return self.lookup_pos(pos);
+        self.lookup_pos(pos)
     }
 
     pub fn lookup_char_pos_adj(&self, pos: BytePos) -> LocWithOpt {
         let loc = self.lookup_char_pos(pos);
         LocWithOpt {
-            filename: loc.file.name.to_str(),
+            filename: loc.file.deref().name.to_str(),
             line: loc.line,
             col: loc.col,
             file: Some(loc.file)
@@ -321,11 +320,8 @@ impl CodeMap {
     }
 
     pub fn span_to_str(&self, sp: Span) -> ~str {
-        {
-            let files = self.files.borrow();
-            if files.get().len() == 0 && sp == DUMMY_SP {
-                return ~"no-location";
-            }
+        if self.files.borrow().get().len() == 0 && sp == DUMMY_SP {
+            return ~"no-location";
         }
 
         let lo = self.lookup_char_pos_adj(sp.lo);
@@ -335,18 +331,17 @@ impl CodeMap {
     }
 
     pub fn span_to_filename(&self, sp: Span) -> FileName {
-        let lo = self.lookup_char_pos(sp.lo);
-        lo.file.name.to_str()
+        self.lookup_char_pos(sp.lo).file.deref().name.to_str()
     }
 
-    pub fn span_to_lines(&self, sp: Span) -> @FileLines {
+    pub fn span_to_lines(&self, sp: Span) -> FileLines {
         let lo = self.lookup_char_pos(sp.lo);
         let hi = self.lookup_char_pos(sp.hi);
         let mut lines = Vec::new();
         for i in range(lo.line - 1u, hi.line as uint) {
             lines.push(i);
         };
-        return @FileLines {file: lo.file, lines: lines};
+        FileLines {file: lo.file, lines: lines}
     }
 
     pub fn span_to_snippet(&self, sp: Span) -> Option<~str> {
@@ -357,27 +352,22 @@ impl CodeMap {
         // it's testing isn't true for all spans in the AST, so to allow the
         // caller to not have to fail (and it can't catch it since the CodeMap
         // isn't sendable), return None
-        if begin.fm.start_pos != end.fm.start_pos {
+        if begin.fm.deref().start_pos != end.fm.deref().start_pos {
             None
         } else {
-            Some(begin.fm.src.slice( begin.pos.to_uint(), end.pos.to_uint()).to_owned())
+            Some(begin.fm.deref().src.slice( begin.pos.to_uint(), end.pos.to_uint()).to_owned())
         }
     }
 
-    pub fn get_filemap(&self, filename: &str) -> @FileMap {
-        let files = self.files.borrow();
-        for fm in files.get().iter() {
-            if filename == fm.name {
-                return *fm
+    pub fn get_filemap(&self, filename: &str) -> Rc<FileMap> {
+        for fm in self.files.borrow().get().iter() {
+            if filename == fm.deref().name {
+                return fm.clone();
             }
         }
-        //XXjdm the following triggers a mismatched type bug
-        //      (or expected function, found _|_)
-        fail!(); // ("asking for " + filename + " which we don't know about");
+        fail!("asking for {} which we don't know about", filename);
     }
-}
 
-impl CodeMap {
     fn lookup_filemap_idx(&self, pos: BytePos) -> uint {
         let files = self.files.borrow();
         let files = files.get();
@@ -386,7 +376,7 @@ impl CodeMap {
         let mut b = len;
         while b - a > 1u {
             let m = (a + b) / 2u;
-            if files.get(m).start_pos > pos {
+            if files.get(m).deref().start_pos > pos {
                 b = m;
             } else {
                 a = m;
@@ -396,7 +386,7 @@ impl CodeMap {
         // filemap, but are not the filemaps we want (because they are length 0, they cannot
         // contain what we are looking for). So, rewind until we find a useful filemap.
         loop {
-            let lines = files.get(a).lines.borrow();
+            let lines = files.get(a).deref().lines.borrow();
             let lines = lines.get();
             if lines.len() > 0 {
                 break;
@@ -413,28 +403,28 @@ impl CodeMap {
         return a;
     }
 
-    fn lookup_line(&self, pos: BytePos) -> FileMapAndLine
-    {
+    fn lookup_line(&self, pos: BytePos) -> FileMapAndLine {
         let idx = self.lookup_filemap_idx(pos);
 
         let files = self.files.borrow();
-        let f = *files.get().get(idx);
+        let f = files.get().get(idx).clone();
         let mut a = 0u;
-        let mut lines = f.lines.borrow_mut();
-        let mut b = lines.get().len();
-        while b - a > 1u {
-            let m = (a + b) / 2u;
-            if *lines.get().get(m) > pos { b = m; } else { a = m; }
+        {
+            let mut lines = f.deref().lines.borrow_mut();
+            let mut b = lines.get().len();
+            while b - a > 1u {
+                let m = (a + b) / 2u;
+                if *lines.get().get(m) > pos { b = m; } else { a = m; }
+            }
         }
-        return FileMapAndLine {fm: f, line: a};
+        FileMapAndLine {fm: f, line: a}
     }
 
     fn lookup_pos(&self, pos: BytePos) -> Loc {
         let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos);
         let line = a + 1u; // Line numbers start at 1
         let chpos = self.bytepos_to_file_charpos(pos);
-        let lines = f.lines.borrow();
-        let linebpos = *lines.get().get(a);
+        let linebpos = *f.deref().lines.borrow().get().get(a);
         let linechpos = self.bytepos_to_file_charpos(linebpos);
         debug!("codemap: byte pos {:?} is on the line at byte pos {:?}",
                pos, linebpos);
@@ -442,20 +432,18 @@ impl CodeMap {
                chpos, linechpos);
         debug!("codemap: byte is on line: {:?}", line);
         assert!(chpos >= linechpos);
-        return Loc {
+        Loc {
             file: f,
             line: line,
             col: chpos - linechpos
-        };
+        }
     }
 
-    fn lookup_byte_offset(&self, bpos: BytePos)
-        -> FileMapAndBytePos {
+    fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
         let idx = self.lookup_filemap_idx(bpos);
-        let files = self.files.borrow();
-        let fm = *files.get().get(idx);
-        let offset = bpos - fm.start_pos;
-        return FileMapAndBytePos {fm: fm, pos: offset};
+        let fm = self.files.borrow().get().get(idx).clone();
+        let offset = bpos - fm.deref().start_pos;
+        FileMapAndBytePos {fm: fm, pos: offset}
     }
 
     // Converts an absolute BytePos to a CharPos relative to the filemap.
@@ -468,8 +456,7 @@ impl CodeMap {
         // The number of extra bytes due to multibyte chars in the FileMap
         let mut total_extra_bytes = 0;
 
-        let multibyte_chars = map.multibyte_chars.borrow();
-        for mbc in multibyte_chars.get().iter() {
+        for mbc in map.deref().multibyte_chars.borrow().get().iter() {
             debug!("codemap: {:?}-byte char at {:?}", mbc.bytes, mbc.pos);
             if mbc.pos < bpos {
                 // every character is at least one byte, so we only
@@ -483,8 +470,8 @@ impl CodeMap {
             }
         }
 
-        assert!(map.start_pos.to_uint() + total_extra_bytes <= bpos.to_uint());
-        CharPos(bpos.to_uint() - map.start_pos.to_uint() - total_extra_bytes)
+        assert!(map.deref().start_pos.to_uint() + total_extra_bytes <= bpos.to_uint());
+        CharPos(bpos.to_uint() - map.deref().start_pos.to_uint() - total_extra_bytes)
     }
 }
 
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 2da8b786805..c88c5a3c4e6 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -40,37 +40,37 @@ pub struct ExplicitBug;
 // accepts span information for source-location
 // reporting.
 pub struct SpanHandler {
-    handler: @Handler,
-    cm: @codemap::CodeMap,
+    handler: Handler,
+    cm: codemap::CodeMap,
 }
 
 impl SpanHandler {
     pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
-        self.handler.emit(Some((&*self.cm, sp)), msg, Fatal);
+        self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
         fail!(FatalError);
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
-        self.handler.emit(Some((&*self.cm, sp)), msg, Error);
+        self.handler.emit(Some((&self.cm, sp)), msg, Error);
         self.handler.bump_err_count();
     }
     pub fn span_warn(&self, sp: Span, msg: &str) {
-        self.handler.emit(Some((&*self.cm, sp)), msg, Warning);
+        self.handler.emit(Some((&self.cm, sp)), msg, Warning);
     }
     pub fn span_note(&self, sp: Span, msg: &str) {
-        self.handler.emit(Some((&*self.cm, sp)), msg, Note);
+        self.handler.emit(Some((&self.cm, sp)), msg, Note);
     }
     pub fn span_end_note(&self, sp: Span, msg: &str) {
-        self.handler.custom_emit(&*self.cm, sp, msg, Note);
+        self.handler.custom_emit(&self.cm, sp, msg, Note);
     }
     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
-        self.handler.emit(Some((&*self.cm, sp)), msg, Bug);
+        self.handler.emit(Some((&self.cm, sp)), msg, Bug);
         fail!(ExplicitBug);
     }
     pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
         self.span_bug(sp, ~"unimplemented " + msg);
     }
-    pub fn handler(&self) -> @Handler {
-        self.handler
+    pub fn handler<'a>(&'a self) -> &'a Handler {
+        &self.handler
     }
 }
 
@@ -137,20 +137,19 @@ impl Handler {
     }
 }
 
-pub fn mk_span_handler(handler: @Handler, cm: @codemap::CodeMap)
-                       -> @SpanHandler {
-    @SpanHandler {
+pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
+    SpanHandler {
         handler: handler,
         cm: cm,
     }
 }
 
-pub fn default_handler() -> @Handler {
+pub fn default_handler() -> Handler {
     mk_handler(~EmitterWriter::stderr())
 }
 
-pub fn mk_handler(e: ~Emitter) -> @Handler {
-    @Handler {
+pub fn mk_handler(e: ~Emitter) -> Handler {
+    Handler {
         err_count: Cell::new(0),
         emit: RefCell::new(e),
     }
@@ -301,8 +300,8 @@ fn highlight_lines(err: &mut EmitterWriter,
                    cm: &codemap::CodeMap,
                    sp: Span,
                    lvl: Level,
-                   lines: &codemap::FileLines) -> io::IoResult<()> {
-    let fm = lines.file;
+                   lines: codemap::FileLines) -> io::IoResult<()> {
+    let fm = lines.file.deref();
 
     let mut elided = false;
     let mut display_lines = lines.lines.as_slice();
@@ -374,8 +373,8 @@ fn custom_highlight_lines(w: &mut EmitterWriter,
                           cm: &codemap::CodeMap,
                           sp: Span,
                           lvl: Level,
-                          lines: &codemap::FileLines) -> io::IoResult<()> {
-    let fm = lines.file;
+                          lines: codemap::FileLines) -> io::IoResult<()> {
+    let fm = lines.file.deref();
 
     let lines = lines.lines.as_slice();
     if lines.len() > MAX_LINES {
@@ -420,8 +419,7 @@ fn print_macro_backtrace(w: &mut EmitterWriter,
     Ok(())
 }
 
-pub fn expect<T:Clone>(diag: @SpanHandler, opt: Option<T>, msg: || -> ~str)
-              -> T {
+pub fn expect<T:Clone>(diag: &SpanHandler, opt: Option<T>, msg: || -> ~str) -> T {
     match opt {
        Some(ref t) => (*t).clone(),
        None => diag.handler().bug(msg()),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 997bfcc2e94..df2c265e6eb 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -289,7 +289,7 @@ pub trait CrateLoader {
 // when a macro expansion occurs, the resulting nodes have the backtrace()
 // -> expn_info of their expansion context stored into their span.
 pub struct ExtCtxt<'a> {
-    parse_sess: @parse::ParseSess,
+    parse_sess: &'a parse::ParseSess,
     cfg: ast::CrateConfig,
     backtrace: Option<@ExpnInfo>,
     ecfg: expand::ExpansionConfig<'a>,
@@ -299,7 +299,7 @@ pub struct ExtCtxt<'a> {
 }
 
 impl<'a> ExtCtxt<'a> {
-    pub fn new<'a>(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig,
+    pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig,
                    ecfg: expand::ExpansionConfig<'a>) -> ExtCtxt<'a> {
         ExtCtxt {
             parse_sess: parse_sess,
@@ -326,8 +326,8 @@ impl<'a> ExtCtxt<'a> {
         }
     }
 
-    pub fn codemap(&self) -> @CodeMap { self.parse_sess.cm }
-    pub fn parse_sess(&self) -> @parse::ParseSess { self.parse_sess }
+    pub fn codemap(&self) -> &'a CodeMap { &self.parse_sess.span_diagnostic.cm }
+    pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess }
     pub fn cfg(&self) -> ast::CrateConfig { self.cfg.clone() }
     pub fn call_site(&self) -> Span {
         match self.backtrace {
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 6aa90e5e842..7c42476bc01 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -633,7 +633,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
             vec!(
                 self.expr_str(span, msg),
                 self.expr_str(span,
-                              token::intern_and_get_ident(loc.file.name)),
+                              token::intern_and_get_ident(loc.file.deref().name)),
                 self.expr_uint(span, loc.line)))
     }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index c24894af3be..75ade160380 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -838,12 +838,12 @@ pub fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
     }
 }
 
-pub struct MacroExpander<'a> {
+pub struct MacroExpander<'a, 'b> {
     extsbox: SyntaxEnv,
-    cx: &'a mut ExtCtxt<'a>,
+    cx: &'a mut ExtCtxt<'b>,
 }
 
-impl<'a> Folder for MacroExpander<'a> {
+impl<'a, 'b> Folder for MacroExpander<'a, 'b> {
     fn fold_expr(&mut self, expr: @ast::Expr) -> @ast::Expr {
         expand_expr(expr, self)
     }
@@ -875,7 +875,7 @@ pub struct ExpansionConfig<'a> {
     crate_id: CrateId,
 }
 
-pub fn expand_crate(parse_sess: @parse::ParseSess,
+pub fn expand_crate(parse_sess: &parse::ParseSess,
                     cfg: ExpansionConfig,
                     c: Crate) -> Crate {
     let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg);
@@ -974,7 +974,7 @@ mod test {
     use ext::mtwt;
     use parse;
     use parse::token;
-    use util::parser_testing::{string_to_crate_and_sess};
+    use util::parser_testing::{string_to_parser};
     use util::parser_testing::{string_to_pat, strs_to_idents};
     use visit;
     use visit::Visitor;
@@ -1044,7 +1044,7 @@ mod test {
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             src,
-            Vec::new(),sess);
+            Vec::new(), &sess);
         // should fail:
         let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
@@ -1052,7 +1052,7 @@ mod test {
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(sess,cfg,crate_ast);
+        expand_crate(&sess,cfg,crate_ast);
     }
 
     // make sure that macros can leave scope for modules
@@ -1064,7 +1064,7 @@ mod test {
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             src,
-            Vec::new(),sess);
+            Vec::new(), &sess);
         // should fail:
         let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
@@ -1072,7 +1072,7 @@ mod test {
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(sess,cfg,crate_ast);
+        expand_crate(&sess,cfg,crate_ast);
     }
 
     // macro_escape modules shouldn't cause macros to leave scope
@@ -1083,7 +1083,7 @@ mod test {
         let crate_ast = parse::parse_crate_from_source_str(
             ~"<test>",
             src,
-            Vec::new(), sess);
+            Vec::new(), &sess);
         // should fail:
         let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
@@ -1091,7 +1091,7 @@ mod test {
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(sess, cfg, crate_ast);
+        expand_crate(&sess, cfg, crate_ast);
     }
 
     #[test] fn test_contains_flatten (){
@@ -1126,7 +1126,8 @@ mod test {
     //}
 
     fn expand_crate_str(crate_str: ~str) -> ast::Crate {
-        let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
+        let ps = parse::new_parse_sess();
+        let crate_ast = string_to_parser(&ps, crate_str).parse_crate_mod();
         // the cfg argument actually does matter, here...
         let mut loader = ErrLoader;
         let cfg = ::syntax::ext::expand::ExpansionConfig {
@@ -1134,7 +1135,7 @@ mod test {
             deriving_hash_type_parameter: false,
             crate_id: from_str("test").unwrap(),
         };
-        expand_crate(ps,cfg,crate_ast)
+        expand_crate(&ps,cfg,crate_ast)
     }
 
     //fn expand_and_resolve(crate_str: @str) -> ast::crate {
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 0db948c30b7..e79e584ed5c 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -35,8 +35,8 @@ enum Position {
     Named(~str),
 }
 
-struct Context<'a> {
-    ecx: &'a mut ExtCtxt<'a>,
+struct Context<'a, 'b> {
+    ecx: &'a mut ExtCtxt<'b>,
     fmtsp: Span,
 
     // Parsed argument expressions and the types that we've found so far for
@@ -142,7 +142,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     return (extra, Some((fmtstr, args, order, names)));
 }
 
-impl<'a> Context<'a> {
+impl<'a, 'b> Context<'a, 'b> {
     /// Verifies one piece of a parse string. All errors are not emitted as
     /// fatal so we can continue giving errors about this and possibly other
     /// format strings.
diff --git a/src/libsyntax/ext/registrar.rs b/src/libsyntax/ext/registrar.rs
index 4c18eb83afc..d8bf726da79 100644
--- a/src/libsyntax/ext/registrar.rs
+++ b/src/libsyntax/ext/registrar.rs
@@ -37,7 +37,7 @@ impl Visitor<()> for MacroRegistrarContext {
     }
 }
 
-pub fn find_macro_registrar(diagnostic: @diagnostic::SpanHandler,
+pub fn find_macro_registrar(diagnostic: &diagnostic::SpanHandler,
                             krate: &ast::Crate) -> Option<ast::DefId> {
     let mut ctx = MacroRegistrarContext { registrars: Vec::new() };
     visit::walk_crate(&mut ctx, krate, ());
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index b31388f58eb..137cd89bf30 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -57,7 +57,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
     let topmost = topmost_expn_info(cx.backtrace().unwrap());
     let loc = cx.codemap().lookup_char_pos(topmost.call_site.lo);
-    let filename = token::intern_and_get_ident(loc.file.name);
+    let filename = token::intern_and_get_ident(loc.file.deref().name);
     base::MRExpr(cx.expr_str(topmost.call_site, filename))
 }
 
@@ -117,7 +117,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
             // dependency information
             let filename = file.display().to_str();
             let interned = token::intern_and_get_ident(src);
-            cx.parse_sess.cm.new_filemap(filename, src);
+            cx.codemap().new_filemap(filename, src);
 
             base::MRExpr(cx.expr_str(sp, interned))
         }
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index 183cccde18e..fa49f06e516 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -22,7 +22,7 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
                         -> base::MacResult {
     let sess = cx.parse_sess();
     let cfg = cx.cfg();
-    let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
+    let tt_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                None,
                                tt.iter().map(|x| (*x).clone()).collect());
     let mut rust_parser = Parser(sess, cfg.clone(), tt_rdr.dup());
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index c9d3150c2cd..698bde4578c 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -170,9 +170,9 @@ pub enum NamedMatch {
     MatchedNonterminal(Nonterminal)
 }
 
-pub fn nameize(p_s: @ParseSess, ms: &[Matcher], res: &[@NamedMatch])
+pub fn nameize(p_s: &ParseSess, ms: &[Matcher], res: &[@NamedMatch])
             -> HashMap<Ident, @NamedMatch> {
-    fn n_rec(p_s: @ParseSess, m: &Matcher, res: &[@NamedMatch],
+    fn n_rec(p_s: &ParseSess, m: &Matcher, res: &[@NamedMatch],
              ret_val: &mut HashMap<Ident, @NamedMatch>) {
         match *m {
           codemap::Spanned {node: MatchTok(_), .. } => (),
@@ -205,7 +205,7 @@ pub enum ParseResult {
     Error(codemap::Span, ~str)
 }
 
-pub fn parse_or_else<R: Reader>(sess: @ParseSess,
+pub fn parse_or_else<R: Reader>(sess: &ParseSess,
                                 cfg: ast::CrateConfig,
                                 rdr: R,
                                 ms: Vec<Matcher> )
@@ -227,7 +227,7 @@ pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
     }
 }
 
-pub fn parse<R: Reader>(sess: @ParseSess,
+pub fn parse<R: Reader>(sess: &ParseSess,
                         cfg: ast::CrateConfig,
                         rdr: R,
                         ms: &[Matcher])
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 712d5f6bd27..3f4ed0b1e8e 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -30,11 +30,11 @@ use util::small_vector::SmallVector;
 use std::cell::RefCell;
 use std::vec_ng::Vec;
 
-struct ParserAnyMacro {
-    parser: RefCell<Parser>,
+struct ParserAnyMacro<'a> {
+    parser: RefCell<Parser<'a>>,
 }
 
-impl ParserAnyMacro {
+impl<'a> ParserAnyMacro<'a> {
     /// Make sure we don't have any tokens left to parse, so we don't
     /// silently drop anything. `allow_semi` is so that "optional"
     /// semilons at the end of normal expressions aren't complained
@@ -57,7 +57,7 @@ impl ParserAnyMacro {
     }
 }
 
-impl AnyMacro for ParserAnyMacro {
+impl<'a> AnyMacro for ParserAnyMacro<'a> {
     fn make_expr(&self) -> @ast::Expr {
         let ret = {
             let mut parser = self.parser.borrow_mut();
@@ -131,13 +131,11 @@ fn generic_extension(cx: &ExtCtxt,
     let mut best_fail_spot = DUMMY_SP;
     let mut best_fail_msg = ~"internal error: ran no matchers";
 
-    let s_d = cx.parse_sess().span_diagnostic;
-
     for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers
         match **lhs {
           MatchedNonterminal(NtMatchers(ref mtcs)) => {
             // `None` is because we're not interpolating
-            let arg_rdr = new_tt_reader(s_d,
+            let arg_rdr = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                         None,
                                         arg.iter()
                                            .map(|x| (*x).clone())
@@ -162,7 +160,8 @@ fn generic_extension(cx: &ExtCtxt,
                     _ => cx.span_bug(sp, "bad thing in rhs")
                 };
                 // rhs has holes ( `$id` and `$(...)` that need filled)
-                let trncbr = new_tt_reader(s_d, Some(named_matches),
+                let trncbr = new_tt_reader(&cx.parse_sess().span_diagnostic,
+                                           Some(named_matches),
                                            rhs);
                 let p = Parser(cx.parse_sess(), cx.cfg(), ~trncbr);
                 // Let the context choose how to interpret the result.
@@ -218,7 +217,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
 
 
     // Parse the macro_rules! invocation (`none` is for no interpolations):
-    let arg_reader = new_tt_reader(cx.parse_sess().span_diagnostic,
+    let arg_reader = new_tt_reader(&cx.parse_sess().span_diagnostic,
                                    None,
                                    arg.clone());
     let argument_map = parse_or_else(cx.parse_sess(),
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index a3f179e851a..e120f07742e 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -30,8 +30,8 @@ struct TtFrame {
     up: Option<@TtFrame>,
 }
 
-pub struct TtReader {
-    sp_diag: @SpanHandler,
+pub struct TtReader<'a> {
+    sp_diag: &'a SpanHandler,
     // the unzipped tree:
     priv stack: RefCell<@TtFrame>,
     /* for MBE-style macro transcription */
@@ -46,10 +46,10 @@ pub struct TtReader {
 /** This can do Macro-By-Example transcription. On the other hand, if
  *  `src` contains no `TTSeq`s and `TTNonterminal`s, `interp` can (and
  *  should) be none. */
-pub fn new_tt_reader(sp_diag: @SpanHandler,
-                     interp: Option<HashMap<Ident, @NamedMatch>>,
-                     src: Vec<ast::TokenTree> )
-                     -> TtReader {
+pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
+                         interp: Option<HashMap<Ident, @NamedMatch>>,
+                         src: Vec<ast::TokenTree> )
+                         -> TtReader<'a> {
     let r = TtReader {
         sp_diag: sp_diag,
         stack: RefCell::new(@TtFrame {
@@ -70,7 +70,7 @@ pub fn new_tt_reader(sp_diag: @SpanHandler,
         cur_span: RefCell::new(DUMMY_SP),
     };
     tt_next_token(&r); /* get cur_tok and cur_span set up */
-    return r;
+    r
 }
 
 fn dup_tt_frame(f: @TtFrame) -> @TtFrame {
@@ -86,7 +86,7 @@ fn dup_tt_frame(f: @TtFrame) -> @TtFrame {
     }
 }
 
-pub fn dup_tt_reader(r: &TtReader) -> TtReader {
+pub fn dup_tt_reader<'a>(r: &TtReader<'a>) -> TtReader<'a> {
     TtReader {
         sp_diag: r.sp_diag,
         stack: RefCell::new(dup_tt_frame(r.stack.get())),
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8cc74641db8..973682ea743 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -880,9 +880,9 @@ mod test {
     use super::*;
 
     // this version doesn't care about getting comments or docstrings in.
-    fn fake_print_crate(s: &mut pprust::State,
-                        krate: &ast::Crate) -> io::IoResult<()> {
-        pprust::print_mod(s, &krate.module, krate.attrs.as_slice())
+    fn fake_print_crate<A: pprust::PpAnn>(s: &mut pprust::State<A>,
+                                          krate: &ast::Crate) -> io::IoResult<()> {
+        s.print_mod(&krate.module, krate.attrs.as_slice())
     }
 
     // change every identifier to "zz"
@@ -914,9 +914,10 @@ mod test {
         let mut zz_fold = ToZzIdentFolder;
         let ast = string_to_crate(
             ~"#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}");
+        let folded_crate = zz_fold.fold_crate(ast);
         assert_pred!(matches_codepattern,
                      "matches_codepattern",
-                     pprust::to_str(&mut zz_fold.fold_crate(ast),fake_print_crate),
+                     pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
                      ~"#[a]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}");
     }
 
@@ -926,9 +927,10 @@ mod test {
         let ast = string_to_crate(
             ~"macro_rules! a {(b $c:expr $(d $e:token)f+ => \
               (g $(d $d $e)+))} ");
+        let folded_crate = zz_fold.fold_crate(ast);
         assert_pred!(matches_codepattern,
                      "matches_codepattern",
-                     pprust::to_str(&mut zz_fold.fold_crate(ast),fake_print_crate),
+                     pprust::to_str(|s| fake_print_crate(s, &folded_crate)),
                      ~"zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))");
     }
 }
diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs
index 0a74c7ca821..399648ef1d8 100644
--- a/src/libsyntax/parse/attr.rs
+++ b/src/libsyntax/parse/attr.rs
@@ -28,7 +28,7 @@ pub trait ParserAttr {
     fn parse_optional_meta(&mut self) -> Vec<@ast::MetaItem> ;
 }
 
-impl ParserAttr for Parser {
+impl<'a> ParserAttr for Parser<'a> {
     // Parse attributes that appear before an item
     fn parse_outer_attributes(&mut self) -> Vec<ast::Attribute> {
         let mut attrs: Vec<ast::Attribute> = Vec::new();
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index c2a2097de24..ed74fd416d1 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -346,10 +346,10 @@ pub struct Literal {
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
 pub fn gather_comments_and_literals(span_diagnostic:
-                                        @diagnostic::SpanHandler,
+                                        &diagnostic::SpanHandler,
                                     path: ~str,
                                     srdr: &mut io::Reader)
-                                 -> (Vec<Comment> , Vec<Literal> ) {
+                                 -> (Vec<Comment>, Vec<Literal>) {
     let src = srdr.read_to_end().unwrap();
     let src = str::from_utf8_owned(src).unwrap();
     let cm = CodeMap::new();
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index 884fc306f22..546aefc1297 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -18,6 +18,7 @@ use parse::token::{str_to_ident};
 
 use std::cell::{Cell, RefCell};
 use std::char;
+use std::rc::Rc;
 use std::mem::replace;
 use std::num::from_str_radix;
 
@@ -27,7 +28,7 @@ pub trait Reader {
     fn is_eof(&self) -> bool;
     fn next_token(&self) -> TokenAndSpan;
     fn fatal(&self, ~str) -> !;
-    fn span_diag(&self) -> @SpanHandler;
+    fn span_diag<'a>(&'a self) -> &'a SpanHandler;
     fn peek(&self) -> TokenAndSpan;
     fn dup(&self) -> ~Reader:;
 }
@@ -38,8 +39,8 @@ pub struct TokenAndSpan {
     sp: Span,
 }
 
-pub struct StringReader {
-    span_diagnostic: @SpanHandler,
+pub struct StringReader<'a> {
+    span_diagnostic: &'a SpanHandler,
     // The absolute offset within the codemap of the next character to read
     pos: Cell<BytePos>,
     // The absolute offset within the codemap of the last character read(curr)
@@ -48,36 +49,36 @@ pub struct StringReader {
     col: Cell<CharPos>,
     // The last character to be read
     curr: Cell<Option<char>>,
-    filemap: @codemap::FileMap,
+    filemap: Rc<codemap::FileMap>,
     /* cached: */
     peek_tok: RefCell<token::Token>,
     peek_span: RefCell<Span>,
 }
 
-impl StringReader {
+impl<'a> StringReader<'a> {
     pub fn curr_is(&self, c: char) -> bool {
         self.curr.get() == Some(c)
     }
 }
 
-pub fn new_string_reader(span_diagnostic: @SpanHandler,
-                         filemap: @codemap::FileMap)
-                      -> StringReader {
+pub fn new_string_reader<'a>(span_diagnostic: &'a SpanHandler,
+                             filemap: Rc<codemap::FileMap>)
+                             -> StringReader<'a> {
     let r = new_low_level_string_reader(span_diagnostic, filemap);
     string_advance_token(&r); /* fill in peek_* */
     r
 }
 
 /* For comments.rs, which hackily pokes into 'pos' and 'curr' */
-pub fn new_low_level_string_reader(span_diagnostic: @SpanHandler,
-                                   filemap: @codemap::FileMap)
-                                -> StringReader {
+pub fn new_low_level_string_reader<'a>(span_diagnostic: &'a SpanHandler,
+                                       filemap: Rc<codemap::FileMap>)
+                                       -> StringReader<'a> {
     // Force the initial reader bump to start on a fresh line
     let initial_char = '\n';
     let r = StringReader {
         span_diagnostic: span_diagnostic,
-        pos: Cell::new(filemap.start_pos),
-        last_pos: Cell::new(filemap.start_pos),
+        pos: Cell::new(filemap.deref().start_pos),
+        last_pos: Cell::new(filemap.deref().start_pos),
         col: Cell::new(CharPos(0)),
         curr: Cell::new(Some(initial_char)),
         filemap: filemap,
@@ -92,20 +93,20 @@ pub fn new_low_level_string_reader(span_diagnostic: @SpanHandler,
 // duplicating the string reader is probably a bad idea, in
 // that using them will cause interleaved pushes of line
 // offsets to the underlying filemap...
-fn dup_string_reader(r: &StringReader) -> StringReader {
+fn dup_string_reader<'a>(r: &StringReader<'a>) -> StringReader<'a> {
     StringReader {
         span_diagnostic: r.span_diagnostic,
         pos: Cell::new(r.pos.get()),
         last_pos: Cell::new(r.last_pos.get()),
         col: Cell::new(r.col.get()),
         curr: Cell::new(r.curr.get()),
-        filemap: r.filemap,
+        filemap: r.filemap.clone(),
         peek_tok: r.peek_tok.clone(),
         peek_span: r.peek_span.clone(),
     }
 }
 
-impl Reader for StringReader {
+impl<'a> Reader for StringReader<'a> {
     fn is_eof(&self) -> bool { is_eof(self) }
     // return the next token. EFFECT: advances the string_reader.
     fn next_token(&self) -> TokenAndSpan {
@@ -122,7 +123,7 @@ impl Reader for StringReader {
     fn fatal(&self, m: ~str) -> ! {
         self.span_diagnostic.span_fatal(self.peek_span.get(), m)
     }
-    fn span_diag(&self) -> @SpanHandler { self.span_diagnostic }
+    fn span_diag<'a>(&'a self) -> &'a SpanHandler { self.span_diagnostic }
     fn peek(&self) -> TokenAndSpan {
         // FIXME(pcwalton): Bad copy!
         TokenAndSpan {
@@ -133,7 +134,7 @@ impl Reader for StringReader {
     fn dup(&self) -> ~Reader: { ~dup_string_reader(self) as ~Reader: }
 }
 
-impl Reader for TtReader {
+impl<'a> Reader for TtReader<'a> {
     fn is_eof(&self) -> bool {
         let cur_tok = self.cur_tok.borrow();
         *cur_tok.get() == token::EOF
@@ -146,7 +147,7 @@ impl Reader for TtReader {
     fn fatal(&self, m: ~str) -> ! {
         self.sp_diag.span_fatal(self.cur_span.get(), m);
     }
-    fn span_diag(&self) -> @SpanHandler { self.sp_diag }
+    fn span_diag<'a>(&'a self) -> &'a SpanHandler { self.sp_diag }
     fn peek(&self) -> TokenAndSpan {
         TokenAndSpan {
             tok: self.cur_tok.get(),
@@ -189,7 +190,7 @@ fn fatal_span_verbose(rdr: &StringReader,
                    -> ! {
     let mut m = m;
     m.push_str(": ");
-    let s = rdr.filemap.src.slice(
+    let s = rdr.filemap.deref().src.slice(
                   byte_offset(rdr, from_pos).to_uint(),
                   byte_offset(rdr, to_pos).to_uint());
     m.push_str(s);
@@ -218,7 +219,7 @@ fn string_advance_token(r: &StringReader) {
 }
 
 fn byte_offset(rdr: &StringReader, pos: BytePos) -> BytePos {
-    (pos - rdr.filemap.start_pos)
+    (pos - rdr.filemap.deref().start_pos)
 }
 
 /// Calls `f` with a string slice of the source text spanning from `start`
@@ -240,7 +241,7 @@ fn with_str_from_to<T>(
                     end: BytePos,
                     f: |s: &str| -> T)
                     -> T {
-    f(rdr.filemap.src.slice(
+    f(rdr.filemap.deref().src.slice(
             byte_offset(rdr, start).to_uint(),
             byte_offset(rdr, end).to_uint()))
 }
@@ -250,21 +251,21 @@ fn with_str_from_to<T>(
 pub fn bump(rdr: &StringReader) {
     rdr.last_pos.set(rdr.pos.get());
     let current_byte_offset = byte_offset(rdr, rdr.pos.get()).to_uint();
-    if current_byte_offset < (rdr.filemap.src).len() {
+    if current_byte_offset < rdr.filemap.deref().src.len() {
         assert!(rdr.curr.get().is_some());
         let last_char = rdr.curr.get().unwrap();
-        let next = rdr.filemap.src.char_range_at(current_byte_offset);
+        let next = rdr.filemap.deref().src.char_range_at(current_byte_offset);
         let byte_offset_diff = next.next - current_byte_offset;
         rdr.pos.set(rdr.pos.get() + Pos::from_uint(byte_offset_diff));
         rdr.curr.set(Some(next.ch));
         rdr.col.set(rdr.col.get() + CharPos(1u));
         if last_char == '\n' {
-            rdr.filemap.next_line(rdr.last_pos.get());
+            rdr.filemap.deref().next_line(rdr.last_pos.get());
             rdr.col.set(CharPos(0u));
         }
 
         if byte_offset_diff > 1 {
-            rdr.filemap.record_multibyte_char(rdr.last_pos.get(), byte_offset_diff);
+            rdr.filemap.deref().record_multibyte_char(rdr.last_pos.get(), byte_offset_diff);
         }
     } else {
         rdr.curr.set(None);
@@ -275,8 +276,8 @@ pub fn is_eof(rdr: &StringReader) -> bool {
 }
 pub fn nextch(rdr: &StringReader) -> Option<char> {
     let offset = byte_offset(rdr, rdr.pos.get()).to_uint();
-    if offset < (rdr.filemap.src).len() {
-        Some(rdr.filemap.src.char_at(offset))
+    if offset < rdr.filemap.deref().src.len() {
+        Some(rdr.filemap.deref().src.char_at(offset))
     } else {
         None
     }
@@ -334,56 +335,55 @@ fn consume_any_line_comment(rdr: &StringReader)
                          -> Option<TokenAndSpan> {
     if rdr.curr_is('/') {
         match nextch(rdr) {
-          Some('/') => {
-            bump(rdr);
-            bump(rdr);
-            // line comments starting with "///" or "//!" are doc-comments
-            if rdr.curr_is('/') || rdr.curr_is('!') {
-                let start_bpos = rdr.pos.get() - BytePos(3);
-                while !rdr.curr_is('\n') && !is_eof(rdr) {
-                    bump(rdr);
-                }
-                let ret = with_str_from(rdr, start_bpos, |string| {
-                    // but comments with only more "/"s are not
-                    if !is_line_non_doc_comment(string) {
-                        Some(TokenAndSpan{
-                            tok: token::DOC_COMMENT(str_to_ident(string)),
-                            sp: codemap::mk_sp(start_bpos, rdr.pos.get())
-                        })
-                    } else {
-                        None
+            Some('/') => {
+                bump(rdr);
+                bump(rdr);
+                // line comments starting with "///" or "//!" are doc-comments
+                if rdr.curr_is('/') || rdr.curr_is('!') {
+                    let start_bpos = rdr.pos.get() - BytePos(3);
+                    while !rdr.curr_is('\n') && !is_eof(rdr) {
+                        bump(rdr);
                     }
-                });
+                    let ret = with_str_from(rdr, start_bpos, |string| {
+                        // but comments with only more "/"s are not
+                        if !is_line_non_doc_comment(string) {
+                            Some(TokenAndSpan{
+                                tok: token::DOC_COMMENT(str_to_ident(string)),
+                                sp: codemap::mk_sp(start_bpos, rdr.pos.get())
+                            })
+                        } else {
+                            None
+                        }
+                    });
 
-                if ret.is_some() {
-                    return ret;
+                    if ret.is_some() {
+                        return ret;
+                    }
+                } else {
+                    while !rdr.curr_is('\n') && !is_eof(rdr) { bump(rdr); }
                 }
-            } else {
-                while !rdr.curr_is('\n') && !is_eof(rdr) { bump(rdr); }
+                // Restart whitespace munch.
+                consume_whitespace_and_comments(rdr)
             }
-            // Restart whitespace munch.
-            return consume_whitespace_and_comments(rdr);
-          }
-          Some('*') => { bump(rdr); bump(rdr); return consume_block_comment(rdr); }
-          _ => ()
+            Some('*') => { bump(rdr); bump(rdr); consume_block_comment(rdr) }
+            _ => None
         }
     } else if rdr.curr_is('#') {
         if nextch_is(rdr, '!') {
             // I guess this is the only way to figure out if
             // we're at the beginning of the file...
-            let cmap = @CodeMap::new();
-            {
-                let mut files = cmap.files.borrow_mut();
-                files.get().push(rdr.filemap);
-            }
+            let cmap = CodeMap::new();
+            cmap.files.borrow_mut().get().push(rdr.filemap.clone());
             let loc = cmap.lookup_char_pos_adj(rdr.last_pos.get());
             if loc.line == 1u && loc.col == CharPos(0u) {
                 while !rdr.curr_is('\n') && !is_eof(rdr) { bump(rdr); }
                 return consume_whitespace_and_comments(rdr);
             }
         }
+        None
+    } else {
+        None
     }
-    return None;
 }
 
 pub fn is_block_non_doc_comment(s: &str) -> bool {
@@ -1007,28 +1007,24 @@ mod test {
     use std::io::util;
     use std::vec_ng::Vec;
 
-    // represents a testing reader (incl. both reader and interner)
-    struct Env {
-        string_reader: StringReader
+    fn mk_sh() -> diagnostic::SpanHandler {
+        let emitter = diagnostic::EmitterWriter::new(~util::NullWriter);
+        let handler = diagnostic::mk_handler(~emitter);
+        diagnostic::mk_span_handler(handler, CodeMap::new())
     }
 
     // open a string reader for the given string
-    fn setup(teststr: ~str) -> Env {
-        let cm = CodeMap::new();
-        let fm = cm.new_filemap(~"zebra.rs", teststr);
-        let writer = ~util::NullWriter;
-        let emitter = diagnostic::EmitterWriter::new(writer);
-        let handler = diagnostic::mk_handler(~emitter);
-        let span_handler = diagnostic::mk_span_handler(handler, @cm);
-        Env {
-            string_reader: new_string_reader(span_handler,fm)
-        }
+    fn setup<'a>(span_handler: &'a diagnostic::SpanHandler,
+                 teststr: ~str) -> StringReader<'a> {
+        let fm = span_handler.cm.new_filemap(~"zebra.rs", teststr);
+        new_string_reader(span_handler, fm)
     }
 
     #[test] fn t1 () {
-        let Env {string_reader} =
-            setup(~"/* my source file */ \
-                    fn main() { println!(\"zebra\"); }\n");
+        let span_handler = mk_sh();
+        let string_reader = setup(&span_handler,
+            ~"/* my source file */ \
+              fn main() { println!(\"zebra\"); }\n");
         let id = str_to_ident("fn");
         let tok1 = string_reader.next_token();
         let tok2 = TokenAndSpan{
@@ -1049,11 +1045,9 @@ mod test {
 
     // check that the given reader produces the desired stream
     // of tokens (stop checking after exhausting the expected vec)
-    fn check_tokenization (env: Env, expected: Vec<token::Token> ) {
+    fn check_tokenization (string_reader: StringReader, expected: Vec<token::Token> ) {
         for expected_tok in expected.iter() {
-            let TokenAndSpan {tok:actual_tok, sp: _} =
-                env.string_reader.next_token();
-            assert_eq!(&actual_tok,expected_tok);
+            assert_eq!(&string_reader.next_token().tok, expected_tok);
         }
     }
 
@@ -1063,71 +1057,55 @@ mod test {
     }
 
     #[test] fn doublecolonparsing () {
-        let env = setup (~"a b");
-        check_tokenization (env,
+        check_tokenization(setup(&mk_sh(), ~"a b"),
                            vec!(mk_ident("a",false),
                              mk_ident("b",false)));
     }
 
     #[test] fn dcparsing_2 () {
-        let env = setup (~"a::b");
-        check_tokenization (env,
+        check_tokenization(setup(&mk_sh(), ~"a::b"),
                            vec!(mk_ident("a",true),
                              token::MOD_SEP,
                              mk_ident("b",false)));
     }
 
     #[test] fn dcparsing_3 () {
-        let env = setup (~"a ::b");
-        check_tokenization (env,
+        check_tokenization(setup(&mk_sh(), ~"a ::b"),
                            vec!(mk_ident("a",false),
                              token::MOD_SEP,
                              mk_ident("b",false)));
     }
 
     #[test] fn dcparsing_4 () {
-        let env = setup (~"a:: b");
-        check_tokenization (env,
+        check_tokenization(setup(&mk_sh(), ~"a:: b"),
                            vec!(mk_ident("a",true),
                              token::MOD_SEP,
                              mk_ident("b",false)));
     }
 
     #[test] fn character_a() {
-        let env = setup(~"'a'");
-        let TokenAndSpan {tok, sp: _} =
-            env.string_reader.next_token();
-        assert_eq!(tok,token::LIT_CHAR('a' as u32));
+        assert_eq!(setup(&mk_sh(), ~"'a'").next_token().tok,
+                   token::LIT_CHAR('a' as u32));
     }
 
     #[test] fn character_space() {
-        let env = setup(~"' '");
-        let TokenAndSpan {tok, sp: _} =
-            env.string_reader.next_token();
-        assert_eq!(tok, token::LIT_CHAR(' ' as u32));
+        assert_eq!(setup(&mk_sh(), ~"' '").next_token().tok,
+                   token::LIT_CHAR(' ' as u32));
     }
 
     #[test] fn character_escaped() {
-        let env = setup(~"'\\n'");
-        let TokenAndSpan {tok, sp: _} =
-            env.string_reader.next_token();
-        assert_eq!(tok, token::LIT_CHAR('\n' as u32));
+        assert_eq!(setup(&mk_sh(), ~"'\\n'").next_token().tok,
+                   token::LIT_CHAR('\n' as u32));
     }
 
     #[test] fn lifetime_name() {
-        let env = setup(~"'abc");
-        let TokenAndSpan {tok, sp: _} =
-            env.string_reader.next_token();
-        let id = token::str_to_ident("abc");
-        assert_eq!(tok, token::LIFETIME(id));
+        assert_eq!(setup(&mk_sh(), ~"'abc").next_token().tok,
+                   token::LIFETIME(token::str_to_ident("abc")));
     }
 
     #[test] fn raw_string() {
-        let env = setup(~"r###\"\"#a\\b\x00c\"\"###");
-        let TokenAndSpan {tok, sp: _} =
-            env.string_reader.next_token();
-        let id = token::str_to_ident("\"#a\\b\x00c\"");
-        assert_eq!(tok, token::LIT_STR_RAW(id, 3));
+        assert_eq!(setup(&mk_sh(), ~"r###\"\"#a\\b\x00c\"\"###").next_token().tok,
+                   token::LIT_STR_RAW(token::str_to_ident("\"#a\\b\x00c\""), 3));
     }
 
     #[test] fn line_doc_comments() {
@@ -1137,10 +1115,8 @@ mod test {
     }
 
     #[test] fn nested_block_comments() {
-        let env = setup(~"/* /* */ */'a'");
-        let TokenAndSpan {tok, sp: _} =
-            env.string_reader.next_token();
-        assert_eq!(tok,token::LIT_CHAR('a' as u32));
+        assert_eq!(setup(&mk_sh(), ~"/* /* */ */'a'").next_token().tok,
+                   token::LIT_CHAR('a' as u32));
     }
 
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index cb49ad0905c..062bc100863 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -13,13 +13,13 @@
 
 use ast;
 use codemap::{Span, CodeMap, FileMap};
-use codemap;
 use diagnostic::{SpanHandler, mk_span_handler, default_handler};
 use parse::attr::ParserAttr;
 use parse::parser::Parser;
 
 use std::cell::RefCell;
 use std::io::File;
+use std::rc::Rc;
 use std::str;
 use std::vec_ng::Vec;
 
@@ -40,26 +40,20 @@ pub mod obsolete;
 
 // info about a parsing session.
 pub struct ParseSess {
-    cm: @codemap::CodeMap, // better be the same as the one in the reader!
-    span_diagnostic: @SpanHandler, // better be the same as the one in the reader!
+    span_diagnostic: SpanHandler, // better be the same as the one in the reader!
     /// Used to determine and report recursive mod inclusions
-    included_mod_stack: RefCell<Vec<Path> >,
+    included_mod_stack: RefCell<Vec<Path>>,
 }
 
-pub fn new_parse_sess() -> @ParseSess {
-    let cm = @CodeMap::new();
-    @ParseSess {
-        cm: cm,
-        span_diagnostic: mk_span_handler(default_handler(), cm),
+pub fn new_parse_sess() -> ParseSess {
+    ParseSess {
+        span_diagnostic: mk_span_handler(default_handler(), CodeMap::new()),
         included_mod_stack: RefCell::new(Vec::new()),
     }
 }
 
-pub fn new_parse_sess_special_handler(sh: @SpanHandler,
-                                      cm: @codemap::CodeMap)
-                                      -> @ParseSess {
-    @ParseSess {
-        cm: cm,
+pub fn new_parse_sess_special_handler(sh: SpanHandler) -> ParseSess {
+    ParseSess {
         span_diagnostic: sh,
         included_mod_stack: RefCell::new(Vec::new()),
     }
@@ -73,7 +67,7 @@ pub fn new_parse_sess_special_handler(sh: @SpanHandler,
 pub fn parse_crate_from_file(
     input: &Path,
     cfg: ast::CrateConfig,
-    sess: @ParseSess
+    sess: &ParseSess
 ) -> ast::Crate {
     new_parser_from_file(sess, cfg, input).parse_crate_mod()
     // why is there no p.abort_if_errors here?
@@ -82,17 +76,17 @@ pub fn parse_crate_from_file(
 pub fn parse_crate_attrs_from_file(
     input: &Path,
     cfg: ast::CrateConfig,
-    sess: @ParseSess
+    sess: &ParseSess
 ) -> Vec<ast::Attribute> {
     let mut parser = new_parser_from_file(sess, cfg, input);
     let (inner, _) = parser.parse_inner_attrs_and_next();
-    return inner;
+    inner
 }
 
 pub fn parse_crate_from_source_str(name: ~str,
                                    source: ~str,
                                    cfg: ast::CrateConfig,
-                                   sess: @ParseSess)
+                                   sess: &ParseSess)
                                    -> ast::Crate {
     let mut p = new_parser_from_source_str(sess,
                                            cfg,
@@ -104,20 +98,20 @@ pub fn parse_crate_from_source_str(name: ~str,
 pub fn parse_crate_attrs_from_source_str(name: ~str,
                                          source: ~str,
                                          cfg: ast::CrateConfig,
-                                         sess: @ParseSess)
+                                         sess: &ParseSess)
                                          -> Vec<ast::Attribute> {
     let mut p = new_parser_from_source_str(sess,
                                            cfg,
                                            name,
                                            source);
     let (inner, _) = maybe_aborted(p.parse_inner_attrs_and_next(),p);
-    return inner;
+    inner
 }
 
 pub fn parse_expr_from_source_str(name: ~str,
                                   source: ~str,
                                   cfg: ast::CrateConfig,
-                                  sess: @ParseSess)
+                                  sess: &ParseSess)
                                   -> @ast::Expr {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_expr(), p)
@@ -126,7 +120,7 @@ pub fn parse_expr_from_source_str(name: ~str,
 pub fn parse_item_from_source_str(name: ~str,
                                   source: ~str,
                                   cfg: ast::CrateConfig,
-                                  sess: @ParseSess)
+                                  sess: &ParseSess)
                                   -> Option<@ast::Item> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     let attrs = p.parse_outer_attributes();
@@ -136,7 +130,7 @@ pub fn parse_item_from_source_str(name: ~str,
 pub fn parse_meta_from_source_str(name: ~str,
                                   source: ~str,
                                   cfg: ast::CrateConfig,
-                                  sess: @ParseSess)
+                                  sess: &ParseSess)
                                   -> @ast::MetaItem {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_meta_item(),p)
@@ -146,7 +140,7 @@ pub fn parse_stmt_from_source_str(name: ~str,
                                   source: ~str,
                                   cfg: ast::CrateConfig,
                                   attrs: Vec<ast::Attribute> ,
-                                  sess: @ParseSess)
+                                  sess: &ParseSess)
                                   -> @ast::Stmt {
     let mut p = new_parser_from_source_str(
         sess,
@@ -160,7 +154,7 @@ pub fn parse_stmt_from_source_str(name: ~str,
 pub fn parse_tts_from_source_str(name: ~str,
                                  source: ~str,
                                  cfg: ast::CrateConfig,
-                                 sess: @ParseSess)
+                                 sess: &ParseSess)
                                  -> Vec<ast::TokenTree> {
     let mut p = new_parser_from_source_str(
         sess,
@@ -174,49 +168,45 @@ pub fn parse_tts_from_source_str(name: ~str,
 }
 
 // Create a new parser from a source string
-pub fn new_parser_from_source_str(sess: @ParseSess,
-                                  cfg: ast::CrateConfig,
-                                  name: ~str,
-                                  source: ~str)
-                                  -> Parser {
-    filemap_to_parser(sess,string_to_filemap(sess,source,name),cfg)
+pub fn new_parser_from_source_str<'a>(sess: &'a ParseSess,
+                                      cfg: ast::CrateConfig,
+                                      name: ~str,
+                                      source: ~str)
+                                      -> Parser<'a> {
+    filemap_to_parser(sess, string_to_filemap(sess, source, name), cfg)
 }
 
 /// Create a new parser, handling errors as appropriate
 /// if the file doesn't exist
-pub fn new_parser_from_file(
-    sess: @ParseSess,
-    cfg: ast::CrateConfig,
-    path: &Path
-) -> Parser {
-    filemap_to_parser(sess,file_to_filemap(sess,path,None),cfg)
+pub fn new_parser_from_file<'a>(sess: &'a ParseSess,
+                                cfg: ast::CrateConfig,
+                                path: &Path) -> Parser<'a> {
+    filemap_to_parser(sess, file_to_filemap(sess, path, None), cfg)
 }
 
 /// Given a session, a crate config, a path, and a span, add
 /// the file at the given path to the codemap, and return a parser.
 /// On an error, use the given span as the source of the problem.
-pub fn new_sub_parser_from_file(
-    sess: @ParseSess,
-    cfg: ast::CrateConfig,
-    path: &Path,
-    sp: Span
-) -> Parser {
-    filemap_to_parser(sess,file_to_filemap(sess,path,Some(sp)),cfg)
+pub fn new_sub_parser_from_file<'a>(sess: &'a ParseSess,
+                                    cfg: ast::CrateConfig,
+                                    path: &Path,
+                                    sp: Span) -> Parser<'a> {
+    filemap_to_parser(sess, file_to_filemap(sess, path, Some(sp)), cfg)
 }
 
 /// Given a filemap and config, return a parser
-pub fn filemap_to_parser(sess: @ParseSess,
-                         filemap: @FileMap,
-                         cfg: ast::CrateConfig) -> Parser {
-    tts_to_parser(sess,filemap_to_tts(sess,filemap),cfg)
+pub fn filemap_to_parser<'a>(sess: &'a ParseSess,
+                             filemap: Rc<FileMap>,
+                             cfg: ast::CrateConfig) -> Parser<'a> {
+    tts_to_parser(sess, filemap_to_tts(sess, filemap), cfg)
 }
 
 // must preserve old name for now, because quote! from the *existing*
 // compiler expands into it
-pub fn new_parser_from_tts(sess: @ParseSess,
-                     cfg: ast::CrateConfig,
-                     tts: Vec<ast::TokenTree> ) -> Parser {
-    tts_to_parser(sess,tts,cfg)
+pub fn new_parser_from_tts<'a>(sess: &'a ParseSess,
+                               cfg: ast::CrateConfig,
+                               tts: Vec<ast::TokenTree>) -> Parser<'a> {
+    tts_to_parser(sess, tts, cfg)
 }
 
 
@@ -224,8 +214,8 @@ pub fn new_parser_from_tts(sess: @ParseSess,
 
 /// Given a session and a path and an optional span (for error reporting),
 /// add the path to the session's codemap and return the new filemap.
-pub fn file_to_filemap(sess: @ParseSess, path: &Path, spanopt: Option<Span>)
-    -> @FileMap {
+pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
+    -> Rc<FileMap> {
     let err = |msg: &str| {
         match spanopt {
             Some(sp) => sess.span_diagnostic.span_fatal(sp, msg),
@@ -250,27 +240,27 @@ pub fn file_to_filemap(sess: @ParseSess, path: &Path, spanopt: Option<Span>)
 
 // given a session and a string, add the string to
 // the session's codemap and return the new filemap
-pub fn string_to_filemap(sess: @ParseSess, source: ~str, path: ~str)
-                         -> @FileMap {
-    sess.cm.new_filemap(path, source)
+pub fn string_to_filemap(sess: &ParseSess, source: ~str, path: ~str)
+                         -> Rc<FileMap> {
+    sess.span_diagnostic.cm.new_filemap(path, source)
 }
 
 // given a filemap, produce a sequence of token-trees
-pub fn filemap_to_tts(sess: @ParseSess, filemap: @FileMap)
+pub fn filemap_to_tts(sess: &ParseSess, filemap: Rc<FileMap>)
     -> Vec<ast::TokenTree> {
     // it appears to me that the cfg doesn't matter here... indeed,
     // parsing tt's probably shouldn't require a parser at all.
     let cfg = Vec::new();
-    let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap);
+    let srdr = lexer::new_string_reader(&sess.span_diagnostic, filemap);
     let mut p1 = Parser(sess, cfg, ~srdr);
     p1.parse_all_token_trees()
 }
 
 // given tts and cfg, produce a parser
-pub fn tts_to_parser(sess: @ParseSess,
-                     tts: Vec<ast::TokenTree> ,
-                     cfg: ast::CrateConfig) -> Parser {
-    let trdr = lexer::new_tt_reader(sess.span_diagnostic, None, tts);
+pub fn tts_to_parser<'a>(sess: &'a ParseSess,
+                         tts: Vec<ast::TokenTree>,
+                         cfg: ast::CrateConfig) -> Parser<'a> {
+    let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, tts);
     Parser(sess, cfg, ~trdr)
 }
 
@@ -594,7 +584,8 @@ mod test {
     }
 
     #[test] fn parse_ident_pat () {
-        let mut parser = string_to_parser(~"b");
+        let sess = new_parse_sess();
+        let mut parser = string_to_parser(&sess, ~"b");
         assert!(parser.parse_pat() ==
                    @ast::Pat{id: ast::DUMMY_NODE_ID,
                              node: ast::PatIdent(
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 393282dd063..1d7bf2ef6da 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -59,7 +59,7 @@ pub trait ParserObsoleteMethods {
     fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
 }
 
-impl ParserObsoleteMethods for Parser {
+impl<'a> ParserObsoleteMethods for Parser<'a> {
     /// Reports an obsolete syntax non-fatal error.
     fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
         let (kind_str, desc) = match kind {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f52effb8c81..27c86956499 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -284,8 +284,8 @@ struct ParsedItemsAndViewItems {
 
 /* ident is handled by common.rs */
 
-pub fn Parser(sess: @ParseSess, cfg: ast::CrateConfig, rdr: ~Reader:)
-              -> Parser {
+pub fn Parser<'a>(sess: &'a ParseSess, cfg: ast::CrateConfig, rdr: ~Reader:)
+              -> Parser<'a> {
     let tok0 = rdr.next_token();
     let span = tok0.sp;
     let placeholder = TokenAndSpan {
@@ -320,8 +320,8 @@ pub fn Parser(sess: @ParseSess, cfg: ast::CrateConfig, rdr: ~Reader:)
     }
 }
 
-pub struct Parser {
-    sess: @ParseSess,
+pub struct Parser<'a> {
+    sess: &'a ParseSess,
     cfg: CrateConfig,
     // the current token:
     token: token::Token,
@@ -354,7 +354,7 @@ fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
     is_plain_ident(t) || *t == token::UNDERSCORE
 }
 
-impl Parser {
+impl<'a> Parser<'a> {
     // convert a token to a string using self's reader
     pub fn token_to_str(token: &token::Token) -> ~str {
         token::to_str(token)
@@ -4150,7 +4150,7 @@ impl Parser {
                     outer_attrs: &[ast::Attribute],
                     id_sp: Span)
                     -> (ast::Item_, Vec<ast::Attribute> ) {
-        let mut prefix = Path::new(self.sess.cm.span_to_filename(self.span));
+        let mut prefix = Path::new(self.sess.span_diagnostic.cm.span_to_filename(self.span));
         prefix.pop();
         let mod_path = Path::new(".").join_many(self.mod_path_stack.as_slice());
         let dir_path = prefix.join(&mod_path);
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b1990476094..a35bdc307c0 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -25,27 +25,26 @@ use parse;
 use print::pp::{break_offset, word, space, zerobreak, hardbreak};
 use print::pp::{Breaks, Consistent, Inconsistent, eof};
 use print::pp;
-use print::pprust;
 
 use std::cast;
 use std::cell::RefCell;
 use std::char;
 use std::str;
 use std::io;
-use std::io::MemWriter;
+use std::io::{IoResult, MemWriter};
 use std::vec_ng::Vec;
 
 // The &mut State is stored here to prevent recursive type.
-pub enum AnnNode<'a, 'b> {
-    NodeBlock(&'a mut State<'a>, &'b ast::Block),
-    NodeItem(&'a mut State<'a>, &'b ast::Item),
-    NodeExpr(&'a mut State<'a>, &'b ast::Expr),
-    NodePat(&'a mut State<'a>, &'b ast::Pat),
+pub enum AnnNode<'a> {
+    NodeBlock(&'a ast::Block),
+    NodeItem(&'a ast::Item),
+    NodeExpr(&'a ast::Expr),
+    NodePat(&'a ast::Pat),
 }
 
 pub trait PpAnn {
-    fn pre(&self, _node: AnnNode) -> io::IoResult<()> { Ok(()) }
-    fn post(&self, _node: AnnNode) -> io::IoResult<()> { Ok(()) }
+    fn pre(&self, _state: &mut State<Self>, _node: AnnNode) -> IoResult<()> { Ok(()) }
+    fn post(&self, _state: &mut State<Self>, _node: AnnNode) -> IoResult<()> { Ok(()) }
 }
 
 pub struct NoAnn;
@@ -57,38 +56,23 @@ pub struct CurrentCommentAndLiteral {
     cur_lit: uint,
 }
 
-pub struct State<'a> {
+pub struct State<'a, A> {
     s: pp::Printer,
-    cm: Option<@CodeMap>,
+    cm: Option<&'a CodeMap>,
     intr: @token::IdentInterner,
     comments: Option<Vec<comments::Comment> >,
     literals: Option<Vec<comments::Literal> >,
     cur_cmnt_and_lit: CurrentCommentAndLiteral,
     boxes: RefCell<Vec<pp::Breaks> >,
-    ann: &'a PpAnn
+    ann: &'a A
 }
 
-pub fn ibox(s: &mut State, u: uint) -> io::IoResult<()> {
-    {
-        let mut boxes = s.boxes.borrow_mut();
-        boxes.get().push(pp::Inconsistent);
-    }
-    pp::ibox(&mut s.s, u)
+pub fn rust_printer(writer: ~io::Writer) -> State<'static, NoAnn> {
+    static NO_ANN: NoAnn = NoAnn;
+    rust_printer_annotated(writer, &NO_ANN)
 }
 
-pub fn end(s: &mut State) -> io::IoResult<()> {
-    {
-        let mut boxes = s.boxes.borrow_mut();
-        boxes.get().pop().unwrap();
-    }
-    pp::end(&mut s.s)
-}
-
-pub fn rust_printer(writer: ~io::Writer) -> State<'static> {
-    rust_printer_annotated(writer, &NoAnn)
-}
-
-pub fn rust_printer_annotated<'a>(writer: ~io::Writer, ann: &'a PpAnn) -> State<'a> {
+pub fn rust_printer_annotated<'a, A: PpAnn>(writer: ~io::Writer, ann: &'a A) -> State<'a, A> {
     State {
         s: pp::mk_printer(writer, default_columns),
         cm: None,
@@ -111,14 +95,14 @@ pub static default_columns: uint = 78u;
 // Requires you to pass an input filename and reader so that
 // it can scan the input text for comments and literals to
 // copy forward.
-pub fn print_crate(cm: @CodeMap,
-                   span_diagnostic: @diagnostic::SpanHandler,
-                   krate: &ast::Crate,
-                   filename: ~str,
-                   input: &mut io::Reader,
-                   out: ~io::Writer,
-                   ann: &PpAnn,
-                   is_expanded: bool) -> io::IoResult<()> {
+pub fn print_crate<'a, A: PpAnn>(cm: &'a CodeMap,
+                                 span_diagnostic: &diagnostic::SpanHandler,
+                                 krate: &ast::Crate,
+                                 filename: ~str,
+                                 input: &mut io::Reader,
+                                 out: ~io::Writer,
+                                 ann: &'a A,
+                                 is_expanded: bool) -> IoResult<()> {
     let (cmnts, lits) = comments::gather_comments_and_literals(
         span_diagnostic,
         filename,
@@ -144,973 +128,922 @@ pub fn print_crate(cm: @CodeMap,
         boxes: RefCell::new(Vec::new()),
         ann: ann
     };
-    print_crate_(&mut s, krate)
+    try!(s.print_mod(&krate.module, krate.attrs.as_slice()));
+    try!(s.print_remaining_comments());
+    eof(&mut s.s)
 }
 
-pub fn print_crate_(s: &mut State, krate: &ast::Crate) -> io::IoResult<()> {
-    try!(print_mod(s, &krate.module, krate.attrs.as_slice()));
-    try!(print_remaining_comments(s));
-    try!(eof(&mut s.s));
-    Ok(())
+pub fn to_str(f: |&mut State<NoAnn>| -> IoResult<()>) -> ~str {
+    let mut s = rust_printer(~MemWriter::new());
+    f(&mut s).unwrap();
+    eof(&mut s.s).unwrap();
+    unsafe {
+        // FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
+        // that we "know" to be a `MemWriter` that works around the lack of checked
+        // downcasts.
+        let (_, wr): (uint, ~MemWriter) = cast::transmute_copy(&s.s.out);
+        let result = str::from_utf8_owned(wr.get_ref().to_owned()).unwrap();
+        cast::forget(wr);
+        result
+    }
 }
 
 pub fn ty_to_str(ty: &ast::Ty) -> ~str {
-    to_str(ty, print_type)
+    to_str(|s| s.print_type(ty))
 }
 
 pub fn pat_to_str(pat: &ast::Pat) -> ~str {
-    to_str(pat, print_pat)
+    to_str(|s| s.print_pat(pat))
 }
 
 pub fn expr_to_str(e: &ast::Expr) -> ~str {
-    to_str(e, print_expr)
+    to_str(|s| s.print_expr(e))
 }
 
 pub fn lifetime_to_str(e: &ast::Lifetime) -> ~str {
-    to_str(e, print_lifetime)
+    to_str(|s| s.print_lifetime(e))
 }
 
 pub fn tt_to_str(tt: &ast::TokenTree) -> ~str {
-    to_str(tt, print_tt)
+    to_str(|s| s.print_tt(tt))
 }
 
 pub fn tts_to_str(tts: &[ast::TokenTree]) -> ~str {
-    to_str(&tts, print_tts)
+    to_str(|s| s.print_tts(&tts))
 }
 
-pub fn stmt_to_str(s: &ast::Stmt) -> ~str {
-    to_str(s, print_stmt)
+pub fn stmt_to_str(stmt: &ast::Stmt) -> ~str {
+    to_str(|s| s.print_stmt(stmt))
 }
 
 pub fn item_to_str(i: &ast::Item) -> ~str {
-    to_str(i, print_item)
+    to_str(|s| s.print_item(i))
 }
 
 pub fn generics_to_str(generics: &ast::Generics) -> ~str {
-    to_str(generics, print_generics)
+    to_str(|s| s.print_generics(generics))
 }
 
 pub fn path_to_str(p: &ast::Path) -> ~str {
-    to_str(p, |a,b| print_path(a, b, false))
+    to_str(|s| s.print_path(p, false))
 }
 
 pub fn fun_to_str(decl: &ast::FnDecl, purity: ast::Purity, name: ast::Ident,
                   opt_explicit_self: Option<ast::ExplicitSelf_>,
                   generics: &ast::Generics) -> ~str {
-    let wr = ~MemWriter::new();
-    let mut s = rust_printer(wr as ~io::Writer);
-    print_fn(&mut s, decl, Some(purity), AbiSet::Rust(),
-             name, generics, opt_explicit_self, ast::Inherited).unwrap();
-    end(&mut s).unwrap(); // Close the head box
-    end(&mut s).unwrap(); // Close the outer box
-    eof(&mut s.s).unwrap();
-    unsafe {
-        get_mem_writer(&mut s.s.out)
-    }
+    to_str(|s| {
+        try!(s.print_fn(decl, Some(purity), AbiSet::Rust(),
+                        name, generics, opt_explicit_self, ast::Inherited));
+        try!(s.end()); // Close the head box
+        s.end() // Close the outer box
+    })
 }
 
 pub fn block_to_str(blk: &ast::Block) -> ~str {
-    let wr = ~MemWriter::new();
-    let mut s = rust_printer(wr as ~io::Writer);
-    // containing cbox, will be closed by print-block at }
-    cbox(&mut s, indent_unit).unwrap();
-    // head-ibox, will be closed by print-block after {
-    ibox(&mut s, 0u).unwrap();
-    print_block(&mut s, blk).unwrap();
-    eof(&mut s.s).unwrap();
-    unsafe {
-        get_mem_writer(&mut s.s.out)
-    }
+    to_str(|s| {
+        // containing cbox, will be closed by print-block at }
+        try!(s.cbox(indent_unit));
+        // head-ibox, will be closed by print-block after {
+        try!(s.ibox(0u));
+        s.print_block(blk)
+    })
 }
 
 pub fn meta_item_to_str(mi: &ast::MetaItem) -> ~str {
-    to_str(mi, print_meta_item)
+    to_str(|s| s.print_meta_item(mi))
 }
 
 pub fn attribute_to_str(attr: &ast::Attribute) -> ~str {
-    to_str(attr, print_attribute)
+    to_str(|s| s.print_attribute(attr))
 }
 
-pub fn variant_to_str(var: &ast::Variant) -> ~str {
-    to_str(var, print_variant)
+pub fn lit_to_str(l: &ast::Lit) -> ~str {
+    to_str(|s| s.print_literal(l))
 }
 
-pub fn cbox(s: &mut State, u: uint) -> io::IoResult<()> {
-    {
-        let mut boxes = s.boxes.borrow_mut();
-        boxes.get().push(pp::Consistent);
-    }
-    pp::cbox(&mut s.s, u)
+pub fn explicit_self_to_str(explicit_self: ast::ExplicitSelf_) -> ~str {
+    to_str(|s| s.print_explicit_self(explicit_self, ast::MutImmutable).map(|_| {}))
 }
 
-// "raw box"
-pub fn rbox(s: &mut State, u: uint, b: pp::Breaks) -> io::IoResult<()> {
-    {
-        let mut boxes = s.boxes.borrow_mut();
-        boxes.get().push(b);
-    }
-    pp::rbox(&mut s.s, u, b)
+pub fn variant_to_str(var: &ast::Variant) -> ~str {
+    to_str(|s| s.print_variant(var))
 }
 
-pub fn nbsp(s: &mut State) -> io::IoResult<()> { word(&mut s.s, " ") }
-
-pub fn word_nbsp(s: &mut State, w: &str) -> io::IoResult<()> {
-    try!(word(&mut s.s, w));
-    nbsp(s)
+pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> ~str {
+    match vis {
+        ast::Private => format!("priv {}", s),
+        ast::Public => format!("pub {}", s),
+        ast::Inherited => s.to_owned()
+    }
 }
 
-pub fn word_space(s: &mut State, w: &str) -> io::IoResult<()> {
-    try!(word(&mut s.s, w));
-    space(&mut s.s)
-}
+impl<'a, A: PpAnn> State<'a, A> {
+    pub fn ibox(&mut self, u: uint) -> IoResult<()> {
+        self.boxes.borrow_mut().get().push(pp::Inconsistent);
+        pp::ibox(&mut self.s, u)
+    }
 
-pub fn popen(s: &mut State) -> io::IoResult<()> { word(&mut s.s, "(") }
+    pub fn end(&mut self) -> IoResult<()> {
+        self.boxes.borrow_mut().get().pop().unwrap();
+        pp::end(&mut self.s)
+    }
 
-pub fn pclose(s: &mut State) -> io::IoResult<()> { word(&mut s.s, ")") }
+    pub fn cbox(&mut self, u: uint) -> IoResult<()> {
+        self.boxes.borrow_mut().get().push(pp::Consistent);
+        pp::cbox(&mut self.s, u)
+    }
 
-pub fn head(s: &mut State, w: &str) -> io::IoResult<()> {
-    // outer-box is consistent
-    try!(cbox(s, indent_unit));
-    // head-box is inconsistent
-    try!(ibox(s, w.len() + 1));
-    // keyword that starts the head
-    if !w.is_empty() {
-        try!(word_nbsp(s, w));
+    // "raw box"
+    pub fn rbox(&mut self, u: uint, b: pp::Breaks) -> IoResult<()> {
+        self.boxes.borrow_mut().get().push(b);
+        pp::rbox(&mut self.s, u, b)
     }
-    Ok(())
-}
 
-pub fn bopen(s: &mut State) -> io::IoResult<()> {
-    try!(word(&mut s.s, "{"));
-    try!(end(s)); // close the head-box
-    Ok(())
-}
+    pub fn nbsp(&mut self) -> IoResult<()> { word(&mut self.s, " ") }
 
-pub fn bclose_(s: &mut State, span: codemap::Span,
-               indented: uint) -> io::IoResult<()> {
-    bclose_maybe_open(s, span, indented, true)
-}
-pub fn bclose_maybe_open (s: &mut State, span: codemap::Span,
-                          indented: uint, close_box: bool) -> io::IoResult<()> {
-    try!(maybe_print_comment(s, span.hi));
-    try!(break_offset_if_not_bol(s, 1u, -(indented as int)));
-    try!(word(&mut s.s, "}"));
-    if close_box {
-        try!(end(s)); // close the outer-box
-    }
-    Ok(())
-}
-pub fn bclose(s: &mut State, span: codemap::Span) -> io::IoResult<()> {
-    bclose_(s, span, indent_unit)
-}
+    pub fn word_nbsp(&mut self, w: &str) -> IoResult<()> {
+        try!(word(&mut self.s, w));
+        self.nbsp()
+    }
 
-pub fn is_begin(s: &mut State) -> bool {
-    match s.s.last_token() { pp::Begin(_) => true, _ => false }
-}
+    pub fn word_space(&mut self, w: &str) -> IoResult<()> {
+        try!(word(&mut self.s, w));
+        space(&mut self.s)
+    }
 
-pub fn is_end(s: &mut State) -> bool {
-    match s.s.last_token() { pp::End => true, _ => false }
-}
+    pub fn popen(&mut self) -> IoResult<()> { word(&mut self.s, "(") }
 
-pub fn is_bol(s: &mut State) -> bool {
-    return s.s.last_token().is_eof() || s.s.last_token().is_hardbreak_tok();
-}
+    pub fn pclose(&mut self) -> IoResult<()> { word(&mut self.s, ")") }
 
-pub fn in_cbox(s: &mut State) -> bool {
-    let boxes = s.boxes.borrow();
-    let len = boxes.get().len();
-    if len == 0u { return false; }
-    return *boxes.get().get(len - 1u) == pp::Consistent;
-}
+    pub fn head(&mut self, w: &str) -> IoResult<()> {
+        // outer-box is consistent
+        try!(self.cbox(indent_unit));
+        // head-box is inconsistent
+        try!(self.ibox(w.len() + 1));
+        // keyword that starts the head
+        if !w.is_empty() {
+            try!(self.word_nbsp(w));
+        }
+        Ok(())
+    }
 
-pub fn hardbreak_if_not_bol(s: &mut State) -> io::IoResult<()> {
-    if !is_bol(s) {
-        try!(hardbreak(&mut s.s))
+    pub fn bopen(&mut self) -> IoResult<()> {
+        try!(word(&mut self.s, "{"));
+        self.end() // close the head-box
     }
-    Ok(())
-}
-pub fn space_if_not_bol(s: &mut State) -> io::IoResult<()> {
-    if !is_bol(s) { try!(space(&mut s.s)); }
-    Ok(())
-}
-pub fn break_offset_if_not_bol(s: &mut State, n: uint,
-                               off: int) -> io::IoResult<()> {
-    if !is_bol(s) {
-        try!(break_offset(&mut s.s, n, off));
-    } else {
-        if off != 0 && s.s.last_token().is_hardbreak_tok() {
-            // We do something pretty sketchy here: tuck the nonzero
-            // offset-adjustment we were going to deposit along with the
-            // break into the previous hardbreak.
-            s.s.replace_last_token(pp::hardbreak_tok_offset(off));
-        }
-    }
-    Ok(())
-}
 
-// Synthesizes a comment that was not textually present in the original source
-// file.
-pub fn synth_comment(s: &mut State, text: ~str) -> io::IoResult<()> {
-    try!(word(&mut s.s, "/*"));
-    try!(space(&mut s.s));
-    try!(word(&mut s.s, text));
-    try!(space(&mut s.s));
-    try!(word(&mut s.s, "*/"));
-    Ok(())
-}
+    pub fn bclose_(&mut self, span: codemap::Span,
+                   indented: uint) -> IoResult<()> {
+        self.bclose_maybe_open(span, indented, true)
+    }
+    pub fn bclose_maybe_open (&mut self, span: codemap::Span,
+                              indented: uint, close_box: bool) -> IoResult<()> {
+        try!(self.maybe_print_comment(span.hi));
+        try!(self.break_offset_if_not_bol(1u, -(indented as int)));
+        try!(word(&mut self.s, "}"));
+        if close_box {
+            try!(self.end()); // close the outer-box
+        }
+        Ok(())
+    }
+    pub fn bclose(&mut self, span: codemap::Span) -> IoResult<()> {
+        self.bclose_(span, indent_unit)
+    }
 
-pub fn commasep<T>(s: &mut State, b: Breaks, elts: &[T],
-                   op: |&mut State, &T| -> io::IoResult<()>)
-    -> io::IoResult<()>
-{
-    try!(rbox(s, 0u, b));
-    let mut first = true;
-    for elt in elts.iter() {
-        if first { first = false; } else { try!(word_space(s, ",")); }
-        try!(op(s, elt));
-    }
-    end(s)
-}
+    pub fn is_begin(&mut self) -> bool {
+        match self.s.last_token() { pp::Begin(_) => true, _ => false }
+    }
 
+    pub fn is_end(&mut self) -> bool {
+        match self.s.last_token() { pp::End => true, _ => false }
+    }
 
-pub fn commasep_cmnt<T>(
-                     s: &mut State,
-                     b: Breaks,
-                     elts: &[T],
-                     op: |&mut State, &T| -> io::IoResult<()>,
-                     get_span: |&T| -> codemap::Span) -> io::IoResult<()> {
-    try!(rbox(s, 0u, b));
-    let len = elts.len();
-    let mut i = 0u;
-    for elt in elts.iter() {
-        try!(maybe_print_comment(s, get_span(elt).hi));
-        try!(op(s, elt));
-        i += 1u;
-        if i < len {
-            try!(word(&mut s.s, ","));
-            try!(maybe_print_trailing_comment(s, get_span(elt),
-                                                Some(get_span(&elts[i]).hi)));
-            try!(space_if_not_bol(s));
-        }
-    }
-    end(s)
-}
+    pub fn is_bol(&mut self) -> bool {
+        self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok()
+    }
 
-pub fn commasep_exprs(s: &mut State, b: Breaks,
-                      exprs: &[@ast::Expr]) -> io::IoResult<()> {
-    commasep_cmnt(s, b, exprs, |p, &e| print_expr(p, e), |e| e.span)
-}
+    pub fn in_cbox(&mut self) -> bool {
+        match self.boxes.borrow().get().last() {
+            Some(&last_box) => last_box == pp::Consistent,
+            None => false
+        }
+    }
 
-pub fn print_mod(s: &mut State, _mod: &ast::Mod,
-                 attrs: &[ast::Attribute]) -> io::IoResult<()> {
-    try!(print_inner_attributes(s, attrs));
-    for vitem in _mod.view_items.iter() {
-        try!(print_view_item(s, vitem));
+    pub fn hardbreak_if_not_bol(&mut self) -> IoResult<()> {
+        if !self.is_bol() {
+            try!(hardbreak(&mut self.s))
+        }
+        Ok(())
     }
-    for item in _mod.items.iter() {
-        try!(print_item(s, *item));
+    pub fn space_if_not_bol(&mut self) -> IoResult<()> {
+        if !self.is_bol() { try!(space(&mut self.s)); }
+        Ok(())
+    }
+    pub fn break_offset_if_not_bol(&mut self, n: uint,
+                                   off: int) -> IoResult<()> {
+        if !self.is_bol() {
+            break_offset(&mut self.s, n, off)
+        } else {
+            if off != 0 && self.s.last_token().is_hardbreak_tok() {
+                // We do something pretty sketchy here: tuck the nonzero
+                // offset-adjustment we were going to deposit along with the
+                // break into the previous hardbreak.
+                self.s.replace_last_token(pp::hardbreak_tok_offset(off));
+            }
+            Ok(())
+        }
     }
-    Ok(())
-}
 
-pub fn print_foreign_mod(s: &mut State, nmod: &ast::ForeignMod,
-                         attrs: &[ast::Attribute]) -> io::IoResult<()> {
-    try!(print_inner_attributes(s, attrs));
-    for vitem in nmod.view_items.iter() {
-        try!(print_view_item(s, vitem));
+    // Synthesizes a comment that was not textually present in the original source
+    // file.
+    pub fn synth_comment(&mut self, text: ~str) -> IoResult<()> {
+        try!(word(&mut self.s, "/*"));
+        try!(space(&mut self.s));
+        try!(word(&mut self.s, text));
+        try!(space(&mut self.s));
+        word(&mut self.s, "*/")
     }
-    for item in nmod.items.iter() {
-        try!(print_foreign_item(s, *item));
+
+    pub fn commasep<T>(&mut self, b: Breaks, elts: &[T],
+                       op: |&mut State<A>, &T| -> IoResult<()>)
+        -> IoResult<()> {
+        try!(self.rbox(0u, b));
+        let mut first = true;
+        for elt in elts.iter() {
+            if first { first = false; } else { try!(self.word_space(",")); }
+            try!(op(self, elt));
+        }
+        self.end()
+    }
+
+
+    pub fn commasep_cmnt<T>(
+                         &mut self,
+                         b: Breaks,
+                         elts: &[T],
+                         op: |&mut State<A>, &T| -> IoResult<()>,
+                         get_span: |&T| -> codemap::Span) -> IoResult<()> {
+        try!(self.rbox(0u, b));
+        let len = elts.len();
+        let mut i = 0u;
+        for elt in elts.iter() {
+            try!(self.maybe_print_comment(get_span(elt).hi));
+            try!(op(self, elt));
+            i += 1u;
+            if i < len {
+                try!(word(&mut self.s, ","));
+                try!(self.maybe_print_trailing_comment(get_span(elt),
+                                                    Some(get_span(&elts[i]).hi)));
+                try!(self.space_if_not_bol());
+            }
+        }
+        self.end()
     }
-    Ok(())
-}
 
-pub fn print_opt_lifetime(s: &mut State,
-                          lifetime: &Option<ast::Lifetime>) -> io::IoResult<()> {
-    for l in lifetime.iter() {
-        try!(print_lifetime(s, l));
-        try!(nbsp(s));
+    pub fn commasep_exprs(&mut self, b: Breaks,
+                          exprs: &[@ast::Expr]) -> IoResult<()> {
+        self.commasep_cmnt(b, exprs, |s, &e| s.print_expr(e), |e| e.span)
     }
-    Ok(())
-}
 
-pub fn print_type(s: &mut State, ty: &ast::Ty) -> io::IoResult<()> {
-    try!(maybe_print_comment(s, ty.span.lo));
-    try!(ibox(s, 0u));
-    match ty.node {
-        ast::TyNil => try!(word(&mut s.s, "()")),
-        ast::TyBot => try!(word(&mut s.s, "!")),
-        ast::TyBox(ty) => {
-            try!(word(&mut s.s, "@"));
-            try!(print_type(s, ty));
-        }
-        ast::TyUniq(ty) => {
-            try!(word(&mut s.s, "~"));
-            try!(print_type(s, ty));
-        }
-        ast::TyVec(ty) => {
-            try!(word(&mut s.s, "["));
-            try!(print_type(s, ty));
-            try!(word(&mut s.s, "]"));
-        }
-        ast::TyPtr(ref mt) => {
-            try!(word(&mut s.s, "*"));
-            try!(print_mt(s, mt));
-        }
-        ast::TyRptr(ref lifetime, ref mt) => {
-            try!(word(&mut s.s, "&"));
-            try!(print_opt_lifetime(s, lifetime));
-            try!(print_mt(s, mt));
-        }
-        ast::TyTup(ref elts) => {
-            try!(popen(s));
-            try!(commasep(s, Inconsistent, elts.as_slice(), print_type_ref));
-            if elts.len() == 1 {
-                try!(word(&mut s.s, ","));
-            }
-            try!(pclose(s));
-        }
-        ast::TyBareFn(f) => {
-            let generics = ast::Generics {
-                lifetimes: f.lifetimes.clone(),
-                ty_params: opt_vec::Empty
-            };
-            try!(print_ty_fn(s, Some(f.abis), None, &None,
-                               f.purity, ast::Many, f.decl, None, &None,
-                               Some(&generics), None));
-        }
-        ast::TyClosure(f) => {
-            let generics = ast::Generics {
-                lifetimes: f.lifetimes.clone(),
-                ty_params: opt_vec::Empty
-            };
-            try!(print_ty_fn(s, None, Some(f.sigil), &f.region,
-                               f.purity, f.onceness, f.decl, None, &f.bounds,
-                               Some(&generics), None));
+    pub fn print_mod(&mut self, _mod: &ast::Mod,
+                     attrs: &[ast::Attribute]) -> IoResult<()> {
+        try!(self.print_inner_attributes(attrs));
+        for vitem in _mod.view_items.iter() {
+            try!(self.print_view_item(vitem));
         }
-        ast::TyPath(ref path, ref bounds, _) => {
-            try!(print_bounded_path(s, path, bounds));
+        for item in _mod.items.iter() {
+            try!(self.print_item(*item));
         }
-        ast::TyFixedLengthVec(ty, v) => {
-            try!(word(&mut s.s, "["));
-            try!(print_type(s, ty));
-            try!(word(&mut s.s, ", .."));
-            try!(print_expr(s, v));
-            try!(word(&mut s.s, "]"));
+        Ok(())
+    }
+
+    pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
+                             attrs: &[ast::Attribute]) -> IoResult<()> {
+        try!(self.print_inner_attributes(attrs));
+        for vitem in nmod.view_items.iter() {
+            try!(self.print_view_item(vitem));
         }
-        ast::TyTypeof(e) => {
-            try!(word(&mut s.s, "typeof("));
-            try!(print_expr(s, e));
-            try!(word(&mut s.s, ")"));
+        for item in nmod.items.iter() {
+            try!(self.print_foreign_item(*item));
         }
-        ast::TyInfer => {
-            try!(word(&mut s.s, "_"));
+        Ok(())
+    }
+
+    pub fn print_opt_lifetime(&mut self,
+                              lifetime: &Option<ast::Lifetime>) -> IoResult<()> {
+        for l in lifetime.iter() {
+            try!(self.print_lifetime(l));
+            try!(self.nbsp());
         }
+        Ok(())
     }
-    end(s)
-}
 
-pub fn print_type_ref(s: &mut State, ty: &P<ast::Ty>) -> io::IoResult<()> {
-    print_type(s, *ty)
-}
+    pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
+        try!(self.maybe_print_comment(ty.span.lo));
+        try!(self.ibox(0u));
+        match ty.node {
+            ast::TyNil => try!(word(&mut self.s, "()")),
+            ast::TyBot => try!(word(&mut self.s, "!")),
+            ast::TyBox(ty) => {
+                try!(word(&mut self.s, "@"));
+                try!(self.print_type(ty));
+            }
+            ast::TyUniq(ty) => {
+                try!(word(&mut self.s, "~"));
+                try!(self.print_type(ty));
+            }
+            ast::TyVec(ty) => {
+                try!(word(&mut self.s, "["));
+                try!(self.print_type(ty));
+                try!(word(&mut self.s, "]"));
+            }
+            ast::TyPtr(ref mt) => {
+                try!(word(&mut self.s, "*"));
+                try!(self.print_mt(mt));
+            }
+            ast::TyRptr(ref lifetime, ref mt) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.print_opt_lifetime(lifetime));
+                try!(self.print_mt(mt));
+            }
+            ast::TyTup(ref elts) => {
+                try!(self.popen());
+                try!(self.commasep(Inconsistent, elts.as_slice(),
+                                   |s, ty| s.print_type_ref(ty)));
+                if elts.len() == 1 {
+                    try!(word(&mut self.s, ","));
+                }
+                try!(self.pclose());
+            }
+            ast::TyBareFn(f) => {
+                let generics = ast::Generics {
+                    lifetimes: f.lifetimes.clone(),
+                    ty_params: opt_vec::Empty
+                };
+                try!(self.print_ty_fn(Some(f.abis), None, &None,
+                                   f.purity, ast::Many, f.decl, None, &None,
+                                   Some(&generics), None));
+            }
+            ast::TyClosure(f) => {
+                let generics = ast::Generics {
+                    lifetimes: f.lifetimes.clone(),
+                    ty_params: opt_vec::Empty
+                };
+                try!(self.print_ty_fn(None, Some(f.sigil), &f.region,
+                                   f.purity, f.onceness, f.decl, None, &f.bounds,
+                                   Some(&generics), None));
+            }
+            ast::TyPath(ref path, ref bounds, _) => {
+                try!(self.print_bounded_path(path, bounds));
+            }
+            ast::TyFixedLengthVec(ty, v) => {
+                try!(word(&mut self.s, "["));
+                try!(self.print_type(ty));
+                try!(word(&mut self.s, ", .."));
+                try!(self.print_expr(v));
+                try!(word(&mut self.s, "]"));
+            }
+            ast::TyTypeof(e) => {
+                try!(word(&mut self.s, "typeof("));
+                try!(self.print_expr(e));
+                try!(word(&mut self.s, ")"));
+            }
+            ast::TyInfer => {
+                try!(word(&mut self.s, "_"));
+            }
+        }
+        self.end()
+    }
 
-pub fn print_foreign_item(s: &mut State,
-                          item: &ast::ForeignItem) -> io::IoResult<()> {
-    try!(hardbreak_if_not_bol(s));
-    try!(maybe_print_comment(s, item.span.lo));
-    try!(print_outer_attributes(s, item.attrs.as_slice()));
-    match item.node {
-        ast::ForeignItemFn(decl, ref generics) => {
-            try!(print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics,
-            None, item.vis));
-            try!(end(s)); // end head-ibox
-            try!(word(&mut s.s, ";"));
-            try!(end(s)); // end the outer fn box
-        }
-        ast::ForeignItemStatic(t, m) => {
-            try!(head(s, visibility_qualified(item.vis, "static")));
-            if m {
-                try!(word_space(s, "mut"));
-            }
-            try!(print_ident(s, item.ident));
-            try!(word_space(s, ":"));
-            try!(print_type(s, t));
-            try!(word(&mut s.s, ";"));
-            try!(end(s)); // end the head-ibox
-            try!(end(s)); // end the outer cbox
-        }
-    }
-    Ok(())
-}
+    pub fn print_type_ref(&mut self, ty: &P<ast::Ty>) -> IoResult<()> {
+        self.print_type(*ty)
+    }
 
-pub fn print_item(s: &mut State, item: &ast::Item) -> io::IoResult<()> {
-    try!(hardbreak_if_not_bol(s));
-    try!(maybe_print_comment(s, item.span.lo));
-    try!(print_outer_attributes(s, item.attrs.as_slice()));
-    {
-        let ann_node = NodeItem(s, item);
-        try!(s.ann.pre(ann_node));
-    }
-    match item.node {
-      ast::ItemStatic(ty, m, expr) => {
-        try!(head(s, visibility_qualified(item.vis, "static")));
-        if m == ast::MutMutable {
-            try!(word_space(s, "mut"));
-        }
-        try!(print_ident(s, item.ident));
-        try!(word_space(s, ":"));
-        try!(print_type(s, ty));
-        try!(space(&mut s.s));
-        try!(end(s)); // end the head-ibox
-
-        try!(word_space(s, "="));
-        try!(print_expr(s, expr));
-        try!(word(&mut s.s, ";"));
-        try!(end(s)); // end the outer cbox
-
-      }
-      ast::ItemFn(decl, purity, abi, ref typarams, body) => {
-        try!(print_fn(
-            s,
-            decl,
-            Some(purity),
-            abi,
-            item.ident,
-            typarams,
-            None,
-            item.vis
-        ));
-        try!(word(&mut s.s, " "));
-        try!(print_block_with_attrs(s, body, item.attrs.as_slice()));
-      }
-      ast::ItemMod(ref _mod) => {
-        try!(head(s, visibility_qualified(item.vis, "mod")));
-        try!(print_ident(s, item.ident));
-        try!(nbsp(s));
-        try!(bopen(s));
-        try!(print_mod(s, _mod, item.attrs.as_slice()));
-        try!(bclose(s, item.span));
-      }
-      ast::ItemForeignMod(ref nmod) => {
-        try!(head(s, "extern"));
-        try!(word_nbsp(s, nmod.abis.to_str()));
-        try!(bopen(s));
-        try!(print_foreign_mod(s, nmod, item.attrs.as_slice()));
-        try!(bclose(s, item.span));
-      }
-      ast::ItemTy(ty, ref params) => {
-        try!(ibox(s, indent_unit));
-        try!(ibox(s, 0u));
-        try!(word_nbsp(s, visibility_qualified(item.vis, "type")));
-        try!(print_ident(s, item.ident));
-        try!(print_generics(s, params));
-        try!(end(s)); // end the inner ibox
-
-        try!(space(&mut s.s));
-        try!(word_space(s, "="));
-        try!(print_type(s, ty));
-        try!(word(&mut s.s, ";"));
-        try!(end(s)); // end the outer ibox
-      }
-      ast::ItemEnum(ref enum_definition, ref params) => {
-        try!(print_enum_def(
-            s,
-            enum_definition,
-            params,
-            item.ident,
-            item.span,
-            item.vis
-        ));
-      }
-      ast::ItemStruct(struct_def, ref generics) => {
-          try!(head(s, visibility_qualified(item.vis, "struct")));
-          try!(print_struct(s, struct_def, generics, item.ident, item.span));
-      }
-
-      ast::ItemImpl(ref generics, ref opt_trait, ty, ref methods) => {
-        try!(head(s, visibility_qualified(item.vis, "impl")));
-        if generics.is_parameterized() {
-            try!(print_generics(s, generics));
-            try!(space(&mut s.s));
-        }
-
-        match opt_trait {
-            &Some(ref t) => {
-                try!(print_trait_ref(s, t));
-                try!(space(&mut s.s));
-                try!(word_space(s, "for"));
-            }
-            &None => ()
-        };
+    pub fn print_foreign_item(&mut self,
+                              item: &ast::ForeignItem) -> IoResult<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(item.span.lo));
+        try!(self.print_outer_attributes(item.attrs.as_slice()));
+        match item.node {
+            ast::ForeignItemFn(decl, ref generics) => {
+                try!(self.print_fn(decl, None, AbiSet::Rust(), item.ident, generics,
+                None, item.vis));
+                try!(self.end()); // end head-ibox
+                try!(word(&mut self.s, ";"));
+                self.end() // end the outer fn box
+            }
+            ast::ForeignItemStatic(t, m) => {
+                try!(self.head(visibility_qualified(item.vis, "static")));
+                if m {
+                    try!(self.word_space("mut"));
+                }
+                try!(self.print_ident(item.ident));
+                try!(self.word_space(":"));
+                try!(self.print_type(t));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the head-ibox
+                self.end() // end the outer cbox
+            }
+        }
+    }
 
-        try!(print_type(s, ty));
-
-        try!(space(&mut s.s));
-        try!(bopen(s));
-        try!(print_inner_attributes(s, item.attrs.as_slice()));
-        for meth in methods.iter() {
-           try!(print_method(s, *meth));
-        }
-        try!(bclose(s, item.span));
-      }
-      ast::ItemTrait(ref generics, ref traits, ref methods) => {
-        try!(head(s, visibility_qualified(item.vis, "trait")));
-        try!(print_ident(s, item.ident));
-        try!(print_generics(s, generics));
-        if traits.len() != 0u {
-            try!(word(&mut s.s, ":"));
-            for (i, trait_) in traits.iter().enumerate() {
-                try!(nbsp(s));
-                if i != 0 {
-                    try!(word_space(s, "+"));
+    pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(item.span.lo));
+        try!(self.print_outer_attributes(item.attrs.as_slice()));
+        try!(self.ann.pre(self, NodeItem(item)));
+        match item.node {
+            ast::ItemStatic(ty, m, expr) => {
+                try!(self.head(visibility_qualified(item.vis, "static")));
+                if m == ast::MutMutable {
+                    try!(self.word_space("mut"));
                 }
-                try!(print_path(s, &trait_.path, false));
-            }
-        }
-        try!(word(&mut s.s, " "));
-        try!(bopen(s));
-        for meth in methods.iter() {
-            try!(print_trait_method(s, meth));
-        }
-        try!(bclose(s, item.span));
-      }
-      // I think it's reasonable to hide the context here:
-      ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
-                                   ..}) => {
-        try!(print_visibility(s, item.vis));
-        try!(print_path(s, pth, false));
-        try!(word(&mut s.s, "! "));
-        try!(print_ident(s, item.ident));
-        try!(cbox(s, indent_unit));
-        try!(popen(s));
-        try!(print_tts(s, &(tts.as_slice())));
-        try!(pclose(s));
-        try!(end(s));
-      }
-    }
-    {
-        let ann_node = NodeItem(s, item);
-        try!(s.ann.post(ann_node));
-    }
-    Ok(())
-}
+                try!(self.print_ident(item.ident));
+                try!(self.word_space(":"));
+                try!(self.print_type(ty));
+                try!(space(&mut self.s));
+                try!(self.end()); // end the head-ibox
+
+                try!(self.word_space("="));
+                try!(self.print_expr(expr));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the outer cbox
+            }
+            ast::ItemFn(decl, purity, abi, ref typarams, body) => {
+                try!(self.print_fn(
+                    decl,
+                    Some(purity),
+                    abi,
+                    item.ident,
+                    typarams,
+                    None,
+                    item.vis
+                ));
+                try!(word(&mut self.s, " "));
+                try!(self.print_block_with_attrs(body, item.attrs.as_slice()));
+            }
+            ast::ItemMod(ref _mod) => {
+                try!(self.head(visibility_qualified(item.vis, "mod")));
+                try!(self.print_ident(item.ident));
+                try!(self.nbsp());
+                try!(self.bopen());
+                try!(self.print_mod(_mod, item.attrs.as_slice()));
+                try!(self.bclose(item.span));
+            }
+            ast::ItemForeignMod(ref nmod) => {
+                try!(self.head("extern"));
+                try!(self.word_nbsp(nmod.abis.to_str()));
+                try!(self.bopen());
+                try!(self.print_foreign_mod(nmod, item.attrs.as_slice()));
+                try!(self.bclose(item.span));
+            }
+            ast::ItemTy(ty, ref params) => {
+                try!(self.ibox(indent_unit));
+                try!(self.ibox(0u));
+                try!(self.word_nbsp(visibility_qualified(item.vis, "type")));
+                try!(self.print_ident(item.ident));
+                try!(self.print_generics(params));
+                try!(self.end()); // end the inner ibox
+
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                try!(self.print_type(ty));
+                try!(word(&mut self.s, ";"));
+                try!(self.end()); // end the outer ibox
+            }
+            ast::ItemEnum(ref enum_definition, ref params) => {
+                try!(self.print_enum_def(
+                    enum_definition,
+                    params,
+                    item.ident,
+                    item.span,
+                    item.vis
+                ));
+            }
+            ast::ItemStruct(struct_def, ref generics) => {
+                try!(self.head(visibility_qualified(item.vis, "struct")));
+                try!(self.print_struct(struct_def, generics, item.ident, item.span));
+            }
 
-fn print_trait_ref(s: &mut State, t: &ast::TraitRef) -> io::IoResult<()> {
-    print_path(s, &t.path, false)
-}
+            ast::ItemImpl(ref generics, ref opt_trait, ty, ref methods) => {
+                try!(self.head(visibility_qualified(item.vis, "impl")));
+                if generics.is_parameterized() {
+                    try!(self.print_generics(generics));
+                    try!(space(&mut self.s));
+                }
 
-pub fn print_enum_def(s: &mut State, enum_definition: &ast::EnumDef,
-                      generics: &ast::Generics, ident: ast::Ident,
-                      span: codemap::Span,
-                      visibility: ast::Visibility) -> io::IoResult<()> {
-    try!(head(s, visibility_qualified(visibility, "enum")));
-    try!(print_ident(s, ident));
-    try!(print_generics(s, generics));
-    try!(space(&mut s.s));
-    try!(print_variants(s, enum_definition.variants.as_slice(), span));
-    Ok(())
-}
+                match opt_trait {
+                    &Some(ref t) => {
+                        try!(self.print_trait_ref(t));
+                        try!(space(&mut self.s));
+                        try!(self.word_space("for"));
+                    }
+                    &None => {}
+                }
 
-pub fn print_variants(s: &mut State,
-                      variants: &[P<ast::Variant>],
-                      span: codemap::Span) -> io::IoResult<()> {
-    try!(bopen(s));
-    for &v in variants.iter() {
-        try!(space_if_not_bol(s));
-        try!(maybe_print_comment(s, v.span.lo));
-        try!(print_outer_attributes(s, v.node.attrs.as_slice()));
-        try!(ibox(s, indent_unit));
-        try!(print_variant(s, v));
-        try!(word(&mut s.s, ","));
-        try!(end(s));
-        try!(maybe_print_trailing_comment(s, v.span, None));
-    }
-    bclose(s, span)
-}
+                try!(self.print_type(ty));
 
-pub fn visibility_to_str(vis: ast::Visibility) -> ~str {
-    match vis {
-        ast::Private => ~"priv",
-        ast::Public => ~"pub",
-        ast::Inherited => ~""
-    }
-}
+                try!(space(&mut self.s));
+                try!(self.bopen());
+                try!(self.print_inner_attributes(item.attrs.as_slice()));
+                for meth in methods.iter() {
+                    try!(self.print_method(*meth));
+                }
+                try!(self.bclose(item.span));
+            }
+            ast::ItemTrait(ref generics, ref traits, ref methods) => {
+                try!(self.head(visibility_qualified(item.vis, "trait")));
+                try!(self.print_ident(item.ident));
+                try!(self.print_generics(generics));
+                if traits.len() != 0u {
+                    try!(word(&mut self.s, ":"));
+                    for (i, trait_) in traits.iter().enumerate() {
+                        try!(self.nbsp());
+                        if i != 0 {
+                            try!(self.word_space("+"));
+                        }
+                        try!(self.print_path(&trait_.path, false));
+                    }
+                }
+                try!(word(&mut self.s, " "));
+                try!(self.bopen());
+                for meth in methods.iter() {
+                    try!(self.print_trait_method(meth));
+                }
+                try!(self.bclose(item.span));
+            }
+            // I think it's reasonable to hide the context here:
+            ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
+                                            ..}) => {
+                try!(self.print_visibility(item.vis));
+                try!(self.print_path(pth, false));
+                try!(word(&mut self.s, "! "));
+                try!(self.print_ident(item.ident));
+                try!(self.cbox(indent_unit));
+                try!(self.popen());
+                try!(self.print_tts(&(tts.as_slice())));
+                try!(self.pclose());
+                try!(self.end());
+            }
+        }
+        self.ann.post(self, NodeItem(item))
+    }
+
+    fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
+        self.print_path(&t.path, false)
+    }
+
+    pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef,
+                          generics: &ast::Generics, ident: ast::Ident,
+                          span: codemap::Span,
+                          visibility: ast::Visibility) -> IoResult<()> {
+        try!(self.head(visibility_qualified(visibility, "enum")));
+        try!(self.print_ident(ident));
+        try!(self.print_generics(generics));
+        try!(space(&mut self.s));
+        self.print_variants(enum_definition.variants.as_slice(), span)
+    }
+
+    pub fn print_variants(&mut self,
+                          variants: &[P<ast::Variant>],
+                          span: codemap::Span) -> IoResult<()> {
+        try!(self.bopen());
+        for &v in variants.iter() {
+            try!(self.space_if_not_bol());
+            try!(self.maybe_print_comment(v.span.lo));
+            try!(self.print_outer_attributes(v.node.attrs.as_slice()));
+            try!(self.ibox(indent_unit));
+            try!(self.print_variant(v));
+            try!(word(&mut self.s, ","));
+            try!(self.end());
+            try!(self.maybe_print_trailing_comment(v.span, None));
+        }
+        self.bclose(span)
+    }
+
+    pub fn print_visibility(&mut self, vis: ast::Visibility) -> IoResult<()> {
+        match vis {
+            ast::Private => self.word_nbsp("priv"),
+            ast::Public => self.word_nbsp("pub"),
+            ast::Inherited => Ok(())
+        }
+    }
+
+    pub fn print_struct(&mut self,
+                        struct_def: &ast::StructDef,
+                        generics: &ast::Generics,
+                        ident: ast::Ident,
+                        span: codemap::Span) -> IoResult<()> {
+        try!(self.print_ident(ident));
+        try!(self.print_generics(generics));
+        if ast_util::struct_def_is_tuple_like(struct_def) {
+            if !struct_def.fields.is_empty() {
+                try!(self.popen());
+                try!(self.commasep(
+                    Inconsistent, struct_def.fields.as_slice(),
+                    |s, field| {
+                        match field.node.kind {
+                            ast::NamedField(..) => fail!("unexpected named field"),
+                            ast::UnnamedField => {
+                                try!(s.maybe_print_comment(field.span.lo));
+                                s.print_type(field.node.ty)
+                            }
+                        }
+                    }
+                ));
+                try!(self.pclose());
+            }
+            try!(word(&mut self.s, ";"));
+            try!(self.end());
+            self.end() // close the outer-box
+        } else {
+            try!(self.nbsp());
+            try!(self.bopen());
+            try!(self.hardbreak_if_not_bol());
 
-pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> ~str {
-    match vis {
-        ast::Private | ast::Public => visibility_to_str(vis) + " " + s,
-        ast::Inherited => s.to_owned()
-    }
-}
+            for field in struct_def.fields.iter() {
+                match field.node.kind {
+                    ast::UnnamedField => fail!("unexpected unnamed field"),
+                    ast::NamedField(ident, visibility) => {
+                        try!(self.hardbreak_if_not_bol());
+                        try!(self.maybe_print_comment(field.span.lo));
+                        try!(self.print_outer_attributes(field.node.attrs.as_slice()));
+                        try!(self.print_visibility(visibility));
+                        try!(self.print_ident(ident));
+                        try!(self.word_nbsp(":"));
+                        try!(self.print_type(field.node.ty));
+                        try!(word(&mut self.s, ","));
+                    }
+                }
+            }
 
-pub fn print_visibility(s: &mut State, vis: ast::Visibility) -> io::IoResult<()> {
-    match vis {
-        ast::Private | ast::Public =>
-            try!(word_nbsp(s, visibility_to_str(vis))),
-        ast::Inherited => ()
+            self.bclose(span)
+        }
     }
-    Ok(())
-}
 
-pub fn print_struct(s: &mut State,
-                    struct_def: &ast::StructDef,
-                    generics: &ast::Generics,
-                    ident: ast::Ident,
-                    span: codemap::Span) -> io::IoResult<()> {
-    try!(print_ident(s, ident));
-    try!(print_generics(s, generics));
-    if ast_util::struct_def_is_tuple_like(struct_def) {
-        if !struct_def.fields.is_empty() {
-            try!(popen(s));
-            try!(commasep(s,
-                          Inconsistent,
-                          struct_def.fields.as_slice(),
-                          |s, field| {
-                match field.node.kind {
-                    ast::NamedField(..) => fail!("unexpected named field"),
-                    ast::UnnamedField => {
-                        try!(maybe_print_comment(s, field.span.lo));
-                        try!(print_type(s, field.node.ty));
-                    }
+    /// This doesn't deserve to be called "pretty" printing, but it should be
+    /// meaning-preserving. A quick hack that might help would be to look at the
+    /// spans embedded in the TTs to decide where to put spaces and newlines.
+    /// But it'd be better to parse these according to the grammar of the
+    /// appropriate macro, transcribe back into the grammar we just parsed from,
+    /// and then pretty-print the resulting AST nodes (so, e.g., we print
+    /// expression arguments as expressions). It can be done! I think.
+    pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> {
+        match *tt {
+            ast::TTDelim(ref tts) => self.print_tts(&(tts.as_slice())),
+            ast::TTTok(_, ref tk) => {
+                word(&mut self.s, parse::token::to_str(tk))
+            }
+            ast::TTSeq(_, ref tts, ref sep, zerok) => {
+                try!(word(&mut self.s, "$("));
+                for tt_elt in (*tts).iter() {
+                    try!(self.print_tt(tt_elt));
                 }
-                Ok(())
-            }));
-            try!(pclose(s));
-        }
-        try!(word(&mut s.s, ";"));
-        try!(end(s));
-        end(s) // close the outer-box
-    } else {
-        try!(nbsp(s));
-        try!(bopen(s));
-        try!(hardbreak_if_not_bol(s));
-
-        for field in struct_def.fields.iter() {
-            match field.node.kind {
-                ast::UnnamedField => fail!("unexpected unnamed field"),
-                ast::NamedField(ident, visibility) => {
-                    try!(hardbreak_if_not_bol(s));
-                    try!(maybe_print_comment(s, field.span.lo));
-                    try!(print_outer_attributes(s,
-                                                field.node.attrs.as_slice()));
-                    try!(print_visibility(s, visibility));
-                    try!(print_ident(s, ident));
-                    try!(word_nbsp(s, ":"));
-                    try!(print_type(s, field.node.ty));
-                    try!(word(&mut s.s, ","));
+                try!(word(&mut self.s, ")"));
+                match *sep {
+                    Some(ref tk) => {
+                        try!(word(&mut self.s, parse::token::to_str(tk)));
+                    }
+                    None => ()
                 }
+                word(&mut self.s, if zerok { "*" } else { "+" })
+            }
+            ast::TTNonterminal(_, name) => {
+                try!(word(&mut self.s, "$"));
+                self.print_ident(name)
             }
         }
-
-        bclose(s, span)
     }
-}
 
-/// This doesn't deserve to be called "pretty" printing, but it should be
-/// meaning-preserving. A quick hack that might help would be to look at the
-/// spans embedded in the TTs to decide where to put spaces and newlines.
-/// But it'd be better to parse these according to the grammar of the
-/// appropriate macro, transcribe back into the grammar we just parsed from,
-/// and then pretty-print the resulting AST nodes (so, e.g., we print
-/// expression arguments as expressions). It can be done! I think.
-pub fn print_tt(s: &mut State, tt: &ast::TokenTree) -> io::IoResult<()> {
-    match *tt {
-        ast::TTDelim(ref tts) => print_tts(s, &(tts.as_slice())),
-        ast::TTTok(_, ref tk) => {
-            word(&mut s.s, parse::token::to_str(tk))
-        }
-        ast::TTSeq(_, ref tts, ref sep, zerok) => {
-            try!(word(&mut s.s, "$("));
-            for tt_elt in (*tts).iter() {
-                try!(print_tt(s, tt_elt));
-            }
-            try!(word(&mut s.s, ")"));
-            match *sep {
-                Some(ref tk) => {
-                    try!(word(&mut s.s, parse::token::to_str(tk)));
+    pub fn print_tts(&mut self, tts: & &[ast::TokenTree]) -> IoResult<()> {
+        try!(self.ibox(0));
+        for (i, tt) in tts.iter().enumerate() {
+            if i != 0 {
+                try!(space(&mut self.s));
+            }
+            try!(self.print_tt(tt));
+        }
+        self.end()
+    }
+
+    pub fn print_variant(&mut self, v: &ast::Variant) -> IoResult<()> {
+        try!(self.print_visibility(v.node.vis));
+        match v.node.kind {
+            ast::TupleVariantKind(ref args) => {
+                try!(self.print_ident(v.node.name));
+                if !args.is_empty() {
+                    try!(self.popen());
+                    try!(self.commasep(Consistent,
+                                       args.as_slice(),
+                                       |s, arg| s.print_type(arg.ty)));
+                    try!(self.pclose());
                 }
-                None => ()
             }
-            word(&mut s.s, if zerok { "*" } else { "+" })
+            ast::StructVariantKind(struct_def) => {
+                try!(self.head(""));
+                let generics = ast_util::empty_generics();
+                try!(self.print_struct(struct_def, &generics, v.node.name, v.span));
+            }
         }
-        ast::TTNonterminal(_, name) => {
-            try!(word(&mut s.s, "$"));
-            print_ident(s, name)
+        match v.node.disr_expr {
+            Some(d) => {
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                self.print_expr(d)
+            }
+            _ => Ok(())
+        }
+    }
+
+    pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(m.span.lo));
+        try!(self.print_outer_attributes(m.attrs.as_slice()));
+        try!(self.print_ty_fn(None,
+                              None,
+                              &None,
+                              m.purity,
+                              ast::Many,
+                              m.decl,
+                              Some(m.ident),
+                              &None,
+                              Some(&m.generics),
+                              Some(m.explicit_self.node)));
+        word(&mut self.s, ";")
+    }
+
+    pub fn print_trait_method(&mut self,
+                              m: &ast::TraitMethod) -> IoResult<()> {
+        match *m {
+            Required(ref ty_m) => self.print_ty_method(ty_m),
+            Provided(m) => self.print_method(m)
+        }
+    }
+
+    pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(meth.span.lo));
+        try!(self.print_outer_attributes(meth.attrs.as_slice()));
+        try!(self.print_fn(meth.decl, Some(meth.purity), AbiSet::Rust(),
+                        meth.ident, &meth.generics, Some(meth.explicit_self.node),
+                        meth.vis));
+        try!(word(&mut self.s, " "));
+        self.print_block_with_attrs(meth.body, meth.attrs.as_slice())
+    }
+
+    pub fn print_outer_attributes(&mut self,
+                                  attrs: &[ast::Attribute]) -> IoResult<()> {
+        let mut count = 0;
+        for attr in attrs.iter() {
+            match attr.node.style {
+                ast::AttrOuter => {
+                    try!(self.print_attribute(attr));
+                    count += 1;
+                }
+                _ => {/* fallthrough */ }
+            }
         }
-    }
-}
-
-pub fn print_tts(s: &mut State, tts: & &[ast::TokenTree]) -> io::IoResult<()> {
-    try!(ibox(s, 0));
-    for (i, tt) in tts.iter().enumerate() {
-        if i != 0 {
-            try!(space(&mut s.s));
+        if count > 0 {
+            try!(self.hardbreak_if_not_bol());
         }
-        try!(print_tt(s, tt));
+        Ok(())
     }
-    end(s)
-}
 
-pub fn print_variant(s: &mut State, v: &ast::Variant) -> io::IoResult<()> {
-    try!(print_visibility(s, v.node.vis));
-    match v.node.kind {
-        ast::TupleVariantKind(ref args) => {
-            try!(print_ident(s, v.node.name));
-            if !args.is_empty() {
-                try!(popen(s));
-                fn print_variant_arg(s: &mut State,
-                                     arg: &ast::VariantArg) -> io::IoResult<()> {
-                    print_type(s, arg.ty)
+    pub fn print_inner_attributes(&mut self,
+                                  attrs: &[ast::Attribute]) -> IoResult<()> {
+        let mut count = 0;
+        for attr in attrs.iter() {
+            match attr.node.style {
+                ast::AttrInner => {
+                    try!(self.print_attribute(attr));
+                    if !attr.node.is_sugared_doc {
+                        try!(word(&mut self.s, ";"));
+                    }
+                    count += 1;
                 }
-                try!(commasep(s,
-                              Consistent,
-                              args.as_slice(),
-                              print_variant_arg));
-                try!(pclose(s));
+                _ => {/* fallthrough */ }
             }
         }
-        ast::StructVariantKind(struct_def) => {
-            try!(head(s, ""));
-            let generics = ast_util::empty_generics();
-            try!(print_struct(s, struct_def, &generics, v.node.name, v.span));
+        if count > 0 {
+            try!(self.hardbreak_if_not_bol());
         }
+        Ok(())
     }
-    match v.node.disr_expr {
-      Some(d) => {
-        try!(space(&mut s.s));
-        try!(word_space(s, "="));
-        try!(print_expr(s, d));
-      }
-      _ => ()
-    }
-    Ok(())
-}
-
-pub fn print_ty_method(s: &mut State, m: &ast::TypeMethod) -> io::IoResult<()> {
-    try!(hardbreak_if_not_bol(s));
-    try!(maybe_print_comment(s, m.span.lo));
-    try!(print_outer_attributes(s, m.attrs.as_slice()));
-    try!(print_ty_fn(s,
-                       None,
-                       None,
-                       &None,
-                       m.purity,
-                       ast::Many,
-                       m.decl,
-                       Some(m.ident),
-                       &None,
-                       Some(&m.generics),
-                       Some(m.explicit_self.node)));
-    word(&mut s.s, ";")
-}
-
-pub fn print_trait_method(s: &mut State,
-                          m: &ast::TraitMethod) -> io::IoResult<()> {
-    match *m {
-        Required(ref ty_m) => print_ty_method(s, ty_m),
-        Provided(m) => print_method(s, m)
-    }
-}
 
-pub fn print_method(s: &mut State, meth: &ast::Method) -> io::IoResult<()> {
-    try!(hardbreak_if_not_bol(s));
-    try!(maybe_print_comment(s, meth.span.lo));
-    try!(print_outer_attributes(s, meth.attrs.as_slice()));
-    try!(print_fn(s, meth.decl, Some(meth.purity), AbiSet::Rust(),
-                    meth.ident, &meth.generics, Some(meth.explicit_self.node),
-                    meth.vis));
-    try!(word(&mut s.s, " "));
-    print_block_with_attrs(s, meth.body, meth.attrs.as_slice())
-}
-
-pub fn print_outer_attributes(s: &mut State,
-                              attrs: &[ast::Attribute]) -> io::IoResult<()> {
-    let mut count = 0;
-    for attr in attrs.iter() {
-        match attr.node.style {
-          ast::AttrOuter => {
-              try!(print_attribute(s, attr));
-              count += 1;
-          }
-          _ => {/* fallthrough */ }
+    pub fn print_attribute(&mut self, attr: &ast::Attribute) -> IoResult<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(attr.span.lo));
+        if attr.node.is_sugared_doc {
+            word(&mut self.s, attr.value_str().unwrap().get())
+        } else {
+            try!(word(&mut self.s, "#["));
+            try!(self.print_meta_item(attr.meta()));
+            word(&mut self.s, "]")
         }
     }
-    if count > 0 {
-        try!(hardbreak_if_not_bol(s));
-    }
-    Ok(())
-}
 
-pub fn print_inner_attributes(s: &mut State,
-                              attrs: &[ast::Attribute]) -> io::IoResult<()> {
-    let mut count = 0;
-    for attr in attrs.iter() {
-        match attr.node.style {
-          ast::AttrInner => {
-            try!(print_attribute(s, attr));
-            if !attr.node.is_sugared_doc {
-                try!(word(&mut s.s, ";"));
+
+    pub fn print_stmt(&mut self, st: &ast::Stmt) -> IoResult<()> {
+        try!(self.maybe_print_comment(st.span.lo));
+        match st.node {
+            ast::StmtDecl(decl, _) => {
+                try!(self.print_decl(decl));
+            }
+            ast::StmtExpr(expr, _) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_expr(expr));
+            }
+            ast::StmtSemi(expr, _) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_expr(expr));
+                try!(word(&mut self.s, ";"));
+            }
+            ast::StmtMac(ref mac, semi) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_mac(mac));
+                if semi {
+                    try!(word(&mut self.s, ";"));
+                }
             }
-            count += 1;
-          }
-          _ => {/* fallthrough */ }
         }
+        if parse::classify::stmt_ends_with_semi(st) {
+            try!(word(&mut self.s, ";"));
+        }
+        self.maybe_print_trailing_comment(st.span, None)
     }
-    if count > 0 {
-        try!(hardbreak_if_not_bol(s));
-    }
-    Ok(())
-}
-
-pub fn print_attribute(s: &mut State, attr: &ast::Attribute) -> io::IoResult<()> {
-    try!(hardbreak_if_not_bol(s));
-    try!(maybe_print_comment(s, attr.span.lo));
-    if attr.node.is_sugared_doc {
-        let comment = attr.value_str().unwrap();
-        try!(word(&mut s.s, comment.get()));
-    } else {
-        try!(word(&mut s.s, "#["));
-        try!(print_meta_item(s, attr.meta()));
-        try!(word(&mut s.s, "]"));
-    }
-    Ok(())
-}
-
-
-pub fn print_stmt(s: &mut State, st: &ast::Stmt) -> io::IoResult<()> {
-    try!(maybe_print_comment(s, st.span.lo));
-    match st.node {
-      ast::StmtDecl(decl, _) => {
-        try!(print_decl(s, decl));
-      }
-      ast::StmtExpr(expr, _) => {
-        try!(space_if_not_bol(s));
-        try!(print_expr(s, expr));
-      }
-      ast::StmtSemi(expr, _) => {
-        try!(space_if_not_bol(s));
-        try!(print_expr(s, expr));
-        try!(word(&mut s.s, ";"));
-      }
-      ast::StmtMac(ref mac, semi) => {
-        try!(space_if_not_bol(s));
-        try!(print_mac(s, mac));
-        if semi {
-            try!(word(&mut s.s, ";"));
-        }
-      }
-    }
-    if parse::classify::stmt_ends_with_semi(st) {
-        try!(word(&mut s.s, ";"));
-    }
-    maybe_print_trailing_comment(s, st.span, None)
-}
 
-pub fn print_block(s: &mut State, blk: &ast::Block) -> io::IoResult<()> {
-    print_possibly_embedded_block(s, blk, BlockNormal, indent_unit)
-}
-
-pub fn print_block_unclosed(s: &mut State, blk: &ast::Block) -> io::IoResult<()> {
-    print_possibly_embedded_block_(s, blk, BlockNormal, indent_unit, &[],
-                                   false)
-}
-
-pub fn print_block_unclosed_indent(s: &mut State, blk: &ast::Block,
-                                   indented: uint) -> io::IoResult<()> {
-    print_possibly_embedded_block_(s, blk, BlockNormal, indented, &[], false)
-}
+    pub fn print_block(&mut self, blk: &ast::Block) -> IoResult<()> {
+        self.print_block_with_attrs(blk, &[])
+    }
 
-pub fn print_block_with_attrs(s: &mut State,
-                              blk: &ast::Block,
-                              attrs: &[ast::Attribute]) -> io::IoResult<()> {
-    print_possibly_embedded_block_(s, blk, BlockNormal, indent_unit, attrs,
-                                  true)
-}
+    pub fn print_block_unclosed(&mut self, blk: &ast::Block) -> IoResult<()> {
+        self.print_block_unclosed_indent(blk, indent_unit)
+    }
 
-pub enum EmbedType {
-    BlockBlockFn,
-    BlockNormal,
-}
+    pub fn print_block_unclosed_indent(&mut self, blk: &ast::Block,
+                                       indented: uint) -> IoResult<()> {
+        self.print_block_maybe_unclosed(blk, indented, &[], false)
+    }
 
-pub fn print_possibly_embedded_block(s: &mut State,
-                                     blk: &ast::Block,
-                                     embedded: EmbedType,
-                                     indented: uint) -> io::IoResult<()> {
-    print_possibly_embedded_block_(
-        s, blk, embedded, indented, &[], true)
-}
+    pub fn print_block_with_attrs(&mut self,
+                                  blk: &ast::Block,
+                                  attrs: &[ast::Attribute]) -> IoResult<()> {
+        self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
+    }
 
-pub fn print_possibly_embedded_block_(s: &mut State,
+    pub fn print_block_maybe_unclosed(&mut self,
                                       blk: &ast::Block,
-                                      embedded: EmbedType,
                                       indented: uint,
                                       attrs: &[ast::Attribute],
-                                      close_box: bool) -> io::IoResult<()> {
-    match blk.rules {
-      ast::UnsafeBlock(..) => try!(word_space(s, "unsafe")),
-      ast::DefaultBlock => ()
-    }
-    try!(maybe_print_comment(s, blk.span.lo));
-    {
-        let ann_node = NodeBlock(s, blk);
-        try!(s.ann.pre(ann_node));
-    }
-    try!(match embedded {
-        BlockBlockFn => end(s),
-        BlockNormal => bopen(s)
-    });
-
-    try!(print_inner_attributes(s, attrs));
-
-    for vi in blk.view_items.iter() {
-        try!(print_view_item(s, vi));
-    }
-    for st in blk.stmts.iter() {
-        try!(print_stmt(s, *st));
-    }
-    match blk.expr {
-      Some(expr) => {
-        try!(space_if_not_bol(s));
-        try!(print_expr(s, expr));
-        try!(maybe_print_trailing_comment(s, expr.span, Some(blk.span.hi)));
-      }
-      _ => ()
-    }
-    try!(bclose_maybe_open(s, blk.span, indented, close_box));
-    {
-        let ann_node = NodeBlock(s, blk);
-        try!(s.ann.post(ann_node));
-    }
-    Ok(())
-}
+                                      close_box: bool) -> IoResult<()> {
+        match blk.rules {
+            ast::UnsafeBlock(..) => try!(self.word_space("unsafe")),
+            ast::DefaultBlock => ()
+        }
+        try!(self.maybe_print_comment(blk.span.lo));
+        try!(self.ann.pre(self, NodeBlock(blk)));
+        try!(self.bopen());
+
+        try!(self.print_inner_attributes(attrs));
 
-pub fn print_if(s: &mut State, test: &ast::Expr, blk: &ast::Block,
-                elseopt: Option<@ast::Expr>, chk: bool) -> io::IoResult<()> {
-    try!(head(s, "if"));
-    if chk { try!(word_nbsp(s, "check")); }
-    try!(print_expr(s, test));
-    try!(space(&mut s.s));
-    try!(print_block(s, blk));
-    fn do_else(s: &mut State, els: Option<@ast::Expr>) -> io::IoResult<()> {
+        for vi in blk.view_items.iter() {
+            try!(self.print_view_item(vi));
+        }
+        for st in blk.stmts.iter() {
+            try!(self.print_stmt(*st));
+        }
+        match blk.expr {
+            Some(expr) => {
+                try!(self.space_if_not_bol());
+                try!(self.print_expr(expr));
+                try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
+            }
+            _ => ()
+        }
+        try!(self.bclose_maybe_open(blk.span, indented, close_box));
+        self.ann.post(self, NodeBlock(blk))
+    }
+
+    fn print_else(&mut self, els: Option<@ast::Expr>) -> IoResult<()> {
         match els {
             Some(_else) => {
                 match _else.node {
                     // "another else-if"
                     ast::ExprIf(i, t, e) => {
-                        try!(cbox(s, indent_unit - 1u));
-                        try!(ibox(s, 0u));
-                        try!(word(&mut s.s, " else if "));
-                        try!(print_expr(s, i));
-                        try!(space(&mut s.s));
-                        try!(print_block(s, t));
-                        try!(do_else(s, e));
+                        try!(self.cbox(indent_unit - 1u));
+                        try!(self.ibox(0u));
+                        try!(word(&mut self.s, " else if "));
+                        try!(self.print_expr(i));
+                        try!(space(&mut self.s));
+                        try!(self.print_block(t));
+                        self.print_else(e)
                     }
                     // "final else"
                     ast::ExprBlock(b) => {
-                        try!(cbox(s, indent_unit - 1u));
-                        try!(ibox(s, 0u));
-                        try!(word(&mut s.s, " else "));
-                        try!(print_block(s, b));
+                        try!(self.cbox(indent_unit - 1u));
+                        try!(self.ibox(0u));
+                        try!(word(&mut self.s, " else "));
+                        self.print_block(b)
                     }
                     // BLEAH, constraints would be great here
                     _ => {
@@ -1118,1411 +1051,1334 @@ pub fn print_if(s: &mut State, test: &ast::Expr, blk: &ast::Block,
                     }
                 }
             }
-            _ => {/* fall through */ }
+            _ => Ok(())
         }
-        Ok(())
     }
-    do_else(s, elseopt)
-}
 
-pub fn print_mac(s: &mut State, m: &ast::Mac) -> io::IoResult<()> {
-    match m.node {
-      // I think it's reasonable to hide the ctxt here:
-      ast::MacInvocTT(ref pth, ref tts, _) => {
-        try!(print_path(s, pth, false));
-        try!(word(&mut s.s, "!"));
-        try!(popen(s));
-        try!(print_tts(s, &tts.as_slice()));
-        pclose(s)
-      }
+    pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
+                    elseopt: Option<@ast::Expr>, chk: bool) -> IoResult<()> {
+        try!(self.head("if"));
+        if chk { try!(self.word_nbsp("check")); }
+        try!(self.print_expr(test));
+        try!(space(&mut self.s));
+        try!(self.print_block(blk));
+        self.print_else(elseopt)
     }
-}
 
-pub fn print_expr_vstore(s: &mut State, t: ast::ExprVstore) -> io::IoResult<()> {
-    match t {
-      ast::ExprVstoreUniq => word(&mut s.s, "~"),
-      ast::ExprVstoreSlice => word(&mut s.s, "&"),
-      ast::ExprVstoreMutSlice => {
-        try!(word(&mut s.s, "&"));
-        word(&mut s.s, "mut")
-      }
+    pub fn print_mac(&mut self, m: &ast::Mac) -> IoResult<()> {
+        match m.node {
+            // I think it's reasonable to hide the ctxt here:
+            ast::MacInvocTT(ref pth, ref tts, _) => {
+                try!(self.print_path(pth, false));
+                try!(word(&mut self.s, "!"));
+                try!(self.popen());
+                try!(self.print_tts(&tts.as_slice()));
+                self.pclose()
+            }
+        }
     }
-}
-
-fn print_call_post(s: &mut State, args: &[@ast::Expr]) -> io::IoResult<()> {
-    try!(popen(s));
-    try!(commasep_exprs(s, Inconsistent, args));
-    try!(pclose(s));
-    Ok(())
-}
 
-pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
-    fn print_field(s: &mut State, field: &ast::Field) -> io::IoResult<()> {
-        try!(ibox(s, indent_unit));
-        try!(print_ident(s, field.ident.node));
-        try!(word_space(s, ":"));
-        try!(print_expr(s, field.expr));
-        try!(end(s));
-        Ok(())
+    pub fn print_expr_vstore(&mut self, t: ast::ExprVstore) -> IoResult<()> {
+        match t {
+            ast::ExprVstoreUniq => word(&mut self.s, "~"),
+            ast::ExprVstoreSlice => word(&mut self.s, "&"),
+            ast::ExprVstoreMutSlice => {
+                try!(word(&mut self.s, "&"));
+                word(&mut self.s, "mut")
+            }
+        }
     }
-    fn get_span(field: &ast::Field) -> codemap::Span { return field.span; }
 
-    try!(maybe_print_comment(s, expr.span.lo));
-    try!(ibox(s, indent_unit));
-    {
-        let ann_node = NodeExpr(s, expr);
-        try!(s.ann.pre(ann_node));
-    }
-    match expr.node {
-        ast::ExprVstore(e, v) => {
-            try!(print_expr_vstore(s, v));
-            try!(print_expr(s, e));
-        },
-        ast::ExprBox(p, e) => {
-            try!(word(&mut s.s, "box"));
-            try!(word(&mut s.s, "("));
-            try!(print_expr(s, p));
-            try!(word_space(s, ")"));
-            try!(print_expr(s, e));
-        }
-      ast::ExprVec(ref exprs, mutbl) => {
-        try!(ibox(s, indent_unit));
-        try!(word(&mut s.s, "["));
-        if mutbl == ast::MutMutable {
-            try!(word(&mut s.s, "mut"));
-            if exprs.len() > 0u { try!(nbsp(s)); }
-        }
-        try!(commasep_exprs(s, Inconsistent, exprs.as_slice()));
-        try!(word(&mut s.s, "]"));
-        try!(end(s));
-      }
-
-      ast::ExprRepeat(element, count, mutbl) => {
-        try!(ibox(s, indent_unit));
-        try!(word(&mut s.s, "["));
-        if mutbl == ast::MutMutable {
-            try!(word(&mut s.s, "mut"));
-            try!(nbsp(s));
-        }
-        try!(print_expr(s, element));
-        try!(word(&mut s.s, ","));
-        try!(word(&mut s.s, ".."));
-        try!(print_expr(s, count));
-        try!(word(&mut s.s, "]"));
-        try!(end(s));
-      }
-
-      ast::ExprStruct(ref path, ref fields, wth) => {
-        try!(print_path(s, path, true));
-        try!(word(&mut s.s, "{"));
-        try!(commasep_cmnt(s,
-                           Consistent,
-                           fields.as_slice(),
-                           print_field,
-                           get_span));
-        match wth {
-            Some(expr) => {
-                try!(ibox(s, indent_unit));
-                if !fields.is_empty() {
-                    try!(word(&mut s.s, ","));
-                    try!(space(&mut s.s));
+    fn print_call_post(&mut self, args: &[@ast::Expr]) -> IoResult<()> {
+        try!(self.popen());
+        try!(self.commasep_exprs(Inconsistent, args));
+        self.pclose()
+    }
+
+    pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
+        try!(self.maybe_print_comment(expr.span.lo));
+        try!(self.ibox(indent_unit));
+        try!(self.ann.pre(self, NodeExpr(expr)));
+        match expr.node {
+            ast::ExprVstore(e, v) => {
+                try!(self.print_expr_vstore(v));
+                try!(self.print_expr(e));
+            },
+            ast::ExprBox(p, e) => {
+                try!(word(&mut self.s, "box"));
+                try!(word(&mut self.s, "("));
+                try!(self.print_expr(p));
+                try!(self.word_space(")"));
+                try!(self.print_expr(e));
+            }
+            ast::ExprVec(ref exprs, mutbl) => {
+                try!(self.ibox(indent_unit));
+                try!(word(&mut self.s, "["));
+                if mutbl == ast::MutMutable {
+                    try!(word(&mut self.s, "mut"));
+                    if exprs.len() > 0u { try!(self.nbsp()); }
                 }
-                try!(word(&mut s.s, ".."));
-                try!(print_expr(s, expr));
-                try!(end(s));
-            }
-            _ => try!(word(&mut s.s, ","))
-        }
-        try!(word(&mut s.s, "}"));
-      }
-      ast::ExprTup(ref exprs) => {
-        try!(popen(s));
-        try!(commasep_exprs(s, Inconsistent, exprs.as_slice()));
-        if exprs.len() == 1 {
-            try!(word(&mut s.s, ","));
-        }
-        try!(pclose(s));
-      }
-      ast::ExprCall(func, ref args) => {
-        try!(print_expr(s, func));
-        try!(print_call_post(s, args.as_slice()));
-      }
-      ast::ExprMethodCall(ident, ref tys, ref args) => {
-        let base_args = args.slice_from(1);
-        try!(print_expr(s, *args.get(0)));
-        try!(word(&mut s.s, "."));
-        try!(print_ident(s, ident));
-        if tys.len() > 0u {
-            try!(word(&mut s.s, "::<"));
-            try!(commasep(s, Inconsistent, tys.as_slice(), print_type_ref));
-            try!(word(&mut s.s, ">"));
-        }
-        try!(print_call_post(s, base_args));
-      }
-      ast::ExprBinary(op, lhs, rhs) => {
-        try!(print_expr(s, lhs));
-        try!(space(&mut s.s));
-        try!(word_space(s, ast_util::binop_to_str(op)));
-        try!(print_expr(s, rhs));
-      }
-      ast::ExprUnary(op, expr) => {
-        try!(word(&mut s.s, ast_util::unop_to_str(op)));
-        try!(print_expr(s, expr));
-      }
-      ast::ExprAddrOf(m, expr) => {
-        try!(word(&mut s.s, "&"));
-        try!(print_mutability(s, m));
-        // Avoid `& &e` => `&&e`.
-        match (m, &expr.node) {
-            (ast::MutImmutable, &ast::ExprAddrOf(..)) => try!(space(&mut s.s)),
-            _ => { }
-        }
-        try!(print_expr(s, expr));
-      }
-      ast::ExprLit(lit) => try!(print_literal(s, lit)),
-      ast::ExprCast(expr, ty) => {
-        try!(print_expr(s, expr));
-        try!(space(&mut s.s));
-        try!(word_space(s, "as"));
-        try!(print_type(s, ty));
-      }
-      ast::ExprIf(test, blk, elseopt) => {
-        try!(print_if(s, test, blk, elseopt, false));
-      }
-      ast::ExprWhile(test, blk) => {
-        try!(head(s, "while"));
-        try!(print_expr(s, test));
-        try!(space(&mut s.s));
-        try!(print_block(s, blk));
-      }
-      ast::ExprForLoop(pat, iter, blk, opt_ident) => {
-        for ident in opt_ident.iter() {
-            try!(word(&mut s.s, "'"));
-            try!(print_ident(s, *ident));
-            try!(word_space(s, ":"));
-        }
-        try!(head(s, "for"));
-        try!(print_pat(s, pat));
-        try!(space(&mut s.s));
-        try!(word_space(s, "in"));
-        try!(print_expr(s, iter));
-        try!(space(&mut s.s));
-        try!(print_block(s, blk));
-      }
-      ast::ExprLoop(blk, opt_ident) => {
-        for ident in opt_ident.iter() {
-            try!(word(&mut s.s, "'"));
-            try!(print_ident(s, *ident));
-            try!(word_space(s, ":"));
-        }
-        try!(head(s, "loop"));
-        try!(space(&mut s.s));
-        try!(print_block(s, blk));
-      }
-      ast::ExprMatch(expr, ref arms) => {
-        try!(cbox(s, indent_unit));
-        try!(ibox(s, 4));
-        try!(word_nbsp(s, "match"));
-        try!(print_expr(s, expr));
-        try!(space(&mut s.s));
-        try!(bopen(s));
-        let len = arms.len();
-        for (i, arm) in arms.iter().enumerate() {
-            try!(space(&mut s.s));
-            try!(cbox(s, indent_unit));
-            try!(ibox(s, 0u));
-            let mut first = true;
-            for p in arm.pats.iter() {
-                if first {
-                    first = false;
-                } else {
-                    try!(space(&mut s.s));
-                    try!(word_space(s, "|"));
+                try!(self.commasep_exprs(Inconsistent, exprs.as_slice()));
+                try!(word(&mut self.s, "]"));
+                try!(self.end());
+            }
+
+            ast::ExprRepeat(element, count, mutbl) => {
+                try!(self.ibox(indent_unit));
+                try!(word(&mut self.s, "["));
+                if mutbl == ast::MutMutable {
+                    try!(word(&mut self.s, "mut"));
+                    try!(self.nbsp());
                 }
-                try!(print_pat(s, *p));
-            }
-            try!(space(&mut s.s));
-            match arm.guard {
-              Some(e) => {
-                try!(word_space(s, "if"));
-                try!(print_expr(s, e));
-                try!(space(&mut s.s));
-              }
-              None => ()
-            }
-            try!(word_space(s, "=>"));
-
-            match arm.body.node {
-                ast::ExprBlock(blk) => {
-                    // the block will close the pattern's ibox
-                    try!(print_block_unclosed_indent(
-                                s, blk, indent_unit));
+                try!(self.print_expr(element));
+                try!(word(&mut self.s, ","));
+                try!(word(&mut self.s, ".."));
+                try!(self.print_expr(count));
+                try!(word(&mut self.s, "]"));
+                try!(self.end());
+            }
+
+            ast::ExprStruct(ref path, ref fields, wth) => {
+                try!(self.print_path(path, true));
+                try!(word(&mut self.s, "{"));
+                try!(self.commasep_cmnt(
+                    Consistent,
+                    fields.as_slice(),
+                    |s, field| {
+                        try!(s.ibox(indent_unit));
+                        try!(s.print_ident(field.ident.node));
+                        try!(s.word_space(":"));
+                        try!(s.print_expr(field.expr));
+                        s.end()
+                    },
+                    |f| f.span));
+                match wth {
+                    Some(expr) => {
+                        try!(self.ibox(indent_unit));
+                        if !fields.is_empty() {
+                            try!(word(&mut self.s, ","));
+                            try!(space(&mut self.s));
+                        }
+                        try!(word(&mut self.s, ".."));
+                        try!(self.print_expr(expr));
+                        try!(self.end());
+                    }
+                    _ => try!(word(&mut self.s, ","))
                 }
-                _ => {
-                    try!(end(s)); // close the ibox for the pattern
-                    try!(print_expr(s, arm.body));
+                try!(word(&mut self.s, "}"));
+            }
+            ast::ExprTup(ref exprs) => {
+                try!(self.popen());
+                try!(self.commasep_exprs(Inconsistent, exprs.as_slice()));
+                if exprs.len() == 1 {
+                    try!(word(&mut self.s, ","));
                 }
+                try!(self.pclose());
             }
-            if !expr_is_simple_block(expr)
-                && i < len - 1 {
-                try!(word(&mut s.s, ","));
-            }
-            try!(end(s)); // close enclosing cbox
-        }
-        try!(bclose_(s, expr.span, indent_unit));
-      }
-      ast::ExprFnBlock(decl, body) => {
-        // in do/for blocks we don't want to show an empty
-        // argument list, but at this point we don't know which
-        // we are inside.
-        //
-        // if !decl.inputs.is_empty() {
-        try!(print_fn_block_args(s, decl));
-        try!(space(&mut s.s));
-        // }
-        assert!(body.stmts.is_empty());
-        assert!(body.expr.is_some());
-        // we extract the block, so as not to create another set of boxes
-        match body.expr.unwrap().node {
-            ast::ExprBlock(blk) => {
-                try!(print_block_unclosed(s, blk));
+            ast::ExprCall(func, ref args) => {
+                try!(self.print_expr(func));
+                try!(self.print_call_post(args.as_slice()));
+            }
+            ast::ExprMethodCall(ident, ref tys, ref args) => {
+                let base_args = args.slice_from(1);
+                try!(self.print_expr(*args.get(0)));
+                try!(word(&mut self.s, "."));
+                try!(self.print_ident(ident));
+                if tys.len() > 0u {
+                    try!(word(&mut self.s, "::<"));
+                    try!(self.commasep(Inconsistent, tys.as_slice(),
+                                       |s, ty| s.print_type_ref(ty)));
+                    try!(word(&mut self.s, ">"));
+                }
+                try!(self.print_call_post(base_args));
+            }
+            ast::ExprBinary(op, lhs, rhs) => {
+                try!(self.print_expr(lhs));
+                try!(space(&mut self.s));
+                try!(self.word_space(ast_util::binop_to_str(op)));
+                try!(self.print_expr(rhs));
+            }
+            ast::ExprUnary(op, expr) => {
+                try!(word(&mut self.s, ast_util::unop_to_str(op)));
+                try!(self.print_expr(expr));
+            }
+            ast::ExprAddrOf(m, expr) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.print_mutability(m));
+                // Avoid `& &e` => `&&e`.
+                match (m, &expr.node) {
+                    (ast::MutImmutable, &ast::ExprAddrOf(..)) => try!(space(&mut self.s)),
+                    _ => { }
+                }
+                try!(self.print_expr(expr));
+            }
+            ast::ExprLit(lit) => try!(self.print_literal(lit)),
+            ast::ExprCast(expr, ty) => {
+                try!(self.print_expr(expr));
+                try!(space(&mut self.s));
+                try!(self.word_space("as"));
+                try!(self.print_type(ty));
+            }
+            ast::ExprIf(test, blk, elseopt) => {
+                try!(self.print_if(test, blk, elseopt, false));
+            }
+            ast::ExprWhile(test, blk) => {
+                try!(self.head("while"));
+                try!(self.print_expr(test));
+                try!(space(&mut self.s));
+                try!(self.print_block(blk));
+            }
+            ast::ExprForLoop(pat, iter, blk, opt_ident) => {
+                for ident in opt_ident.iter() {
+                    try!(word(&mut self.s, "'"));
+                    try!(self.print_ident(*ident));
+                    try!(self.word_space(":"));
+                }
+                try!(self.head("for"));
+                try!(self.print_pat(pat));
+                try!(space(&mut self.s));
+                try!(self.word_space("in"));
+                try!(self.print_expr(iter));
+                try!(space(&mut self.s));
+                try!(self.print_block(blk));
+            }
+            ast::ExprLoop(blk, opt_ident) => {
+                for ident in opt_ident.iter() {
+                    try!(word(&mut self.s, "'"));
+                    try!(self.print_ident(*ident));
+                    try!(self.word_space(":"));
+                }
+                try!(self.head("loop"));
+                try!(space(&mut self.s));
+                try!(self.print_block(blk));
+            }
+            ast::ExprMatch(expr, ref arms) => {
+                try!(self.cbox(indent_unit));
+                try!(self.ibox(4));
+                try!(self.word_nbsp("match"));
+                try!(self.print_expr(expr));
+                try!(space(&mut self.s));
+                try!(self.bopen());
+                let len = arms.len();
+                for (i, arm) in arms.iter().enumerate() {
+                    try!(space(&mut self.s));
+                    try!(self.cbox(indent_unit));
+                    try!(self.ibox(0u));
+                    let mut first = true;
+                    for p in arm.pats.iter() {
+                        if first {
+                            first = false;
+                        } else {
+                            try!(space(&mut self.s));
+                            try!(self.word_space("|"));
+                        }
+                        try!(self.print_pat(*p));
+                    }
+                    try!(space(&mut self.s));
+                    match arm.guard {
+                        Some(e) => {
+                            try!(self.word_space("if"));
+                            try!(self.print_expr(e));
+                            try!(space(&mut self.s));
+                        }
+                        None => ()
+                    }
+                    try!(self.word_space("=>"));
+
+                    match arm.body.node {
+                        ast::ExprBlock(blk) => {
+                            // the block will close the pattern's ibox
+                            try!(self.print_block_unclosed_indent(blk, indent_unit));
+                        }
+                        _ => {
+                            try!(self.end()); // close the ibox for the pattern
+                            try!(self.print_expr(arm.body));
+                        }
+                    }
+                    if !expr_is_simple_block(expr)
+                        && i < len - 1 {
+                        try!(word(&mut self.s, ","));
+                    }
+                    try!(self.end()); // close enclosing cbox
+                }
+                try!(self.bclose_(expr.span, indent_unit));
+            }
+            ast::ExprFnBlock(decl, body) => {
+                // in do/for blocks we don't want to show an empty
+                // argument list, but at this point we don't know which
+                // we are inside.
+                //
+                // if !decl.inputs.is_empty() {
+                try!(self.print_fn_block_args(decl));
+                try!(space(&mut self.s));
+                // }
+                assert!(body.stmts.is_empty());
+                assert!(body.expr.is_some());
+                // we extract the block, so as not to create another set of boxes
+                match body.expr.unwrap().node {
+                    ast::ExprBlock(blk) => {
+                        try!(self.print_block_unclosed(blk));
+                    }
+                    _ => {
+                        // this is a bare expression
+                        try!(self.print_expr(body.expr.unwrap()));
+                        try!(self.end()); // need to close a box
+                    }
+                }
+                // a box will be closed by print_expr, but we didn't want an overall
+                // wrapper so we closed the corresponding opening. so create an
+                // empty box to satisfy the close.
+                try!(self.ibox(0));
+            }
+            ast::ExprProc(decl, body) => {
+                // in do/for blocks we don't want to show an empty
+                // argument list, but at this point we don't know which
+                // we are inside.
+                //
+                // if !decl.inputs.is_empty() {
+                try!(self.print_proc_args(decl));
+                try!(space(&mut self.s));
+                // }
+                assert!(body.stmts.is_empty());
+                assert!(body.expr.is_some());
+                // we extract the block, so as not to create another set of boxes
+                match body.expr.unwrap().node {
+                    ast::ExprBlock(blk) => {
+                        try!(self.print_block_unclosed(blk));
+                    }
+                    _ => {
+                        // this is a bare expression
+                        try!(self.print_expr(body.expr.unwrap()));
+                        try!(self.end()); // need to close a box
+                    }
+                }
+                // a box will be closed by print_expr, but we didn't want an overall
+                // wrapper so we closed the corresponding opening. so create an
+                // empty box to satisfy the close.
+                try!(self.ibox(0));
             }
-            _ => {
-                // this is a bare expression
-                try!(print_expr(s, body.expr.unwrap()));
-                try!(end(s)); // need to close a box
-            }
-        }
-        // a box will be closed by print_expr, but we didn't want an overall
-        // wrapper so we closed the corresponding opening. so create an
-        // empty box to satisfy the close.
-        try!(ibox(s, 0));
-      }
-      ast::ExprProc(decl, body) => {
-        // in do/for blocks we don't want to show an empty
-        // argument list, but at this point we don't know which
-        // we are inside.
-        //
-        // if !decl.inputs.is_empty() {
-        try!(print_proc_args(s, decl));
-        try!(space(&mut s.s));
-        // }
-        assert!(body.stmts.is_empty());
-        assert!(body.expr.is_some());
-        // we extract the block, so as not to create another set of boxes
-        match body.expr.unwrap().node {
             ast::ExprBlock(blk) => {
-                try!(print_block_unclosed(s, blk));
+                // containing cbox, will be closed by print-block at }
+                try!(self.cbox(indent_unit));
+                // head-box, will be closed by print-block after {
+                try!(self.ibox(0u));
+                try!(self.print_block(blk));
             }
-            _ => {
-                // this is a bare expression
-                try!(print_expr(s, body.expr.unwrap()));
-                try!(end(s)); // need to close a box
+            ast::ExprAssign(lhs, rhs) => {
+                try!(self.print_expr(lhs));
+                try!(space(&mut self.s));
+                try!(self.word_space("="));
+                try!(self.print_expr(rhs));
+            }
+            ast::ExprAssignOp(op, lhs, rhs) => {
+                try!(self.print_expr(lhs));
+                try!(space(&mut self.s));
+                try!(word(&mut self.s, ast_util::binop_to_str(op)));
+                try!(self.word_space("="));
+                try!(self.print_expr(rhs));
+            }
+            ast::ExprField(expr, id, ref tys) => {
+                try!(self.print_expr(expr));
+                try!(word(&mut self.s, "."));
+                try!(self.print_ident(id));
+                if tys.len() > 0u {
+                    try!(word(&mut self.s, "::<"));
+                    try!(self.commasep(
+                        Inconsistent, tys.as_slice(),
+                        |s, ty| s.print_type_ref(ty)));
+                    try!(word(&mut self.s, ">"));
+                }
+            }
+            ast::ExprIndex(expr, index) => {
+                try!(self.print_expr(expr));
+                try!(word(&mut self.s, "["));
+                try!(self.print_expr(index));
+                try!(word(&mut self.s, "]"));
+            }
+            ast::ExprPath(ref path) => try!(self.print_path(path, true)),
+            ast::ExprBreak(opt_ident) => {
+                try!(word(&mut self.s, "break"));
+                try!(space(&mut self.s));
+                for ident in opt_ident.iter() {
+                    try!(word(&mut self.s, "'"));
+                    try!(self.print_ident(*ident));
+                    try!(space(&mut self.s));
+                }
+            }
+            ast::ExprAgain(opt_ident) => {
+                try!(word(&mut self.s, "continue"));
+                try!(space(&mut self.s));
+                for ident in opt_ident.iter() {
+                    try!(word(&mut self.s, "'"));
+                    try!(self.print_ident(*ident));
+                    try!(space(&mut self.s))
+                }
+            }
+            ast::ExprRet(result) => {
+                try!(word(&mut self.s, "return"));
+                match result {
+                    Some(expr) => {
+                        try!(word(&mut self.s, " "));
+                        try!(self.print_expr(expr));
+                    }
+                    _ => ()
+                }
+            }
+            ast::ExprInlineAsm(ref a) => {
+                if a.volatile {
+                    try!(word(&mut self.s, "__volatile__ asm!"));
+                } else {
+                    try!(word(&mut self.s, "asm!"));
+                }
+                try!(self.popen());
+                try!(self.print_string(a.asm.get(), a.asm_str_style));
+                try!(self.word_space(":"));
+                for &(ref co, o) in a.outputs.iter() {
+                    try!(self.print_string(co.get(), ast::CookedStr));
+                    try!(self.popen());
+                    try!(self.print_expr(o));
+                    try!(self.pclose());
+                    try!(self.word_space(","));
+                }
+                try!(self.word_space(":"));
+                for &(ref co, o) in a.inputs.iter() {
+                    try!(self.print_string(co.get(), ast::CookedStr));
+                    try!(self.popen());
+                    try!(self.print_expr(o));
+                    try!(self.pclose());
+                    try!(self.word_space(","));
+                }
+                try!(self.word_space(":"));
+                try!(self.print_string(a.clobbers.get(), ast::CookedStr));
+                try!(self.pclose());
+            }
+            ast::ExprMac(ref m) => try!(self.print_mac(m)),
+            ast::ExprParen(e) => {
+                try!(self.popen());
+                try!(self.print_expr(e));
+                try!(self.pclose());
             }
         }
-        // a box will be closed by print_expr, but we didn't want an overall
-        // wrapper so we closed the corresponding opening. so create an
-        // empty box to satisfy the close.
-        try!(ibox(s, 0));
-      }
-      ast::ExprBlock(blk) => {
-        // containing cbox, will be closed by print-block at }
-        try!(cbox(s, indent_unit));
-        // head-box, will be closed by print-block after {
-        try!(ibox(s, 0u));
-        try!(print_block(s, blk));
-      }
-      ast::ExprAssign(lhs, rhs) => {
-        try!(print_expr(s, lhs));
-        try!(space(&mut s.s));
-        try!(word_space(s, "="));
-        try!(print_expr(s, rhs));
-      }
-      ast::ExprAssignOp(op, lhs, rhs) => {
-        try!(print_expr(s, lhs));
-        try!(space(&mut s.s));
-        try!(word(&mut s.s, ast_util::binop_to_str(op)));
-        try!(word_space(s, "="));
-        try!(print_expr(s, rhs));
-      }
-      ast::ExprField(expr, id, ref tys) => {
-        try!(print_expr(s, expr));
-        try!(word(&mut s.s, "."));
-        try!(print_ident(s, id));
-        if tys.len() > 0u {
-            try!(word(&mut s.s, "::<"));
-            try!(commasep(s, Inconsistent, tys.as_slice(), print_type_ref));
-            try!(word(&mut s.s, ">"));
-        }
-      }
-      ast::ExprIndex(expr, index) => {
-        try!(print_expr(s, expr));
-        try!(word(&mut s.s, "["));
-        try!(print_expr(s, index));
-        try!(word(&mut s.s, "]"));
-      }
-      ast::ExprPath(ref path) => try!(print_path(s, path, true)),
-      ast::ExprBreak(opt_ident) => {
-        try!(word(&mut s.s, "break"));
-        try!(space(&mut s.s));
-        for ident in opt_ident.iter() {
-            try!(word(&mut s.s, "'"));
-            try!(print_ident(s, *ident));
-            try!(space(&mut s.s));
-        }
-      }
-      ast::ExprAgain(opt_ident) => {
-        try!(word(&mut s.s, "continue"));
-        try!(space(&mut s.s));
-        for ident in opt_ident.iter() {
-            try!(word(&mut s.s, "'"));
-            try!(print_ident(s, *ident));
-            try!(space(&mut s.s))
-        }
-      }
-      ast::ExprRet(result) => {
-        try!(word(&mut s.s, "return"));
-        match result {
-          Some(expr) => {
-              try!(word(&mut s.s, " "));
-              try!(print_expr(s, expr));
-          }
-          _ => ()
-        }
-      }
-      ast::ExprInlineAsm(ref a) => {
-        if a.volatile {
-            try!(word(&mut s.s, "__volatile__ asm!"));
-        } else {
-            try!(word(&mut s.s, "asm!"));
-        }
-        try!(popen(s));
-        try!(print_string(s, a.asm.get(), a.asm_str_style));
-        try!(word_space(s, ":"));
-        for &(ref co, o) in a.outputs.iter() {
-            try!(print_string(s, co.get(), ast::CookedStr));
-            try!(popen(s));
-            try!(print_expr(s, o));
-            try!(pclose(s));
-            try!(word_space(s, ","));
-        }
-        try!(word_space(s, ":"));
-        for &(ref co, o) in a.inputs.iter() {
-            try!(print_string(s, co.get(), ast::CookedStr));
-            try!(popen(s));
-            try!(print_expr(s, o));
-            try!(pclose(s));
-            try!(word_space(s, ","));
-        }
-        try!(word_space(s, ":"));
-        try!(print_string(s, a.clobbers.get(), ast::CookedStr));
-        try!(pclose(s));
-      }
-      ast::ExprMac(ref m) => try!(print_mac(s, m)),
-      ast::ExprParen(e) => {
-          try!(popen(s));
-          try!(print_expr(s, e));
-          try!(pclose(s));
-      }
-    }
-    {
-        let ann_node = NodeExpr(s, expr);
-        try!(s.ann.post(ann_node));
-    }
-    end(s)
-}
+        try!(self.ann.post(self, NodeExpr(expr)));
+        self.end()
+    }
 
-pub fn print_local_decl(s: &mut State, loc: &ast::Local) -> io::IoResult<()> {
-    try!(print_pat(s, loc.pat));
-    match loc.ty.node {
-        ast::TyInfer => {}
-        _ => {
-            try!(word_space(s, ":"));
-            try!(print_type(s, loc.ty));
+    pub fn print_local_decl(&mut self, loc: &ast::Local) -> IoResult<()> {
+        try!(self.print_pat(loc.pat));
+        match loc.ty.node {
+            ast::TyInfer => Ok(()),
+            _ => {
+                try!(self.word_space(":"));
+                self.print_type(loc.ty)
+            }
         }
     }
-    Ok(())
-}
 
-pub fn print_decl(s: &mut State, decl: &ast::Decl) -> io::IoResult<()> {
-    try!(maybe_print_comment(s, decl.span.lo));
-    match decl.node {
-      ast::DeclLocal(ref loc) => {
-        try!(space_if_not_bol(s));
-        try!(ibox(s, indent_unit));
-        try!(word_nbsp(s, "let"));
-
-        fn print_local(s: &mut State, loc: &ast::Local) -> io::IoResult<()> {
-            try!(ibox(s, indent_unit));
-            try!(print_local_decl(s, loc));
-            try!(end(s));
-            match loc.init {
-              Some(init) => {
-                try!(nbsp(s));
-                try!(word_space(s, "="));
-                try!(print_expr(s, init));
-              }
-              _ => ()
+    pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> {
+        try!(self.maybe_print_comment(decl.span.lo));
+        match decl.node {
+            ast::DeclLocal(loc) => {
+                try!(self.space_if_not_bol());
+                try!(self.ibox(indent_unit));
+                try!(self.word_nbsp("let"));
+
+                try!(self.ibox(indent_unit));
+                try!(self.print_local_decl(loc));
+                try!(self.end());
+                match loc.init {
+                    Some(init) => {
+                        try!(self.nbsp());
+                        try!(self.word_space("="));
+                        try!(self.print_expr(init));
+                    }
+                    _ => {}
+                }
+                self.end()
             }
-            Ok(())
+            ast::DeclItem(item) => self.print_item(item)
         }
-
-        try!(print_local(s, *loc));
-        end(s)
-      }
-      ast::DeclItem(item) => print_item(s, item)
     }
-}
 
-pub fn print_ident(s: &mut State, ident: ast::Ident) -> io::IoResult<()> {
-    word(&mut s.s, token::get_ident(ident).get())
-}
+    pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> {
+        word(&mut self.s, token::get_ident(ident).get())
+    }
 
-pub fn print_name(s: &mut State, name: ast::Name) -> io::IoResult<()> {
-    word(&mut s.s, token::get_name(name).get())
-}
+    pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
+        word(&mut self.s, token::get_name(name).get())
+    }
 
-pub fn print_for_decl(s: &mut State, loc: &ast::Local,
-                      coll: &ast::Expr) -> io::IoResult<()> {
-    try!(print_local_decl(s, loc));
-    try!(space(&mut s.s));
-    try!(word_space(s, "in"));
-    print_expr(s, coll)
-}
+    pub fn print_for_decl(&mut self, loc: &ast::Local,
+                          coll: &ast::Expr) -> IoResult<()> {
+        try!(self.print_local_decl(loc));
+        try!(space(&mut self.s));
+        try!(self.word_space("in"));
+        self.print_expr(coll)
+    }
 
-fn print_path_(s: &mut State,
-               path: &ast::Path,
-               colons_before_params: bool,
-               opt_bounds: &Option<OptVec<ast::TyParamBound>>)
-    -> io::IoResult<()>
-{
-    try!(maybe_print_comment(s, path.span.lo));
-    if path.global {
-        try!(word(&mut s.s, "::"));
-    }
-
-    let mut first = true;
-    for (i, segment) in path.segments.iter().enumerate() {
-        if first {
-            first = false
-        } else {
-            try!(word(&mut s.s, "::"))
+    fn print_path_(&mut self,
+                   path: &ast::Path,
+                   colons_before_params: bool,
+                   opt_bounds: &Option<OptVec<ast::TyParamBound>>)
+        -> IoResult<()> {
+        try!(self.maybe_print_comment(path.span.lo));
+        if path.global {
+            try!(word(&mut self.s, "::"));
         }
 
-        try!(print_ident(s, segment.identifier));
-
-        // If this is the last segment, print the bounds.
-        if i == path.segments.len() - 1 {
-            match *opt_bounds {
-                None => {}
-                Some(ref bounds) => try!(print_bounds(s, bounds, true)),
+        let mut first = true;
+        for (i, segment) in path.segments.iter().enumerate() {
+            if first {
+                first = false
+            } else {
+                try!(word(&mut self.s, "::"))
             }
-        }
 
-        if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
-            if colons_before_params {
-                try!(word(&mut s.s, "::"))
-            }
-            try!(word(&mut s.s, "<"));
+            try!(self.print_ident(segment.identifier));
 
-            let mut comma = false;
-            for lifetime in segment.lifetimes.iter() {
-                if comma {
-                    try!(word_space(s, ","))
+            // If this is the last segment, print the bounds.
+            if i == path.segments.len() - 1 {
+                match *opt_bounds {
+                    None => {}
+                    Some(ref bounds) => try!(self.print_bounds(bounds, true)),
                 }
-                try!(print_lifetime(s, lifetime));
-                comma = true;
             }
 
-            if !segment.types.is_empty() {
-                if comma {
-                    try!(word_space(s, ","))
+            if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
+                if colons_before_params {
+                    try!(word(&mut self.s, "::"))
+                }
+                try!(word(&mut self.s, "<"));
+
+                let mut comma = false;
+                for lifetime in segment.lifetimes.iter() {
+                    if comma {
+                        try!(self.word_space(","))
+                    }
+                    try!(self.print_lifetime(lifetime));
+                    comma = true;
+                }
+
+                if !segment.types.is_empty() {
+                    if comma {
+                        try!(self.word_space(","))
+                    }
+                    try!(self.commasep(
+                        Inconsistent,
+                        segment.types.map_to_vec(|&t| t).as_slice(),
+                        |s, ty| s.print_type_ref(ty)));
                 }
-                try!(commasep(s,
-                                Inconsistent,
-                                segment.types.map_to_vec(|&t| t).as_slice(),
-                                print_type_ref));
-            }
 
-            try!(word(&mut s.s, ">"))
+                try!(word(&mut self.s, ">"))
+            }
         }
+        Ok(())
     }
-    Ok(())
-}
 
-fn print_path(s: &mut State, path: &ast::Path,
-              colons_before_params: bool) -> io::IoResult<()> {
-    print_path_(s, path, colons_before_params, &None)
-}
+    fn print_path(&mut self, path: &ast::Path,
+                  colons_before_params: bool) -> IoResult<()> {
+        self.print_path_(path, colons_before_params, &None)
+    }
 
-fn print_bounded_path(s: &mut State, path: &ast::Path,
-                      bounds: &Option<OptVec<ast::TyParamBound>>)
-    -> io::IoResult<()> {
-    print_path_(s, path, false, bounds)
-}
+    fn print_bounded_path(&mut self, path: &ast::Path,
+                          bounds: &Option<OptVec<ast::TyParamBound>>)
+        -> IoResult<()> {
+        self.print_path_(path, false, bounds)
+    }
 
-pub fn print_pat(s: &mut State, pat: &ast::Pat) -> io::IoResult<()> {
-    try!(maybe_print_comment(s, pat.span.lo));
-    {
-        let ann_node = NodePat(s, pat);
-        try!(s.ann.pre(ann_node));
-    }
-    /* Pat isn't normalized, but the beauty of it
-     is that it doesn't matter */
-    match pat.node {
-      ast::PatWild => try!(word(&mut s.s, "_")),
-      ast::PatWildMulti => try!(word(&mut s.s, "..")),
-      ast::PatIdent(binding_mode, ref path, sub) => {
-          match binding_mode {
-              ast::BindByRef(mutbl) => {
-                  try!(word_nbsp(s, "ref"));
-                  try!(print_mutability(s, mutbl));
-              }
-              ast::BindByValue(ast::MutImmutable) => {}
-              ast::BindByValue(ast::MutMutable) => {
-                  try!(word_nbsp(s, "mut"));
-              }
-          }
-          try!(print_path(s, path, true));
-          match sub {
-              Some(p) => {
-                  try!(word(&mut s.s, "@"));
-                  try!(print_pat(s, p));
-              }
-              None => ()
-          }
-      }
-      ast::PatEnum(ref path, ref args_) => {
-        try!(print_path(s, path, true));
-        match *args_ {
-          None => try!(word(&mut s.s, "(..)")),
-          Some(ref args) => {
-            if !args.is_empty() {
-              try!(popen(s));
-              try!(commasep(s, Inconsistent, args.as_slice(),
-                              |s, &p| print_pat(s, p)));
-              try!(pclose(s));
-            } else { }
-          }
-        }
-      }
-      ast::PatStruct(ref path, ref fields, etc) => {
-        try!(print_path(s, path, true));
-        try!(word(&mut s.s, "{"));
-        fn print_field(s: &mut State, f: &ast::FieldPat) -> io::IoResult<()> {
-            try!(cbox(s, indent_unit));
-            try!(print_ident(s, f.ident));
-            try!(word_space(s, ":"));
-            try!(print_pat(s, f.pat));
-            try!(end(s));
-            Ok(())
-        }
-        fn get_span(f: &ast::FieldPat) -> codemap::Span { return f.pat.span; }
-        try!(commasep_cmnt(s, Consistent, fields.as_slice(),
-                             |s, f| print_field(s,f),
-                             get_span));
-        if etc {
-            if fields.len() != 0u { try!(word_space(s, ",")); }
-            try!(word(&mut s.s, ".."));
-        }
-        try!(word(&mut s.s, "}"));
-      }
-      ast::PatTup(ref elts) => {
-        try!(popen(s));
-        try!(commasep(s,
-                      Inconsistent,
-                      elts.as_slice(),
-                      |s, &p| print_pat(s, p)));
-        if elts.len() == 1 {
-            try!(word(&mut s.s, ","));
-        }
-        try!(pclose(s));
-      }
-      ast::PatUniq(inner) => {
-          try!(word(&mut s.s, "~"));
-          try!(print_pat(s, inner));
-      }
-      ast::PatRegion(inner) => {
-          try!(word(&mut s.s, "&"));
-          try!(print_pat(s, inner));
-      }
-      ast::PatLit(e) => try!(print_expr(s, e)),
-      ast::PatRange(begin, end) => {
-        try!(print_expr(s, begin));
-        try!(space(&mut s.s));
-        try!(word(&mut s.s, ".."));
-        try!(print_expr(s, end));
-      }
-      ast::PatVec(ref before, slice, ref after) => {
-        try!(word(&mut s.s, "["));
-        try!(commasep(s,
-                      Inconsistent,
-                      before.as_slice(),
-                      |s, &p| print_pat(s, p)));
-        for &p in slice.iter() {
-            if !before.is_empty() { try!(word_space(s, ",")); }
-            match *p {
-                ast::Pat { node: ast::PatWildMulti, .. } => {
-                    // this case is handled by print_pat
+    pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
+        try!(self.maybe_print_comment(pat.span.lo));
+        try!(self.ann.pre(self, NodePat(pat)));
+        /* Pat isn't normalized, but the beauty of it
+         is that it doesn't matter */
+        match pat.node {
+            ast::PatWild => try!(word(&mut self.s, "_")),
+            ast::PatWildMulti => try!(word(&mut self.s, "..")),
+            ast::PatIdent(binding_mode, ref path, sub) => {
+                match binding_mode {
+                    ast::BindByRef(mutbl) => {
+                        try!(self.word_nbsp("ref"));
+                        try!(self.print_mutability(mutbl));
+                    }
+                    ast::BindByValue(ast::MutImmutable) => {}
+                    ast::BindByValue(ast::MutMutable) => {
+                        try!(self.word_nbsp("mut"));
+                    }
+                }
+                try!(self.print_path(path, true));
+                match sub {
+                    Some(p) => {
+                        try!(word(&mut self.s, "@"));
+                        try!(self.print_pat(p));
+                    }
+                    None => ()
                 }
-                _ => try!(word(&mut s.s, "..")),
             }
-            try!(print_pat(s, p));
-            if !after.is_empty() { try!(word_space(s, ",")); }
+            ast::PatEnum(ref path, ref args_) => {
+                try!(self.print_path(path, true));
+                match *args_ {
+                    None => try!(word(&mut self.s, "(..)")),
+                    Some(ref args) => {
+                        if !args.is_empty() {
+                            try!(self.popen());
+                            try!(self.commasep(Inconsistent, args.as_slice(),
+                                              |s, &p| s.print_pat(p)));
+                            try!(self.pclose());
+                        }
+                    }
+                }
+            }
+            ast::PatStruct(ref path, ref fields, etc) => {
+                try!(self.print_path(path, true));
+                try!(word(&mut self.s, "{"));
+                try!(self.commasep_cmnt(
+                    Consistent, fields.as_slice(),
+                    |s, f| {
+                        try!(s.cbox(indent_unit));
+                        try!(s.print_ident(f.ident));
+                        try!(s.word_space(":"));
+                        try!(s.print_pat(f.pat));
+                        s.end()
+                    },
+                    |f| f.pat.span));
+                if etc {
+                    if fields.len() != 0u { try!(self.word_space(",")); }
+                    try!(word(&mut self.s, ".."));
+                }
+                try!(word(&mut self.s, "}"));
+            }
+            ast::PatTup(ref elts) => {
+                try!(self.popen());
+                try!(self.commasep(Inconsistent,
+                                   elts.as_slice(),
+                                   |s, &p| s.print_pat(p)));
+                if elts.len() == 1 {
+                    try!(word(&mut self.s, ","));
+                }
+                try!(self.pclose());
+            }
+            ast::PatUniq(inner) => {
+                try!(word(&mut self.s, "~"));
+                try!(self.print_pat(inner));
+            }
+            ast::PatRegion(inner) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.print_pat(inner));
+            }
+            ast::PatLit(e) => try!(self.print_expr(e)),
+            ast::PatRange(begin, end) => {
+                try!(self.print_expr(begin));
+                try!(space(&mut self.s));
+                try!(word(&mut self.s, ".."));
+                try!(self.print_expr(end));
+            }
+            ast::PatVec(ref before, slice, ref after) => {
+                try!(word(&mut self.s, "["));
+                try!(self.commasep(Inconsistent,
+                                   before.as_slice(),
+                                   |s, &p| s.print_pat(p)));
+                for &p in slice.iter() {
+                    if !before.is_empty() { try!(self.word_space(",")); }
+                    match *p {
+                        ast::Pat { node: ast::PatWildMulti, .. } => {
+                            // this case is handled by print_pat
+                        }
+                        _ => try!(word(&mut self.s, "..")),
+                    }
+                    try!(self.print_pat(p));
+                    if !after.is_empty() { try!(self.word_space(",")); }
+                }
+                try!(self.commasep(Inconsistent,
+                                   after.as_slice(),
+                                   |s, &p| s.print_pat(p)));
+                try!(word(&mut self.s, "]"));
+            }
         }
-        try!(commasep(s,
-                      Inconsistent,
-                      after.as_slice(),
-                      |s, &p| print_pat(s, p)));
-        try!(word(&mut s.s, "]"));
-      }
+        self.ann.post(self, NodePat(pat))
     }
-    {
-        let ann_node = NodePat(s, pat);
-        try!(s.ann.post(ann_node));
-    }
-    Ok(())
-}
 
-pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_) -> ~str {
-    to_str(explicit_self, |a, &b| {
-        print_explicit_self(a, b, ast::MutImmutable).map(|_| ())
-    })
-}
-
-// Returns whether it printed anything
-fn print_explicit_self(s: &mut State,
-                       explicit_self: ast::ExplicitSelf_,
-                       mutbl: ast::Mutability) -> io::IoResult<bool> {
-    try!(print_mutability(s, mutbl));
-    match explicit_self {
-        ast::SelfStatic => { return Ok(false); }
-        ast::SelfValue => {
-            try!(word(&mut s.s, "self"));
-        }
-        ast::SelfUniq => {
-            try!(word(&mut s.s, "~self"));
-        }
-        ast::SelfRegion(ref lt, m) => {
-            try!(word(&mut s.s, "&"));
-            try!(print_opt_lifetime(s, lt));
-            try!(print_mutability(s, m));
-            try!(word(&mut s.s, "self"));
+    // Returns whether it printed anything
+    fn print_explicit_self(&mut self,
+                           explicit_self: ast::ExplicitSelf_,
+                           mutbl: ast::Mutability) -> IoResult<bool> {
+        try!(self.print_mutability(mutbl));
+        match explicit_self {
+            ast::SelfStatic => { return Ok(false); }
+            ast::SelfValue => {
+                try!(word(&mut self.s, "self"));
+            }
+            ast::SelfUniq => {
+                try!(word(&mut self.s, "~self"));
+            }
+            ast::SelfRegion(ref lt, m) => {
+                try!(word(&mut self.s, "&"));
+                try!(self.print_opt_lifetime(lt));
+                try!(self.print_mutability(m));
+                try!(word(&mut self.s, "self"));
+            }
         }
+        return Ok(true);
     }
-    return Ok(true);
-}
 
-pub fn print_fn(s: &mut State,
-                decl: &ast::FnDecl,
-                purity: Option<ast::Purity>,
-                abis: AbiSet,
-                name: ast::Ident,
-                generics: &ast::Generics,
-                opt_explicit_self: Option<ast::ExplicitSelf_>,
-                vis: ast::Visibility) -> io::IoResult<()> {
-    try!(head(s, ""));
-    try!(print_fn_header_info(s, opt_explicit_self, purity, abis,
-                                ast::Many, None, vis));
-    try!(nbsp(s));
-    try!(print_ident(s, name));
-    try!(print_generics(s, generics));
-    try!(print_fn_args_and_ret(s, decl, opt_explicit_self));
-    Ok(())
-}
+    pub fn print_fn(&mut self,
+                    decl: &ast::FnDecl,
+                    purity: Option<ast::Purity>,
+                    abis: AbiSet,
+                    name: ast::Ident,
+                    generics: &ast::Generics,
+                    opt_explicit_self: Option<ast::ExplicitSelf_>,
+                    vis: ast::Visibility) -> IoResult<()> {
+        try!(self.head(""));
+        try!(self.print_fn_header_info(opt_explicit_self, purity, abis,
+                                    ast::Many, None, vis));
+        try!(self.nbsp());
+        try!(self.print_ident(name));
+        try!(self.print_generics(generics));
+        self.print_fn_args_and_ret(decl, opt_explicit_self)
+    }
+
+    pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
+                         opt_explicit_self: Option<ast::ExplicitSelf_>)
+        -> IoResult<()> {
+        // It is unfortunate to duplicate the commasep logic, but we want the
+        // self type and the args all in the same box.
+        try!(self.rbox(0u, Inconsistent));
+        let mut first = true;
+        for &explicit_self in opt_explicit_self.iter() {
+            let m = match explicit_self {
+                ast::SelfStatic => ast::MutImmutable,
+                _ => match decl.inputs.get(0).pat.node {
+                    ast::PatIdent(ast::BindByValue(m), _, _) => m,
+                    _ => ast::MutImmutable
+                }
+            };
+            first = !try!(self.print_explicit_self(explicit_self, m));
+        }
 
-pub fn print_fn_args(s: &mut State, decl: &ast::FnDecl,
-                     opt_explicit_self: Option<ast::ExplicitSelf_>)
-    -> io::IoResult<()>
-{
-    // It is unfortunate to duplicate the commasep logic, but we want the
-    // self type and the args all in the same box.
-    try!(rbox(s, 0u, Inconsistent));
-    let mut first = true;
-    for &explicit_self in opt_explicit_self.iter() {
-        let m = match explicit_self {
-            ast::SelfStatic => ast::MutImmutable,
-            _ => match decl.inputs.get(0).pat.node {
-                ast::PatIdent(ast::BindByValue(m), _, _) => m,
-                _ => ast::MutImmutable
-            }
+        // HACK(eddyb) ignore the separately printed self argument.
+        let args = if first {
+            decl.inputs.as_slice()
+        } else {
+            decl.inputs.slice_from(1)
         };
-        first = !try!(print_explicit_self(s, explicit_self, m));
-    }
 
-    // HACK(eddyb) ignore the separately printed self argument.
-    let args = if first {
-        decl.inputs.as_slice()
-    } else {
-        decl.inputs.slice_from(1)
-    };
+        for arg in args.iter() {
+            if first { first = false; } else { try!(self.word_space(",")); }
+            try!(self.print_arg(arg));
+        }
 
-    for arg in args.iter() {
-        if first { first = false; } else { try!(word_space(s, ",")); }
-        try!(print_arg(s, arg));
+        self.end()
     }
 
-    end(s)
-}
+    pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl,
+                                 opt_explicit_self: Option<ast::ExplicitSelf_>)
+        -> IoResult<()> {
+        try!(self.popen());
+        try!(self.print_fn_args(decl, opt_explicit_self));
+        if decl.variadic {
+            try!(word(&mut self.s, ", ..."));
+        }
+        try!(self.pclose());
 
-pub fn print_fn_args_and_ret(s: &mut State, decl: &ast::FnDecl,
-                             opt_explicit_self: Option<ast::ExplicitSelf_>)
-    -> io::IoResult<()>
-{
-    try!(popen(s));
-    try!(print_fn_args(s, decl, opt_explicit_self));
-    if decl.variadic {
-        try!(word(&mut s.s, ", ..."));
+        try!(self.maybe_print_comment(decl.output.span.lo));
+        match decl.output.node {
+            ast::TyNil => Ok(()),
+            _ => {
+                try!(self.space_if_not_bol());
+                try!(self.word_space("->"));
+                self.print_type(decl.output)
+            }
+        }
     }
-    try!(pclose(s));
 
-    try!(maybe_print_comment(s, decl.output.span.lo));
-    match decl.output.node {
-        ast::TyNil => {}
-        _ => {
-            try!(space_if_not_bol(s));
-            try!(word_space(s, "->"));
-            try!(print_type(s, decl.output));
+    pub fn print_fn_block_args(&mut self,
+                               decl: &ast::FnDecl) -> IoResult<()> {
+        try!(word(&mut self.s, "|"));
+        try!(self.print_fn_args(decl, None));
+        try!(word(&mut self.s, "|"));
+
+        match decl.output.node {
+            ast::TyInfer => {}
+            _ => {
+                try!(self.space_if_not_bol());
+                try!(self.word_space("->"));
+                try!(self.print_type(decl.output));
+            }
         }
+
+        self.maybe_print_comment(decl.output.span.lo)
     }
-    Ok(())
-}
 
-pub fn print_fn_block_args(s: &mut State,
-                           decl: &ast::FnDecl) -> io::IoResult<()> {
-    try!(word(&mut s.s, "|"));
-    try!(print_fn_args(s, decl, None));
-    try!(word(&mut s.s, "|"));
+    pub fn print_proc_args(&mut self, decl: &ast::FnDecl) -> IoResult<()> {
+        try!(word(&mut self.s, "proc"));
+        try!(word(&mut self.s, "("));
+        try!(self.print_fn_args(decl, None));
+        try!(word(&mut self.s, ")"));
 
-    match decl.output.node {
-        ast::TyInfer => {}
-        _ => {
-            try!(space_if_not_bol(s));
-            try!(word_space(s, "->"));
-            try!(print_type(s, decl.output));
+        match decl.output.node {
+            ast::TyInfer => {}
+            _ => {
+                try!(self.space_if_not_bol());
+                try!(self.word_space("->"));
+                try!(self.print_type(decl.output));
+            }
         }
-    }
 
-    maybe_print_comment(s, decl.output.span.lo)
-}
+        self.maybe_print_comment(decl.output.span.lo)
+    }
 
-pub fn print_proc_args(s: &mut State, decl: &ast::FnDecl) -> io::IoResult<()> {
-    try!(word(&mut s.s, "proc"));
-    try!(word(&mut s.s, "("));
-    try!(print_fn_args(s, decl, None));
-    try!(word(&mut s.s, ")"));
+    pub fn print_bounds(&mut self, bounds: &OptVec<ast::TyParamBound>,
+                        print_colon_anyway: bool) -> IoResult<()> {
+        if !bounds.is_empty() {
+            try!(word(&mut self.s, ":"));
+            let mut first = true;
+            for bound in bounds.iter() {
+                try!(self.nbsp());
+                if first {
+                    first = false;
+                } else {
+                    try!(self.word_space("+"));
+                }
 
-    match decl.output.node {
-        ast::TyInfer => {}
-        _ => {
-            try!(space_if_not_bol(s));
-            try!(word_space(s, "->"));
-            try!(print_type(s, decl.output));
+                try!(match *bound {
+                    TraitTyParamBound(ref tref) => self.print_trait_ref(tref),
+                    RegionTyParamBound => word(&mut self.s, "'static"),
+                })
+            }
+            Ok(())
+        } else if print_colon_anyway {
+            word(&mut self.s, ":")
+        } else {
+            Ok(())
         }
     }
 
-    maybe_print_comment(s, decl.output.span.lo)
-}
+    pub fn print_lifetime(&mut self,
+                          lifetime: &ast::Lifetime) -> IoResult<()> {
+        try!(word(&mut self.s, "'"));
+        self.print_name(lifetime.name)
+    }
 
-pub fn print_bounds(s: &mut State, bounds: &OptVec<ast::TyParamBound>,
-                    print_colon_anyway: bool) -> io::IoResult<()> {
-    if !bounds.is_empty() {
-        try!(word(&mut s.s, ":"));
-        let mut first = true;
-        for bound in bounds.iter() {
-            try!(nbsp(s));
-            if first {
-                first = false;
-            } else {
-                try!(word_space(s, "+"));
+    pub fn print_generics(&mut self,
+                          generics: &ast::Generics) -> IoResult<()> {
+        let total = generics.lifetimes.len() + generics.ty_params.len();
+        if total > 0 {
+            try!(word(&mut self.s, "<"));
+
+            let mut ints = Vec::new();
+            for i in range(0u, total) {
+                ints.push(i);
             }
 
-            try!(match *bound {
-                TraitTyParamBound(ref tref) => print_trait_ref(s, tref),
-                RegionTyParamBound => word(&mut s.s, "'static"),
-            })
+            try!(self.commasep(
+                Inconsistent, ints.as_slice(),
+                |s, &idx| {
+                    if idx < generics.lifetimes.len() {
+                        let lifetime = generics.lifetimes.get(idx);
+                        s.print_lifetime(lifetime)
+                    } else {
+                        let idx = idx - generics.lifetimes.len();
+                        let param = generics.ty_params.get(idx);
+                        try!(s.print_ident(param.ident));
+                        try!(s.print_bounds(&param.bounds, false));
+                        match param.default {
+                            Some(default) => {
+                                try!(space(&mut s.s));
+                                try!(s.word_space("="));
+                                s.print_type(default)
+                            }
+                            _ => Ok(())
+                        }
+                    }
+                }));
+            word(&mut self.s, ">")
+        } else {
+            Ok(())
         }
-    } else if print_colon_anyway {
-        try!(word(&mut s.s, ":"));
     }
-    Ok(())
-}
 
-pub fn print_lifetime(s: &mut State,
-                      lifetime: &ast::Lifetime) -> io::IoResult<()> {
-    try!(word(&mut s.s, "'"));
-    print_name(s, lifetime.name)
-}
-
-pub fn print_generics(s: &mut State,
-                      generics: &ast::Generics) -> io::IoResult<()> {
-    let total = generics.lifetimes.len() + generics.ty_params.len();
-    if total > 0 {
-        try!(word(&mut s.s, "<"));
-        fn print_item(s: &mut State, generics: &ast::Generics,
-                      idx: uint) -> io::IoResult<()> {
-            if idx < generics.lifetimes.len() {
-                let lifetime = generics.lifetimes.get(idx);
-                print_lifetime(s, lifetime)
-            } else {
-                let idx = idx - generics.lifetimes.len();
-                let param = generics.ty_params.get(idx);
-                try!(print_ident(s, param.ident));
-                try!(print_bounds(s, &param.bounds, false));
-                match param.default {
-                    Some(default) => {
-                        try!(space(&mut s.s));
-                        try!(word_space(s, "="));
-                        try!(print_type(s, default));
-                    }
-                    _ => {}
-                }
-                Ok(())
+    pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> {
+        try!(self.ibox(indent_unit));
+        match item.node {
+            ast::MetaWord(ref name) => {
+                try!(word(&mut self.s, name.get()));
+            }
+            ast::MetaNameValue(ref name, ref value) => {
+                try!(self.word_space(name.get()));
+                try!(self.word_space("="));
+                try!(self.print_literal(value));
+            }
+            ast::MetaList(ref name, ref items) => {
+                try!(word(&mut self.s, name.get()));
+                try!(self.popen());
+                try!(self.commasep(Consistent,
+                                   items.as_slice(),
+                                   |s, &i| s.print_meta_item(i)));
+                try!(self.pclose());
             }
         }
+        self.end()
+    }
 
-        let mut ints = Vec::new();
-        for i in range(0u, total) {
-            ints.push(i);
-        }
+    pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
+        match vp.node {
+            ast::ViewPathSimple(ident, ref path, _) => {
+                // FIXME(#6993) can't compare identifiers directly here
+                if path.segments.last().unwrap().identifier.name != ident.name {
+                    try!(self.print_ident(ident));
+                    try!(space(&mut self.s));
+                    try!(self.word_space("="));
+                }
+                self.print_path(path, false)
+            }
 
-        try!(commasep(s, Inconsistent, ints.as_slice(),
-                        |s, &i| print_item(s, generics, i)));
-        try!(word(&mut s.s, ">"));
-    }
-    Ok(())
-}
+            ast::ViewPathGlob(ref path, _) => {
+                try!(self.print_path(path, false));
+                word(&mut self.s, "::*")
+            }
 
-pub fn print_meta_item(s: &mut State, item: &ast::MetaItem) -> io::IoResult<()> {
-    try!(ibox(s, indent_unit));
-    match item.node {
-        ast::MetaWord(ref name) => {
-            try!(word(&mut s.s, name.get()));
-        }
-        ast::MetaNameValue(ref name, ref value) => {
-            try!(word_space(s, name.get()));
-            try!(word_space(s, "="));
-            try!(print_literal(s, value));
-        }
-        ast::MetaList(ref name, ref items) => {
-            try!(word(&mut s.s, name.get()));
-            try!(popen(s));
-            try!(commasep(s,
-                            Consistent,
-                            items.as_slice(),
-                            |p, &i| print_meta_item(p, i)));
-            try!(pclose(s));
+            ast::ViewPathList(ref path, ref idents, _) => {
+                if path.segments.is_empty() {
+                    try!(word(&mut self.s, "{"));
+                } else {
+                    try!(self.print_path(path, false));
+                    try!(word(&mut self.s, "::{"));
+                }
+                try!(self.commasep(Inconsistent, idents.as_slice(), |s, w| {
+                    s.print_ident(w.node.name)
+                }));
+                word(&mut self.s, "}")
+            }
         }
     }
-    end(s)
-}
 
-pub fn print_view_path(s: &mut State, vp: &ast::ViewPath) -> io::IoResult<()> {
-    match vp.node {
-      ast::ViewPathSimple(ident, ref path, _) => {
-        // FIXME(#6993) can't compare identifiers directly here
-        if path.segments.last().unwrap().identifier.name != ident.name {
-            try!(print_ident(s, ident));
-            try!(space(&mut s.s));
-            try!(word_space(s, "="));
-        }
-        print_path(s, path, false)
-      }
-
-      ast::ViewPathGlob(ref path, _) => {
-        try!(print_path(s, path, false));
-        word(&mut s.s, "::*")
-      }
-
-      ast::ViewPathList(ref path, ref idents, _) => {
-        if path.segments.is_empty() {
-            try!(word(&mut s.s, "{"));
-        } else {
-            try!(print_path(s, path, false));
-            try!(word(&mut s.s, "::{"));
-        }
-        try!(commasep(s, Inconsistent, idents.as_slice(), |s, w| {
-            print_ident(s, w.node.name)
-        }));
-        word(&mut s.s, "}")
-      }
+    pub fn print_view_paths(&mut self,
+                            vps: &[@ast::ViewPath]) -> IoResult<()> {
+        self.commasep(Inconsistent, vps, |s, &vp| s.print_view_path(vp))
     }
-}
 
-pub fn print_view_paths(s: &mut State,
-                        vps: &[@ast::ViewPath]) -> io::IoResult<()> {
-    commasep(s, Inconsistent, vps, |p, &vp| print_view_path(p, vp))
-}
+    pub fn print_view_item(&mut self, item: &ast::ViewItem) -> IoResult<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(item.span.lo));
+        try!(self.print_outer_attributes(item.attrs.as_slice()));
+        try!(self.print_visibility(item.vis));
+        match item.node {
+            ast::ViewItemExternCrate(id, ref optional_path, _) => {
+                try!(self.head("extern crate"));
+                try!(self.print_ident(id));
+                for &(ref p, style) in optional_path.iter() {
+                    try!(space(&mut self.s));
+                    try!(word(&mut self.s, "="));
+                    try!(space(&mut self.s));
+                    try!(self.print_string(p.get(), style));
+                }
+            }
 
-pub fn print_view_item(s: &mut State, item: &ast::ViewItem) -> io::IoResult<()> {
-    try!(hardbreak_if_not_bol(s));
-    try!(maybe_print_comment(s, item.span.lo));
-    try!(print_outer_attributes(s, item.attrs.as_slice()));
-    try!(print_visibility(s, item.vis));
-    match item.node {
-        ast::ViewItemExternCrate(id, ref optional_path, _) => {
-            try!(head(s, "extern crate"));
-            try!(print_ident(s, id));
-            for &(ref p, style) in optional_path.iter() {
-                try!(space(&mut s.s));
-                try!(word(&mut s.s, "="));
-                try!(space(&mut s.s));
-                try!(print_string(s, p.get(), style));
+            ast::ViewItemUse(ref vps) => {
+                try!(self.head("use"));
+                try!(self.print_view_paths(vps.as_slice()));
             }
         }
+        try!(word(&mut self.s, ";"));
+        try!(self.end()); // end inner head-block
+        self.end() // end outer head-block
+    }
 
-        ast::ViewItemUse(ref vps) => {
-            try!(head(s, "use"));
-            try!(print_view_paths(s, vps.as_slice()));
+    pub fn print_mutability(&mut self,
+                            mutbl: ast::Mutability) -> IoResult<()> {
+        match mutbl {
+            ast::MutMutable => self.word_nbsp("mut"),
+            ast::MutImmutable => Ok(()),
         }
     }
-    try!(word(&mut s.s, ";"));
-    try!(end(s)); // end inner head-block
-    try!(end(s)); // end outer head-block
-    Ok(())
-}
 
-pub fn print_mutability(s: &mut State,
-                        mutbl: ast::Mutability) -> io::IoResult<()> {
-    match mutbl {
-      ast::MutMutable => word_nbsp(s, "mut"),
-      ast::MutImmutable => Ok(()),
+    pub fn print_mt(&mut self, mt: &ast::MutTy) -> IoResult<()> {
+        try!(self.print_mutability(mt.mutbl));
+        self.print_type(mt.ty)
     }
-}
-
-pub fn print_mt(s: &mut State, mt: &ast::MutTy) -> io::IoResult<()> {
-    try!(print_mutability(s, mt.mutbl));
-    print_type(s, mt.ty)
-}
 
-pub fn print_arg(s: &mut State, input: &ast::Arg) -> io::IoResult<()> {
-    try!(ibox(s, indent_unit));
-    match input.ty.node {
-        ast::TyInfer => try!(print_pat(s, input.pat)),
-        _ => {
-            match input.pat.node {
-                ast::PatIdent(_, ref path, _) if
-                    path.segments.len() == 1 &&
-                    path.segments.get(0).identifier.name ==
-                        parse::token::special_idents::invalid.name => {
-                    // Do nothing.
-                }
-                _ => {
-                    try!(print_pat(s, input.pat));
-                    try!(word(&mut s.s, ":"));
-                    try!(space(&mut s.s));
+    pub fn print_arg(&mut self, input: &ast::Arg) -> IoResult<()> {
+        try!(self.ibox(indent_unit));
+        match input.ty.node {
+            ast::TyInfer => try!(self.print_pat(input.pat)),
+            _ => {
+                match input.pat.node {
+                    ast::PatIdent(_, ref path, _) if
+                        path.segments.len() == 1 &&
+                        path.segments.get(0).identifier.name ==
+                            parse::token::special_idents::invalid.name => {
+                        // Do nothing.
+                    }
+                    _ => {
+                        try!(self.print_pat(input.pat));
+                        try!(word(&mut self.s, ":"));
+                        try!(space(&mut self.s));
+                    }
                 }
+                try!(self.print_type(input.ty));
             }
-            try!(print_type(s, input.ty));
         }
-    }
-    end(s)
-}
+        self.end()
+    }
+
+    pub fn print_ty_fn(&mut self,
+                       opt_abis: Option<AbiSet>,
+                       opt_sigil: Option<ast::Sigil>,
+                       opt_region: &Option<ast::Lifetime>,
+                       purity: ast::Purity,
+                       onceness: ast::Onceness,
+                       decl: &ast::FnDecl,
+                       id: Option<ast::Ident>,
+                       opt_bounds: &Option<OptVec<ast::TyParamBound>>,
+                       generics: Option<&ast::Generics>,
+                       opt_explicit_self: Option<ast::ExplicitSelf_>)
+        -> IoResult<()> {
+        try!(self.ibox(indent_unit));
+
+        // Duplicates the logic in `print_fn_header_info()`.  This is because that
+        // function prints the sigil in the wrong place.  That should be fixed.
+        if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once {
+            try!(word(&mut self.s, "proc"));
+        } else if opt_sigil == Some(ast::BorrowedSigil) {
+            try!(self.print_extern_opt_abis(opt_abis));
+            for lifetime in opt_region.iter() {
+                try!(self.print_lifetime(lifetime));
+            }
+            try!(self.print_purity(purity));
+            try!(self.print_onceness(onceness));
+        } else {
+            try!(self.print_opt_abis_and_extern_if_nondefault(opt_abis));
+            try!(self.print_opt_sigil(opt_sigil));
+            try!(self.print_opt_lifetime(opt_region));
+            try!(self.print_purity(purity));
+            try!(self.print_onceness(onceness));
+            try!(word(&mut self.s, "fn"));
+        }
+
+        match id {
+            Some(id) => {
+                try!(word(&mut self.s, " "));
+                try!(self.print_ident(id));
+            }
+            _ => ()
+        }
 
-pub fn print_ty_fn(s: &mut State,
-                   opt_abis: Option<AbiSet>,
-                   opt_sigil: Option<ast::Sigil>,
-                   opt_region: &Option<ast::Lifetime>,
-                   purity: ast::Purity,
-                   onceness: ast::Onceness,
-                   decl: &ast::FnDecl,
-                   id: Option<ast::Ident>,
-                   opt_bounds: &Option<OptVec<ast::TyParamBound>>,
-                   generics: Option<&ast::Generics>,
-                   opt_explicit_self: Option<ast::ExplicitSelf_>)
-    -> io::IoResult<()>
-{
-    try!(ibox(s, indent_unit));
-
-    // Duplicates the logic in `print_fn_header_info()`.  This is because that
-    // function prints the sigil in the wrong place.  That should be fixed.
-    if opt_sigil == Some(ast::OwnedSigil) && onceness == ast::Once {
-        try!(word(&mut s.s, "proc"));
-    } else if opt_sigil == Some(ast::BorrowedSigil) {
-        try!(print_extern_opt_abis(s, opt_abis));
-        for lifetime in opt_region.iter() {
-            try!(print_lifetime(s, lifetime));
-        }
-        try!(print_purity(s, purity));
-        try!(print_onceness(s, onceness));
-    } else {
-        try!(print_opt_abis_and_extern_if_nondefault(s, opt_abis));
-        try!(print_opt_sigil(s, opt_sigil));
-        try!(print_opt_lifetime(s, opt_region));
-        try!(print_purity(s, purity));
-        try!(print_onceness(s, onceness));
-        try!(word(&mut s.s, "fn"));
-    }
-
-    match id {
-        Some(id) => {
-            try!(word(&mut s.s, " "));
-            try!(print_ident(s, id));
-        }
-        _ => ()
-    }
-
-    if opt_sigil != Some(ast::BorrowedSigil) {
-        opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true));
-    }
-
-    match generics { Some(g) => try!(print_generics(s, g)), _ => () }
-    try!(zerobreak(&mut s.s));
-
-    if opt_sigil == Some(ast::BorrowedSigil) {
-        try!(word(&mut s.s, "|"));
-    } else {
-        try!(popen(s));
-    }
-
-    try!(print_fn_args(s, decl, opt_explicit_self));
-
-    if opt_sigil == Some(ast::BorrowedSigil) {
-        try!(word(&mut s.s, "|"));
-
-        opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true));
-    } else {
-        if decl.variadic {
-            try!(word(&mut s.s, ", ..."));
+        if opt_sigil != Some(ast::BorrowedSigil) {
+            opt_bounds.as_ref().map(|bounds| self.print_bounds(bounds, true));
         }
-        try!(pclose(s));
-    }
 
-    try!(maybe_print_comment(s, decl.output.span.lo));
+        match generics { Some(g) => try!(self.print_generics(g)), _ => () }
+        try!(zerobreak(&mut self.s));
 
-    match decl.output.node {
-        ast::TyNil => {}
-        _ => {
-            try!(space_if_not_bol(s));
-            try!(ibox(s, indent_unit));
-            try!(word_space(s, "->"));
-            if decl.cf == ast::NoReturn {
-                try!(word_nbsp(s, "!"));
-            } else {
-                try!(print_type(s, decl.output));
+        if opt_sigil == Some(ast::BorrowedSigil) {
+            try!(word(&mut self.s, "|"));
+        } else {
+            try!(self.popen());
+        }
+
+        try!(self.print_fn_args(decl, opt_explicit_self));
+
+        if opt_sigil == Some(ast::BorrowedSigil) {
+            try!(word(&mut self.s, "|"));
+
+            opt_bounds.as_ref().map(|bounds| self.print_bounds(bounds, true));
+        } else {
+            if decl.variadic {
+                try!(word(&mut self.s, ", ..."));
             }
-            try!(end(s));
+            try!(self.pclose());
         }
-    }
 
-    end(s)
-}
+        try!(self.maybe_print_comment(decl.output.span.lo));
 
-pub fn maybe_print_trailing_comment(s: &mut State, span: codemap::Span,
-                                    next_pos: Option<BytePos>)
-    -> io::IoResult<()>
-{
-    let cm;
-    match s.cm { Some(ccm) => cm = ccm, _ => return Ok(()) }
-    match next_comment(s) {
-        Some(ref cmnt) => {
-            if (*cmnt).style != comments::Trailing { return Ok(()) }
-            let span_line = cm.lookup_char_pos(span.hi);
-            let comment_line = cm.lookup_char_pos((*cmnt).pos);
-            let mut next = (*cmnt).pos + BytePos(1);
-            match next_pos { None => (), Some(p) => next = p }
-            if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
-                span_line.line == comment_line.line {
-                    try!(print_comment(s, cmnt));
-                    s.cur_cmnt_and_lit.cur_cmnt += 1u;
+        match decl.output.node {
+            ast::TyNil => {}
+            _ => {
+                try!(self.space_if_not_bol());
+                try!(self.ibox(indent_unit));
+                try!(self.word_space("->"));
+                if decl.cf == ast::NoReturn {
+                    try!(self.word_nbsp("!"));
+                } else {
+                    try!(self.print_type(decl.output));
                 }
+                try!(self.end());
+            }
         }
-        _ => ()
-    }
-    Ok(())
-}
 
-pub fn print_remaining_comments(s: &mut State) -> io::IoResult<()> {
-    // If there aren't any remaining comments, then we need to manually
-    // make sure there is a line break at the end.
-    if next_comment(s).is_none() {
-        try!(hardbreak(&mut s.s));
+        self.end()
     }
-    loop {
-        match next_comment(s) {
+
+    pub fn maybe_print_trailing_comment(&mut self, span: codemap::Span,
+                                        next_pos: Option<BytePos>)
+        -> IoResult<()> {
+        let cm = match self.cm {
+            Some(cm) => cm,
+            _ => return Ok(())
+        };
+        match self.next_comment() {
             Some(ref cmnt) => {
-                try!(print_comment(s, cmnt));
-                s.cur_cmnt_and_lit.cur_cmnt += 1u;
+                if (*cmnt).style != comments::Trailing { return Ok(()) }
+                let span_line = cm.lookup_char_pos(span.hi);
+                let comment_line = cm.lookup_char_pos((*cmnt).pos);
+                let mut next = (*cmnt).pos + BytePos(1);
+                match next_pos { None => (), Some(p) => next = p }
+                if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
+                    span_line.line == comment_line.line {
+                        try!(self.print_comment(cmnt));
+                        self.cur_cmnt_and_lit.cur_cmnt += 1u;
+                    }
             }
-            _ => break
+            _ => ()
         }
+        Ok(())
     }
-    Ok(())
-}
 
-pub fn print_literal(s: &mut State, lit: &ast::Lit) -> io::IoResult<()> {
-    try!(maybe_print_comment(s, lit.span.lo));
-    match next_lit(s, lit.span.lo) {
-      Some(ref ltrl) => {
-        return word(&mut s.s, (*ltrl).lit);
-      }
-      _ => ()
-    }
-    match lit.node {
-      ast::LitStr(ref st, style) => print_string(s, st.get(), style),
-      ast::LitChar(ch) => {
-          let mut res = ~"'";
-          char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c));
-          res.push_char('\'');
-          word(&mut s.s, res)
-      }
-      ast::LitInt(i, t) => {
-        word(&mut s.s, format!("{}{}", i, ast_util::int_ty_to_str(t)))
-      }
-      ast::LitUint(u, t) => {
-        word(&mut s.s, format!("{}{}", u, ast_util::uint_ty_to_str(t)))
-      }
-      ast::LitIntUnsuffixed(i) => {
-        word(&mut s.s, format!("{}", i))
-      }
-      ast::LitFloat(ref f, t) => {
-        word(&mut s.s, f.get() + ast_util::float_ty_to_str(t))
-      }
-      ast::LitFloatUnsuffixed(ref f) => word(&mut s.s, f.get()),
-      ast::LitNil => word(&mut s.s, "()"),
-      ast::LitBool(val) => {
-        if val { word(&mut s.s, "true") } else { word(&mut s.s, "false") }
-      }
-      ast::LitBinary(ref arr) => {
-        try!(ibox(s, indent_unit));
-        try!(word(&mut s.s, "["));
-        try!(commasep_cmnt(s, Inconsistent, arr.deref().as_slice(),
-                             |s, u| word(&mut s.s, format!("{}", *u)),
-                             |_| lit.span));
-        try!(word(&mut s.s, "]"));
-        end(s)
-      }
+    pub fn print_remaining_comments(&mut self) -> IoResult<()> {
+        // If there aren't any remaining comments, then we need to manually
+        // make sure there is a line break at the end.
+        if self.next_comment().is_none() {
+            try!(hardbreak(&mut self.s));
+        }
+        loop {
+            match self.next_comment() {
+                Some(ref cmnt) => {
+                    try!(self.print_comment(cmnt));
+                    self.cur_cmnt_and_lit.cur_cmnt += 1u;
+                }
+                _ => break
+            }
+        }
+        Ok(())
     }
-}
 
-pub fn lit_to_str(l: &ast::Lit) -> ~str {
-    to_str(l, print_literal)
-}
-
-pub fn next_lit(s: &mut State, pos: BytePos) -> Option<comments::Literal> {
-    match s.literals {
-      Some(ref lits) => {
-        while s.cur_cmnt_and_lit.cur_lit < lits.len() {
-            let ltrl = (*(*lits).get(s.cur_cmnt_and_lit.cur_lit)).clone();
-            if ltrl.pos > pos { return None; }
-            s.cur_cmnt_and_lit.cur_lit += 1u;
-            if ltrl.pos == pos { return Some(ltrl); }
+    pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> {
+        try!(self.maybe_print_comment(lit.span.lo));
+        match self.next_lit(lit.span.lo) {
+            Some(ref ltrl) => {
+                return word(&mut self.s, (*ltrl).lit);
+            }
+            _ => ()
+        }
+        match lit.node {
+            ast::LitStr(ref st, style) => self.print_string(st.get(), style),
+            ast::LitChar(ch) => {
+                let mut res = ~"'";
+                char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c));
+                res.push_char('\'');
+                word(&mut self.s, res)
+            }
+            ast::LitInt(i, t) => {
+                word(&mut self.s, format!("{}{}", i, ast_util::int_ty_to_str(t)))
+            }
+            ast::LitUint(u, t) => {
+                word(&mut self.s, format!("{}{}", u, ast_util::uint_ty_to_str(t)))
+            }
+            ast::LitIntUnsuffixed(i) => {
+                word(&mut self.s, format!("{}", i))
+            }
+            ast::LitFloat(ref f, t) => {
+                word(&mut self.s, f.get() + ast_util::float_ty_to_str(t))
+            }
+            ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()),
+            ast::LitNil => word(&mut self.s, "()"),
+            ast::LitBool(val) => {
+                if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
+            }
+            ast::LitBinary(ref arr) => {
+                try!(self.ibox(indent_unit));
+                try!(word(&mut self.s, "["));
+                try!(self.commasep_cmnt(Inconsistent, arr.deref().as_slice(),
+                                        |s, u| word(&mut s.s, format!("{}", *u)),
+                                        |_| lit.span));
+                try!(word(&mut self.s, "]"));
+                self.end()
+            }
         }
-        return None;
-      }
-      _ => return None
     }
-}
 
-pub fn maybe_print_comment(s: &mut State, pos: BytePos) -> io::IoResult<()> {
-    loop {
-        match next_comment(s) {
-          Some(ref cmnt) => {
-            if (*cmnt).pos < pos {
-                try!(print_comment(s, cmnt));
-                s.cur_cmnt_and_lit.cur_cmnt += 1u;
-            } else { break; }
-          }
-          _ => break
+    pub fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
+        match self.literals {
+            Some(ref lits) => {
+                while self.cur_cmnt_and_lit.cur_lit < lits.len() {
+                    let ltrl = (*(*lits).get(self.cur_cmnt_and_lit.cur_lit)).clone();
+                    if ltrl.pos > pos { return None; }
+                    self.cur_cmnt_and_lit.cur_lit += 1u;
+                    if ltrl.pos == pos { return Some(ltrl); }
+                }
+                None
+            }
+            _ => None
         }
     }
-    Ok(())
-}
 
-pub fn print_comment(s: &mut State,
-                     cmnt: &comments::Comment) -> io::IoResult<()> {
-    match cmnt.style {
-        comments::Mixed => {
-            assert_eq!(cmnt.lines.len(), 1u);
-            try!(zerobreak(&mut s.s));
-            try!(word(&mut s.s, *cmnt.lines.get(0)));
-            try!(zerobreak(&mut s.s));
-        }
-        comments::Isolated => {
-            try!(pprust::hardbreak_if_not_bol(s));
-            for line in cmnt.lines.iter() {
-                // Don't print empty lines because they will end up as trailing
-                // whitespace
-                if !line.is_empty() {
-                    try!(word(&mut s.s, *line));
+    pub fn maybe_print_comment(&mut self, pos: BytePos) -> IoResult<()> {
+        loop {
+            match self.next_comment() {
+                Some(ref cmnt) => {
+                    if (*cmnt).pos < pos {
+                        try!(self.print_comment(cmnt));
+                        self.cur_cmnt_and_lit.cur_cmnt += 1u;
+                    } else { break; }
                 }
-                try!(hardbreak(&mut s.s));
+                _ => break
             }
         }
-        comments::Trailing => {
-            try!(word(&mut s.s, " "));
-            if cmnt.lines.len() == 1u {
-                try!(word(&mut s.s, *cmnt.lines.get(0)));
-                try!(hardbreak(&mut s.s));
-            } else {
-                try!(ibox(s, 0u));
+        Ok(())
+    }
+
+    pub fn print_comment(&mut self,
+                         cmnt: &comments::Comment) -> IoResult<()> {
+        match cmnt.style {
+            comments::Mixed => {
+                assert_eq!(cmnt.lines.len(), 1u);
+                try!(zerobreak(&mut self.s));
+                try!(word(&mut self.s, *cmnt.lines.get(0)));
+                zerobreak(&mut self.s)
+            }
+            comments::Isolated => {
+                try!(self.hardbreak_if_not_bol());
                 for line in cmnt.lines.iter() {
+                    // Don't print empty lines because they will end up as trailing
+                    // whitespace
                     if !line.is_empty() {
-                        try!(word(&mut s.s, *line));
+                        try!(word(&mut self.s, *line));
                     }
-                    try!(hardbreak(&mut s.s));
+                    try!(hardbreak(&mut self.s));
                 }
-                try!(end(s));
+                Ok(())
             }
-        }
-        comments::BlankLine => {
-            // We need to do at least one, possibly two hardbreaks.
-            let is_semi = match s.s.last_token() {
-                pp::String(s, _) => ";" == s,
-                _ => false
-            };
-            if is_semi || is_begin(s) || is_end(s) {
-                try!(hardbreak(&mut s.s));
+            comments::Trailing => {
+                try!(word(&mut self.s, " "));
+                if cmnt.lines.len() == 1u {
+                    try!(word(&mut self.s, *cmnt.lines.get(0)));
+                    hardbreak(&mut self.s)
+                } else {
+                    try!(self.ibox(0u));
+                    for line in cmnt.lines.iter() {
+                        if !line.is_empty() {
+                            try!(word(&mut self.s, *line));
+                        }
+                        try!(hardbreak(&mut self.s));
+                    }
+                    self.end()
+                }
+            }
+            comments::BlankLine => {
+                // We need to do at least one, possibly two hardbreaks.
+                let is_semi = match self.s.last_token() {
+                    pp::String(s, _) => ";" == s,
+                    _ => false
+                };
+                if is_semi || self.is_begin() || self.is_end() {
+                    try!(hardbreak(&mut self.s));
+                }
+                hardbreak(&mut self.s)
             }
-            try!(hardbreak(&mut s.s));
         }
     }
-    Ok(())
-}
-
-pub fn print_string(s: &mut State, st: &str,
-                    style: ast::StrStyle) -> io::IoResult<()> {
-    let st = match style {
-        ast::CookedStr => format!("\"{}\"", st.escape_default()),
-        ast::RawStr(n) => format!("r{delim}\"{string}\"{delim}",
-                                  delim="#".repeat(n), string=st)
-    };
-    word(&mut s.s, st)
-}
 
-// FIXME(pcwalton): A nasty function to extract the string from an `io::Writer`
-// that we "know" to be a `MemWriter` that works around the lack of checked
-// downcasts.
-unsafe fn get_mem_writer(writer: &mut ~io::Writer) -> ~str {
-    let (_, wr): (uint, ~MemWriter) = cast::transmute_copy(writer);
-    let result = str::from_utf8_owned(wr.get_ref().to_owned()).unwrap();
-    cast::forget(wr);
-    result
-}
-
-pub fn to_str<T>(t: &T, f: |&mut State, &T| -> io::IoResult<()>) -> ~str {
-    let wr = ~MemWriter::new();
-    let mut s = rust_printer(wr as ~io::Writer);
-    f(&mut s, t).unwrap();
-    eof(&mut s.s).unwrap();
-    unsafe {
-        get_mem_writer(&mut s.s.out)
+    pub fn print_string(&mut self, st: &str,
+                        style: ast::StrStyle) -> IoResult<()> {
+        let st = match style {
+            ast::CookedStr => format!("\"{}\"", st.escape_default()),
+            ast::RawStr(n) => format!("r{delim}\"{string}\"{delim}",
+                                      delim="#".repeat(n), string=st)
+        };
+        word(&mut self.s, st)
     }
-}
 
-pub fn next_comment(s: &mut State) -> Option<comments::Comment> {
-    match s.comments {
-        Some(ref cmnts) => {
-            if s.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
-                Some((*cmnts.get(s.cur_cmnt_and_lit.cur_cmnt)).clone())
-            } else {
-                None
+    pub fn next_comment(&mut self) -> Option<comments::Comment> {
+        match self.comments {
+            Some(ref cmnts) => {
+                if self.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
+                    Some((*cmnts.get(self.cur_cmnt_and_lit.cur_cmnt)).clone())
+                } else {
+                    None
+                }
             }
+            _ => None
         }
-        _ => None
     }
-}
 
-pub fn print_opt_purity(s: &mut State,
-                        opt_purity: Option<ast::Purity>) -> io::IoResult<()> {
-    match opt_purity {
-        Some(ast::ImpureFn) => { }
-        Some(purity) => {
-            try!(word_nbsp(s, purity_to_str(purity)));
+    pub fn print_opt_purity(&mut self,
+                            opt_purity: Option<ast::Purity>) -> IoResult<()> {
+        match opt_purity {
+            Some(purity) => self.print_purity(purity),
+            None => Ok(())
         }
-        None => {}
     }
-    Ok(())
-}
 
-pub fn print_opt_abis_and_extern_if_nondefault(s: &mut State,
-                                               opt_abis: Option<AbiSet>)
-    -> io::IoResult<()>
-{
-    match opt_abis {
-        Some(abis) if !abis.is_rust() => {
-            try!(word_nbsp(s, "extern"));
-            try!(word_nbsp(s, abis.to_str()));
+    pub fn print_opt_abis_and_extern_if_nondefault(&mut self,
+                                                   opt_abis: Option<AbiSet>)
+        -> IoResult<()> {
+        match opt_abis {
+            Some(abis) if !abis.is_rust() => {
+                try!(self.word_nbsp("extern"));
+                self.word_nbsp(abis.to_str())
+            }
+            Some(_) | None => Ok(())
         }
-        Some(_) | None => {}
-    };
-    Ok(())
-}
+    }
 
-pub fn print_extern_opt_abis(s: &mut State,
-                             opt_abis: Option<AbiSet>) -> io::IoResult<()> {
-    match opt_abis {
-        Some(abis) => {
-            try!(word_nbsp(s, "extern"));
-            try!(word_nbsp(s, abis.to_str()));
+    pub fn print_extern_opt_abis(&mut self,
+                                 opt_abis: Option<AbiSet>) -> IoResult<()> {
+        match opt_abis {
+            Some(abis) => {
+                try!(self.word_nbsp("extern"));
+                self.word_nbsp(abis.to_str())
+            }
+            None => Ok(())
         }
-        None => {}
     }
-    Ok(())
-}
 
-pub fn print_opt_sigil(s: &mut State,
-                       opt_sigil: Option<ast::Sigil>) -> io::IoResult<()> {
-    match opt_sigil {
-        Some(ast::BorrowedSigil) => word(&mut s.s, "&"),
-        Some(ast::OwnedSigil) => word(&mut s.s, "~"),
-        Some(ast::ManagedSigil) => word(&mut s.s, "@"),
-        None => Ok(())
+    pub fn print_opt_sigil(&mut self,
+                           opt_sigil: Option<ast::Sigil>) -> IoResult<()> {
+        match opt_sigil {
+            Some(ast::BorrowedSigil) => word(&mut self.s, "&"),
+            Some(ast::OwnedSigil) => word(&mut self.s, "~"),
+            Some(ast::ManagedSigil) => word(&mut self.s, "@"),
+            None => Ok(())
+        }
     }
-}
 
-pub fn print_fn_header_info(s: &mut State,
-                            _opt_explicit_self: Option<ast::ExplicitSelf_>,
-                            opt_purity: Option<ast::Purity>,
-                            abis: AbiSet,
-                            onceness: ast::Onceness,
-                            opt_sigil: Option<ast::Sigil>,
-                            vis: ast::Visibility) -> io::IoResult<()> {
-    try!(word(&mut s.s, visibility_qualified(vis, "")));
+    pub fn print_fn_header_info(&mut self,
+                                _opt_explicit_self: Option<ast::ExplicitSelf_>,
+                                opt_purity: Option<ast::Purity>,
+                                abis: AbiSet,
+                                onceness: ast::Onceness,
+                                opt_sigil: Option<ast::Sigil>,
+                                vis: ast::Visibility) -> IoResult<()> {
+        try!(word(&mut self.s, visibility_qualified(vis, "")));
 
-    if abis != AbiSet::Rust() {
-        try!(word_nbsp(s, "extern"));
-        try!(word_nbsp(s, abis.to_str()));
+        if abis != AbiSet::Rust() {
+            try!(self.word_nbsp("extern"));
+            try!(self.word_nbsp(abis.to_str()));
 
-        if opt_purity != Some(ast::ExternFn) {
-            try!(print_opt_purity(s, opt_purity));
+            if opt_purity != Some(ast::ExternFn) {
+                try!(self.print_opt_purity(opt_purity));
+            }
+        } else {
+            try!(self.print_opt_purity(opt_purity));
         }
-    } else {
-        try!(print_opt_purity(s, opt_purity));
-    }
 
-    try!(print_onceness(s, onceness));
-    try!(word(&mut s.s, "fn"));
-    try!(print_opt_sigil(s, opt_sigil));
-    Ok(())
-}
-
-pub fn purity_to_str(p: ast::Purity) -> &'static str {
-    match p {
-      ast::ImpureFn => "impure",
-      ast::UnsafeFn => "unsafe",
-      ast::ExternFn => "extern"
-    }
-}
-
-pub fn onceness_to_str(o: ast::Onceness) -> &'static str {
-    match o {
-        ast::Once => "once",
-        ast::Many => "many"
+        try!(self.print_onceness(onceness));
+        try!(word(&mut self.s, "fn"));
+        self.print_opt_sigil(opt_sigil)
     }
-}
 
-pub fn print_purity(s: &mut State, p: ast::Purity) -> io::IoResult<()> {
-    match p {
-      ast::ImpureFn => Ok(()),
-      _ => word_nbsp(s, purity_to_str(p))
+    pub fn print_purity(&mut self, p: ast::Purity) -> IoResult<()> {
+        match p {
+            ast::ImpureFn => Ok(()),
+            ast::UnsafeFn => self.word_nbsp("unsafe"),
+            ast::ExternFn => self.word_nbsp("extern")
+        }
     }
-}
 
-pub fn print_onceness(s: &mut State, o: ast::Onceness) -> io::IoResult<()> {
-    match o {
-        ast::Once => word_nbsp(s, "once"),
-        ast::Many => Ok(())
+    pub fn print_onceness(&mut self, o: ast::Onceness) -> IoResult<()> {
+        match o {
+            ast::Once => self.word_nbsp("once"),
+            ast::Many => Ok(())
+        }
     }
 }
 
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index 03fc30e2fd7..658e9709750 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -17,32 +17,20 @@ use parse::token;
 
 use std::vec_ng::Vec;
 
-// map a string to tts, using a made-up filename: return both the TokenTree's
-// and the ParseSess
-pub fn string_to_tts_and_sess (source_str : ~str) -> (Vec<ast::TokenTree> , @ParseSess) {
-    let ps = new_parse_sess();
-    (filemap_to_tts(ps,string_to_filemap(ps,source_str,~"bogofile")),ps)
-}
-
 // map a string to tts, using a made-up filename:
-pub fn string_to_tts(source_str : ~str) -> Vec<ast::TokenTree> {
-    let (tts,_) = string_to_tts_and_sess(source_str);
-    tts
-}
-
-pub fn string_to_parser_and_sess(source_str: ~str) -> (Parser,@ParseSess) {
+pub fn string_to_tts(source_str: ~str) -> Vec<ast::TokenTree> {
     let ps = new_parse_sess();
-    (new_parser_from_source_str(ps,Vec::new(),~"bogofile",source_str),ps)
+    filemap_to_tts(&ps, string_to_filemap(&ps, source_str,~"bogofile"))
 }
 
 // map string to parser (via tts)
-pub fn string_to_parser(source_str: ~str) -> Parser {
-    let (p,_) = string_to_parser_and_sess(source_str);
-    p
+pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: ~str) -> Parser<'a> {
+    new_parser_from_source_str(ps, Vec::new(), ~"bogofile", source_str)
 }
 
 fn with_error_checking_parse<T>(s: ~str, f: |&mut Parser| -> T) -> T {
-    let mut p = string_to_parser(s);
+    let ps = new_parse_sess();
+    let mut p = string_to_parser(&ps, s);
     let x = f(&mut p);
     p.abort_if_errors();
     x
@@ -55,12 +43,6 @@ pub fn string_to_crate (source_str : ~str) -> ast::Crate {
     })
 }
 
-// parse a string, return a crate and the ParseSess
-pub fn string_to_crate_and_sess (source_str : ~str) -> (ast::Crate,@ParseSess) {
-    let (mut p,ps) = string_to_parser_and_sess(source_str);
-    (p.parse_crate_mod(),ps)
-}
-
 // parse a string, return an expr
 pub fn string_to_expr (source_str : ~str) -> @ast::Expr {
     with_error_checking_parse(source_str, |p| {
@@ -84,8 +66,8 @@ pub fn string_to_stmt(source_str : ~str) -> @ast::Stmt {
 
 // parse a string, return a pat. Uses "irrefutable"... which doesn't
 // (currently) affect parsing.
-pub fn string_to_pat(source_str : ~str) -> @ast::Pat {
-    string_to_parser(source_str).parse_pat()
+pub fn string_to_pat(source_str: ~str) -> @ast::Pat {
+    string_to_parser(&new_parse_sess(), source_str).parse_pat()
 }
 
 // convert a vector of strings to a vector of ast::Ident's