about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-01-03 22:36:53 -0800
committerbors <bors@rust-lang.org>2014-01-03 22:36:53 -0800
commit3dd7c49faf5ae3a9158ab242a264c0f0eb99f657 (patch)
tree0393c0b2e10c7579d86c222071bb9c64b0451b60 /src
parent0ff6c12ce94993dae702d597a213eee6b969231a (diff)
parent80921536343e87d2f7d7f19ad90d63f50b557e06 (diff)
downloadrust-3dd7c49faf5ae3a9158ab242a264c0f0eb99f657.tar.gz
rust-3dd7c49faf5ae3a9158ab242a264c0f0eb99f657.zip
auto merge of #11251 : pcwalton/rust/remove-at-mut, r=pcwalton
r? @nikomatsakis 

for the borrow checker changes. Write guards are now eliminated.
Diffstat (limited to 'src')
-rw-r--r--src/libextra/arena.rs61
-rw-r--r--src/libextra/list.rs27
-rw-r--r--src/libextra/serialize.rs12
-rw-r--r--src/libextra/term.rs3
-rw-r--r--src/libextra/terminfo/searcher.rs14
-rw-r--r--src/libextra/test.rs3
-rw-r--r--src/libextra/uuid.rs4
-rw-r--r--src/libextra/workcache.rs10
-rw-r--r--src/librustc/driver/driver.rs45
-rw-r--r--src/librustc/driver/session.rs6
-rw-r--r--src/librustc/front/feature_gate.rs5
-rw-r--r--src/librustc/metadata/creader.rs2
-rw-r--r--src/librustc/metadata/encoder.rs13
-rw-r--r--src/librustc/metadata/loader.rs3
-rw-r--r--src/librustc/metadata/tydecode.rs2
-rw-r--r--src/librustc/metadata/tyencode.rs4
-rw-r--r--src/librustc/middle/astencode.rs7
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs22
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs2
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs45
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs50
-rw-r--r--src/librustc/middle/borrowck/mod.rs60
-rw-r--r--src/librustc/middle/check_const.rs13
-rw-r--r--src/librustc/middle/const_eval.rs50
-rw-r--r--src/librustc/middle/dataflow.rs20
-rw-r--r--src/librustc/middle/dead.rs8
-rw-r--r--src/librustc/middle/entry.rs29
-rw-r--r--src/librustc/middle/kind.rs2
-rw-r--r--src/librustc/middle/lang_items.rs24
-rw-r--r--src/librustc/middle/lint.rs5
-rw-r--r--src/librustc/middle/mem_categorization.rs46
-rw-r--r--src/librustc/middle/privacy.rs6
-rw-r--r--src/librustc/middle/reachable.rs21
-rw-r--r--src/librustc/middle/trans/base.rs16
-rw-r--r--src/librustc/middle/trans/callee.rs25
-rw-r--r--src/librustc/middle/trans/common.rs60
-rw-r--r--src/librustc/middle/trans/consts.rs12
-rw-r--r--src/librustc/middle/trans/datum.rs2
-rw-r--r--src/librustc/middle/trans/debuginfo.rs64
-rw-r--r--src/librustc/middle/trans/expr.rs22
-rw-r--r--src/librustc/middle/trans/foreign.rs15
-rw-r--r--src/librustc/middle/trans/glue.rs9
-rw-r--r--src/librustc/middle/trans/intrinsic.rs9
-rw-r--r--src/librustc/middle/trans/meth.rs11
-rw-r--r--src/librustc/middle/trans/monomorphize.rs16
-rw-r--r--src/librustc/middle/trans/reflect.rs7
-rw-r--r--src/librustc/middle/trans/type_of.rs4
-rw-r--r--src/librustc/middle/trans/write_guard.rs147
-rw-r--r--src/librustc/middle/ty.rs322
-rw-r--r--src/librustc/middle/ty_fold.rs4
-rw-r--r--src/librustc/middle/typeck/astconv.rs13
-rw-r--r--src/librustc/middle/typeck/check/_match.rs8
-rw-r--r--src/librustc/middle/typeck/check/method.rs24
-rw-r--r--src/librustc/middle/typeck/check/mod.rs47
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs24
-rw-r--r--src/librustc/middle/typeck/coherence.rs30
-rw-r--r--src/librustc/middle/typeck/collect.rs42
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs2
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs4
-rw-r--r--src/librustc/middle/typeck/mod.rs6
-rw-r--r--src/librustc/middle/typeck/variance.rs5
-rw-r--r--src/librustc/util/ppaux.rs34
-rw-r--r--src/librustdoc/clean.rs4
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/html/format.rs8
-rw-r--r--src/librustdoc/lib.rs8
-rw-r--r--src/librustdoc/test.rs2
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/librustpkg/util.rs27
-rw-r--r--src/libstd/clone.rs31
-rw-r--r--src/libstd/default.rs4
-rw-r--r--src/libstd/io/extensions.rs6
-rw-r--r--src/libstd/managed.rs38
-rw-r--r--src/libstd/num/mod.rs5
-rw-r--r--src/libstd/repr.rs3
-rw-r--r--src/libstd/rt/task.rs12
-rw-r--r--src/libstd/to_bytes.rs7
-rw-r--r--src/libsyntax/ast.rs12
-rw-r--r--src/libsyntax/ast_map.rs147
-rw-r--r--src/libsyntax/ast_util.rs132
-rw-r--r--src/libsyntax/attr.rs5
-rw-r--r--src/libsyntax/codemap.rs78
-rw-r--r--src/libsyntax/diagnostic.rs68
-rw-r--r--src/libsyntax/ext/base.rs6
-rw-r--r--src/libsyntax/ext/build.rs11
-rw-r--r--src/libsyntax/ext/deriving/ty.rs8
-rw-r--r--src/libsyntax/ext/expand.rs50
-rw-r--r--src/libsyntax/ext/source_util.rs8
-rw-r--r--src/libsyntax/ext/trace_macros.rs2
-rw-r--r--src/libsyntax/ext/tt/macro_parser.rs26
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs13
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs179
-rw-r--r--src/libsyntax/fold.rs4
-rw-r--r--src/libsyntax/parse/comments.rs85
-rw-r--r--src/libsyntax/parse/lexer.rs373
-rw-r--r--src/libsyntax/parse/mod.rs65
-rw-r--r--src/libsyntax/parse/parser.rs73
-rw-r--r--src/libsyntax/print/pp.rs40
-rw-r--r--src/libsyntax/print/pprust.rs864
-rw-r--r--src/libsyntax/util/interner.rs75
-rw-r--r--src/libsyntax/util/parser_testing.rs6
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/test/auxiliary/cci_nested_lib.rs20
-rw-r--r--src/test/auxiliary/issue-2631-a.rs5
-rw-r--r--src/test/bench/sudoku.rs4
-rw-r--r--src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs8
-rw-r--r--src/test/compile-fail/borrowck-loan-rcvr.rs11
-rw-r--r--src/test/compile-fail/borrowck-mut-boxed-vec.rs18
-rw-r--r--src/test/compile-fail/borrowck-mut-deref-comp.rs2
-rw-r--r--src/test/compile-fail/borrowck-object-mutability.rs5
-rw-r--r--src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-2.rs5
-rw-r--r--src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-3.rs7
-rw-r--r--src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail.rs6
-rw-r--r--src/test/compile-fail/borrowck-wg-move-base-2.rs9
-rw-r--r--src/test/compile-fail/cast-immutable-mutable-trait.rs30
-rw-r--r--src/test/compile-fail/fn-variance-1.rs13
-rw-r--r--src/test/compile-fail/issue-10487.rs1
-rw-r--r--src/test/compile-fail/issue-2548.rs14
-rw-r--r--src/test/compile-fail/issue-3668.rs2
-rw-r--r--src/test/compile-fail/kindck-destructor-owned.rs3
-rw-r--r--src/test/compile-fail/lub-in-args.rs26
-rw-r--r--src/test/compile-fail/object-pointer-types.rs13
-rw-r--r--src/test/compile-fail/pinned-deep-copy.rs10
-rw-r--r--src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs2
-rw-r--r--src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs2
-rw-r--r--src/test/compile-fail/unique-vec-res.rs14
-rw-r--r--src/test/pretty/block-disambig.rs13
-rw-r--r--src/test/run-fail/borrowck-wg-autoderef-and-autoborrowvec-combined-fail-issue-6272.rs23
-rw-r--r--src/test/run-fail/borrowck-wg-fail-2.rs17
-rw-r--r--src/test/run-fail/borrowck-wg-fail-3.rs13
-rw-r--r--src/test/run-fail/borrowck-wg-fail-object-arg.rs24
-rw-r--r--src/test/run-fail/borrowck-wg-fail-object.rs23
-rw-r--r--src/test/run-fail/borrowck-wg-fail.rs15
-rw-r--r--src/test/run-fail/borrowck-wg-imm-then-mut.rs21
-rw-r--r--src/test/run-fail/borrowck-wg-mut-then-imm.rs21
-rw-r--r--src/test/run-fail/borrowck-wg-one-mut-one-imm-slice-method.rs39
-rw-r--r--src/test/run-fail/borrowck-wg-one-mut-one-imm-slices.rs18
-rw-r--r--src/test/run-fail/borrowck-wg-one-mut-one-imm.rs19
-rw-r--r--src/test/run-fail/borrowck-wg-two-array-indices.rs19
-rw-r--r--src/test/run-fail/unwind-misc-1.rs2
-rw-r--r--src/test/run-pass/alignment-gep-tup-like-2.rs11
-rw-r--r--src/test/run-pass/auto-encode.rs4
-rw-r--r--src/test/run-pass/borrowck-assign-to-subfield.rs (renamed from src/test/compile-fail/borrowck-assign-to-subfield.rs)13
-rw-r--r--src/test/run-pass/borrowck-nested-calls.rs2
-rw-r--r--src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs13
-rw-r--r--src/test/run-pass/borrowck-preserve-box-in-pat.rs14
-rw-r--r--src/test/run-pass/borrowck-root-while-cond-2.rs2
-rw-r--r--src/test/run-pass/borrowck-root-while-cond.rs2
-rw-r--r--src/test/run-pass/borrowck-univariant-enum.rs12
-rw-r--r--src/test/run-pass/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs42
-rw-r--r--src/test/run-pass/borrowck-wg-borrow-mut-to-imm-2.rs13
-rw-r--r--src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs18
-rw-r--r--src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs12
-rw-r--r--src/test/run-pass/borrowck-wg-simple.rs10
-rw-r--r--src/test/run-pass/borrowck-wg-two-imm-borrows.rs16
-rw-r--r--src/test/run-pass/builtin-superkinds-capabilities-xc.rs2
-rw-r--r--src/test/run-pass/builtin-superkinds-in-metadata.rs2
-rw-r--r--src/test/run-pass/cast-mutable-trait.rs36
-rw-r--r--src/test/run-pass/cfg-macros-foo.rs2
-rw-r--r--src/test/run-pass/cfg-macros-notfoo.rs2
-rw-r--r--src/test/run-pass/cfg_inner_static.rs2
-rw-r--r--src/test/run-pass/cfgs-on-items.rs2
-rw-r--r--src/test/run-pass/class-cast-to-trait-multiple-types.rs78
-rw-r--r--src/test/run-pass/class-cast-to-trait.rs5
-rw-r--r--src/test/run-pass/conditional-debug-macro-off.rs2
-rw-r--r--src/test/run-pass/conditional-debug-macro-on.rs2
-rw-r--r--src/test/run-pass/const-cross-crate-const.rs2
-rw-r--r--src/test/run-pass/cross-crate-const-pat.rs2
-rw-r--r--src/test/run-pass/cross-crate-newtype-struct-pat.rs2
-rw-r--r--src/test/run-pass/cycle-collection.rs8
-rw-r--r--src/test/run-pass/cycle-collection2.rs42
-rw-r--r--src/test/run-pass/deref-lval.rs8
-rw-r--r--src/test/run-pass/deriving-encodable-decodable.rs4
-rw-r--r--src/test/run-pass/deriving-global.rs2
-rw-r--r--src/test/run-pass/deriving-rand.rs2
-rw-r--r--src/test/run-pass/deriving-zero.rs2
-rw-r--r--src/test/run-pass/dupe-first-attr.rc2
-rw-r--r--src/test/run-pass/explicit-self-closures.rs3
-rw-r--r--src/test/run-pass/expr-repeat-vstore.rs6
-rw-r--r--src/test/run-pass/exterior.rs14
-rw-r--r--src/test/run-pass/extern-calling-convention-test.rs2
-rw-r--r--src/test/run-pass/extern-fn-reachable.rs2
-rw-r--r--src/test/run-pass/extern-mod-ordering-exe.rs2
-rw-r--r--src/test/run-pass/hashmap-memory.rs4
-rw-r--r--src/test/run-pass/init-res-into-things.rs32
-rw-r--r--src/test/run-pass/issue-10626.rs2
-rw-r--r--src/test/run-pass/issue-10806.rs2
-rw-r--r--src/test/run-pass/issue-11085.rs2
-rw-r--r--src/test/run-pass/issue-11224.rs2
-rw-r--r--src/test/run-pass/issue-11225-1.rs2
-rw-r--r--src/test/run-pass/issue-11225-2.rs2
-rw-r--r--src/test/run-pass/issue-2631-b.rs3
-rw-r--r--src/test/run-pass/issue-2735-2.rs12
-rw-r--r--src/test/run-pass/issue-2735-3.rs12
-rw-r--r--src/test/run-pass/issue-2904.rs4
-rw-r--r--src/test/run-pass/issue-3290.rs2
-rw-r--r--src/test/run-pass/issue-3447.rs6
-rw-r--r--src/test/run-pass/issue-3796.rs2
-rw-r--r--src/test/run-pass/issue-3860.rs26
-rw-r--r--src/test/run-pass/issue-4208.rs2
-rw-r--r--src/test/run-pass/issue-4241.rs2
-rw-r--r--src/test/run-pass/issue-4252.rs2
-rw-r--r--src/test/run-pass/issue-4545.rs2
-rw-r--r--src/test/run-pass/issue-5275.rs31
-rw-r--r--src/test/run-pass/issue-5517.rs16
-rw-r--r--src/test/run-pass/issue-5950.rs2
-rw-r--r--src/test/run-pass/issue-6334.rs2
-rw-r--r--src/test/run-pass/issue-7178.rs2
-rw-r--r--src/test/run-pass/issue-8044.rs2
-rw-r--r--src/test/run-pass/issue-8259.rs2
-rw-r--r--src/test/run-pass/issue-8498.rs2
-rw-r--r--src/test/run-pass/issue-9188.rs2
-rw-r--r--src/test/run-pass/issue-979.rs12
-rw-r--r--src/test/run-pass/issue-980.rs12
-rw-r--r--src/test/run-pass/issue-9906.rs2
-rw-r--r--src/test/run-pass/issue-9968.rs2
-rw-r--r--src/test/run-pass/issue_9155.rs2
-rw-r--r--src/test/run-pass/lambda-infer-unresolved.rs4
-rw-r--r--src/test/run-pass/linkage-visibility.rs2
-rw-r--r--src/test/run-pass/log-linearized.rs36
-rw-r--r--src/test/run-pass/logging-enabled-debug.rs2
-rw-r--r--src/test/run-pass/logging-enabled.rs2
-rw-r--r--src/test/run-pass/logging-only-prints-once.rs13
-rw-r--r--src/test/run-pass/logging-right-crate.rs2
-rw-r--r--src/test/run-pass/logging_before_rt_started.rs2
-rw-r--r--src/test/run-pass/macro-with-attrs1.rs2
-rw-r--r--src/test/run-pass/mlist-cycle.rs26
-rw-r--r--src/test/run-pass/native-print-no-runtime.rs2
-rw-r--r--src/test/run-pass/new-vstore-mut-box-syntax.rs16
-rw-r--r--src/test/run-pass/newtype-struct-drop-run.rs10
-rw-r--r--src/test/run-pass/no-std-xcrate.rs2
-rw-r--r--src/test/run-pass/no-std-xcrate2.rs2
-rw-r--r--src/test/run-pass/objects-coerce-from-managed-to-borrowed.rs17
-rw-r--r--src/test/run-pass/once-move-out-on-heap.rs2
-rw-r--r--src/test/run-pass/once-move-out-on-stack.rs2
-rw-r--r--src/test/run-pass/option-unwrap.rs11
-rw-r--r--src/test/run-pass/osx-frameworks.rs2
-rw-r--r--src/test/run-pass/packed-struct-generic-size.rs4
-rw-r--r--src/test/run-pass/packed-struct-size-xc.rs2
-rw-r--r--src/test/run-pass/packed-struct-size.rs4
-rw-r--r--src/test/run-pass/packed-tuple-struct-size.rs4
-rw-r--r--src/test/run-pass/priv-impl-prim-ty.rs2
-rw-r--r--src/test/run-pass/privacy-reexport.rs2
-rw-r--r--src/test/run-pass/rcvr-borrowed-to-region.rs2
-rw-r--r--src/test/run-pass/reexport-should-still-link.rs2
-rw-r--r--src/test/run-pass/reflect-visit-data.rs34
-rw-r--r--src/test/run-pass/reflect-visit-type.rs6
-rw-r--r--src/test/run-pass/rename-directory.rs2
-rw-r--r--src/test/run-pass/resource-assign-is-not-copy.rs12
-rw-r--r--src/test/run-pass/resource-cycle.rs83
-rw-r--r--src/test/run-pass/resource-cycle2.rs71
-rw-r--r--src/test/run-pass/resource-cycle3.rs80
-rw-r--r--src/test/run-pass/resource-destruct.rs16
-rw-r--r--src/test/run-pass/resource-in-struct.rs10
-rw-r--r--src/test/run-pass/signal-exit-status.rs2
-rw-r--r--src/test/run-pass/smallest-hello-world.rs2
-rw-r--r--src/test/run-pass/spawning-with-debug.rs2
-rw-r--r--src/test/run-pass/static-function-pointer-xc.rs2
-rw-r--r--src/test/run-pass/struct_variant_xc.rs2
-rw-r--r--src/test/run-pass/syntax-extension-cfg.rs2
-rw-r--r--src/test/run-pass/task-killjoin-rsrc.rs10
-rw-r--r--src/test/run-pass/tempfile.rs2
-rw-r--r--src/test/run-pass/trait-bounds-in-arc.rs2
-rw-r--r--src/test/run-pass/trait-cast.rs27
-rw-r--r--src/test/run-pass/trait-default-method-xc-2.rs2
-rw-r--r--src/test/run-pass/trait-default-method-xc.rs2
-rw-r--r--src/test/run-pass/tydesc-name.rs2
-rw-r--r--src/test/run-pass/typeid-intrinsic.rs2
-rw-r--r--src/test/run-pass/uniq-cc-generic.rs14
-rw-r--r--src/test/run-pass/uniq-cc.rs15
-rw-r--r--src/test/run-pass/unique-pinned-nocopy-2.rs36
-rw-r--r--src/test/run-pass/use_inline_dtor.rs2
-rw-r--r--src/test/run-pass/vec-slice-drop.rs14
-rw-r--r--src/test/run-pass/weird-exprs.rs9
-rw-r--r--src/test/run-pass/xcrate-address-insignificant.rs2
-rw-r--r--src/test/run-pass/xcrate-unit-struct.rs2
276 files changed, 2427 insertions, 3457 deletions
diff --git a/src/libextra/arena.rs b/src/libextra/arena.rs
index dc5f3b5d3cf..5ee0099561a 100644
--- a/src/libextra/arena.rs
+++ b/src/libextra/arena.rs
@@ -35,11 +35,13 @@
 #[allow(missing_doc)];
 
 
-use list::{MutList, MutCons, MutNil};
+use list::{List, Cons, Nil};
+use list;
 
 use std::at_vec;
 use std::cast::{transmute, transmute_mut, transmute_mut_region};
 use std::cast;
+use std::cell::{Cell, RefCell};
 use std::num;
 use std::ptr;
 use std::mem;
@@ -50,10 +52,11 @@ use std::unstable::intrinsics::{TyDesc, get_tydesc};
 // The way arena uses arrays is really deeply awful. The arrays are
 // allocated, and have capacities reserved, but the fill for the array
 // will always stay at 0.
+#[deriving(Clone)]
 struct Chunk {
-    data: @[u8],
-    fill: uint,
-    is_pod: bool,
+    data: RefCell<@[u8]>,
+    fill: Cell<uint>,
+    is_pod: Cell<bool>,
 }
 
 #[no_freeze]
@@ -63,7 +66,7 @@ pub struct Arena {
     // access the head.
     priv head: Chunk,
     priv pod_head: Chunk,
-    priv chunks: @mut MutList<Chunk>,
+    priv chunks: RefCell<@List<Chunk>>,
 }
 
 impl Arena {
@@ -75,7 +78,7 @@ impl Arena {
         Arena {
             head: chunk(initial_size, false),
             pod_head: chunk(initial_size, true),
-            chunks: @mut MutNil,
+            chunks: RefCell::new(@Nil),
         }
     }
 }
@@ -84,9 +87,9 @@ fn chunk(size: uint, is_pod: bool) -> Chunk {
     let mut v: @[u8] = @[];
     unsafe { at_vec::raw::reserve(&mut v, size); }
     Chunk {
-        data: unsafe { cast::transmute(v) },
-        fill: 0u,
-        is_pod: is_pod,
+        data: RefCell::new(unsafe { cast::transmute(v) }),
+        fill: Cell::new(0u),
+        is_pod: Cell::new(is_pod),
     }
 }
 
@@ -95,8 +98,9 @@ impl Drop for Arena {
     fn drop(&mut self) {
         unsafe {
             destroy_chunk(&self.head);
-            self.chunks.each(|chunk| {
-                if !chunk.is_pod {
+
+            list::each(self.chunks.get(), |chunk| {
+                if !chunk.is_pod.get() {
                     destroy_chunk(chunk);
                 }
                 true
@@ -114,8 +118,11 @@ fn round_up_to(base: uint, align: uint) -> uint {
 // in it.
 unsafe fn destroy_chunk(chunk: &Chunk) {
     let mut idx = 0;
-    let buf = chunk.data.as_ptr();
-    let fill = chunk.fill;
+    let buf = {
+        let data = chunk.data.borrow();
+        data.get().as_ptr()
+    };
+    let fill = chunk.fill.get();
 
     while idx < fill {
         let tydesc_data: *uint = transmute(ptr::offset(buf, idx as int));
@@ -155,9 +162,9 @@ impl Arena {
     // Functions for the POD part of the arena
     fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 {
         // Allocate a new chunk.
-        let chunk_size = at_vec::capacity(self.pod_head.data);
+        let chunk_size = at_vec::capacity(self.pod_head.data.get());
         let new_min_chunk_size = num::max(n_bytes, chunk_size);
-        self.chunks = @mut MutCons(self.pod_head, self.chunks);
+        self.chunks.set(@Cons(self.pod_head.clone(), self.chunks.get()));
         self.pod_head =
             chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true);
 
@@ -168,17 +175,17 @@ impl Arena {
     fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 {
         unsafe {
             let this = transmute_mut_region(self);
-            let start = round_up_to(this.pod_head.fill, align);
+            let start = round_up_to(this.pod_head.fill.get(), align);
             let end = start + n_bytes;
-            if end > at_vec::capacity(this.pod_head.data) {
+            if end > at_vec::capacity(this.pod_head.data.get()) {
                 return this.alloc_pod_grow(n_bytes, align);
             }
-            this.pod_head.fill = end;
+            this.pod_head.fill.set(end);
 
             //debug!("idx = {}, size = {}, align = {}, fill = {}",
-            //       start, n_bytes, align, head.fill);
+            //       start, n_bytes, align, head.fill.get());
 
-            ptr::offset(this.pod_head.data.as_ptr(), start as int)
+            ptr::offset(this.pod_head.data.get().as_ptr(), start as int)
         }
     }
 
@@ -197,9 +204,9 @@ impl Arena {
     fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint)
                          -> (*u8, *u8) {
         // Allocate a new chunk.
-        let chunk_size = at_vec::capacity(self.head.data);
+        let chunk_size = at_vec::capacity(self.head.data.get());
         let new_min_chunk_size = num::max(n_bytes, chunk_size);
-        self.chunks = @mut MutCons(self.head, self.chunks);
+        self.chunks.set(@Cons(self.head.clone(), self.chunks.get()));
         self.head =
             chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false);
 
@@ -218,23 +225,23 @@ impl Arena {
             {
                 let head = transmute_mut_region(&mut self.head);
 
-                tydesc_start = head.fill;
-                after_tydesc = head.fill + mem::size_of::<*TyDesc>();
+                tydesc_start = head.fill.get();
+                after_tydesc = head.fill.get() + mem::size_of::<*TyDesc>();
                 start = round_up_to(after_tydesc, align);
                 end = start + n_bytes;
             }
 
-            if end > at_vec::capacity(self.head.data) {
+            if end > at_vec::capacity(self.head.data.get()) {
                 return self.alloc_nonpod_grow(n_bytes, align);
             }
 
             let head = transmute_mut_region(&mut self.head);
-            head.fill = round_up_to(end, mem::pref_align_of::<*TyDesc>());
+            head.fill.set(round_up_to(end, mem::pref_align_of::<*TyDesc>()));
 
             //debug!("idx = {}, size = {}, align = {}, fill = {}",
             //       start, n_bytes, align, head.fill);
 
-            let buf = self.head.data.as_ptr();
+            let buf = self.head.data.get().as_ptr();
             return (ptr::offset(buf, tydesc_start as int), ptr::offset(buf, start as int));
         }
     }
diff --git a/src/libextra/list.rs b/src/libextra/list.rs
index a2540d3948e..b530d9c9bc1 100644
--- a/src/libextra/list.rs
+++ b/src/libextra/list.rs
@@ -19,13 +19,6 @@ pub enum List<T> {
     Nil,
 }
 
-#[deriving(Eq)]
-#[allow(missing_doc)]
-pub enum MutList<T> {
-    MutCons(T, @mut MutList<T>),
-    MutNil,
-}
-
 /// Create a list from a vector
 pub fn from_vec<T:Clone + 'static>(v: &[T]) -> @List<T> {
     v.rev_iter().fold(@Nil::<T>, |t, h| @Cons((*h).clone(), t))
@@ -158,26 +151,6 @@ pub fn each<T>(l: @List<T>, f: |&T| -> bool) -> bool {
     }
 }
 
-impl<T> MutList<T> {
-    /// Iterate over a mutable list
-    pub fn each(@mut self, f: |&mut T| -> bool) -> bool {
-        let mut cur = self;
-        loop {
-            let borrowed = &mut *cur;
-            cur = match *borrowed {
-                MutCons(ref mut hd, tl) => {
-                    if !f(hd) {
-                        return false;
-                    }
-                    tl
-                }
-                MutNil => break
-            }
-        }
-        return true;
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use list::*;
diff --git a/src/libextra/serialize.rs b/src/libextra/serialize.rs
index 6b298d877da..e7ccb91fb75 100644
--- a/src/libextra/serialize.rs
+++ b/src/libextra/serialize.rs
@@ -426,18 +426,6 @@ impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @T {
     }
 }
 
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for @mut T {
-    fn encode(&self, s: &mut S) {
-        (**self).encode(s)
-    }
-}
-
-impl<D:Decoder,T:Decodable<D> + 'static> Decodable<D> for @mut T {
-    fn decode(d: &mut D) -> @mut T {
-        @mut Decodable::decode(d)
-    }
-}
-
 impl<'a, S:Encoder,T:Encodable<S>> Encodable<S> for &'a [T] {
     fn encode(&self, s: &mut S) {
         s.emit_seq(self.len(), |s| {
diff --git a/src/libextra/term.rs b/src/libextra/term.rs
index 05e9b65d19c..1f119ca9db4 100644
--- a/src/libextra/term.rs
+++ b/src/libextra/term.rs
@@ -113,7 +113,8 @@ impl<T: Writer> Terminal<T> {
             return Err(entry.unwrap_err());
         }
 
-        let ti = parse(entry.unwrap(), false);
+        let mut file = entry.unwrap();
+        let ti = parse(&mut file, false);
         if ti.is_err() {
             return Err(ti.unwrap_err());
         }
diff --git a/src/libextra/terminfo/searcher.rs b/src/libextra/terminfo/searcher.rs
index 09f8cc0efef..8cbb0902697 100644
--- a/src/libextra/terminfo/searcher.rs
+++ b/src/libextra/terminfo/searcher.rs
@@ -11,10 +11,9 @@
 /// Implement ncurses-compatible database discovery
 /// Does not support hashed database, only filesystem!
 
-use std::{os, str};
-use std::os::getenv;
-use std::io;
 use std::io::File;
+use std::os::getenv;
+use std::{os, str};
 
 /// Return path to database entry for `term`
 pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
@@ -74,9 +73,14 @@ pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
 }
 
 /// Return open file for `term`
-pub fn open(term: &str) -> Result<@mut io::Reader, ~str> {
+pub fn open(term: &str) -> Result<File, ~str> {
     match get_dbpath_for_term(term) {
-        Some(x) => Ok(@mut File::open(x) as @mut io::Reader),
+        Some(x) => {
+            match File::open(x) {
+                Some(file) => Ok(file),
+                None => Err(~"error opening file"),
+            }
+        }
         None => Err(format!("could not find terminfo entry for {}", term))
     }
 }
diff --git a/src/libextra/test.rs b/src/libextra/test.rs
index 63e19df9519..79fb9e3935a 100644
--- a/src/libextra/test.rs
+++ b/src/libextra/test.rs
@@ -949,7 +949,8 @@ impl MetricMap {
 
     /// Write MetricDiff to a file.
     pub fn save(&self, p: &Path) {
-        self.to_json().to_pretty_writer(@mut File::create(p) as @mut io::Writer);
+        let mut file = File::create(p);
+        self.to_json().to_pretty_writer(&mut file)
     }
 
     /// Compare against another MetricMap. Optionally compare all
diff --git a/src/libextra/uuid.rs b/src/libextra/uuid.rs
index cf40a59a8c5..ef6c9e7f9cd 100644
--- a/src/libextra/uuid.rs
+++ b/src/libextra/uuid.rs
@@ -796,8 +796,8 @@ mod test {
         use serialize::{Encodable, Decodable};
 
         let u = Uuid::new_v4();
-        let wr = @mut MemWriter::new();
-        u.encode(&mut ebml::writer::Encoder(wr));
+        let mut wr = MemWriter::new();
+        u.encode(&mut ebml::writer::Encoder(&mut wr));
         let doc = ebml::reader::Doc(wr.inner_ref().as_slice());
         let u2 = Decodable::decode(&mut ebml::reader::Decoder(doc));
         assert_eq!(u, u2);
diff --git a/src/libextra/workcache.rs b/src/libextra/workcache.rs
index 8713dbde920..874e3c70af0 100644
--- a/src/libextra/workcache.rs
+++ b/src/libextra/workcache.rs
@@ -173,8 +173,8 @@ impl Database {
 
     // FIXME #4330: This should have &mut self and should set self.db_dirty to false.
     fn save(&self) {
-        let f = @mut File::create(&self.db_filename);
-        self.db_cache.to_json().to_pretty_writer(f as @mut io::Writer);
+        let mut f = File::create(&self.db_filename);
+        self.db_cache.to_json().to_pretty_writer(&mut f);
     }
 
     fn load(&mut self) {
@@ -184,14 +184,16 @@ impl Database {
             Err(e) => fail!("Couldn't load workcache database {}: {}",
                             self.db_filename.display(),
                             e.desc),
-            Ok(r) =>
-                match json::from_reader(@mut r.unwrap() as @mut io::Reader) {
+            Ok(r) => {
+                let mut stream = r.unwrap();
+                match json::from_reader(&mut stream) {
                     Err(e) => fail!("Couldn't parse workcache database (from file {}): {}",
                                     self.db_filename.display(), e.to_str()),
                     Ok(r) => {
                         let mut decoder = json::Decoder::new(r);
                         self.db_cache = Decodable::decode(&mut decoder);
                     }
+                }
             }
         }
     }
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 9269893c062..c185b5cda34 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -295,7 +295,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
          middle::liveness::check_crate(ty_cx, method_map,
                                        capture_map, crate));
 
-    let (root_map, write_guard_map) =
+    let root_map =
         time(time_passes, "borrow checking", (), |_|
              middle::borrowck::check_crate(ty_cx, method_map,
                                            moves_map, moved_variables_set,
@@ -330,7 +330,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
             root_map: root_map,
             method_map: method_map,
             vtable_map: vtable_map,
-            write_guard_map: write_guard_map,
             capture_map: capture_map
         },
         reachable: reachable_map
@@ -464,9 +463,19 @@ fn write_out_deps(sess: Session, input: &input, outputs: &OutputFilenames, crate
 
     // Build a list of files used to compile the output and
     // write Makefile-compatible dependency rules
-    let files: ~[@str] = sess.codemap.files.iter()
-        .filter_map(|fmap| if fmap.is_real_file() { Some(fmap.name) } else { None })
-        .collect();
+    let files: ~[@str] = {
+        let files = sess.codemap.files.borrow();
+        files.get()
+             .iter()
+             .filter_map(|fmap| {
+                 if fmap.is_real_file() {
+                     Some(fmap.name)
+                 } else {
+                     None
+                 }
+             })
+             .collect()
+    };
     let mut file = io::File::create(&deps_filename);
     for path in out_filenames.iter() {
         write!(&mut file as &mut Writer,
@@ -517,20 +526,20 @@ impl pprust::pp_ann for IdentifiedAnnotation {
     fn post(&self, node: pprust::ann_node) {
         match node {
             pprust::node_item(s, item) => {
-                pp::space(s.s);
+                pp::space(&mut s.s);
                 pprust::synth_comment(s, item.id.to_str());
             }
-            pprust::node_block(s, ref blk) => {
-                pp::space(s.s);
+            pprust::node_block(s, blk) => {
+                pp::space(&mut s.s);
                 pprust::synth_comment(s, ~"block " + blk.id.to_str());
             }
             pprust::node_expr(s, expr) => {
-                pp::space(s.s);
+                pp::space(&mut s.s);
                 pprust::synth_comment(s, expr.id.to_str());
                 pprust::pclose(s);
             }
             pprust::node_pat(s, pat) => {
-                pp::space(s.s);
+                pp::space(&mut s.s);
                 pprust::synth_comment(s, ~"pat " + pat.id.to_str());
             }
         }
@@ -552,10 +561,10 @@ impl pprust::pp_ann for TypedAnnotation {
         let tcx = self.analysis.ty_cx;
         match node {
             pprust::node_expr(s, expr) => {
-                pp::space(s.s);
-                pp::word(s.s, "as");
-                pp::space(s.s);
-                pp::word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
+                pp::space(&mut s.s);
+                pp::word(&mut s.s, "as");
+                pp::space(&mut s.s);
+                pp::word(&mut s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
                 pprust::pclose(s);
             }
             _ => ()
@@ -592,15 +601,15 @@ pub fn pretty_print_input(sess: Session,
     };
 
     let src = sess.codemap.get_filemap(source_name(input)).src;
-    let rdr = @mut MemReader::new(src.as_bytes().to_owned());
+    let mut rdr = MemReader::new(src.as_bytes().to_owned());
     let stdout = io::stdout();
     pprust::print_crate(sess.codemap,
                         token::get_ident_interner(),
                         sess.span_diagnostic,
                         &crate,
                         source_name(input),
-                        rdr as @mut io::Reader,
-                        @mut stdout as @mut io::Writer,
+                        &mut rdr,
+                        ~stdout as ~io::Writer,
                         annotation,
                         is_expanded);
 }
@@ -883,7 +892,7 @@ pub fn build_session(sopts: @session::options, demitter: @diagnostic::Emitter)
 pub fn build_session_(sopts: @session::options,
                       cm: @codemap::CodeMap,
                       demitter: @diagnostic::Emitter,
-                      span_diagnostic_handler: @mut diagnostic::SpanHandler)
+                      span_diagnostic_handler: @diagnostic::SpanHandler)
                       -> Session {
     let target_cfg = build_target_config(sopts, demitter);
     let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index b3f093f7677..4295d14441e 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -204,12 +204,12 @@ pub struct Session_ {
     targ_cfg: @config,
     opts: @options,
     cstore: @metadata::cstore::CStore,
-    parse_sess: @mut ParseSess,
+    parse_sess: @ParseSess,
     codemap: @codemap::CodeMap,
     // For a library crate, this is always none
     entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
     entry_type: Cell<Option<EntryFnType>>,
-    span_diagnostic: @mut diagnostic::SpanHandler,
+    span_diagnostic: @diagnostic::SpanHandler,
     filesearch: @filesearch::FileSearch,
     building_library: Cell<bool>,
     working_dir: Path,
@@ -292,7 +292,7 @@ impl Session_ {
 
         v
     }
-    pub fn diagnostic(&self) -> @mut diagnostic::SpanHandler {
+    pub fn diagnostic(&self) -> @diagnostic::SpanHandler {
         self.span_diagnostic
     }
     pub fn debugging_opt(&self, opt: uint) -> bool {
diff --git a/src/librustc/front/feature_gate.rs b/src/librustc/front/feature_gate.rs
index 6bbf18de693..fa0be72b830 100644
--- a/src/librustc/front/feature_gate.rs
+++ b/src/librustc/front/feature_gate.rs
@@ -189,9 +189,8 @@ impl Visitor<()> for Context {
 
     fn visit_expr(&mut self, e: @ast::Expr, _: ()) {
         match e.node {
-            ast::ExprUnary(_, ast::UnBox(..), _) |
-            ast::ExprVstore(_, ast::ExprVstoreBox) |
-            ast::ExprVstore(_, ast::ExprVstoreMutBox) => {
+            ast::ExprUnary(_, ast::UnBox, _) |
+            ast::ExprVstore(_, ast::ExprVstoreBox) => {
                 self.gate_box(e.span);
             }
             _ => {}
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index f14c9780bc4..cb6d5e3c99c 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -86,7 +86,7 @@ fn dump_crates(crate_cache: &[cache_entry]) {
 }
 
 fn warn_if_multiple_versions(e: &mut Env,
-                             diag: @mut SpanHandler,
+                             diag: @SpanHandler,
                              crate_cache: &[cache_entry]) {
     if crate_cache.len() != 0u {
         let name = crate_cache[crate_cache.len() - 1].crateid.name.clone();
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index ba46d29902e..4592b88a0fa 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -57,7 +57,7 @@ pub type encode_inlined_item<'a> = 'a |ecx: &EncodeContext,
                                              ii: ast::inlined_item|;
 
 pub struct EncodeParams<'a> {
-    diag: @mut SpanHandler,
+    diag: @SpanHandler,
     tcx: ty::ctxt,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'a RefCell<HashMap<ast::NodeId, ~str>>,
@@ -83,7 +83,7 @@ struct Stats {
 }
 
 pub struct EncodeContext<'a> {
-    diag: @mut SpanHandler,
+    diag: @SpanHandler,
     tcx: ty::ctxt,
     stats: @Stats,
     reexports2: middle::resolve::ExportMap2,
@@ -489,7 +489,8 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
                                     ebml_w: &mut writer::Encoder,
                                     mod_path: &[ast_map::path_elt],
                                     exp: &middle::resolve::Export2) {
-    match ecx.tcx.items.find(&exp.def_id.node) {
+    let items = ecx.tcx.items.borrow();
+    match items.get().find(&exp.def_id.node) {
         Some(&ast_map::node_item(item, path)) => {
             let original_name = ecx.tcx.sess.str_of(item.ident);
 
@@ -1338,7 +1339,8 @@ fn my_visit_item(i: @item,
                  ebml_w: &mut writer::Encoder,
                  ecx_ptr: *int,
                  index: @RefCell<~[entry<i64>]>) {
-    match items.get_copy(&i.id) {
+    let items = items.borrow();
+    match items.get().get_copy(&i.id) {
         ast_map::node_item(_, pt) => {
             let mut ebml_w = unsafe {
                 ebml_w.unsafe_clone()
@@ -1356,7 +1358,8 @@ fn my_visit_foreign_item(ni: @foreign_item,
                          ebml_w: &mut writer::Encoder,
                          ecx_ptr:*int,
                          index: @RefCell<~[entry<i64>]>) {
-    match items.get_copy(&ni.id) {
+    let items = items.borrow();
+    match items.get().get_copy(&ni.id) {
         ast_map::node_foreign_item(_, abi, _, pt) => {
             debug!("writing foreign item {}::{}",
                    ast_map::path_to_str(
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 37e6a46d6ba..d4f940ab486 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -231,8 +231,7 @@ impl Context {
     }
 }
 
-pub fn note_crateid_attr(diag: @mut 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 22fc7f4b3ea..f0cb4533968 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -342,7 +342,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
         return ty::mk_self(st.tcx, did);
       }
-      '@' => return ty::mk_box(st.tcx, parse_mt(st, |x,y| conv(x,y))),
+      '@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))),
       '~' => return ty::mk_uniq(st.tcx, parse_mt(st, |x,y| conv(x,y))),
       '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))),
       '&' => {
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index e6ed70bd4dc..2ba4038e5b4 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -32,7 +32,7 @@ macro_rules! mywrite( ($wr:expr, $($arg:tt)*) => (
 ) )
 
 pub struct ctxt {
-    diag: @mut SpanHandler,
+    diag: @SpanHandler,
     // Def -> str Callback:
     ds: extern "Rust" fn(DefId) -> ~str,
     // The type context.
@@ -292,7 +292,7 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
             for t in ts.iter() { enc_ty(w, cx, *t); }
             mywrite!(w, "]");
         }
-        ty::ty_box(mt) => { mywrite!(w, "@"); enc_mt(w, cx, mt); }
+        ty::ty_box(typ) => { mywrite!(w, "@"); enc_ty(w, cx, typ); }
         ty::ty_uniq(mt) => { mywrite!(w, "~"); enc_mt(w, cx, mt); }
         ty::ty_ptr(mt) => { mywrite!(w, "*"); enc_mt(w, cx, mt); }
         ty::ty_rptr(r, mt) => {
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index f413dfd2451..2e18b9a7244 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -55,7 +55,6 @@ pub struct Maps {
     root_map: middle::borrowck::root_map,
     method_map: middle::typeck::method_map,
     vtable_map: middle::typeck::vtable_map,
-    write_guard_map: middle::borrowck::write_guard_map,
     capture_map: middle::moves::CaptureMap,
 }
 
@@ -1429,18 +1428,18 @@ 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) -> @mut parse::ParseSess;
+    fn parse_sess(&self) -> @parse::ParseSess;
     fn call_site(&self) -> Span;
     fn ident_of(&self, st: &str) -> ast::Ident;
 }
 
 #[cfg(test)]
-type fake_session = @mut parse::ParseSess;
+type fake_session = @parse::ParseSess;
 
 #[cfg(test)]
 impl fake_ext_ctxt for fake_session {
     fn cfg(&self) -> ast::CrateConfig { ~[] }
-    fn parse_sess(&self) -> @mut parse::ParseSess { *self }
+    fn parse_sess(&self) -> @parse::ParseSess { *self }
     fn call_site(&self) -> Span {
         codemap::Span {
             lo: codemap::BytePos(0),
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 6176f5601c1..c26efbcb498 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -368,11 +368,15 @@ impl<'a> CheckLoanCtxt<'a> {
                         cmt = b;
                     }
 
+                    mc::cat_deref(_, _, mc::gc_ptr) => {
+                        assert_eq!(cmt.mutbl, mc::McImmutable);
+                        return;
+                    }
+
                     mc::cat_rvalue(..) |
                     mc::cat_static_item |
                     mc::cat_copied_upvar(..) |
                     mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
-                    mc::cat_deref(_, _, mc::gc_ptr(..)) |
                     mc::cat_deref(_, _, mc::region_ptr(..)) => {
                         assert_eq!(cmt.mutbl, mc::McDeclared);
                         return;
@@ -411,20 +415,6 @@ impl<'a> CheckLoanCtxt<'a> {
                     check_for_aliasability_violation(this, expr, b);
                 }
 
-                mc::cat_deref(_, deref_count, mc::gc_ptr(ast::MutMutable)) => {
-                    // Dynamically check writes to `@mut`
-
-                    let key = root_map_key {
-                        id: guarantor.id,
-                        derefs: deref_count
-                    };
-                    debug!("Inserting write guard at {:?}", key);
-                    let mut write_guard_map = this.bccx
-                                                  .write_guard_map
-                                                  .borrow_mut();
-                    write_guard_map.get().insert(key);
-                }
-
                 _ => {}
             }
 
@@ -455,7 +445,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     mc::cat_self(..) |
                     mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
                     mc::cat_static_item(..) |
-                    mc::cat_deref(_, _, mc::gc_ptr(_)) |
+                    mc::cat_deref(_, _, mc::gc_ptr) |
                     mc::cat_deref(_, _, mc::region_ptr(MutImmutable, _)) => {
                         // Aliasability is independent of base cmt
                         match cmt.freely_aliasable() {
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index 907a8e8fdd9..3b16d7e7e1c 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -102,7 +102,7 @@ fn check_is_legal_to_move_from(bccx: &BorrowckCtxt,
                                cmt: mc::cmt) -> bool {
     match cmt.cat {
         mc::cat_deref(_, _, mc::region_ptr(..)) |
-        mc::cat_deref(_, _, mc::gc_ptr(..)) |
+        mc::cat_deref(_, _, mc::gc_ptr) |
         mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
         mc::cat_stack_upvar(..) |
         mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index 38598e8b78f..9a56ec52cce 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -16,10 +16,8 @@
 use middle::borrowck::*;
 use mc = middle::mem_categorization;
 use middle::ty;
-use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
 use syntax::codemap::Span;
-use util::ppaux::{note_and_explain_region};
 
 type R = Result<(),()>;
 
@@ -89,12 +87,11 @@ impl<'a> GuaranteeLifetimeContext<'a> {
                 Ok(())
             }
 
-            mc::cat_deref(base, derefs, mc::gc_ptr(ptr_mutbl)) => {
+            mc::cat_deref(base, derefs, mc::gc_ptr) => {
                 let base_scope = self.scope(base);
 
                 // L-Deref-Managed-Imm-User-Root
                 let omit_root = (
-                    ptr_mutbl == MutImmutable &&
                     self.bccx.is_subregion_of(self.loan_region, base_scope) &&
                     self.is_rvalue_or_immutable(base) &&
                     !self.is_moved(base)
@@ -103,7 +100,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
                 if !omit_root {
                     // L-Deref-Managed-Imm-Compiler-Root
                     // L-Deref-Managed-Mut-Compiler-Root
-                    self.check_root(cmt, base, derefs, ptr_mutbl, discr_scope)
+                    self.check_root(cmt, base, derefs, discr_scope)
                 } else {
                     debug!("omitting root, base={}, base_scope={:?}",
                            base.repr(self.tcx()), base_scope);
@@ -192,14 +189,12 @@ impl<'a> GuaranteeLifetimeContext<'a> {
                   cmt_deref: mc::cmt,
                   cmt_base: mc::cmt,
                   derefs: uint,
-                  ptr_mutbl: ast::Mutability,
                   discr_scope: Option<ast::NodeId>) -> R {
-        debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, ptr_mutbl={:?}, \
+        debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, \
                 discr_scope={:?})",
                cmt_deref.repr(self.tcx()),
                cmt_base.repr(self.tcx()),
                derefs,
-               ptr_mutbl,
                discr_scope);
 
         // Make sure that the loan does not exceed the maximum time
@@ -235,19 +230,6 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             }
         };
 
-        // If we are borrowing the inside of an `@mut` box,
-        // we need to dynamically mark it to prevent incompatible
-        // borrows from happening later.
-        let opt_dyna = match ptr_mutbl {
-            MutImmutable => None,
-            MutMutable => {
-                match self.loan_mutbl {
-                    MutableMutability => Some(DynaMut),
-                    ImmutableMutability | ConstMutability => Some(DynaImm)
-                }
-            }
-        };
-
         // FIXME(#3511) grow to the nearest cleanup scope---this can
         // cause observable errors if freezing!
         if !self.bccx.tcx.region_maps.is_cleanup_scope(root_scope) {
@@ -256,29 +238,12 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             let cleanup_scope =
                 self.bccx.tcx.region_maps.cleanup_scope(root_scope);
 
-            if opt_dyna.is_some() {
-                self.tcx().sess.span_warn(
-                    self.span,
-                    format!("Dynamic freeze scope artifically extended \
-                          (see Issue \\#6248)"));
-                note_and_explain_region(
-                    self.bccx.tcx,
-                    "managed value only needs to be frozen for ",
-                    ty::ReScope(root_scope),
-                    "...");
-                note_and_explain_region(
-                    self.bccx.tcx,
-                    "...but due to Issue #6248, it will be frozen for ",
-                    ty::ReScope(cleanup_scope),
-                    "");
-            }
-
             root_scope = cleanup_scope;
         }
 
         // Add a record of what is required
         let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
-        let root_info = RootInfo {scope: root_scope, freeze: opt_dyna};
+        let root_info = RootInfo {scope: root_scope};
 
         let mut root_map = self.bccx.root_map.borrow_mut();
         root_map.get().insert(rm_key, root_info);
@@ -357,7 +322,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             }
             mc::cat_downcast(cmt) |
             mc::cat_deref(cmt, _, mc::uniq_ptr) |
-            mc::cat_deref(cmt, _, mc::gc_ptr(..)) |
+            mc::cat_deref(cmt, _, mc::gc_ptr) |
             mc::cat_interior(cmt, _) |
             mc::cat_stack_upvar(cmt) |
             mc::cat_discr(cmt, _) => {
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index ae6b828ecaa..50b437e95d5 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -132,59 +132,11 @@ impl<'a> RestrictionsContext<'a> {
                 Safe
             }
 
-            mc::cat_deref(_, _, mc::gc_ptr(MutImmutable)) => {
+            mc::cat_deref(_, _, mc::gc_ptr) => {
                 // R-Deref-Imm-Managed
                 Safe
             }
 
-            mc::cat_deref(cmt_base, _, pk @ mc::gc_ptr(MutMutable)) => {
-                // R-Deref-Managed-Borrowed
-                //
-                // Technically, no restrictions are *necessary* here.
-                // The validity of the borrow is guaranteed
-                // dynamically.  However, nonetheless we add a
-                // restriction to make a "best effort" to report
-                // static errors. For example, if there is code like
-                //
-                //    let v = @mut ~[1, 2, 3];
-                //    for e in v.iter() {
-                //        v.push(e + 1);
-                //    }
-                //
-                // Then the code below would add restrictions on `*v`,
-                // which means that an error would be reported
-                // here. This of course is not perfect. For example,
-                // a function like the following would not report an error
-                // at compile-time but would fail dynamically:
-                //
-                //    let v = @mut ~[1, 2, 3];
-                //    let w = v;
-                //    for e in v.iter() {
-                //        w.push(e + 1);
-                //    }
-                //
-                // In addition, we only add a restriction for those cases
-                // where we can construct a sensible loan path, so an
-                // example like the following will fail dynamically:
-                //
-                //    impl V {
-                //      fn get_list(&self) -> @mut ~[int];
-                //    }
-                //    ...
-                //    let v: &V = ...;
-                //    for e in v.get_list().iter() {
-                //        v.get_list().push(e + 1);
-                //    }
-                match opt_loan_path(cmt_base) {
-                    None => Safe,
-                    Some(lp_base) => {
-                        let lp = @LpExtend(lp_base, cmt.mutbl, LpDeref(pk));
-                        SafeIf(lp, ~[Restriction {loan_path: lp,
-                                                  set: restrictions}])
-                    }
-                }
-            }
-
             mc::cat_deref(cmt_base, _, pk @ mc::region_ptr(MutMutable, lt)) => {
                 // R-Deref-Mut-Borrowed
                 if !self.bccx.is_subregion_of(self.loan_region, lt) {
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index ddc31598d67..6193c6fc898 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -20,7 +20,7 @@ use middle::dataflow::DataFlowOperator;
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
 use std::cell::{Cell, RefCell};
-use std::hashmap::{HashSet, HashMap};
+use std::hashmap::HashMap;
 use std::ops::{BitOr, BitAnd};
 use std::result::{Result};
 use syntax::ast;
@@ -67,14 +67,13 @@ impl Visitor<()> for BorrowckCtxt {
     }
 }
 
-pub fn check_crate(
-    tcx: ty::ctxt,
-    method_map: typeck::method_map,
-    moves_map: moves::MovesMap,
-    moved_variables_set: moves::MovedVariablesSet,
-    capture_map: moves::CaptureMap,
-    crate: &ast::Crate) -> (root_map, write_guard_map)
-{
+pub fn check_crate(tcx: ty::ctxt,
+                   method_map: typeck::method_map,
+                   moves_map: moves::MovesMap,
+                   moved_variables_set: moves::MovedVariablesSet,
+                   capture_map: moves::CaptureMap,
+                   crate: &ast::Crate)
+                   -> root_map {
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
         method_map: method_map,
@@ -82,7 +81,6 @@ pub fn check_crate(
         moved_variables_set: moved_variables_set,
         capture_map: capture_map,
         root_map: root_map(),
-        write_guard_map: @RefCell::new(HashSet::new()),
         stats: @BorrowStats {
             loaned_paths_same: Cell::new(0),
             loaned_paths_imm: Cell::new(0),
@@ -106,7 +104,7 @@ pub fn check_crate(
                  make_stat(bccx, bccx.stats.stable_paths.get()));
     }
 
-    return (bccx.root_map, bccx.write_guard_map);
+    return bccx.root_map;
 
     fn make_stat(bccx: &mut BorrowckCtxt, stat: uint) -> ~str {
         let stat_f = stat as f64;
@@ -171,7 +169,6 @@ pub struct BorrowckCtxt {
     moved_variables_set: moves::MovedVariablesSet,
     capture_map: moves::CaptureMap,
     root_map: root_map,
-    write_guard_map: write_guard_map,
 
     // Statistics:
     stats: @BorrowStats
@@ -213,10 +210,6 @@ pub struct root_map_key {
     derefs: uint
 }
 
-// A set containing IDs of expressions of gc'd type that need to have a write
-// guard.
-pub type write_guard_map = @RefCell<HashSet<root_map_key>>;
-
 pub type BckResult<T> = Result<T, BckError>;
 
 #[deriving(Eq)]
@@ -402,7 +395,6 @@ impl BitAnd<RestrictionSet,RestrictionSet> for RestrictionSet {
 
 pub struct RootInfo {
     scope: ast::NodeId,
-    freeze: Option<DynaFreezeKind> // Some() if we should freeze box at runtime
 }
 
 pub type root_map = @RefCell<HashMap<root_map_key, RootInfo>>;
@@ -411,20 +403,6 @@ pub fn root_map() -> root_map {
     return @RefCell::new(HashMap::new());
 }
 
-pub enum DynaFreezeKind {
-    DynaImm,
-    DynaMut
-}
-
-impl ToStr for DynaFreezeKind {
-    fn to_str(&self) -> ~str {
-        match *self {
-            DynaMut => ~"mutable",
-            DynaImm => ~"immutable"
-        }
-    }
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Errors
 
@@ -691,20 +669,9 @@ impl BorrowckCtxt {
                     span,
                     format!("{} in an aliasable location", prefix));
             }
-            mc::AliasableManaged(ast::MutMutable) => {
-                // FIXME(#6269) reborrow @mut to &mut
-                self.tcx.sess.span_err(
-                    span,
-                    format!("{} in a `@mut` pointer; \
-                          try borrowing as `&mut` first", prefix));
-            }
-            mc::AliasableManaged(m) => {
-                self.tcx.sess.span_err(
-                    span,
-                    format!("{} in a `@{}` pointer; \
-                          try an `@mut` instead",
-                         prefix,
-                         self.mut_to_keyword(m)));
+            mc::AliasableManaged => {
+                self.tcx.sess.span_err(span, format!("{} in a `@` pointer",
+                                                     prefix))
             }
             mc::AliasableBorrowed(m) => {
                 self.tcx.sess.span_err(
@@ -788,7 +755,8 @@ impl BorrowckCtxt {
                                    out: &mut ~str) {
         match *loan_path {
             LpVar(id) => {
-                match self.tcx.items.find(&id) {
+                let items = self.tcx.items.borrow();
+                match items.get().find(&id) {
                     Some(&ast_map::node_local(ref ident)) => {
                         out.push_str(token::ident_to_str(ident));
                     }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 4dfdd00c27a..c56a268c48f 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -116,7 +116,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
     if is_const {
         match e.node {
           ExprUnary(_, UnDeref, _) => { }
-          ExprUnary(_, UnBox(_), _) | ExprUnary(_, UnUniq, _) => {
+          ExprUnary(_, UnBox, _) | ExprUnary(_, UnUniq, _) => {
             sess.span_err(e.span,
                           "cannot do allocations in constant expressions");
             return;
@@ -197,8 +197,7 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
                      immutable values");
           },
           ExprVstore(_, ExprVstoreUniq) |
-          ExprVstore(_, ExprVstoreBox) |
-          ExprVstore(_, ExprVstoreMutBox) => {
+          ExprVstore(_, ExprVstoreBox) => {
               sess.span_err(e.span, "cannot allocate vectors in constant expressions")
           },
 
@@ -266,13 +265,15 @@ impl Visitor<()> for CheckItemRecursionVisitor {
                 let def_map = self.env.def_map.borrow();
                 match def_map.get().find(&e.id) {
                     Some(&DefStatic(def_id, _)) if
-                            ast_util::is_local(def_id) =>
-                        match self.env.ast_map.get_copy(&def_id.node) {
+                            ast_util::is_local(def_id) => {
+                        let ast_map = self.env.ast_map.borrow();
+                        match ast_map.get().get_copy(&def_id.node) {
                             ast_map::node_item(it, _) => {
                                 self.visit_item(it, ());
                             }
                             _ => fail!("const not bound to an item")
-                        },
+                        }
+                    }
                     _ => ()
                 }
             },
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index d0dd36cda96..20db51861d6 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -20,7 +20,7 @@ use syntax::visit::Visitor;
 use syntax::ast::*;
 
 use std::cell::RefCell;
-use std::hashmap::{HashMap, HashSet};
+use std::hashmap::HashMap;
 
 //
 // This pass classifies expressions by their constant-ness.
@@ -107,15 +107,18 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
     }
 
     if ast_util::is_local(enum_def) {
-        match tcx.items.find(&enum_def.node) {
-            None => None,
-            Some(&ast_map::node_item(it, _)) => match it.node {
-                item_enum(ast::enum_def { variants: ref variants }, _) => {
-                    variant_expr(*variants, variant_def.node)
-                }
-                _ => None
-            },
-            Some(_) => None
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&enum_def.node) {
+                None => None,
+                Some(&ast_map::node_item(it, _)) => match it.node {
+                    item_enum(ast::enum_def { variants: ref variants }, _) => {
+                        variant_expr(*variants, variant_def.node)
+                    }
+                    _ => None
+                },
+                Some(_) => None
+            }
         }
     } else {
         {
@@ -129,7 +132,6 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
             root_map: @RefCell::new(HashMap::new()),
             method_map: @RefCell::new(HashMap::new()),
             vtable_map: @RefCell::new(HashMap::new()),
-            write_guard_map: @RefCell::new(HashSet::new()),
             capture_map: @RefCell::new(HashMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, enum_def,
@@ -155,17 +157,21 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
     }
 }
 
-pub fn lookup_const_by_id(tcx: ty::ctxt,
-                          def_id: ast::DefId)
-                       -> Option<@Expr> {
+pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
+                          -> Option<@Expr> {
     if ast_util::is_local(def_id) {
-        match tcx.items.find(&def_id.node) {
-            None => None,
-            Some(&ast_map::node_item(it, _)) => match it.node {
-                item_static(_, ast::MutImmutable, const_expr) => Some(const_expr),
-                _ => None
-            },
-            Some(_) => None
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&def_id.node) {
+                None => None,
+                Some(&ast_map::node_item(it, _)) => match it.node {
+                    item_static(_, ast::MutImmutable, const_expr) => {
+                        Some(const_expr)
+                    }
+                    _ => None
+                },
+                Some(_) => None
+            }
         }
     } else {
         {
@@ -179,7 +185,6 @@ pub fn lookup_const_by_id(tcx: ty::ctxt,
             root_map: @RefCell::new(HashMap::new()),
             method_map: @RefCell::new(HashMap::new()),
             vtable_map: @RefCell::new(HashMap::new()),
-            write_guard_map: @RefCell::new(HashSet::new()),
             capture_map: @RefCell::new(HashMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, def_id,
@@ -234,7 +239,6 @@ impl ConstEvalVisitor {
                     ast::ExprVstoreSlice => self.classify(e),
                     ast::ExprVstoreUniq |
                     ast::ExprVstoreBox |
-                    ast::ExprVstoreMutBox |
                     ast::ExprVstoreMutSlice => non_const
                 }
             }
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 142c69a5233..b0ca03181f8 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -118,7 +118,7 @@ impl<O:DataFlowOperator> pprust::pp_ann for DataFlowContext<O> {
             let comment_str = format!("id {}: {}{}{}",
                                       id, entry_str, gens_str, kills_str);
             pprust::synth_comment(ps, comment_str);
-            pp::space(ps.s);
+            pp::space(&mut ps.s);
         }
     }
 }
@@ -347,19 +347,19 @@ impl<O:DataFlowOperator+Clone+'static> DataFlowContext<O> {
         debug!("Dataflow result:");
         debug!("{}", {
             let this = @(*self).clone();
-            this.pretty_print_to(@mut io::stderr() as @mut io::Writer, blk);
+            this.pretty_print_to(~io::stderr() as ~io::Writer, blk);
             ""
         });
     }
 
-    fn pretty_print_to(@self, wr: @mut io::Writer, blk: &ast::Block) {
-        let ps = pprust::rust_printer_annotated(wr,
-                                                self.tcx.sess.intr(),
-                                                self as @pprust::pp_ann);
-        pprust::cbox(ps, pprust::indent_unit);
-        pprust::ibox(ps, 0u);
-        pprust::print_block(ps, blk);
-        pp::eof(ps.s);
+    fn pretty_print_to(@self, wr: ~io::Writer, blk: &ast::Block) {
+        let mut ps = pprust::rust_printer_annotated(wr,
+                                                    self.tcx.sess.intr(),
+                                                    self as @pprust::pp_ann);
+        pprust::cbox(&mut ps, pprust::indent_unit);
+        pprust::ibox(&mut ps, 0u);
+        pprust::print_block(&mut ps, blk);
+        pp::eof(&mut ps.s);
     }
 }
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 727360a361f..2bdbce9b763 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -34,7 +34,9 @@ fn should_explore(tcx: ty::ctxt, def_id: ast::DefId) -> bool {
     if !is_local(def_id) {
         return false;
     }
-    match tcx.items.find(&def_id.node) {
+
+    let items = tcx.items.borrow();
+    match items.get().find(&def_id.node) {
         Some(&ast_map::node_item(..))
         | Some(&ast_map::node_method(..))
         | Some(&ast_map::node_foreign_item(..))
@@ -130,7 +132,9 @@ impl MarkSymbolVisitor {
                 continue
             }
             scanned.insert(id);
-            match self.tcx.items.find(&id) {
+
+            let items = self.tcx.items.borrow();
+            match items.get().find(&id) {
                 Some(node) => {
                     self.live_symbols.insert(id);
                     self.visit_node(node);
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 53a8b93c232..89cb902cf10 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -74,23 +74,26 @@ fn find_item(item: @item, ctxt: &mut EntryContext) {
     match item.node {
         item_fn(..) => {
             if item.ident.name == special_idents::main.name {
-                match ctxt.ast_map.find(&item.id) {
-                    Some(&ast_map::node_item(_, path)) => {
-                        if path.len() == 0 {
-                            // This is a top-level function so can be 'main'
-                            if ctxt.main_fn.is_none() {
-                                ctxt.main_fn = Some((item.id, item.span));
+                {
+                    let ast_map = ctxt.ast_map.borrow();
+                    match ast_map.get().find(&item.id) {
+                        Some(&ast_map::node_item(_, path)) => {
+                            if path.len() == 0 {
+                                // This is a top-level function so can be 'main'
+                                if ctxt.main_fn.is_none() {
+                                    ctxt.main_fn = Some((item.id, item.span));
+                                } else {
+                                    ctxt.session.span_err(
+                                        item.span,
+                                        "multiple 'main' functions");
+                                }
                             } else {
-                                ctxt.session.span_err(
-                                    item.span,
-                                    "multiple 'main' functions");
+                                // This isn't main
+                                ctxt.non_main_fns.push((item.id, item.span));
                             }
-                        } else {
-                            // This isn't main
-                            ctxt.non_main_fns.push((item.id, item.span));
                         }
+                        _ => unreachable!()
                     }
-                    _ => unreachable!()
                 }
             }
 
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index 70abd94ea31..49e57306c12 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -306,7 +306,7 @@ pub fn check_expr(cx: &mut Context, e: @Expr) {
     }
 
     match e.node {
-        ExprUnary(_, UnBox(_), interior) => {
+        ExprUnary(_, UnBox, interior) => {
             let interior_type = ty::expr_ty(cx.tcx, interior);
             let _ = check_durable(cx.tcx, interior_type, interior.span);
         }
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 87ae74321a1..8e86fa4611f 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -207,7 +207,7 @@ pub fn collect_language_items(crate: &ast::Crate,
 }
 
 lets_do_this! {
-    There are 43 lang items.
+    There are 37 lang items.
 
 //  ID, Variant name,                    Name,                      Method name;
     0,  FreezeTraitLangItem,             "freeze",                  freeze_trait;
@@ -243,24 +243,18 @@ lets_do_this! {
     26, ExchangeFreeFnLangItem,          "exchange_free",           exchange_free_fn;
     27, MallocFnLangItem,                "malloc",                  malloc_fn;
     28, FreeFnLangItem,                  "free",                    free_fn;
-    29, BorrowAsImmFnLangItem,           "borrow_as_imm",           borrow_as_imm_fn;
-    30, BorrowAsMutFnLangItem,           "borrow_as_mut",           borrow_as_mut_fn;
-    31, ReturnToMutFnLangItem,           "return_to_mut",           return_to_mut_fn;
-    32, CheckNotBorrowedFnLangItem,      "check_not_borrowed",      check_not_borrowed_fn;
-    33, StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
-    34, RecordBorrowFnLangItem,          "record_borrow",           record_borrow_fn;
-    35, UnrecordBorrowFnLangItem,        "unrecord_borrow",         unrecord_borrow_fn;
+    29, StrDupUniqFnLangItem,            "strdup_uniq",             strdup_uniq_fn;
 
-    36, StartFnLangItem,                 "start",                   start_fn;
+    30, StartFnLangItem,                 "start",                   start_fn;
 
-    37, TyDescStructLangItem,            "ty_desc",                 ty_desc;
-    38, TyVisitorTraitLangItem,          "ty_visitor",              ty_visitor;
-    39, OpaqueStructLangItem,            "opaque",                  opaque;
+    31, TyDescStructLangItem,            "ty_desc",                 ty_desc;
+    32, TyVisitorTraitLangItem,          "ty_visitor",              ty_visitor;
+    33, OpaqueStructLangItem,            "opaque",                  opaque;
 
-    40, EventLoopFactoryLangItem,        "event_loop_factory",      event_loop_factory;
+    34, EventLoopFactoryLangItem,        "event_loop_factory",      event_loop_factory;
 
-    41, TypeIdLangItem,                  "type_id",                 type_id;
+    35, TypeIdLangItem,                  "type_id",                 type_id;
 
-    42, EhPersonalityLangItem,           "eh_personality",          eh_personality_fn;
+    36, EhPersonalityLangItem,           "eh_personality",          eh_personality_fn;
 }
 
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index fbd9d414769..666c7d84a9a 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -1076,7 +1076,7 @@ fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
             }
         }
         ast::ExprUnary(_, ast::UnUniq, _) |
-        ast::ExprUnary(_, ast::UnBox(..), _) => BoxAllocation,
+        ast::ExprUnary(_, ast::UnBox, _) => BoxAllocation,
 
         _ => return
     };
@@ -1246,7 +1246,8 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
 
     let stability = if ast_util::is_local(id) {
         // this crate
-        match cx.tcx.items.find(&id.node) {
+        let items = cx.tcx.items.borrow();
+        match items.get().find(&id.node) {
             Some(ast_node) => {
                 let s = ast_node.with_attrs(|attrs| {
                     attrs.map(|a| {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 2349b5f4dd3..8459581dba4 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -85,7 +85,7 @@ pub struct CopiedUpvar {
 #[deriving(Eq, IterBytes)]
 pub enum PointerKind {
     uniq_ptr,
-    gc_ptr(ast::Mutability),
+    gc_ptr,
     region_ptr(ast::Mutability, ty::Region),
     unsafe_ptr(ast::Mutability)
 }
@@ -178,17 +178,11 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_ptr(region_ptr(ast::MutImmutable, r)))
         }
 
-        ty::ty_box(ref mt) |
-        ty::ty_evec(ref mt, ty::vstore_box) => {
-            Some(deref_ptr(gc_ptr(mt.mutbl)))
-        }
-
-        ty::ty_trait(_, _, ty::BoxTraitStore, m, _) => {
-            Some(deref_ptr(gc_ptr(m)))
-        }
-
+        ty::ty_box(_) |
+        ty::ty_evec(_, ty::vstore_box) |
+        ty::ty_trait(_, _, ty::BoxTraitStore, _, _) |
         ty::ty_estr(ty::vstore_box) => {
-            Some(deref_ptr(gc_ptr(ast::MutImmutable)))
+            Some(deref_ptr(gc_ptr))
         }
 
         ty::ty_ptr(ref mt) => {
@@ -681,7 +675,10 @@ impl mem_categorization_ctxt {
                     uniq_ptr => {
                         base_cmt.mutbl.inherit()
                     }
-                    gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
+                    gc_ptr => {
+                        McImmutable
+                    }
+                    region_ptr(m, _) | unsafe_ptr(m) => {
                         MutabilityCategory::from_mutbl(m)
                     }
                 };
@@ -759,12 +756,15 @@ impl mem_categorization_ctxt {
             // for unique ptrs, we inherit mutability from the
             // owning reference.
             let m = match ptr {
-              uniq_ptr => {
-                base_cmt.mutbl.inherit()
-              }
-              gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
-                MutabilityCategory::from_mutbl(m)
-              }
+                uniq_ptr => {
+                    base_cmt.mutbl.inherit()
+                }
+                gc_ptr => {
+                    McImmutable
+                }
+                region_ptr(m, _) | unsafe_ptr(m) => {
+                    MutabilityCategory::from_mutbl(m)
+                }
             };
 
             // the deref is explicit in the resulting cmt
@@ -1103,7 +1103,7 @@ pub fn field_mutbl(tcx: ty::ctxt,
 }
 
 pub enum AliasableReason {
-    AliasableManaged(ast::Mutability),
+    AliasableManaged,
     AliasableBorrowed(ast::Mutability),
     AliasableOther
 }
@@ -1122,7 +1122,7 @@ impl cmt_ {
             cat_self(..) |
             cat_arg(..) |
             cat_deref(_, _, unsafe_ptr(..)) |
-            cat_deref(_, _, gc_ptr(..)) |
+            cat_deref(_, _, gc_ptr) |
             cat_deref(_, _, region_ptr(..)) => {
                 self
             }
@@ -1166,8 +1166,8 @@ impl cmt_ {
                 Some(AliasableOther)
             }
 
-            cat_deref(_, _, gc_ptr(m)) => {
-                Some(AliasableManaged(m))
+            cat_deref(_, _, gc_ptr) => {
+                Some(AliasableManaged)
             }
 
             cat_deref(_, _, region_ptr(m @ MutImmutable, _)) => {
@@ -1229,7 +1229,7 @@ impl Repr for categorization {
 pub fn ptr_sigil(ptr: PointerKind) -> ~str {
     match ptr {
         uniq_ptr => ~"~",
-        gc_ptr(_) => ~"@",
+        gc_ptr => ~"@",
         region_ptr(_, _) => ~"&",
         unsafe_ptr(_) => ~"*"
     }
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index a0da1680d00..435bdcc2607 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -413,7 +413,8 @@ impl<'a> PrivacyVisitor<'a> {
         let mut closest_private_id = did.node;
         loop {
             debug!("privacy - examining {}", self.nodestr(closest_private_id));
-            let vis = match self.tcx.items.find(&closest_private_id) {
+            let items = self.tcx.items.borrow();
+            let vis = match items.get().find(&closest_private_id) {
                 // If this item is a method, then we know for sure that it's an
                 // actual method and not a static method. The reason for this is
                 // that these cases are only hit in the ExprMethodCall
@@ -519,7 +520,8 @@ impl<'a> PrivacyVisitor<'a> {
                     self.tcx.sess.span_err(span, format!("{} is inaccessible",
                                                          msg));
                 }
-                match self.tcx.items.find(&id) {
+                let items = self.tcx.items.borrow();
+                match items.get().find(&id) {
                     Some(&ast_map::node_item(item, _)) => {
                         let desc = match item.node {
                             ast::item_mod(..) => "module",
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index bbf366c0b06..5e50017b93e 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -65,10 +65,15 @@ fn method_might_be_inlined(tcx: ty::ctxt, method: &ast::method,
         return true
     }
     if is_local(impl_src) {
-        match tcx.items.find(&impl_src.node) {
-            Some(&ast_map::node_item(item, _)) => item_might_be_inlined(item),
-            Some(..) | None => {
-                tcx.sess.span_bug(method.span, "impl did is not an item")
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&impl_src.node) {
+                Some(&ast_map::node_item(item, _)) => {
+                    item_might_be_inlined(item)
+                }
+                Some(..) | None => {
+                    tcx.sess.span_bug(method.span, "impl did is not an item")
+                }
             }
         }
     } else {
@@ -208,7 +213,8 @@ impl ReachableContext {
         }
 
         let node_id = def_id.node;
-        match tcx.items.find(&node_id) {
+        let items = tcx.items.borrow();
+        match items.get().find(&node_id) {
             Some(&ast_map::node_item(item, _)) => {
                 match item.node {
                     ast::item_fn(..) => item_might_be_inlined(item),
@@ -229,7 +235,7 @@ impl ReachableContext {
                     // Check the impl. If the generics on the self type of the
                     // impl require inlining, this method does too.
                     assert!(impl_did.crate == ast::LOCAL_CRATE);
-                    match tcx.items.find(&impl_did.node) {
+                    match items.get().find(&impl_did.node) {
                         Some(&ast_map::node_item(item, _)) => {
                             match item.node {
                                 ast::item_impl(ref generics, _, _, _) => {
@@ -288,7 +294,8 @@ impl ReachableContext {
             };
 
             scanned.insert(search_item);
-            match self.tcx.items.find(&search_item) {
+            let items = self.tcx.items.borrow();
+            match items.get().find(&search_item) {
                 Some(item) => self.propagate_node(item, search_item,
                                                   &mut visitor),
                 None if search_item == ast::CRATE_NODE_ID => {}
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index ad953440316..59f6fede198 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2210,10 +2210,13 @@ impl Visitor<()> for TransItemVisitor {
 
 pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
     let _icx = push_ctxt("trans_item");
-    let path = match ccx.tcx.items.get_copy(&item.id) {
-        ast_map::node_item(_, p) => p,
-        // tjc: ?
-        _ => fail!("trans_item"),
+    let path = {
+        let items = ccx.tcx.items.borrow();
+        match items.get().get_copy(&item.id) {
+            ast_map::node_item(_, p) => p,
+            // tjc: ?
+            _ => fail!("trans_item"),
+        }
     };
     match item.node {
       ast::item_fn(decl, purity, _abis, ref generics, body) => {
@@ -2508,7 +2511,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
         Some(v) => v,
         None => {
             let mut foreign = false;
-            let item = ccx.tcx.items.get_copy(&id);
+            let item = {
+                let items = ccx.tcx.items.borrow();
+                items.get().get_copy(&id)
+            };
             let val = match item {
                 ast_map::node_item(i, pth) => {
 
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index df916f0463b..05b3e8275a3 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -360,17 +360,20 @@ pub fn trans_fn_ref_with_vtables(
     if type_params.len() > 0 || is_default {
         must_monomorphise = true;
     } else if def_id.crate == ast::LOCAL_CRATE {
-        let map_node = session::expect(
-            ccx.sess,
-            ccx.tcx.items.find(&def_id.node),
-            || format!("local item should be in ast map"));
-
-        match *map_node {
-            ast_map::node_foreign_item(_, abis, _, _) => {
-                must_monomorphise = abis.is_intrinsic()
-            }
-            _ => {
-                must_monomorphise = false;
+        {
+            let items = ccx.tcx.items.borrow();
+            let map_node = session::expect(
+                ccx.sess,
+                items.get().find(&def_id.node),
+                || format!("local item should be in ast map"));
+
+            match *map_node {
+                ast_map::node_foreign_item(_, abis, _, _) => {
+                    must_monomorphise = abis.is_intrinsic()
+                }
+                _ => {
+                    must_monomorphise = false;
+                }
             }
         }
     } else {
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 0fadcbe53be..973d2003ecb 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -22,12 +22,10 @@ use middle::trans::base;
 use middle::trans::build;
 use middle::trans::datum;
 use middle::trans::glue;
-use middle::trans::write_guard;
 use middle::trans::debuginfo;
 use middle::ty::substs;
 use middle::ty;
 use middle::typeck;
-use middle::borrowck::root_map_key;
 use util::ppaux::Repr;
 
 use middle::trans::type_::Type;
@@ -363,27 +361,6 @@ impl CleanupFunction for ImmediateTypeDroppingCleanupFunction {
     }
 }
 
-/// A cleanup function that releases a write guard, returning a value to
-/// mutable status.
-pub struct WriteGuardReleasingCleanupFunction {
-    root_key: root_map_key,
-    frozen_val_ref: ValueRef,
-    bits_val_ref: ValueRef,
-    filename_val: ValueRef,
-    line_val: ValueRef,
-}
-
-impl CleanupFunction for WriteGuardReleasingCleanupFunction {
-    fn clean(&self, bcx: @Block) -> @Block {
-        write_guard::return_to_mut(bcx,
-                                   self.root_key,
-                                   self.frozen_val_ref,
-                                   self.bits_val_ref,
-                                   self.filename_val,
-                                   self.line_val)
-    }
-}
-
 /// A cleanup function that frees some memory in the garbage-collected heap.
 pub struct GCHeapFreeingCleanupFunction {
     ptr: ValueRef,
@@ -527,42 +504,7 @@ pub fn add_clean_temp_mem_in_scope_(bcx: @Block, scope_id: Option<ast::NodeId>,
         grow_scope_clean(scope_info);
     })
 }
-pub fn add_clean_return_to_mut(bcx: @Block,
-                               scope_id: ast::NodeId,
-                               root_key: root_map_key,
-                               frozen_val_ref: ValueRef,
-                               bits_val_ref: ValueRef,
-                               filename_val: ValueRef,
-                               line_val: ValueRef) {
-    //! When an `@mut` has been frozen, we have to
-    //! call the lang-item `return_to_mut` when the
-    //! freeze goes out of scope. We need to pass
-    //! in both the value which was frozen (`frozen_val`) and
-    //! the value (`bits_val_ref`) which was returned when the
-    //! box was frozen initially. Here, both `frozen_val_ref` and
-    //! `bits_val_ref` are in fact pointers to stack slots.
-
-    debug!("add_clean_return_to_mut({}, {}, {})",
-           bcx.to_str(),
-           bcx.val_to_str(frozen_val_ref),
-           bcx.val_to_str(bits_val_ref));
-    in_scope_cx(bcx, Some(scope_id), |scope_info| {
-        {
-            let mut cleanups = scope_info.cleanups.borrow_mut();
-            cleanups.get().push(clean_temp(
-                    frozen_val_ref,
-                    @WriteGuardReleasingCleanupFunction {
-                        root_key: root_key,
-                        frozen_val_ref: frozen_val_ref,
-                        bits_val_ref: bits_val_ref,
-                        filename_val: filename_val,
-                        line_val: line_val,
-                    } as @CleanupFunction,
-                    normal_exit_only));
-        }
-        grow_scope_clean(scope_info);
-    })
-}
+
 pub fn add_clean_free(cx: @Block, ptr: ValueRef, heap: heap) {
     let free_fn = match heap {
         heap_managed | heap_managed_unique => {
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index c9d30ec1994..9c3a7f4f671 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -165,7 +165,13 @@ pub fn get_const_val(cx: @CrateContext,
         if !ast_util::is_local(def_id) {
             def_id = inline::maybe_instantiate_inline(cx, def_id);
         }
-        match cx.tcx.items.get_copy(&def_id.node) {
+
+        let opt_item = {
+            let items = cx.tcx.items.borrow();
+            items.get().get_copy(&def_id.node)
+        };
+
+        match opt_item {
             ast_map::node_item(@ast::item {
                 node: ast::item_static(_, ast::MutImmutable, _), ..
             }, _) => {
@@ -371,9 +377,7 @@ fn const_expr_unadjusted(cx: @CrateContext,
             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  => {
+              ast::UnBox | ast::UnUniq | ast::UnDeref => {
                 let (dv, _dt) = const_deref(cx, te, ty, true);
                 dv
               }
diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs
index 6b8ff815a83..f57f31a56f4 100644
--- a/src/librustc/middle/trans/datum.rs
+++ b/src/librustc/middle/trans/datum.rs
@@ -552,7 +552,7 @@ impl Datum {
          * by-ref datum of type T, pointing at the contents. */
 
         let (content_ty, header) = match ty::get(self.ty).sty {
-            ty::ty_box(mt) => (mt.ty, true),
+            ty::ty_box(typ) => (typ, true),
             ty::ty_uniq(mt) => (mt.ty, false),
             ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) => {
                 let unit_ty = ty::sequence_element_type(bcx.tcx(), self.ty);
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 88dc4928164..49577a13953 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -323,7 +323,10 @@ pub fn create_captured_var_metadata(bcx: @Block,
 
     let cx = bcx.ccx();
 
-    let ast_item = cx.tcx.items.find_copy(&node_id);
+    let ast_item = {
+        let items = cx.tcx.items.borrow();
+        items.get().find_copy(&node_id)
+    };
     let variable_ident = match ast_item {
         None => {
             cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
@@ -422,7 +425,10 @@ pub fn create_self_argument_metadata(bcx: @Block,
     }
 
     // Extract the span of the self argument from the method's AST
-    let fnitem = bcx.ccx().tcx.items.get_copy(&bcx.fcx.id);
+    let fnitem = {
+        let items = bcx.ccx().tcx.items.borrow();
+        items.get().get_copy(&bcx.fcx.id)
+    };
     let span = match fnitem {
         ast_map::node_method(@ast::method { explicit_self: explicit_self, .. }, _, _) => {
             explicit_self.span
@@ -609,7 +615,10 @@ pub fn create_function_debug_context(cx: &CrateContext,
 
     let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty };
 
-    let fnitem = cx.tcx.items.get_copy(&fn_ast_id);
+    let fnitem = {
+        let items = cx.tcx.items.borrow();
+        items.get().get_copy(&fn_ast_id)
+    };
     let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
         ast_map::node_item(ref item, _) => {
             match item.node {
@@ -1092,7 +1101,8 @@ fn scope_metadata(fcx: &FunctionContext,
     match scope_map.get().find_copy(&node_id) {
         Some(scope_metadata) => scope_metadata,
         None => {
-            let node = fcx.ccx.tcx.items.get_copy(&node_id);
+            let items = fcx.ccx.tcx.items.borrow();
+            let node = items.get().get_copy(&node_id);
 
             fcx.ccx.sess.span_bug(span,
                 format!("debuginfo: Could not find scope info for node {:?}", node));
@@ -1411,13 +1421,17 @@ fn describe_enum_variant(cx: &CrateContext,
 
     // Find the source code location of the variant's definition
     let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
-        match cx.tcx.items.find(&variant_info.id.node) {
-            Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
-            ref node => {
-                cx.sess.span_warn(span,
-                    format!("debuginfo::enum_metadata()::adt_struct_metadata() - Unexpected node \
-                          type: {:?}. This is a bug.", node));
-                codemap::DUMMY_SP
+        {
+            let items = cx.tcx.items.borrow();
+            match items.get().find(&variant_info.id.node) {
+                Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
+                ref node => {
+                    cx.sess.span_warn(span,
+                        format!("debuginfo::enum_metadata()::\
+                                 adt_struct_metadata() - Unexpected node \
+                                 type: {:?}. This is a bug.", node));
+                    codemap::DUMMY_SP
+                }
             }
         }
     } else {
@@ -2128,8 +2142,8 @@ fn type_metadata(cx: &CrateContext,
         ty::ty_enum(def_id, _) => {
             prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
         },
-        ty::ty_box(ref mt) => {
-            create_pointer_to_box_metadata(cx, t, mt.ty)
+        ty::ty_box(typ) => {
+            create_pointer_to_box_metadata(cx, t, typ)
         },
         ty::ty_evec(ref mt, ref vstore) => {
             match *vstore {
@@ -2296,16 +2310,20 @@ fn get_namespace_and_span_for_item(cx: &CrateContext,
                                 -> (DIScope, Span) {
     let containing_scope = namespace_for_item(cx, def_id, warning_span).scope;
     let definition_span = if def_id.crate == ast::LOCAL_CRATE {
-        let definition_span = match cx.tcx.items.find(&def_id.node) {
-            Some(&ast_map::node_item(@ast::item { span, .. }, _)) => span,
-            ref node => {
-                cx.sess.span_warn(warning_span,
-                    format!("debuginfo::get_namespace_and_span_for_item() \
-                             - Unexpected node type: {:?}", *node));
-                codemap::DUMMY_SP
-            }
-        };
-        definition_span
+        {
+            let items = cx.tcx.items.borrow();
+            let definition_span = match items.get().find(&def_id.node) {
+                Some(&ast_map::node_item(@ast::item { span, .. }, _)) => span,
+                ref node => {
+                    cx.sess.span_warn(warning_span,
+                        format!("debuginfo::\
+                                 get_namespace_and_span_for_item() \
+                                 - Unexpected node type: {:?}", *node));
+                    codemap::DUMMY_SP
+                }
+            };
+            definition_span
+        }
     } else {
         // For external items there is no span information
         codemap::DUMMY_SP
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 9fcd0f458b3..640f9339a7d 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -378,18 +378,12 @@ pub fn trans_to_datum(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         let source_data = Load(bcx, source_data_ptr); // always a ptr
         let target_data = match source_store {
             ty::BoxTraitStore(..) => {
-                // For deref of @T or @mut T, create a dummy datum and
-                // use the datum's deref method. This is more work
-                // than just calling GEPi ourselves, but it ensures
-                // that any write guards will be appropriate
-                // processed.  Note that we don't know the type T, so
+                // For deref of @T, create a dummy datum and use the datum's
+                // deref method. This is more work than just calling GEPi
+                // ourselves. Note that we don't know the type T, so
                 // just substitute `i8`-- it doesn't really matter for
                 // our purposes right now.
-                let source_ty =
-                    ty::mk_box(tcx,
-                               ty::mt {
-                                   ty: ty::mk_i8(),
-                                   mutbl: source_mutbl});
+                let source_ty = ty::mk_box(tcx, ty::mk_i8());
                 let source_datum =
                     Datum {val: source_data,
                            ty: source_ty,
@@ -596,8 +590,7 @@ fn trans_rvalue_datum_unadjusted(bcx: @Block, expr: &ast::Expr) -> DatumBlock {
         ast::ExprPath(_) | ast::ExprSelf => {
             return trans_def_datum_unadjusted(bcx, expr, bcx.def(expr.id));
         }
-        ast::ExprVstore(contents, ast::ExprVstoreBox) |
-        ast::ExprVstore(contents, ast::ExprVstoreMutBox) => {
+        ast::ExprVstore(contents, ast::ExprVstoreBox) => {
             return tvec::trans_uniq_or_managed_vstore(bcx, heap_managed,
                                                       expr, contents);
         }
@@ -1412,9 +1405,8 @@ fn trans_unary_datum(bcx: @Block,
             };
             immediate_rvalue_bcx(bcx, llneg, un_ty)
         }
-        ast::UnBox(_) => {
-            trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty,
-                             heap_managed)
+        ast::UnBox => {
+            trans_boxed_expr(bcx, un_ty, sub_expr, sub_ty, heap_managed)
         }
         ast::UnUniq => {
             let heap  = heap_for_unique(bcx, un_ty);
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 21f268fb947..7c4c9f8937f 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -355,10 +355,17 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
     for &foreign_item in foreign_mod.items.iter() {
         match foreign_item.node {
             ast::foreign_item_fn(..) => {
-                let (abis, mut path) = match ccx.tcx.items.get_copy(&foreign_item.id) {
-                    ast_map::node_foreign_item(_, abis, _, path) => (abis, (*path).clone()),
-                    _ => fail!("Unable to find foreign item in tcx.items table.")
-                };
+                let items = ccx.tcx.items.borrow();
+                let (abis, mut path) =
+                    match items.get().get_copy(&foreign_item.id) {
+                        ast_map::node_foreign_item(_, abis, _, path) => {
+                            (abis, (*path).clone())
+                        }
+                        _ => {
+                            fail!("Unable to find foreign item in tcx.items \
+                                   table.")
+                        }
+                    };
                 if !(abis.is_rust() || abis.is_intrinsic()) {
                     path.push(ast_map::path_name(foreign_item.ident));
                     register_foreign_item_fn(ccx, abis, &path, foreign_item);
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index cff0f5b316c..85efd2d40d0 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -157,7 +157,10 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
     if (field == abi::tydesc_field_free_glue ||
         field == abi::tydesc_field_drop_glue) {
         match ty::get(t).sty {
-          ty::ty_box(mt) |
+          ty::ty_box(typ)
+          if ! ty::type_needs_drop(tcx, typ) =>
+          return ty::mk_imm_box(tcx, ty::mk_u32()),
+
           ty::ty_evec(mt, ty::vstore_box)
           if ! ty::type_needs_drop(tcx, mt.ty) =>
           return ty::mk_imm_box(tcx, ty::mk_u32()),
@@ -356,10 +359,10 @@ pub fn make_free_glue(bcx: @Block, v: ValueRef, t: ty::t) -> @Block {
     // NB: v0 is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("make_free_glue");
     match ty::get(t).sty {
-      ty::ty_box(body_mt) => {
+      ty::ty_box(body_ty) => {
         let v = Load(bcx, v);
         let body = GEPi(bcx, v, [0u, abi::box_field_body]);
-        let bcx = drop_ty(bcx, body, body_mt.ty);
+        let bcx = drop_ty(bcx, body, body_ty);
         trans_free(bcx, v)
       }
       ty::ty_opaque_box => {
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index f652fbec228..c1096f73322 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -346,9 +346,12 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             let in_type_size = machine::llbitsize_of_real(ccx, llintype);
             let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
             if in_type_size != out_type_size {
-                let sp = match ccx.tcx.items.get_copy(&ref_id.unwrap()) {
-                    ast_map::node_expr(e) => e.span,
-                    _ => fail!("transmute has non-expr arg"),
+                let sp = {
+                    let items = ccx.tcx.items.borrow();
+                    match items.get().get_copy(&ref_id.unwrap()) {
+                        ast_map::node_expr(e) => e.span,
+                        _ => fail!("transmute has non-expr arg"),
+                    }
                 };
                 let pluralize = |n| if 1u == n { "" } else { "s" };
                 ccx.sess.span_fatal(sp,
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index d16cf6f1c3b..d54dd23af96 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -246,11 +246,14 @@ pub fn trans_static_method_callee(bcx: @Block,
         generics.type_param_defs.len();
 
     let mname = if method_id.crate == ast::LOCAL_CRATE {
-        match bcx.tcx().items.get_copy(&method_id.node) {
-            ast_map::node_trait_method(trait_method, _, _) => {
-                ast_util::trait_method_to_ty_method(trait_method).ident
+        {
+            let items = bcx.tcx().items.borrow();
+            match items.get().get_copy(&method_id.node) {
+                ast_map::node_trait_method(trait_method, _, _) => {
+                    ast_util::trait_method_to_ty_method(trait_method).ident
+                }
+                _ => fail!("callee is not a trait method")
             }
-            _ => fail!("callee is not a trait method")
         }
     } else {
         let path = csearch::get_item_path(bcx.tcx(), method_id);
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index cf6bebbb1a2..a60ddc9d8b6 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -95,12 +95,16 @@ pub fn monomorphic_fn(ccx: @CrateContext,
     // calling a static provided method. This is sort of unfortunate.
     let mut is_static_provided = None;
 
-    let map_node = session::expect(
-        ccx.sess,
-        ccx.tcx.items.find_copy(&fn_id.node),
-        || format!("While monomorphizing {:?}, couldn't find it in the item map \
-                 (may have attempted to monomorphize an item \
-                 defined in a different crate?)", fn_id));
+    let map_node = {
+        let items = ccx.tcx.items.borrow();
+        session::expect(
+            ccx.sess,
+            items.get().find_copy(&fn_id.node),
+            || format!("While monomorphizing {:?}, couldn't find it in the \
+                        item map (may have attempted to monomorphize an item \
+                        defined in a different crate?)", fn_id))
+    };
+
     // Get the path so that we can create a symbol
     let (pt, name, span) = match map_node {
       ast_map::node_item(i, pt) => (pt, i.ident, i.span),
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index c30f421c9e5..f0ec7fb75dd 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -189,8 +189,11 @@ impl Reflector {
                   self.visit(~"evec_" + name, extra)
               }
           }
-          ty::ty_box(ref mt) => {
-              let extra = self.c_mt(mt);
+          ty::ty_box(typ) => {
+              let extra = self.c_mt(&ty::mt {
+                  ty: typ,
+                  mutbl: ast::MutImmutable,
+              });
               self.visit("box", extra)
           }
           ty::ty_uniq(ref mt) => {
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index c1e6e466761..e5f946213f3 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -236,8 +236,8 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
           let v_ty = Type::vec(cx.sess.targ_cfg.arch, &e_ty);
           Type::smart_ptr(cx, &v_ty).ptr_to()
       }
-      ty::ty_box(ref mt) => {
-          let ty = type_of(cx, mt.ty);
+      ty::ty_box(typ) => {
+          let ty = type_of(cx, typ);
           Type::smart_ptr(cx, &ty).ptr_to()
       }
       ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index 3b60dc3dd37..d7c952a38f6 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -15,26 +15,15 @@
 //! `RUST_LOG=rustc::middle::trans::write_guard`).
 
 
-use lib::llvm::ValueRef;
-use middle::borrowck::{RootInfo, root_map_key, DynaImm, DynaMut};
-use middle::lang_items::CheckNotBorrowedFnLangItem;
-use middle::lang_items::{BorrowAsImmFnLangItem, BorrowAsMutFnLangItem};
-use middle::lang_items::{RecordBorrowFnLangItem, UnrecordBorrowFnLangItem};
-use middle::lang_items::ReturnToMutFnLangItem;
+use middle::borrowck::{RootInfo, root_map_key};
 use middle::trans::base::*;
-use middle::trans::build::*;
-use middle::trans::callee;
 use middle::trans::common::*;
 use middle::trans::datum::*;
-use middle::trans::expr;
-use middle::ty;
 use syntax::codemap::Span;
 use syntax::ast;
 
-use middle::trans::type_::Type;
-
 pub fn root_and_write_guard(datum: &Datum,
-                            mut bcx: @Block,
+                            bcx: @Block,
                             span: Span,
                             expr_id: ast::NodeId,
                             derefs: uint) -> @Block {
@@ -45,69 +34,16 @@ pub fn root_and_write_guard(datum: &Datum,
     //
     // (Note: root'd values are always boxes)
     let ccx = bcx.ccx();
-    bcx = {
-        let root_map = ccx.maps.root_map.borrow();
-        match root_map.get().find(&key) {
-            None => bcx,
-            Some(&root_info) => root(datum, bcx, span, key, root_info)
-        }
-    };
-
-    // Perform the write guard, if necessary.
-    //
-    // (Note: write-guarded values are always boxes)
-    let write_guard_map = ccx.maps.write_guard_map.borrow();
-    if write_guard_map.get().contains(&key) {
-        perform_write_guard(datum, bcx, span)
-    } else {
-        bcx
+    let root_map = ccx.maps.root_map.borrow();
+    match root_map.get().find(&key) {
+        None => bcx,
+        Some(&root_info) => root(datum, bcx, span, key, root_info)
     }
 }
 
-pub fn return_to_mut(mut bcx: @Block,
-                     root_key: root_map_key,
-                     frozen_val_ref: ValueRef,
-                     bits_val_ref: ValueRef,
-                     filename_val: ValueRef,
-                     line_val: ValueRef) -> @Block {
-    debug!("write_guard::return_to_mut(root_key={:?}, {}, {}, {})",
-           root_key,
-           bcx.to_str(),
-           bcx.val_to_str(frozen_val_ref),
-           bcx.val_to_str(bits_val_ref));
-
-    let box_ptr = Load(bcx, PointerCast(bcx, frozen_val_ref, Type::i8p().ptr_to()));
-
-    let bits_val = Load(bcx, bits_val_ref);
-
-    if bcx.tcx().sess.debug_borrows() {
-        bcx = callee::trans_lang_call( bcx,
-            langcall(bcx, None, "unborrow", UnrecordBorrowFnLangItem),
-            [
-                box_ptr,
-                bits_val,
-                filename_val,
-                line_val
-            ],
-            Some(expr::Ignore)).bcx;
-    }
-
-    callee::trans_lang_call(
-        bcx,
-        langcall(bcx, None, "unborrow", ReturnToMutFnLangItem),
-        [
-            box_ptr,
-            bits_val,
-            filename_val,
-            line_val
-        ],
-        Some(expr::Ignore)
-    ).bcx
-}
-
 fn root(datum: &Datum,
-        mut bcx: @Block,
-        span: Span,
+        bcx: @Block,
+        _: Span,
         root_key: root_map_key,
         root_info: RootInfo) -> @Block {
     //! In some cases, borrowck will decide that an @T/@[]/@str
@@ -129,73 +65,6 @@ fn root(datum: &Datum,
                                 scratch.val,
                                 scratch.ty);
 
-    // Now, consider also freezing it.
-    match root_info.freeze {
-        None => {}
-        Some(freeze_kind) => {
-            let (filename, line) = filename_and_line_num_from_span(bcx, span);
-
-            // in this case, we don't have to zero, because
-            // scratch.val will be NULL should the cleanup get
-            // called without the freezing actually occurring, and
-            // return_to_mut checks for this condition.
-            let scratch_bits = scratch_datum(bcx, ty::mk_uint(),
-                                             "__write_guard_bits", false);
-
-            let freeze_item = match freeze_kind {
-                DynaImm => BorrowAsImmFnLangItem,
-                DynaMut => BorrowAsMutFnLangItem,
-            };
-
-            let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
-
-            let llresult = unpack_result!(bcx, callee::trans_lang_call(
-                bcx,
-                langcall(bcx, Some(span), "freeze", freeze_item),
-                [
-                    box_ptr,
-                    filename,
-                    line
-                ],
-                Some(expr::SaveIn(scratch_bits.val))));
-
-            if bcx.tcx().sess.debug_borrows() {
-                bcx = callee::trans_lang_call(
-                    bcx,
-                    langcall(bcx, Some(span), "freeze", RecordBorrowFnLangItem),
-                    [
-                        box_ptr,
-                        llresult,
-                        filename,
-                        line
-                    ],
-                    Some(expr::Ignore)).bcx;
-            }
-
-            add_clean_return_to_mut(cleanup_bcx,
-                                    root_info.scope,
-                                    root_key,
-                                    scratch.val,
-                                    scratch_bits.val,
-                                    filename,
-                                    line);
-        }
-    }
-
     bcx
 }
 
-fn perform_write_guard(datum: &Datum,
-                       bcx: @Block,
-                       span: Span) -> @Block {
-    debug!("perform_write_guard");
-
-    let llval = datum.to_value_llval(bcx);
-    let (filename, line) = filename_and_line_num_from_span(bcx, span);
-
-    callee::trans_lang_call(
-        bcx,
-        langcall(bcx, Some(span), "write guard", CheckNotBorrowedFnLangItem),
-        [PointerCast(bcx, llval, Type::i8p()), filename, line],
-        Some(expr::Ignore)).bcx
-}
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 78b06d62480..3ae29eade77 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -267,7 +267,7 @@ pub type ctxt = @ctxt_;
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
 struct ctxt_ {
-    diag: @mut syntax::diagnostic::SpanHandler,
+    diag: @syntax::diagnostic::SpanHandler,
     interner: RefCell<HashMap<intern_key, ~t_box_>>,
     next_id: Cell<uint>,
     cstore: @metadata::cstore::CStore,
@@ -637,7 +637,7 @@ pub enum sty {
     ty_float(ast::float_ty),
     ty_estr(vstore),
     ty_enum(DefId, substs),
-    ty_box(mt),
+    ty_box(t),
     ty_uniq(mt),
     ty_evec(mt, vstore),
     ty_ptr(mt),
@@ -1102,8 +1102,9 @@ pub fn mk_t(cx: ctxt, st: sty) -> t {
               _ => {}
           }
       }
-      &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
-      &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
+      &ty_box(ref tt) => flags |= get(*tt).flags,
+      &ty_uniq(ref m) | &ty_evec(ref m, _) | &ty_ptr(ref m) |
+      &ty_unboxed_vec(ref m) => {
         flags |= get(m.ty).flags;
       }
       &ty_rptr(r, ref m) => {
@@ -1242,10 +1243,10 @@ pub fn mk_enum(cx: ctxt, did: ast::DefId, substs: substs) -> t {
     mk_t(cx, ty_enum(did, substs))
 }
 
-pub fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
+pub fn mk_box(cx: ctxt, ty: t) -> t { mk_t(cx, ty_box(ty)) }
 
 pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
-    mk_box(cx, mt {ty: ty, mutbl: ast::MutImmutable})
+    mk_box(cx, ty)
 }
 
 pub fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
@@ -1368,8 +1369,11 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
       ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
       ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
       }
-      ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
-      ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
+      ty_box(ref ty) => {
+        maybe_walk_ty(*ty, f);
+      }
+      ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
+      ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
         maybe_walk_ty(tm.ty, f);
       }
       ty_enum(_, ref substs) | ty_struct(_, ref substs) |
@@ -2035,8 +2039,8 @@ pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
                 closure_contents(cx, c)
             }
 
-            ty_box(mt) => {
-                tc_mt(cx, mt, cache).managed_pointer()
+            ty_box(typ) => {
+                tc_ty(cx, typ, cache).managed_pointer()
             }
 
             ty_trait(_, _, store, mutbl, bounds) => {
@@ -2334,7 +2338,9 @@ pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
             ty_unboxed_vec(_) => {
                 false
             }
-            ty_box(ref mt) |
+            ty_box(typ) => {
+                type_requires(cx, seen, r_ty, typ)
+            }
             ty_uniq(ref mt) |
             ty_rptr(_, ref mt) => {
                 type_requires(cx, seen, r_ty, mt.ty)
@@ -2610,7 +2616,14 @@ pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
 
 pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
     match *sty {
-      ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
+      ty_box(typ) => {
+        Some(mt {
+          ty: typ,
+          mutbl: ast::MutImmutable,
+        })
+      }
+
+      ty_rptr(_, mt) | ty_uniq(mt) => {
         Some(mt)
       }
 
@@ -3244,7 +3257,6 @@ pub fn expr_kind(tcx: ctxt,
         ast::ExprAddrOf(..) |
         ast::ExprBinary(..) |
         ast::ExprVstore(_, ast::ExprVstoreBox) |
-        ast::ExprVstore(_, ast::ExprVstoreMutBox) |
         ast::ExprVstore(_, ast::ExprVstoreUniq) => {
             RvalueDatumExpr
         }
@@ -3556,16 +3568,19 @@ pub fn provided_source(cx: ctxt, id: ast::DefId) -> Option<ast::DefId> {
 
 pub fn provided_trait_methods(cx: ctxt, id: ast::DefId) -> ~[@Method] {
     if is_local(id) {
-        match cx.items.find(&id.node) {
-            Some(&ast_map::node_item(@ast::item {
-                        node: item_trait(_, _, ref ms),
-                        ..
-                    }, _)) =>
-                match ast_util::split_trait_methods(*ms) {
-                   (_, p) => p.map(|m| method(cx, ast_util::local_def(m.id)))
-                },
-            _ => cx.sess.bug(format!("provided_trait_methods: {:?} is not a trait",
-                                  id))
+        {
+            let items = cx.items.borrow();
+            match items.get().find(&id.node) {
+                Some(&ast_map::node_item(@ast::item {
+                            node: item_trait(_, _, ref ms),
+                            ..
+                        }, _)) =>
+                    match ast_util::split_trait_methods(*ms) {
+                       (_, p) => p.map(|m| method(cx, ast_util::local_def(m.id)))
+                    },
+                _ => cx.sess.bug(format!("provided_trait_methods: {:?} is not a trait",
+                                      id))
+            }
         }
     } else {
         csearch::get_provided_trait_methods(cx, id)
@@ -3675,17 +3690,20 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::DefId) -> Option<@TraitRef> {
 
     let ret = if id.crate == ast::LOCAL_CRATE {
         debug!("(impl_trait_ref) searching for trait impl {:?}", id);
-        match cx.items.find(&id.node) {
-            Some(&ast_map::node_item(@ast::item {
-                                     node: ast::item_impl(_, ref opt_trait, _, _),
-                                     ..},
-                                     _)) => {
-                match opt_trait {
-                    &Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
-                    &None => None
+        {
+            let items = cx.items.borrow();
+            match items.get().find(&id.node) {
+                Some(&ast_map::node_item(@ast::item {
+                     node: ast::item_impl(_, ref opt_trait, _, _),
+                     ..},
+                     _)) => {
+                    match opt_trait {
+                        &Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
+                        &None => None
+                    }
                 }
+                _ => None
             }
-            _ => None
         }
     } else {
         csearch::get_impl_trait(cx, id)
@@ -3857,54 +3875,55 @@ pub fn has_dtor(cx: ctxt, struct_id: DefId) -> bool {
 
 pub fn item_path(cx: ctxt, id: ast::DefId) -> ast_map::path {
     if id.crate != ast::LOCAL_CRATE {
-        csearch::get_item_path(cx, id)
-    } else {
-        // FIXME (#5521): uncomment this code and don't have a catch-all at the
-        //                end of the match statement. Favor explicitly listing
-        //                each variant.
-        // let node = cx.items.get(&id.node);
-        // match *node {
-        match *cx.items.get(&id.node) {
-          ast_map::node_item(item, path) => {
-            let item_elt = match item.node {
-              item_mod(_) | item_foreign_mod(_) => {
-                ast_map::path_mod(item.ident)
-              }
-              _ => {
-                ast_map::path_name(item.ident)
-              }
-            };
-            vec::append_one((*path).clone(), item_elt)
+        return csearch::get_item_path(cx, id)
+    }
+
+    // FIXME (#5521): uncomment this code and don't have a catch-all at the
+    //                end of the match statement. Favor explicitly listing
+    //                each variant.
+    // let node = cx.items.get(&id.node);
+    // match *node {
+    let items = cx.items.borrow();
+    match *items.get().get(&id.node) {
+      ast_map::node_item(item, path) => {
+        let item_elt = match item.node {
+          item_mod(_) | item_foreign_mod(_) => {
+            ast_map::path_mod(item.ident)
           }
-
-          ast_map::node_foreign_item(nitem, _, _, path) => {
-            vec::append_one((*path).clone(),
-                            ast_map::path_name(nitem.ident))
+          _ => {
+            ast_map::path_name(item.ident)
           }
+        };
+        vec::append_one((*path).clone(), item_elt)
+      }
 
-          ast_map::node_method(method, _, path) => {
-            vec::append_one((*path).clone(),
-                            ast_map::path_name(method.ident))
-          }
-          ast_map::node_trait_method(trait_method, _, path) => {
-            let method = ast_util::trait_method_to_ty_method(&*trait_method);
-            vec::append_one((*path).clone(),
-                            ast_map::path_name(method.ident))
-          }
+      ast_map::node_foreign_item(nitem, _, _, path) => {
+        vec::append_one((*path).clone(),
+                        ast_map::path_name(nitem.ident))
+      }
 
-          ast_map::node_variant(ref variant, _, path) => {
-            vec::append_one(path.init().to_owned(),
-                            ast_map::path_name((*variant).node.name))
-          }
+      ast_map::node_method(method, _, path) => {
+        vec::append_one((*path).clone(),
+                        ast_map::path_name(method.ident))
+      }
+      ast_map::node_trait_method(trait_method, _, path) => {
+        let method = ast_util::trait_method_to_ty_method(&*trait_method);
+        vec::append_one((*path).clone(),
+                        ast_map::path_name(method.ident))
+      }
 
-          ast_map::node_struct_ctor(_, item, path) => {
-            vec::append_one((*path).clone(), ast_map::path_name(item.ident))
-          }
+      ast_map::node_variant(ref variant, _, path) => {
+        vec::append_one(path.init().to_owned(),
+                        ast_map::path_name((*variant).node.name))
+      }
 
-          ref node => {
-            cx.sess.bug(format!("cannot find item_path for node {:?}", node));
-          }
-        }
+      ast_map::node_struct_ctor(_, item, path) => {
+        vec::append_one((*path).clone(), ast_map::path_name(item.ident))
+      }
+
+      ref node => {
+        cx.sess.bug(format!("cannot find item_path for node {:?}", node));
+      }
     }
 }
 
@@ -3936,40 +3955,43 @@ pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @~[@VariantInfo] {
           call eval_const_expr, it should never get called twice for the same
           expr, since check_enum_variants also updates the enum_var_cache
          */
-        match cx.items.get_copy(&id.node) {
-          ast_map::node_item(@ast::item {
-                    node: ast::item_enum(ref enum_definition, _),
-                    ..
-                }, _) => {
-            let mut last_discriminant: Option<Disr> = None;
-            @enum_definition.variants.iter().map(|&variant| {
-
-                let mut discriminant = match last_discriminant {
-                    Some(val) => val + 1,
-                    None => INITIAL_DISCRIMINANT_VALUE
-                };
-
-                match variant.node.disr_expr {
-                    Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
-                        Ok(const_eval::const_int(val)) => discriminant = val as Disr,
-                        Ok(const_eval::const_uint(val)) => discriminant = val as Disr,
-                        Ok(_) => {
-                            cx.sess.span_err(e.span, "expected signed integer constant");
-                        }
-                        Err(ref err) => {
-                            cx.sess.span_err(e.span, format!("expected constant: {}", (*err)));
-                        }
-                    },
-                    None => {}
-                };
-
-                let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
-                last_discriminant = Some(discriminant);
-                variant_info
-
-            }).collect()
-          }
-          _ => cx.sess.bug("enum_variants: id not bound to an enum")
+        {
+            let items = cx.items.borrow();
+            match items.get().get_copy(&id.node) {
+              ast_map::node_item(@ast::item {
+                        node: ast::item_enum(ref enum_definition, _),
+                        ..
+                    }, _) => {
+                let mut last_discriminant: Option<Disr> = None;
+                @enum_definition.variants.iter().map(|&variant| {
+
+                    let mut discriminant = match last_discriminant {
+                        Some(val) => val + 1,
+                        None => INITIAL_DISCRIMINANT_VALUE
+                    };
+
+                    match variant.node.disr_expr {
+                        Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
+                            Ok(const_eval::const_int(val)) => discriminant = val as Disr,
+                            Ok(const_eval::const_uint(val)) => discriminant = val as Disr,
+                            Ok(_) => {
+                                cx.sess.span_err(e.span, "expected signed integer constant");
+                            }
+                            Err(ref err) => {
+                                cx.sess.span_err(e.span, format!("expected constant: {}", (*err)));
+                            }
+                        },
+                        None => {}
+                    };
+
+                    let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
+                    last_discriminant = Some(discriminant);
+                    variant_info
+
+                }).collect()
+              }
+              _ => cx.sess.bug("enum_variants: id not bound to an enum")
+            }
         }
     };
 
@@ -4040,11 +4062,17 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::DefId) -> @ty::TraitDef {
 // decoder to use iterators instead of higher-order functions.)
 pub fn each_attr(tcx: ctxt, did: DefId, f: |@MetaItem| -> bool) -> bool {
     if is_local(did) {
-        match tcx.items.find(&did.node) {
-            Some(&ast_map::node_item(@ast::item {attrs: ref attrs, ..}, _)) =>
-                attrs.iter().advance(|attr| f(attr.node.value)),
-            _ => tcx.sess.bug(format!("has_attr: {:?} is not an item",
-                                      did))
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&did.node) {
+                Some(&ast_map::node_item(@ast::item {
+                    attrs: ref attrs,
+                    ..
+                }, _)) =>
+                    attrs.iter().advance(|attr| f(attr.node.value)),
+                _ => tcx.sess.bug(format!("has_attr: {:?} is not an item",
+                                          did))
+            }
         }
     } else {
         let mut cont = true;
@@ -4120,37 +4148,39 @@ pub fn lookup_field_type(tcx: ctxt,
 // Fails if the id is not bound to a struct.
 pub fn lookup_struct_fields(cx: ctxt, did: ast::DefId) -> ~[field_ty] {
   if did.crate == ast::LOCAL_CRATE {
-    match cx.items.find(&did.node) {
-       Some(&ast_map::node_item(i,_)) => {
-         match i.node {
-            ast::item_struct(struct_def, _) => {
-               struct_field_tys(struct_def.fields)
-            }
-            _ => cx.sess.bug("struct ID bound to non-struct")
-         }
-       }
-       Some(&ast_map::node_variant(ref variant, _, _)) => {
-          match (*variant).node.kind {
-            ast::struct_variant_kind(struct_def) => {
-              struct_field_tys(struct_def.fields)
-            }
-            _ => {
-              cx.sess.bug("struct ID bound to enum variant that isn't \
-                           struct-like")
-            }
+      {
+          let items = cx.items.borrow();
+          match items.get().find(&did.node) {
+           Some(&ast_map::node_item(i,_)) => {
+             match i.node {
+                ast::item_struct(struct_def, _) => {
+                   struct_field_tys(struct_def.fields)
+                }
+                _ => cx.sess.bug("struct ID bound to non-struct")
+             }
+           }
+           Some(&ast_map::node_variant(ref variant, _, _)) => {
+              match (*variant).node.kind {
+                ast::struct_variant_kind(struct_def) => {
+                  struct_field_tys(struct_def.fields)
+                }
+                _ => {
+                  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: {}",
+                        ast_map::node_id_to_str(cx.items, did.node,
+                                                token::get_ident_interner())));
+           }
           }
-       }
-       _ => {
-           cx.sess.bug(
-               format!("struct ID not bound to an item: {}",
-                    ast_map::node_id_to_str(cx.items, did.node,
-                                            token::get_ident_interner())));
-       }
-    }
-        }
-  else {
-        return csearch::get_struct_fields(cx.sess.cstore, did);
-    }
+      }
+  } else {
+    return csearch::get_struct_fields(cx.sess.cstore, did);
+  }
 }
 
 pub fn lookup_struct_field(cx: ctxt,
@@ -4658,7 +4688,8 @@ pub fn populate_implementations_for_trait_if_necessary(
 /// If it implements no trait, return `None`.
 pub fn trait_id_of_impl(tcx: ctxt,
                         def_id: ast::DefId) -> Option<ast::DefId> {
-    let node = match tcx.items.find(&def_id.node) {
+    let items = tcx.items.borrow();
+    let node = match items.get().find(&def_id.node) {
         Some(node) => node,
         None => return None
     };
@@ -4799,9 +4830,8 @@ pub fn hash_crate_independent(tcx: ctxt, t: t, local_hash: @str) -> u64 {
                 hash.input([8]);
                 did(&mut hash, d);
             }
-            ty_box(m) => {
+            ty_box(_) => {
                 hash.input([9]);
-                mt(&mut hash, m);
             }
             ty_uniq(m) => {
                 hash.input([10]);
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index 2d39352ebc4..06a3152056f 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -140,8 +140,8 @@ pub fn super_fold_mt<T:TypeFolder>(this: &mut T,
 pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
                                     sty: &ty::sty) -> ty::sty {
     match *sty {
-        ty::ty_box(ref tm) => {
-            ty::ty_box(this.fold_mt(tm))
+        ty::ty_box(typ) => {
+            ty::ty_box(this.fold_ty(typ))
         }
         ty::ty_uniq(ref tm) => {
             ty::ty_uniq(this.fold_mt(tm))
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 0da9db5d5c2..746389c6044 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -401,9 +401,10 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
     let typ = match ast_ty.node {
       ast::ty_nil => ty::mk_nil(),
       ast::ty_bot => ty::mk_bot(),
-      ast::ty_box(ref mt) => {
-        mk_pointer(this, rscope, mt, ty::vstore_box,
-                   |tmt| ty::mk_box(tcx, tmt))
+      ast::ty_box(ty) => {
+        let mt = ast::mt { ty: ty, mutbl: ast::MutImmutable };
+        mk_pointer(this, rscope, &mt, ty::vstore_box,
+                   |tmt| ty::mk_box(tcx, tmt.ty))
       }
       ast::ty_uniq(ty) => {
         let mt = ast::mt { ty: ty, mutbl: ast::MutImmutable };
@@ -689,10 +690,8 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
                                  ty::mt {ty: self_info.untransformed_self_ty,
                                          mutbl: mutability}))
             }
-            ast::sty_box(mutability) => {
-                Some(ty::mk_box(this.tcx(),
-                                ty::mt {ty: self_info.untransformed_self_ty,
-                                        mutbl: mutability}))
+            ast::sty_box(_) => {
+                Some(ty::mk_box(this.tcx(), self_info.untransformed_self_ty))
             }
             ast::sty_uniq(_) => {
                 Some(ty::mk_uniq(this.tcx(),
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 739437d278d..a7f83a41da6 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -667,8 +667,8 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
                          span: Span,
                          expected: ty::t) {
     let fcx = pcx.fcx;
-    let check_inner: |ty::mt| = |e_inner| {
-        check_pat(pcx, inner, e_inner.ty);
+    let check_inner: |ty::t| = |e_inner| {
+        check_pat(pcx, inner, e_inner);
         fcx.write_ty(pat_id, expected);
     };
     match *structure_of(fcx, span, expected) {
@@ -676,10 +676,10 @@ pub fn check_pointer_pat(pcx: &pat_ctxt,
             check_inner(e_inner);
         }
         ty::ty_uniq(e_inner) if pointer_kind == Send => {
-            check_inner(e_inner);
+            check_inner(e_inner.ty);
         }
         ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
-            check_inner(e_inner);
+            check_inner(e_inner.ty);
         }
         _ => {
             check_pat(pcx, inner, ty::mk_err());
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 7fc2798c7aa..e1ecd919da8 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -1092,9 +1092,9 @@ impl<'a> LookupContext<'a> {
                                      substs, RegionTraitStore(r), mt.mutbl,
                                      ty::EmptyBuiltinBounds())
                     }
-                    ty::ty_box(mt) => { // must be sty_box
+                    ty::ty_box(_) => { // must be sty_box
                         ty::mk_trait(self.tcx(), trait_def_id,
-                                     substs, BoxTraitStore, mt.mutbl,
+                                     substs, BoxTraitStore, ast::MutImmutable,
                                      ty::EmptyBuiltinBounds())
                     }
                     ty::ty_uniq(mt) => { // must be sty_uniq
@@ -1224,9 +1224,8 @@ impl<'a> LookupContext<'a> {
             sty_box(m) => {
                 debug!("(is relevant?) explicit self is a box");
                 match ty::get(rcvr_ty).sty {
-                    ty::ty_box(mt) => {
-                        mutability_matches(mt.mutbl, m) &&
-                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    ty::ty_box(typ) => {
+                        rcvr_matches_ty(self.fcx, typ, candidate)
                     }
 
                     ty::ty_trait(self_did, _, BoxTraitStore, self_m, _) => {
@@ -1309,10 +1308,17 @@ impl<'a> LookupContext<'a> {
 
     fn report_static_candidate(&self, idx: uint, did: DefId) {
         let span = if did.crate == ast::LOCAL_CRATE {
-            match self.tcx().items.find(&did.node) {
-              Some(&ast_map::node_method(m, _, _))
-              | Some(&ast_map::node_trait_method(@ast::provided(m), _, _)) => m.span,
-              _ => fail!("report_static_candidate: bad item {:?}", did)
+            {
+                let items = self.tcx().items.borrow();
+                match items.get().find(&did.node) {
+                  Some(&ast_map::node_method(m, _, _))
+                  | Some(&ast_map::node_trait_method(@ast::provided(m),
+                                                     _,
+                                                     _)) => {
+                      m.span
+                  }
+                  _ => fail!("report_static_candidate: bad item {:?}", did)
+                }
             }
         } else {
             self.expr.span
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 9bdcd191360..088104e84ef 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -1330,8 +1330,7 @@ pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) {
 
         // Some extra checks to detect weird cycles and so forth:
         match *sty {
-            ty::ty_box(inner) | ty::ty_uniq(inner) |
-            ty::ty_rptr(_, inner) => {
+            ty::ty_box(inner) => {
                 match ty::get(t1).sty {
                     ty::ty_infer(ty::TyVar(v1)) => {
                         ty::occurs_check(fcx.ccx.tcx, sp, v1,
@@ -1340,6 +1339,15 @@ pub fn do_autoderef(fcx: @FnCtxt, sp: Span, t: ty::t) -> (ty::t, uint) {
                     _ => ()
                 }
             }
+            ty::ty_uniq(inner) | ty::ty_rptr(_, inner) => {
+                match ty::get(t1).sty {
+                    ty::ty_infer(ty::TyVar(v1)) => {
+                        ty::occurs_check(fcx.ccx.tcx, sp, v1,
+                                         ty::mk_box(fcx.ccx.tcx, inner.ty));
+                    }
+                    _ => ()
+                }
+            }
             ty::ty_enum(ref did, _) => {
                 // Watch out for a type like `enum t = @t`.  Such a
                 // type would otherwise infinitely auto-deref.  Only
@@ -2620,15 +2628,12 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
           }
           ast::ExprVec(ref args, mutbl) => {
             let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
-            let mutability;
             let mut any_error = false;
             let mut any_bot = false;
-            match vst {
-                ast::ExprVstoreMutBox | ast::ExprVstoreMutSlice => {
-                    mutability = ast::MutMutable
-                }
-                _ => mutability = mutbl
-            }
+            let mutability = match vst {
+                ast::ExprVstoreMutSlice => ast::MutMutable,
+                _ => mutbl,
+            };
             let t: ty::t = fcx.infcx().next_ty_var();
             for e in args.iter() {
                 check_expr_has_type(fcx, *e, t);
@@ -2642,11 +2647,9 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             }
             if any_error {
                 ty::mk_err()
-            }
-            else if any_bot {
+            } else if any_bot {
                 ty::mk_bot()
-            }
-            else {
+            } else {
                 ty::mk_evec(tcx, ty::mt {ty: t, mutbl: mutability}, tt)
             }
           }
@@ -2655,10 +2658,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
             let _ = ty::eval_repeat_count(fcx, count_expr);
             let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
             let mutability = match vst {
-                ast::ExprVstoreMutBox | ast::ExprVstoreMutSlice => {
-                    ast::MutMutable
-                }
-                _ => mutbl
+                ast::ExprVstoreMutSlice => ast::MutMutable,
+                _ => mutbl,
             };
             let t: ty::t = fcx.infcx().next_ty_var();
             check_expr_has_type(fcx, element, t);
@@ -2733,8 +2734,9 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
       ast::ExprUnary(callee_id, unop, oprnd) => {
         let exp_inner = unpack_expected(fcx, expected, |sty| {
             match unop {
-              ast::UnBox(_) | ast::UnUniq => match *sty {
-                ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => Some(mt.ty),
+              ast::UnBox | ast::UnUniq => match *sty {
+                ty::ty_box(ty) => Some(ty),
+                ty::ty_uniq(ref mt) => Some(mt.ty),
                 _ => None
               },
               ast::UnNot | ast::UnNeg => expected,
@@ -2746,9 +2748,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
         if !ty::type_is_error(oprnd_t) &&
               !ty::type_is_bot(oprnd_t) {
             match unop {
-                ast::UnBox(mutbl) => {
-                    oprnd_t = ty::mk_box(tcx,
-                                         ty::mt {ty: oprnd_t, mutbl: mutbl});
+                ast::UnBox => {
+                    oprnd_t = ty::mk_box(tcx, oprnd_t)
                 }
                 ast::UnUniq => {
                     oprnd_t = ty::mk_uniq(tcx,
@@ -3912,7 +3913,7 @@ pub fn ast_expr_vstore_to_vstore(fcx: @FnCtxt,
                               -> ty::vstore {
     match v {
         ast::ExprVstoreUniq => ty::vstore_uniq,
-        ast::ExprVstoreBox | ast::ExprVstoreMutBox => ty::vstore_box,
+        ast::ExprVstoreBox => ty::vstore_box,
         ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
             let r = fcx.infcx().next_region_var(infer::AddrOfSlice(e.span));
             ty::vstore_slice(r)
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 35501e5d5eb..fcf219323e1 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -582,7 +582,13 @@ pub fn early_resolve_expr(ex: @ast::Expr,
               let ty = structurally_resolved_type(fcx, ex.span,
                                                   fcx.expr_ty(src));
               match (&ty::get(ty).sty, store) {
-                  (&ty::ty_box(mt), ty::BoxTraitStore) |
+                  (&ty::ty_box(..), ty::BoxTraitStore)
+                    if !mutability_allowed(ast::MutImmutable,
+                                           target_mutbl) => {
+                      fcx.tcx().sess.span_err(ex.span,
+                                              format!("types differ in mutability"));
+                  }
+
                   (&ty::ty_uniq(mt), ty::UniqTraitStore) |
                   (&ty::ty_rptr(_, mt), ty::RegionTraitStore(..))
                     if !mutability_allowed(mt.mutbl, target_mutbl) => {
@@ -590,9 +596,15 @@ pub fn early_resolve_expr(ex: @ast::Expr,
                                               format!("types differ in mutability"));
                   }
 
-                  (&ty::ty_box(mt), ty::BoxTraitStore) |
-                  (&ty::ty_uniq(mt), ty::UniqTraitStore) |
-                  (&ty::ty_rptr(_, mt), ty::RegionTraitStore(..)) => {
+                  (&ty::ty_box(..), ty::BoxTraitStore) |
+                  (&ty::ty_uniq(..), ty::UniqTraitStore) |
+                  (&ty::ty_rptr(..), ty::RegionTraitStore(..)) => {
+                    let typ = match (&ty::get(ty).sty) {
+                        &ty::ty_box(typ) => typ,
+                        &ty::ty_uniq(mt) | &ty::ty_rptr(_, mt) => mt.ty,
+                        _ => fail!("shouldn't get here"),
+                    };
+
                       let location_info =
                           &location_info_for_expr(ex);
                       let vcx = fcx.vtable_context();
@@ -601,7 +613,7 @@ pub fn early_resolve_expr(ex: @ast::Expr,
                           substs: ty::substs {
                               tps: target_substs.tps.clone(),
                               regions: target_substs.regions.clone(),
-                              self_ty: Some(mt.ty)
+                              self_ty: Some(typ)
                           }
                       };
 
@@ -614,7 +626,7 @@ pub fn early_resolve_expr(ex: @ast::Expr,
                                                      location_info,
                                                      None,
                                                      &param_bounds,
-                                                     mt.ty,
+                                                     typ,
                                                      is_early);
 
                       if !is_early {
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 50459cd176b..d18c2419735 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -568,10 +568,8 @@ impl CoherenceChecker {
 
                         // Make sure that this type precisely names a nominal
                         // type.
-                        match self.crate_context
-                                  .tcx
-                                  .items
-                                  .find(&def_id.node) {
+                        let items = self.crate_context.tcx.items.borrow();
+                        match items.get().find(&def_id.node) {
                             None => {
                                 self.crate_context.tcx.sess.span_bug(
                                     original_type.span,
@@ -628,7 +626,8 @@ impl CoherenceChecker {
 
     pub fn span_of_impl(&self, implementation: @Impl) -> Span {
         assert_eq!(implementation.did.crate, LOCAL_CRATE);
-        match self.crate_context.tcx.items.find(&implementation.did.node) {
+        let items = self.crate_context.tcx.items.borrow();
+        match items.get().find(&implementation.did.node) {
             Some(&node_item(item, _)) => {
                 return item.span;
             }
@@ -732,14 +731,19 @@ impl CoherenceChecker {
                 _ => {
                     // Destructors only work on nominal types.
                     if impl_info.did.crate == ast::LOCAL_CRATE {
-                        match tcx.items.find(&impl_info.did.node) {
-                            Some(&ast_map::node_item(@ref item, _)) => {
-                                tcx.sess.span_err((*item).span,
-                                                  "the Drop trait may only be implemented on \
-                                                   structures");
-                            }
-                            _ => {
-                                tcx.sess.bug("didn't find impl in ast map");
+                        {
+                            let items = tcx.items.borrow();
+                            match items.get().find(&impl_info.did.node) {
+                                Some(&ast_map::node_item(@ref item, _)) => {
+                                    tcx.sess.span_err((*item).span,
+                                                      "the Drop trait may \
+                                                       only be implemented \
+                                                       on structures");
+                                }
+                                _ => {
+                                    tcx.sess.bug("didn't find impl in ast \
+                                                  map");
+                                }
                             }
                         }
                     } else {
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 3dfcf15e024..410c94a9a67 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -106,19 +106,18 @@ impl AstConv for CrateCtxt {
 
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
         if id.crate != ast::LOCAL_CRATE {
-            csearch::get_type(self.tcx, id)
-        } else {
-            match self.tcx.items.find(&id.node) {
-              Some(&ast_map::node_item(item, _)) => {
-                ty_of_item(self, item)
-              }
-              Some(&ast_map::node_foreign_item(foreign_item, abis, _, _)) => {
+            return csearch::get_type(self.tcx, id)
+        }
+
+        let items = self.tcx.items.borrow();
+        match items.get().find(&id.node) {
+            Some(&ast_map::node_item(item, _)) => ty_of_item(self, item),
+            Some(&ast_map::node_foreign_item(foreign_item, abis, _, _)) => {
                 ty_of_foreign_item(self, foreign_item, abis)
-              }
-              ref x => {
+            }
+            ref x => {
                 self.tcx.sess.bug(format!("unexpected sort of item \
-                                        in get_item_ty(): {:?}", (*x)));
-              }
+                                           in get_item_ty(): {:?}", (*x)));
             }
         }
     }
@@ -187,7 +186,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                             trait_id: ast::NodeId)
 {
     let tcx = ccx.tcx;
-    match tcx.items.get_copy(&trait_id) {
+    let items = tcx.items.borrow();
+    match items.get().get_copy(&trait_id) {
         ast_map::node_item(@ast::item {
             node: ast::item_trait(ref generics, _, ref ms),
             ..
@@ -715,7 +715,8 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::foreign_item) {
     // map, and I regard each time that I use it as a personal and
     // moral failing, but at the moment it seems like the only
     // convenient way to extract the ABI. - ndm
-    let abis = match ccx.tcx.items.find(&i.id) {
+    let items = ccx.tcx.items.borrow();
+    let abis = match items.get().find(&i.id) {
         Some(&ast_map::node_foreign_item(_, abis, _, _)) => abis,
         ref x => {
             ccx.tcx.sess.bug(format!("unexpected sort of item \
@@ -765,13 +766,14 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
 
 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
     if trait_id.crate != ast::LOCAL_CRATE {
-        ty::lookup_trait_def(ccx.tcx, trait_id)
-    } else {
-        match ccx.tcx.items.get(&trait_id.node) {
-            &ast_map::node_item(item, _) => trait_def_of_item(ccx, item),
-            _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
-                                       trait_id.node))
-        }
+        return ty::lookup_trait_def(ccx.tcx, trait_id)
+    }
+
+    let items = ccx.tcx.items.borrow();
+    match items.get().get(&trait_id.node) {
+        &ast_map::node_item(item, _) => trait_def_of_item(ccx, item),
+        _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
+                                   trait_id.node))
     }
 }
 
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index 0d4c3ef52d3..6e82456e95d 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -241,7 +241,7 @@ impl Coerce {
         let r_borrow = self.infcx.next_region_var(Coercion(self.trace));
 
         let inner_ty = match *sty_a {
-            ty::ty_box(mt_a) => mt_a.ty,
+            ty::ty_box(typ) => typ,
             ty::ty_uniq(mt_a) => mt_a.ty,
             ty::ty_rptr(_, mt_a) => mt_a.ty,
             _ => {
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index c35852d37c9..8d949cc1bc9 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -515,8 +515,8 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
             Ok(ty::mk_struct(tcx, a_id, substs))
       }
 
-      (&ty::ty_box(ref a_mt), &ty::ty_box(ref b_mt)) => {
-        this.mts(a_mt, b_mt).and_then(|mt| Ok(ty::mk_box(tcx, mt)))
+      (&ty::ty_box(a_inner), &ty::ty_box(b_inner)) => {
+        this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_box(tcx, typ)))
       }
 
       (&ty::ty_uniq(ref a_mt), &ty::ty_uniq(ref b_mt)) => {
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 835c739c085..982e2ca0685 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -350,7 +350,8 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
     let main_t = ty::node_id_to_type(tcx, main_id);
     match ty::get(main_t).sty {
         ty::ty_bare_fn(..) => {
-            match tcx.items.find(&main_id) {
+            let items = tcx.items.borrow();
+            match items.get().find(&main_id) {
                 Some(&ast_map::node_item(it,_)) => {
                     match it.node {
                         ast::item_fn(_, _, _, ref ps, _)
@@ -395,7 +396,8 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
     let start_t = ty::node_id_to_type(tcx, start_id);
     match ty::get(start_t).sty {
         ty::ty_bare_fn(_) => {
-            match tcx.items.find(&start_id) {
+            let items = tcx.items.borrow();
+            match items.get().find(&start_id) {
                 Some(&ast_map::node_item(it,_)) => {
                     match it.node {
                         ast::item_fn(_,_,_,ref ps,_)
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 3ae43d60661..7be5791c074 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -637,7 +637,10 @@ impl<'a> ConstraintContext<'a> {
                 self.add_constraints_from_mt(mt, variance);
             }
 
-            ty::ty_box(ref mt) |
+            ty::ty_box(typ) => {
+                self.add_constraints_from_ty(typ, variance);
+            }
+
             ty::ty_uniq(ref mt) |
             ty::ty_ptr(ref mt) => {
                 self.add_constraints_from_mt(mt, variance);
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index ac88018a3c4..6a346eac425 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -72,7 +72,8 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
                             -> (~str, Option<Span>) {
     return match region {
       ReScope(node_id) => {
-        match cx.items.find(&node_id) {
+        let items = cx.items.borrow();
+        match items.get().find(&node_id) {
           Some(&ast_map::node_block(ref blk)) => {
             explain_span(cx, "block", blk.span)
           }
@@ -113,7 +114,8 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
                     bound_region_ptr_to_str(cx, fr.bound_region))
         };
 
-        match cx.items.find(&fr.scope_id) {
+        let items = cx.items.borrow();
+        match items.get().find(&fr.scope_id) {
           Some(&ast_map::node_block(ref blk)) => {
             let (msg, opt_span) = explain_span(cx, "block", blk.span);
             (format!("{} {}", prefix, msg), opt_span)
@@ -172,7 +174,8 @@ pub fn bound_region_to_str(cx: ctxt,
 }
 
 pub fn ReScope_id_to_str(cx: ctxt, node_id: ast::NodeId) -> ~str {
-    match cx.items.find(&node_id) {
+    let items = cx.items.borrow();
+    match items.get().find(&node_id) {
       Some(&ast_map::node_block(ref blk)) => {
         format!("<block at {}>",
              cx.sess.codemap.span_to_str(blk.span))
@@ -451,7 +454,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
       ty_uint(ast::ty_u) => ~"uint",
       ty_uint(t) => ast_util::uint_ty_to_str(t),
       ty_float(t) => ast_util::float_ty_to_str(t),
-      ty_box(ref tm) => ~"@" + mt_to_str(cx, tm),
+      ty_box(typ) => ~"@" + ty_to_str(cx, typ),
       ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm),
       ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
       ty_rptr(r, ref tm) => {
@@ -740,16 +743,21 @@ impl Repr for ast::DefId {
         // a path for a def-id, so I'll just make a best effort for now
         // and otherwise fallback to just printing the crate/node pair
         if self.crate == ast::LOCAL_CRATE {
-            match tcx.items.find(&self.node) {
-                Some(&ast_map::node_item(..)) |
-                Some(&ast_map::node_foreign_item(..)) |
-                Some(&ast_map::node_method(..)) |
-                Some(&ast_map::node_trait_method(..)) |
-                Some(&ast_map::node_variant(..)) |
-                Some(&ast_map::node_struct_ctor(..)) => {
-                    return format!("{:?}:{}", *self, ty::item_path_str(tcx, *self));
+            {
+                let items = tcx.items.borrow();
+                match items.get().find(&self.node) {
+                    Some(&ast_map::node_item(..)) |
+                    Some(&ast_map::node_foreign_item(..)) |
+                    Some(&ast_map::node_method(..)) |
+                    Some(&ast_map::node_trait_method(..)) |
+                    Some(&ast_map::node_variant(..)) |
+                    Some(&ast_map::node_struct_ctor(..)) => {
+                        return format!("{:?}:{}",
+                                       *self,
+                                       ty::item_path_str(tcx, *self));
+                    }
+                    _ => {}
                 }
-                _ => {}
             }
         }
         return format!("{:?}", *self);
diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs
index 4bcf1985ef2..52dbba13ea8 100644
--- a/src/librustdoc/clean.rs
+++ b/src/librustdoc/clean.rs
@@ -594,7 +594,7 @@ pub enum Type {
     /// aka ty_bot
     Bottom,
     Unique(~Type),
-    Managed(Mutability, ~Type),
+    Managed(~Type),
     RawPointer(Mutability, ~Type),
     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: ~Type},
     // region, raw, other boxes, mutable
@@ -620,7 +620,7 @@ impl Clean<Type> for ast::Ty {
             ty_rptr(ref l, ref m) =>
                 BorrowedRef {lifetime: l.clean(), mutability: m.mutbl.clean(),
                              type_: ~m.ty.clean()},
-            ty_box(ref m) => Managed(m.mutbl.clean(), ~m.ty.clean()),
+            ty_box(ty) => Managed(~ty.clean()),
             ty_uniq(ty) => Unique(~ty.clean()),
             ty_vec(ty) => Vector(~ty.clean()),
             ty_fixed_length_vec(ty, ref e) => FixedVector(~ty.clean(),
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 63b92394365..42d888dbbe8 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -88,7 +88,7 @@ pub fn run_core (libs: HashSet<Path>, cfgs: ~[~str], path: &Path) -> (clean::Cra
     let ctxt = @ctxt;
     local_data::set(super::ctxtkey, ctxt);
 
-    let v = @mut RustdocVisitor::new();
+    let mut v = RustdocVisitor::new();
     v.visit(&ctxt.crate);
 
     (v.clean(), analysis)
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 04da17d4ec4..b32ca037261 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -340,13 +340,7 @@ impl fmt::Default for clean::Type {
             clean::Unit => f.buf.write("()".as_bytes()),
             clean::Bottom => f.buf.write("!".as_bytes()),
             clean::Unique(ref t) => write!(f.buf, "~{}", **t),
-            clean::Managed(m, ref t) => {
-                write!(f.buf, "@{}{}",
-                       match m {
-                           clean::Mutable => "mut ",
-                           clean::Immutable => "",
-                       }, **t)
-            }
+            clean::Managed(ref t) => write!(f.buf, "@{}", **t),
             clean::RawPointer(m, ref t) => {
                 write!(f.buf, "*{}{}",
                        match m {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 945cb865d3b..36caed437f5 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -267,11 +267,11 @@ fn rust_input(cratefile: &str, matches: &getopts::Matches) -> Output {
 /// This input format purely deserializes the json output file. No passes are
 /// run over the deserialized output.
 fn json_input(input: &str) -> Result<Output, ~str> {
-    let input = match File::open(&Path::new(input)) {
+    let mut input = match File::open(&Path::new(input)) {
         Some(f) => f,
         None => return Err(format!("couldn't open {} for reading", input)),
     };
-    match json::from_reader(@mut input as @mut io::Reader) {
+    match json::from_reader(&mut input) {
         Err(s) => Err(s.to_str()),
         Ok(json::Object(obj)) => {
             let mut obj = obj;
@@ -332,6 +332,6 @@ fn json_output(crate: clean::Crate, res: ~[plugins::PluginJson], dst: Path) {
     json.insert(~"crate", crate_json);
     json.insert(~"plugins", json::Object(plugins_json));
 
-    let file = @mut File::create(&dst).unwrap();
-    json::Object(json).to_writer(file as @mut io::Writer);
+    let mut file = File::create(&dst).unwrap();
+    json::Object(json).to_writer(&mut file);
 }
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 480ace2e419..0fbe585b9bf 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -67,7 +67,7 @@ pub fn run(input: &str, matches: &getopts::Matches) -> int {
     };
     local_data::set(super::ctxtkey, ctx);
 
-    let v = @mut RustdocVisitor::new();
+    let mut v = RustdocVisitor::new();
     v.visit(&ctx.crate);
     let crate = v.clean();
     let (crate, _) = passes::unindent_comments(crate);
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 03ab85918c7..9b6e809f835 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -32,7 +32,7 @@ impl RustdocVisitor {
 }
 
 impl RustdocVisitor {
-    pub fn visit(@mut self, crate: &ast::Crate) {
+    pub fn visit(&mut self, crate: &ast::Crate) {
         self.attrs = crate.attrs.clone();
         fn visit_struct_def(item: &ast::item, sd: @ast::struct_def, generics:
                             &ast::Generics) -> Struct {
diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs
index c5648d811ed..7e43fde7b32 100644
--- a/src/librustpkg/util.rs
+++ b/src/librustpkg/util.rs
@@ -80,8 +80,7 @@ struct ReadyCtx {
     fns: ~[ListenerFn]
 }
 
-fn fold_mod(_ctx: @mut ReadyCtx, m: &ast::_mod, fold: &mut CrateSetup)
-            -> ast::_mod {
+fn fold_mod(m: &ast::_mod, fold: &mut CrateSetup) -> ast::_mod {
     fn strip_main(item: @ast::item) -> @ast::item {
         @ast::item {
             attrs: item.attrs.iter().filter_map(|attr| {
@@ -101,9 +100,9 @@ fn fold_mod(_ctx: @mut ReadyCtx, m: &ast::_mod, fold: &mut CrateSetup)
     }, fold)
 }
 
-fn fold_item(ctx: @mut ReadyCtx, item: @ast::item, fold: &mut CrateSetup)
+fn fold_item(item: @ast::item, fold: &mut CrateSetup)
              -> SmallVector<@ast::item> {
-    ctx.path.push(item.ident);
+    fold.ctx.path.push(item.ident);
 
     let mut cmds = ~[];
     let mut had_pkg_do = false;
@@ -126,44 +125,44 @@ fn fold_item(ctx: @mut ReadyCtx, item: @ast::item, fold: &mut CrateSetup)
     }
 
     if had_pkg_do {
-        ctx.fns.push(ListenerFn {
+        fold.ctx.fns.push(ListenerFn {
             cmds: cmds,
             span: item.span,
-            path: /*bad*/ctx.path.clone()
+            path: /*bad*/fold.ctx.path.clone()
         });
     }
 
     let res = fold::noop_fold_item(item, fold);
 
-    ctx.path.pop();
+    fold.ctx.path.pop();
 
     res
 }
 
-struct CrateSetup {
-    ctx: @mut ReadyCtx,
+struct CrateSetup<'a> {
+    ctx: &'a mut ReadyCtx,
 }
 
-impl fold::ast_fold for CrateSetup {
+impl<'a> fold::ast_fold for CrateSetup<'a> {
     fn fold_item(&mut self, item: @ast::item) -> SmallVector<@ast::item> {
-        fold_item(self.ctx, item, self)
+        fold_item(item, self)
     }
     fn fold_mod(&mut self, module: &ast::_mod) -> ast::_mod {
-        fold_mod(self.ctx, module, self)
+        fold_mod(module, self)
     }
 }
 
 /// Generate/filter main function, add the list of commands, etc.
 pub fn ready_crate(sess: session::Session,
                    crate: ast::Crate) -> ast::Crate {
-    let ctx = @mut ReadyCtx {
+    let mut ctx = ReadyCtx {
         sess: sess,
         ext_cx: ExtCtxt::new(sess.parse_sess, sess.opts.cfg.clone()),
         path: ~[],
         fns: ~[]
     };
     let mut fold = CrateSetup {
-        ctx: ctx,
+        ctx: &mut ctx,
     };
     fold.fold_crate(crate)
 }
diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs
index b383c9edf36..b26ceb799a7 100644
--- a/src/libstd/clone.rs
+++ b/src/libstd/clone.rs
@@ -58,12 +58,6 @@ impl<T> Clone for @T {
     fn clone(&self) -> @T { *self }
 }
 
-impl<T> Clone for @mut T {
-    /// Return a shallow copy of the managed box.
-    #[inline]
-    fn clone(&self) -> @mut T { *self }
-}
-
 impl<'a, T> Clone for &'a T {
     /// Return a shallow copy of the borrowed pointer.
     #[inline]
@@ -168,14 +162,6 @@ impl<T: Freeze + DeepClone + 'static> DeepClone for @T {
     fn deep_clone(&self) -> @T { @(**self).deep_clone() }
 }
 
-// FIXME: #6525: should also be implemented for `T: Send + DeepClone`
-impl<T: Freeze + DeepClone + 'static> DeepClone for @mut T {
-    /// Return a deep copy of the managed box. The `Freeze` trait is required to prevent performing
-    /// a deep clone of a potentially cyclical type.
-    #[inline]
-    fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }
-}
-
 macro_rules! deep_clone_impl(
     ($t:ty) => {
         impl DeepClone for $t {
@@ -240,23 +226,6 @@ fn test_managed_clone() {
 }
 
 #[test]
-fn test_managed_mut_deep_clone() {
-    let x = @mut 5i;
-    let y: @mut int = x.deep_clone();
-    *x = 20;
-    assert_eq!(*y, 5);
-}
-
-#[test]
-fn test_managed_mut_clone() {
-    let a = @mut 5i;
-    let b: @mut int = a.clone();
-    assert_eq!(a, b);
-    *b = 10;
-    assert_eq!(a, b);
-}
-
-#[test]
 fn test_borrowed_clone() {
     let x = 5i;
     let y: &int = &x;
diff --git a/src/libstd/default.rs b/src/libstd/default.rs
index aaba23c683b..60f38e3b3de 100644
--- a/src/libstd/default.rs
+++ b/src/libstd/default.rs
@@ -16,10 +16,6 @@ pub trait Default {
     fn default() -> Self;
 }
 
-impl<T: Default + 'static> Default for @mut T {
-    fn default() -> @mut T { @mut Default::default() }
-}
-
 impl<T: Default + 'static> Default for @T {
     fn default() -> @T { @Default::default() }
 }
diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs
index a7361fa8c37..1b6d1171a52 100644
--- a/src/libstd/io/extensions.rs
+++ b/src/libstd/io/extensions.rs
@@ -371,15 +371,17 @@ mod test {
 
     #[test]
     #[should_fail]
+    #[ignore] // borrow issues with RefCell
     fn push_bytes_fail_reset_len() {
         // push_bytes unsafely sets the vector length. This is testing that
         // upon failure the length is reset correctly.
         let mut reader = ErroringLaterReader {
             count: 0,
         };
-        let buf = @mut ~[8, 9];
+        // FIXME (#7049): Figure out some other way to do this.
+        //let buf = @mut ~[8, 9];
         (|| {
-            reader.push_bytes(&mut *buf, 4);
+            //reader.push_bytes(&mut *buf, 4);
         }).finally(|| {
             // NB: Using rtassert here to trigger abort on failure since this is a should_fail test
             // FIXME: #7049 This fails because buf is still borrowed
diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs
index 7322f0b0647..c5705665896 100644
--- a/src/libstd/managed.rs
+++ b/src/libstd/managed.rs
@@ -31,13 +31,6 @@ pub fn ptr_eq<T>(a: @T, b: @T) -> bool {
     a_ptr == b_ptr
 }
 
-/// Determine if two mutable shared boxes point to the same object
-#[inline]
-pub fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool {
-    let (a_ptr, b_ptr): (*T, *T) = (to_unsafe_ptr(&*a), to_unsafe_ptr(&*b));
-    a_ptr == b_ptr
-}
-
 #[cfg(not(test))]
 impl<T:Eq> Eq for @T {
     #[inline]
@@ -47,14 +40,6 @@ impl<T:Eq> Eq for @T {
 }
 
 #[cfg(not(test))]
-impl<T:Eq> Eq for @mut T {
-    #[inline]
-    fn eq(&self, other: &@mut T) -> bool { *(*self) == *(*other) }
-    #[inline]
-    fn ne(&self, other: &@mut T) -> bool { *(*self) != *(*other) }
-}
-
-#[cfg(not(test))]
 impl<T:Ord> Ord for @T {
     #[inline]
     fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) }
@@ -67,40 +52,17 @@ impl<T:Ord> Ord for @T {
 }
 
 #[cfg(not(test))]
-impl<T:Ord> Ord for @mut T {
-    #[inline]
-    fn lt(&self, other: &@mut T) -> bool { *(*self) < *(*other) }
-    #[inline]
-    fn le(&self, other: &@mut T) -> bool { *(*self) <= *(*other) }
-    #[inline]
-    fn ge(&self, other: &@mut T) -> bool { *(*self) >= *(*other) }
-    #[inline]
-    fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
-}
-
-#[cfg(not(test))]
 impl<T: TotalOrd> TotalOrd for @T {
     #[inline]
     fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) }
 }
 
 #[cfg(not(test))]
-impl<T: TotalOrd> TotalOrd for @mut T {
-    #[inline]
-    fn cmp(&self, other: &@mut T) -> Ordering { (**self).cmp(*other) }
-}
-
-#[cfg(not(test))]
 impl<T: TotalEq> TotalEq for @T {
     #[inline]
     fn equals(&self, other: &@T) -> bool { (**self).equals(*other) }
 }
 
-#[cfg(not(test))]
-impl<T: TotalEq> TotalEq for @mut T {
-    #[inline]
-    fn equals(&self, other: &@mut T) -> bool { (**self).equals(*other) }
-}
 #[test]
 fn test() {
     let x = @3;
diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs
index 8dbec0f63c6..d66d13657fc 100644
--- a/src/libstd/num/mod.rs
+++ b/src/libstd/num/mod.rs
@@ -1079,11 +1079,6 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Div<T,T>+Mul<T,T>>(radix: uint, pow: uin
     total
 }
 
-impl<T: Zero + 'static> Zero for @mut T {
-    fn zero() -> @mut T { @mut Zero::zero() }
-    fn is_zero(&self) -> bool { (**self).is_zero() }
-}
-
 impl<T: Zero + 'static> Zero for @T {
     fn zero() -> @T { @Zero::zero() }
     fn is_zero(&self) -> bool { (**self).is_zero() }
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
index 2f9478716a3..e60abed42f2 100644
--- a/src/libstd/repr.rs
+++ b/src/libstd/repr.rs
@@ -655,13 +655,10 @@ fn test_repr() {
     exact_test(&(~"he\u10f3llo"), "~\"he\\u10f3llo\"");
 
     exact_test(&(@10), "@10");
-    exact_test(&(@mut 10), "@mut 10");
-    exact_test(&((@mut 10, 2)), "(@mut 10, 2)");
     exact_test(&(~10), "~10");
     exact_test(&(&10), "&10");
     let mut x = 10;
     exact_test(&(&mut x), "&mut 10");
-    exact_test(&(@mut [1, 2]), "@mut [1, 2]");
 
     exact_test(&(0 as *()), "(0x0 as *())");
     exact_test(&(0 as *mut ()), "(0x0 as *mut ())");
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 583a1e0657c..ae12f944f9c 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -444,16 +444,20 @@ mod test {
 
     #[test]
     fn heap_cycles() {
+        use cell::RefCell;
         use option::{Option, Some, None};
 
         struct List {
-            next: Option<@mut List>,
+            next: Option<@RefCell<List>>,
         }
 
-        let a = @mut List { next: None };
-        let b = @mut List { next: Some(a) };
+        let a = @RefCell::new(List { next: None });
+        let b = @RefCell::new(List { next: Some(a) });
 
-        a.next = Some(b);
+        {
+            let mut a = a.borrow_mut();
+            a.get().next = Some(b);
+        }
     }
 
     #[test]
diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs
index 9de812ed385..bd1c49c6c24 100644
--- a/src/libstd/to_bytes.rs
+++ b/src/libstd/to_bytes.rs
@@ -319,13 +319,6 @@ impl<A:IterBytes> IterBytes for @A {
     }
 }
 
-impl<A:IterBytes> IterBytes for @mut A {
-    #[inline]
-    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
-        (**self).iter_bytes(lsb0, f)
-    }
-}
-
 impl<A:IterBytes> IterBytes for Rc<A> {
     #[inline]
     fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 51aa7cd4377..3523d63ef60 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -15,6 +15,7 @@ use abi::AbiSet;
 use opt_vec::OptVec;
 use parse::token::{interner_get, str_to_ident};
 
+use std::cell::RefCell;
 use std::hashmap::HashMap;
 use std::option::Option;
 use std::to_str::ToStr;
@@ -88,9 +89,9 @@ pub type SyntaxContext = u32;
 // it should cut down on memory use *a lot*; applying a mark
 // to a tree containing 50 identifiers would otherwise generate
 pub struct SCTable {
-    table : ~[SyntaxContext_],
-    mark_memo : HashMap<(SyntaxContext,Mrk),SyntaxContext>,
-    rename_memo : HashMap<(SyntaxContext,Ident,Name),SyntaxContext>
+    table: RefCell<~[SyntaxContext_]>,
+    mark_memo: RefCell<HashMap<(SyntaxContext,Mrk),SyntaxContext>>,
+    rename_memo: RefCell<HashMap<(SyntaxContext,Ident,Name),SyntaxContext>>,
 }
 
 // NB: these must be placed in any SCTable...
@@ -414,7 +415,6 @@ pub enum Vstore {
 pub enum ExprVstore {
     ExprVstoreUniq,                 // ~[1,2,3,4]
     ExprVstoreBox,                  // @[1,2,3,4]
-    ExprVstoreMutBox,               // @mut [1,2,3,4]
     ExprVstoreSlice,                // &[1,2,3,4]
     ExprVstoreMutSlice,             // &mut [1,2,3,4]
 }
@@ -443,7 +443,7 @@ pub enum BinOp {
 
 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
 pub enum UnOp {
-    UnBox(Mutability),
+    UnBox,
     UnUniq,
     UnDeref,
     UnNot,
@@ -874,7 +874,7 @@ pub struct TyBareFn {
 pub enum ty_ {
     ty_nil,
     ty_bot, /* bottom type */
-    ty_box(mt),
+    ty_box(P<Ty>),
     ty_uniq(P<Ty>),
     ty_vec(P<Ty>),
     ty_fixed_length_vec(P<Ty>, @Expr),
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index 504a51f80a8..8a5a1d2426c 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -23,6 +23,7 @@ use print::pprust;
 use visit::{Visitor, fn_kind};
 use visit;
 
+use std::cell::RefCell;
 use std::hashmap::HashMap;
 use std::vec;
 
@@ -94,7 +95,7 @@ pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
 fn pretty_ty(ty: &Ty, itr: @ident_interner, out: &mut ~str) {
     let (prefix, subty) = match ty.node {
         ty_uniq(ty) => ("$UP$", &*ty),
-        ty_box(mt { ty, .. }) => ("$SP$", &*ty),
+        ty_box(ty) => ("$SP$", &*ty),
         ty_ptr(mt { ty, mutbl }) => (if mutbl == MutMutable {"$RPmut$"} else {"$RP$"},
                                      &*ty),
         ty_rptr(_, mt { ty, mutbl }) => (if mutbl == MutMutable {"$BPmut$"} else {"$BP$"},
@@ -192,17 +193,17 @@ impl ast_node {
     }
 }
 
-pub type map = @mut HashMap<NodeId, ast_node>;
+pub type map = @RefCell<HashMap<NodeId, ast_node>>;
 
 pub struct Ctx {
     map: map,
-    path: path,
-    diag: @mut SpanHandler,
+    path: RefCell<path>,
+    diag: @SpanHandler,
 }
 
 impl Ctx {
     fn extend(&self, elt: path_elt) -> @path {
-        @vec::append(self.path.clone(), [elt])
+        @vec::append(self.path.get(), [elt])
     }
 
     fn map_method(&mut self,
@@ -215,8 +216,10 @@ impl Ctx {
         } else {
             node_method(m, impl_did, impl_path)
         };
-        self.map.insert(m.id, entry);
-        self.map.insert(m.self_id, node_local(special_idents::self_));
+
+        let mut map = self.map.borrow_mut();
+        map.get().insert(m.id, entry);
+        map.get().insert(m.self_id, node_local(special_idents::self_));
     }
 
     fn map_struct_def(&mut self,
@@ -231,10 +234,11 @@ impl Ctx {
             Some(ctor_id) => {
                 match parent_node {
                     node_item(item, _) => {
-                        self.map.insert(ctor_id,
-                                        node_struct_ctor(struct_def,
-                                                         item,
-                                                         p));
+                        let mut map = self.map.borrow_mut();
+                        map.get().insert(ctor_id,
+                                         node_struct_ctor(struct_def,
+                                                          item,
+                                                          p));
                     }
                     _ => fail!("struct def parent wasn't an item")
                 }
@@ -243,13 +247,17 @@ impl Ctx {
     }
 
     fn map_expr(&mut self, ex: @Expr) {
-        self.map.insert(ex.id, node_expr(ex));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(ex.id, node_expr(ex));
+        }
 
         // Expressions which are or might be calls:
         {
             let r = ex.get_callee_id();
             for callee_id in r.iter() {
-                self.map.insert(*callee_id, node_callee_scope(ex));
+                let mut map = self.map.borrow_mut();
+                map.get().insert(*callee_id, node_callee_scope(ex));
             }
         }
 
@@ -263,26 +271,40 @@ impl Ctx {
               sp: codemap::Span,
               id: NodeId) {
         for a in decl.inputs.iter() {
-            self.map.insert(a.id, node_arg(a.pat));
+            let mut map = self.map.borrow_mut();
+            map.get().insert(a.id, node_arg(a.pat));
         }
         match *fk {
-            visit::fk_method(name, _, _) => { self.path.push(path_name(name)) }
+            visit::fk_method(name, _, _) => {
+                let mut path = self.path.borrow_mut();
+                path.get().push(path_name(name))
+            }
             _ => {}
         }
         visit::walk_fn(self, fk, decl, body, sp, id, ());
         match *fk {
-            visit::fk_method(..) => { self.path.pop(); }
+            visit::fk_method(..) => {
+                let mut path = self.path.borrow_mut();
+                path.get().pop();
+            }
             _ => {}
         }
     }
 
     fn map_stmt(&mut self, stmt: @Stmt) {
-        self.map.insert(stmt_id(stmt), node_stmt(stmt));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(stmt_id(stmt), node_stmt(stmt));
+        }
         visit::walk_stmt(self, stmt, ());
     }
 
     fn map_block(&mut self, b: P<Block>) {
-        self.map.insert(b.id, node_block(b));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(b.id, node_block(b));
+        }
+
         visit::walk_block(self, b, ());
     }
 
@@ -290,8 +312,9 @@ impl Ctx {
         match pat.node {
             PatIdent(_, ref path, _) => {
                 // Note: this is at least *potentially* a pattern...
-                self.map.insert(pat.id,
-                                node_local(ast_util::path_to_ident(path)));
+                let mut map = self.map.borrow_mut();
+                map.get().insert(pat.id,
+                                 node_local(ast_util::path_to_ident(path)));
             }
             _ => ()
         }
@@ -303,8 +326,11 @@ impl Ctx {
 impl Visitor<()> for Ctx {
     fn visit_item(&mut self, i: @item, _: ()) {
         // clone is FIXME #2543
-        let item_path = @self.path.clone();
-        self.map.insert(i.id, node_item(i, item_path));
+        let item_path = @self.path.get();
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(i.id, node_item(i, item_path));
+        }
         match i.node {
             item_impl(_, ref maybe_trait, ty, ref ms) => {
                 // Right now the ident on impls is __extensions__ which isn't
@@ -318,13 +344,15 @@ impl Visitor<()> for Ctx {
                     self.map_method(impl_did, extended, *m, false)
                 }
 
-                self.path.push(elt);
+                let mut path = self.path.borrow_mut();
+                path.get().push(elt);
             }
             item_enum(ref enum_definition, _) => {
                 for &v in enum_definition.variants.iter() {
                     let elt = path_name(i.ident);
-                    self.map.insert(v.node.id,
-                                    node_variant(v, i, self.extend(elt)));
+                    let mut map = self.map.borrow_mut();
+                    map.get().insert(v.node.id,
+                                     node_variant(v, i, self.extend(elt)));
                 }
             }
             item_foreign_mod(ref nm) => {
@@ -336,16 +364,17 @@ impl Visitor<()> for Ctx {
                         inherited => i.vis
                     };
 
-                    self.map.insert(nitem.id,
-                                    node_foreign_item(*nitem,
-                                                      nm.abis,
-                                                      visibility,
-                                                      // FIXME (#2543)
+                    let mut map = self.map.borrow_mut();
+                    map.get().insert(nitem.id,
+                                     node_foreign_item(*nitem,
+                                                       nm.abis,
+                                                       visibility,
+                                                       // FIXME (#2543)
                                                         // Anonymous extern
                                                         // mods go in the
                                                         // parent scope.
-                                                        @self.path.clone()
-                                                      ));
+                                                        @self.path.get()
+                                                       ));
                 }
             }
             item_struct(struct_def, _) => {
@@ -355,7 +384,8 @@ impl Visitor<()> for Ctx {
             }
             item_trait(_, ref traits, ref methods) => {
                 for p in traits.iter() {
-                    self.map.insert(p.ref_id, node_item(i, item_path));
+                    let mut map = self.map.borrow_mut();
+                    map.get().insert(p.ref_id, node_item(i, item_path));
                 }
                 for tm in methods.iter() {
                     let ext = { self.extend(path_name(i.ident)) };
@@ -364,7 +394,8 @@ impl Visitor<()> for Ctx {
                         required(ref m) => {
                             let entry =
                                 node_trait_method(@(*tm).clone(), d_id, ext);
-                            self.map.insert(m.id, entry);
+                            let mut map = self.map.borrow_mut();
+                            map.get().insert(m.id, entry);
                         }
                         provided(m) => {
                             self.map_method(d_id, ext, m, true);
@@ -377,13 +408,19 @@ impl Visitor<()> for Ctx {
 
         match i.node {
             item_mod(_) | item_foreign_mod(_) => {
-                self.path.push(path_mod(i.ident));
+                let mut path = self.path.borrow_mut();
+                path.get().push(path_mod(i.ident));
             }
             item_impl(..) => {} // this was guessed above.
-            _ => self.path.push(path_name(i.ident))
+            _ => {
+                let mut path = self.path.borrow_mut();
+                path.get().push(path_name(i.ident))
+            }
         }
         visit::walk_item(self, i, ());
-        self.path.pop();
+
+        let mut path = self.path.borrow_mut();
+        path.get().pop();
     }
 
     fn visit_pat(&mut self, pat: &Pat, _: ()) {
@@ -418,29 +455,29 @@ impl Visitor<()> for Ctx {
     }
 }
 
-pub fn map_crate(diag: @mut SpanHandler, c: &Crate) -> map {
-    let cx = @mut Ctx {
-        map: @mut HashMap::new(),
-        path: ~[],
+pub fn map_crate(diag: @SpanHandler, c: &Crate) -> map {
+    let mut cx = Ctx {
+        map: @RefCell::new(HashMap::new()),
+        path: RefCell::new(~[]),
         diag: diag,
     };
-    visit::walk_crate(cx, c, ());
+    visit::walk_crate(&mut cx, c, ());
     cx.map
 }
 
 // Used for items loaded from external crate that are being inlined into this
 // crate.  The `path` should be the path to the item but should not include
 // the item itself.
-pub fn map_decoded_item(diag: @mut SpanHandler,
+pub fn map_decoded_item(diag: @SpanHandler,
                         map: map,
                         path: path,
                         ii: &inlined_item) {
     // I believe it is ok for the local IDs of inlined items from other crates
     // to overlap with the local ids from this crate, so just generate the ids
     // starting from 0.
-    let cx = @mut Ctx {
+    let mut cx = Ctx {
         map: map,
-        path: path.clone(),
+        path: RefCell::new(path.clone()),
         diag: diag,
     };
 
@@ -450,10 +487,11 @@ pub fn map_decoded_item(diag: @mut SpanHandler,
     match *ii {
         ii_item(..) => {} // fallthrough
         ii_foreign(i) => {
-            cx.map.insert(i.id, node_foreign_item(i,
-                                                  AbiSet::Intrinsic(),
-                                                  i.vis,    // Wrong but OK
-                                                  @path));
+            let mut map = cx.map.borrow_mut();
+            map.get().insert(i.id, node_foreign_item(i,
+                                                     AbiSet::Intrinsic(),
+                                                     i.vis,    // Wrong but OK
+                                                     @path));
         }
         ii_method(impl_did, is_provided, m) => {
             cx.map_method(impl_did, @path, m, is_provided);
@@ -461,11 +499,12 @@ pub fn map_decoded_item(diag: @mut SpanHandler,
     }
 
     // visit the item / method contents and add those to the map:
-    ii.accept((), cx);
+    ii.accept((), &mut cx);
 }
 
 pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
-    match map.find(&id) {
+    let map = map.borrow();
+    match map.get().find(&id) {
       None => {
         format!("unknown node (id={})", id)
       }
@@ -529,7 +568,8 @@ pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
 
 pub fn node_item_query<Result>(items: map, id: NodeId, query: |@item| -> Result, error_msg: ~str)
                        -> Result {
-    match items.find(&id) {
+    let items = items.borrow();
+    match items.get().find(&id) {
         Some(&node_item(it, _)) => query(it),
         _ => fail!("{}", error_msg)
     }
@@ -538,7 +578,8 @@ pub fn node_item_query<Result>(items: map, id: NodeId, query: |@item| -> Result,
 pub fn node_span(items: map,
                  id: ast::NodeId)
                  -> Span {
-    match items.find(&id) {
+    let items = items.borrow();
+    match items.get().find(&id) {
         Some(&node_item(item, _)) => item.span,
         Some(&node_foreign_item(foreign_item, _, _, _)) => foreign_item.span,
         Some(&node_trait_method(@required(ref type_method), _, _)) => type_method.span,
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index f93eb6754ad..f99fed517b1 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -17,6 +17,7 @@ use parse::token;
 use visit::Visitor;
 use visit;
 
+use std::cell::{Cell, RefCell};
 use std::hashmap::HashMap;
 use std::u32;
 use std::local_data;
@@ -136,13 +137,13 @@ pub fn is_shift_binop(b: BinOp) -> bool {
     }
 }
 
-pub fn unop_to_str(op: UnOp) -> ~str {
+pub fn unop_to_str(op: UnOp) -> &'static str {
     match op {
-      UnBox(mt) => if mt == MutMutable { ~"@mut " } else { ~"@" },
-      UnUniq => ~"~",
-      UnDeref => ~"*",
-      UnNot => ~"!",
-      UnNeg => ~"-"
+      UnBox => "@",
+      UnUniq => "~",
+      UnDeref => "*",
+      UnNot => "!",
+      UnNeg => "-",
     }
 }
 
@@ -601,21 +602,23 @@ pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &inlined_item,
 }
 
 struct IdRangeComputingVisitor {
-    result: @mut id_range,
+    result: Cell<id_range>,
 }
 
 impl IdVisitingOperation for IdRangeComputingVisitor {
     fn visit_id(&self, id: NodeId) {
-        self.result.add(id)
+        let mut id_range = self.result.get();
+        id_range.add(id);
+        self.result.set(id_range)
     }
 }
 
 pub fn compute_id_range_for_inlined_item(item: &inlined_item) -> id_range {
-    let result = @mut id_range::max();
-    visit_ids_for_inlined_item(item, &IdRangeComputingVisitor {
-        result: result,
-    });
-    *result
+    let visitor = IdRangeComputingVisitor {
+        result: Cell::new(id_range::max())
+    };
+    visit_ids_for_inlined_item(item, &visitor);
+    visitor.result.get()
 }
 
 pub fn is_item_impl(item: @ast::item) -> bool {
@@ -709,21 +712,25 @@ pub fn new_mark(m:Mrk, tail:SyntaxContext) -> SyntaxContext {
 
 // Extend a syntax context with a given mark and table
 // FIXME #8215 : currently pub to allow testing
-pub fn new_mark_internal(m:Mrk, tail:SyntaxContext,table:&mut SCTable)
-    -> SyntaxContext {
+pub fn new_mark_internal(m: Mrk, tail: SyntaxContext, table: &SCTable)
+                         -> SyntaxContext {
     let key = (tail,m);
     // FIXME #5074 : can't use more natural style because we're missing
     // flow-sensitivity. Results in two lookups on a hash table hit.
     // also applies to new_rename_internal, below.
     // let try_lookup = table.mark_memo.find(&key);
-    match table.mark_memo.contains_key(&key) {
+    let mut mark_memo = table.mark_memo.borrow_mut();
+    match mark_memo.get().contains_key(&key) {
         false => {
-            let new_idx = idx_push(&mut table.table,Mark(m,tail));
-            table.mark_memo.insert(key,new_idx);
+            let new_idx = {
+                let mut table = table.table.borrow_mut();
+                idx_push(table.get(), Mark(m,tail))
+            };
+            mark_memo.get().insert(key,new_idx);
             new_idx
         }
         true => {
-            match table.mark_memo.find(&key) {
+            match mark_memo.get().find(&key) {
                 None => fail!("internal error: key disappeared 2013042901"),
                 Some(idxptr) => {*idxptr}
             }
@@ -738,19 +745,26 @@ pub fn new_rename(id:Ident, to:Name, tail:SyntaxContext) -> SyntaxContext {
 
 // Extend a syntax context with a given rename and sctable
 // FIXME #8215 : currently pub to allow testing
-pub fn new_rename_internal(id:Ident, to:Name, tail:SyntaxContext, table: &mut SCTable)
-    -> SyntaxContext {
+pub fn new_rename_internal(id: Ident,
+                           to: Name,
+                           tail: SyntaxContext,
+                           table: &SCTable)
+                           -> SyntaxContext {
     let key = (tail,id,to);
     // FIXME #5074
     //let try_lookup = table.rename_memo.find(&key);
-    match table.rename_memo.contains_key(&key) {
+    let mut rename_memo = table.rename_memo.borrow_mut();
+    match rename_memo.get().contains_key(&key) {
         false => {
-            let new_idx = idx_push(&mut table.table,Rename(id,to,tail));
-            table.rename_memo.insert(key,new_idx);
+            let new_idx = {
+                let mut table = table.table.borrow_mut();
+                idx_push(table.get(), Rename(id,to,tail))
+            };
+            rename_memo.get().insert(key,new_idx);
             new_idx
         }
         true => {
-            match table.rename_memo.find(&key) {
+            match rename_memo.get().find(&key) {
                 None => fail!("internal error: key disappeared 2013042902"),
                 Some(idxptr) => {*idxptr}
             }
@@ -763,18 +777,18 @@ pub fn new_rename_internal(id:Ident, to:Name, tail:SyntaxContext, table: &mut SC
 // FIXME #8215 : currently pub to allow testing
 pub fn new_sctable_internal() -> SCTable {
     SCTable {
-        table: ~[EmptyCtxt,IllegalCtxt],
-        mark_memo: HashMap::new(),
-        rename_memo: HashMap::new()
+        table: RefCell::new(~[EmptyCtxt,IllegalCtxt]),
+        mark_memo: RefCell::new(HashMap::new()),
+        rename_memo: RefCell::new(HashMap::new()),
     }
 }
 
 // fetch the SCTable from TLS, create one if it doesn't yet exist.
-pub fn get_sctable() -> @mut SCTable {
-    local_data_key!(sctable_key: @@mut SCTable)
+pub fn get_sctable() -> @SCTable {
+    local_data_key!(sctable_key: @@SCTable)
     match local_data::get(sctable_key, |k| k.map(|k| *k)) {
         None => {
-            let new_table = @@mut new_sctable_internal();
+            let new_table = @@new_sctable_internal();
             local_data::set(sctable_key,new_table);
             *new_table
         },
@@ -785,7 +799,8 @@ pub fn get_sctable() -> @mut SCTable {
 /// print out an SCTable for debugging
 pub fn display_sctable(table : &SCTable) {
     error!("SC table:");
-    for (idx,val) in table.table.iter().enumerate() {
+    let table = table.table.borrow();
+    for (idx,val) in table.get().iter().enumerate() {
         error!("{:4u} : {:?}",idx,val);
     }
 }
@@ -799,7 +814,9 @@ fn idx_push<T>(vec: &mut ~[T], val: T) -> u32 {
 
 /// Resolve a syntax object to a name, per MTWT.
 pub fn mtwt_resolve(id : Ident) -> Name {
-    resolve_internal(id, get_sctable(), get_resolve_table())
+    let resolve_table = get_resolve_table();
+    let mut resolve_table = resolve_table.borrow_mut();
+    resolve_internal(id, get_sctable(), resolve_table.get())
 }
 
 // FIXME #8215: must be pub for testing
@@ -807,12 +824,12 @@ pub type ResolveTable = HashMap<(Name,SyntaxContext),Name>;
 
 // okay, I admit, putting this in TLS is not so nice:
 // fetch the SCTable from TLS, create one if it doesn't yet exist.
-pub fn get_resolve_table() -> @mut ResolveTable {
-    local_data_key!(resolve_table_key: @@mut ResolveTable)
+pub fn get_resolve_table() -> @RefCell<ResolveTable> {
+    local_data_key!(resolve_table_key: @@RefCell<ResolveTable>)
     match local_data::get(resolve_table_key, |k| k.map(|k| *k)) {
         None => {
-            let new_table = @@mut HashMap::new();
-            local_data::set(resolve_table_key,new_table);
+            let new_table = @@RefCell::new(HashMap::new());
+            local_data::set(resolve_table_key, new_table);
             *new_table
         },
         Some(intr) => *intr
@@ -823,13 +840,17 @@ pub fn get_resolve_table() -> @mut ResolveTable {
 // adding memoization to possibly resolve 500+ seconds in resolve for librustc (!)
 // FIXME #8215 : currently pub to allow testing
 pub fn resolve_internal(id : Ident,
-                        table : &mut SCTable,
+                        table : &SCTable,
                         resolve_table : &mut ResolveTable) -> Name {
     let key = (id.name,id.ctxt);
     match resolve_table.contains_key(&key) {
         false => {
             let resolved = {
-                match table.table[id.ctxt] {
+                let result = {
+                    let table = table.table.borrow();
+                    table.get()[id.ctxt]
+                };
+                match result {
                     EmptyCtxt => id.name,
                     // ignore marks here:
                     Mark(_,subctxt) =>
@@ -874,7 +895,11 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
     let mut result = ~[];
     let mut loopvar = ctxt;
     loop {
-        match table.table[loopvar] {
+        let table_entry = {
+            let table = table.table.borrow();
+            table.get()[loopvar]
+        };
+        match table_entry {
             EmptyCtxt => {return result;},
             Mark(mark,tl) => {
                 xorPush(&mut result,mark);
@@ -898,7 +923,8 @@ pub fn marksof(ctxt: SyntaxContext, stopname: Name, table: &SCTable) -> ~[Mrk] {
 /// FAILS when outside is not a mark.
 pub fn mtwt_outer_mark(ctxt: SyntaxContext) -> Mrk {
     let sctable = get_sctable();
-    match sctable.table[ctxt] {
+    let table = sctable.table.borrow();
+    match table.get()[ctxt] {
         ast::Mark(mrk,_) => mrk,
         _ => fail!("can't retrieve outer mark when outside is not a mark")
     }
@@ -1003,7 +1029,7 @@ mod test {
 
     // unfold a vector of TestSC values into a SCTable,
     // returning the resulting index
-    fn unfold_test_sc(tscs : ~[TestSC], tail: SyntaxContext, table : &mut SCTable)
+    fn unfold_test_sc(tscs : ~[TestSC], tail: SyntaxContext, table: &SCTable)
         -> SyntaxContext {
         tscs.rev_iter().fold(tail, |tail : SyntaxContext, tsc : &TestSC|
                   {match *tsc {
@@ -1015,7 +1041,8 @@ mod test {
     fn refold_test_sc(mut sc: SyntaxContext, table : &SCTable) -> ~[TestSC] {
         let mut result = ~[];
         loop {
-            match table.table[sc] {
+            let table = table.table.borrow();
+            match table.get()[sc] {
                 EmptyCtxt => {return result;},
                 Mark(mrk,tail) => {
                     result.push(M(mrk));
@@ -1037,15 +1064,19 @@ mod test {
 
         let test_sc = ~[M(3),R(id(101,0),14),M(9)];
         assert_eq!(unfold_test_sc(test_sc.clone(),EMPTY_CTXT,&mut t),4);
-        assert_eq!(t.table[2],Mark(9,0));
-        assert_eq!(t.table[3],Rename(id(101,0),14,2));
-        assert_eq!(t.table[4],Mark(3,3));
+        {
+            let table = t.table.borrow();
+            assert_eq!(table.get()[2],Mark(9,0));
+            assert_eq!(table.get()[3],Rename(id(101,0),14,2));
+            assert_eq!(table.get()[4],Mark(3,3));
+        }
         assert_eq!(refold_test_sc(4,&t),test_sc);
     }
 
     // extend a syntax context with a sequence of marks given
     // in a vector. v[0] will be the outermost mark.
-    fn unfold_marks(mrks:~[Mrk],tail:SyntaxContext,table: &mut SCTable) -> SyntaxContext {
+    fn unfold_marks(mrks: ~[Mrk], tail: SyntaxContext, table: &SCTable)
+                    -> SyntaxContext {
         mrks.rev_iter().fold(tail, |tail:SyntaxContext, mrk:&Mrk|
                    {new_mark_internal(*mrk,tail,table)})
     }
@@ -1054,8 +1085,11 @@ mod test {
         let mut t = new_sctable_internal();
 
         assert_eq!(unfold_marks(~[3,7],EMPTY_CTXT,&mut t),3);
-        assert_eq!(t.table[2],Mark(7,0));
-        assert_eq!(t.table[3],Mark(3,2));
+        {
+            let table = t.table.borrow();
+            assert_eq!(table.get()[2],Mark(7,0));
+            assert_eq!(table.get()[3],Mark(3,2));
+        }
     }
 
     #[test] fn test_marksof () {
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 7a3ac0f2f4d..df8b45dbcf5 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -355,8 +355,7 @@ pub fn find_stability<AM: AttrMetaMethods, It: Iterator<AM>>(mut metas: It) -> O
     None
 }
 
-pub fn require_unique_names(diagnostic: @mut 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();
@@ -381,7 +380,7 @@ pub fn require_unique_names(diagnostic: @mut SpanHandler,
  * present (before fields, if any) with that type; reprensentation
  * optimizations which would remove it will not be done.
  */
-pub fn find_repr_attr(diagnostic: @mut 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 {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index fffcae0bde3..c0aee7fc634 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -21,6 +21,7 @@ source code snippets, etc.
 
 */
 
+use std::cell::RefCell;
 use std::cmp;
 use extra::serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -220,9 +221,9 @@ pub struct FileMap {
     /// The start position of this source in the CodeMap
     start_pos: BytePos,
     /// Locations of lines beginnings in the source code
-    lines: @mut ~[BytePos],
+    lines: RefCell<~[BytePos]>,
     /// Locations of multi-byte characters in the source code
-    multibyte_chars: @mut ~[MultiByteChar],
+    multibyte_chars: RefCell<~[MultiByteChar]>,
 }
 
 impl FileMap {
@@ -233,14 +234,16 @@ impl FileMap {
     // about what ends a line between this file and parse.rs
     pub fn next_line(&self, pos: BytePos) {
         // the new charpos must be > the last one (or it's the first one).
-        let lines = &mut *self.lines;
-        assert!((lines.len() == 0) || (lines[lines.len() - 1] < pos))
-        lines.push(pos);
+        let mut lines = self.lines.borrow_mut();;
+        let line_len = lines.get().len();
+        assert!(line_len == 0 || (lines.get()[line_len - 1] < pos))
+        lines.get().push(pos);
     }
 
     // get a line from the list of pre-computed line-beginnings
     pub fn get_line(&self, line: int) -> ~str {
-        let begin: BytePos = self.lines[line] - self.start_pos;
+        let mut lines = self.lines.borrow_mut();
+        let begin: BytePos = lines.get()[line] - self.start_pos;
         let begin = begin.to_uint();
         let slice = self.src.slice_from(begin);
         match slice.find('\n') {
@@ -255,7 +258,8 @@ impl FileMap {
             pos: pos,
             bytes: bytes,
         };
-        self.multibyte_chars.push(mbc);
+        let mut multibyte_chars = self.multibyte_chars.borrow_mut();
+        multibyte_chars.get().push(mbc);
     }
 
     pub fn is_real_file(&self) -> bool {
@@ -264,13 +268,13 @@ impl FileMap {
 }
 
 pub struct CodeMap {
-    files: @mut ~[@FileMap]
+    files: RefCell<~[@FileMap]>
 }
 
 impl CodeMap {
     pub fn new() -> CodeMap {
         CodeMap {
-            files: @mut ~[],
+            files: RefCell::new(~[]),
         }
     }
 
@@ -284,23 +288,23 @@ impl CodeMap {
                                 substr: FileSubstr,
                                 src: @str)
                                 -> @FileMap {
-        let files = &mut *self.files;
-        let start_pos = if files.len() == 0 {
+        let mut files = self.files.borrow_mut();
+        let start_pos = if files.get().len() == 0 {
             0
         } else {
-            let last_start = files.last().start_pos.to_uint();
-            let last_len = files.last().src.len();
+            let last_start = files.get().last().start_pos.to_uint();
+            let last_len = files.get().last().src.len();
             last_start + last_len
         };
 
         let filemap = @FileMap {
             name: filename, substr: substr, src: src,
             start_pos: Pos::from_uint(start_pos),
-            lines: @mut ~[],
-            multibyte_chars: @mut ~[],
+            lines: RefCell::new(~[]),
+            multibyte_chars: RefCell::new(~[]),
         };
 
-        files.push(filemap);
+        files.get().push(filemap);
 
         return filemap;
     }
@@ -346,9 +350,11 @@ impl CodeMap {
     }
 
     pub fn span_to_str(&self, sp: Span) -> ~str {
-        let files = &*self.files;
-        if files.len() == 0 && sp == DUMMY_SP {
-            return ~"no-location";
+        {
+            let files = self.files.borrow();
+            if files.get().len() == 0 && sp == DUMMY_SP {
+                return ~"no-location";
+            }
         }
 
         let lo = self.lookup_char_pos_adj(sp.lo);
@@ -388,7 +394,12 @@ impl CodeMap {
     }
 
     pub fn get_filemap(&self, filename: &str) -> @FileMap {
-        for fm in self.files.iter() { if filename == fm.name { return *fm; } }
+        let files = self.files.borrow();
+        for fm in files.get().iter() {
+            if filename == fm.name {
+                return *fm
+            }
+        }
         //XXjdm the following triggers a mismatched type bug
         //      (or expected function, found _|_)
         fail!(); // ("asking for " + filename + " which we don't know about");
@@ -397,13 +408,14 @@ impl CodeMap {
 
 impl CodeMap {
     fn lookup_filemap_idx(&self, pos: BytePos) -> uint {
-        let files = &*self.files;
+        let files = self.files.borrow();
+        let files = files.get();
         let len = files.len();
         let mut a = 0u;
         let mut b = len;
         while b - a > 1u {
             let m = (a + b) / 2u;
-            if self.files[m].start_pos > pos {
+            if files[m].start_pos > pos {
                 b = m;
             } else {
                 a = m;
@@ -419,13 +431,15 @@ impl CodeMap {
     fn lookup_line(&self, pos: BytePos) -> FileMapAndLine
     {
         let idx = self.lookup_filemap_idx(pos);
-        let f = self.files[idx];
+
+        let files = self.files.borrow();
+        let f = files.get()[idx];
         let mut a = 0u;
-        let lines = &*f.lines;
-        let mut b = lines.len();
+        let mut lines = f.lines.borrow_mut();
+        let mut b = lines.get().len();
         while b - a > 1u {
             let m = (a + b) / 2u;
-            if lines[m] > pos { b = m; } else { a = m; }
+            if lines.get()[m] > pos { b = m; } else { a = m; }
         }
         return FileMapAndLine {fm: f, line: a};
     }
@@ -434,7 +448,8 @@ impl CodeMap {
         let FileMapAndLine {fm: f, line: a} = self.lookup_line(pos);
         let line = a + 1u; // Line numbers start at 1
         let chpos = self.bytepos_to_local_charpos(pos);
-        let linebpos = f.lines[a];
+        let mut lines = f.lines.borrow_mut();
+        let linebpos = lines.get()[a];
         let linechpos = self.bytepos_to_local_charpos(linebpos);
         debug!("codemap: byte pos {:?} is on the line at byte pos {:?}",
                pos, linebpos);
@@ -452,7 +467,8 @@ impl CodeMap {
     fn lookup_byte_offset(&self, bpos: BytePos)
         -> FileMapAndBytePos {
         let idx = self.lookup_filemap_idx(bpos);
-        let fm = self.files[idx];
+        let files = self.files.borrow();
+        let fm = files.get()[idx];
         let offset = bpos - fm.start_pos;
         return FileMapAndBytePos {fm: fm, pos: offset};
     }
@@ -462,12 +478,14 @@ impl CodeMap {
     fn bytepos_to_local_charpos(&self, bpos: BytePos) -> CharPos {
         debug!("codemap: converting {:?} to char pos", bpos);
         let idx = self.lookup_filemap_idx(bpos);
-        let map = self.files[idx];
+        let files = self.files.borrow();
+        let map = files.get()[idx];
 
         // The number of extra bytes due to multibyte chars in the FileMap
         let mut total_extra_bytes = 0;
 
-        for mbc in map.multibyte_chars.iter() {
+        let multibyte_chars = map.multibyte_chars.borrow();
+        for mbc in multibyte_chars.get().iter() {
             debug!("codemap: {:?}-byte char at {:?}", mbc.bytes, mbc.pos);
             if mbc.pos < bpos {
                 total_extra_bytes += mbc.bytes;
diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index c905281cdb2..76327c27898 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -11,6 +11,7 @@
 use codemap::{Pos, Span};
 use codemap;
 
+use std::cell::Cell;
 use std::io;
 use std::io::stdio::StdWriter;
 use std::local_data;
@@ -30,32 +31,32 @@ pub trait Emitter {
 // accepts span information for source-location
 // reporting.
 pub struct SpanHandler {
-    handler: @mut Handler,
+    handler: @Handler,
     cm: @codemap::CodeMap,
 }
 
 impl SpanHandler {
-    pub fn span_fatal(@mut self, sp: Span, msg: &str) -> ! {
+    pub fn span_fatal(@self, sp: Span, msg: &str) -> ! {
         self.handler.emit(Some((&*self.cm, sp)), msg, fatal);
         fail!();
     }
-    pub fn span_err(@mut self, sp: Span, msg: &str) {
+    pub fn span_err(@self, sp: Span, msg: &str) {
         self.handler.emit(Some((&*self.cm, sp)), msg, error);
         self.handler.bump_err_count();
     }
-    pub fn span_warn(@mut self, sp: Span, msg: &str) {
+    pub fn span_warn(@self, sp: Span, msg: &str) {
         self.handler.emit(Some((&*self.cm, sp)), msg, warning);
     }
-    pub fn span_note(@mut self, sp: Span, msg: &str) {
+    pub fn span_note(@self, sp: Span, msg: &str) {
         self.handler.emit(Some((&*self.cm, sp)), msg, note);
     }
-    pub fn span_bug(@mut self, sp: Span, msg: &str) -> ! {
+    pub fn span_bug(@self, sp: Span, msg: &str) -> ! {
         self.span_fatal(sp, ice_msg(msg));
     }
-    pub fn span_unimpl(@mut self, sp: Span, msg: &str) -> ! {
+    pub fn span_unimpl(@self, sp: Span, msg: &str) -> ! {
         self.span_bug(sp, ~"unimplemented " + msg);
     }
-    pub fn handler(@mut self) -> @mut Handler {
+    pub fn handler(@self) -> @Handler {
         self.handler
     }
 }
@@ -64,53 +65,53 @@ impl SpanHandler {
 // (fatal, bug, unimpl) may cause immediate exit,
 // others log errors for later reporting.
 pub struct Handler {
-    err_count: uint,
+    err_count: Cell<uint>,
     emit: @Emitter,
 }
 
 impl Handler {
-    pub fn fatal(@mut self, msg: &str) -> ! {
+    pub fn fatal(@self, msg: &str) -> ! {
         self.emit.emit(None, msg, fatal);
         fail!();
     }
-    pub fn err(@mut self, msg: &str) {
+    pub fn err(@self, msg: &str) {
         self.emit.emit(None, msg, error);
         self.bump_err_count();
     }
-    pub fn bump_err_count(@mut self) {
-        self.err_count += 1u;
+    pub fn bump_err_count(@self) {
+        self.err_count.set(self.err_count.get() + 1u);
     }
-    pub fn err_count(@mut self) -> uint {
-        self.err_count
+    pub fn err_count(@self) -> uint {
+        self.err_count.get()
     }
-    pub fn has_errors(@mut self) -> bool {
-        self.err_count > 0u
+    pub fn has_errors(@self) -> bool {
+        self.err_count.get()> 0u
     }
-    pub fn abort_if_errors(@mut self) {
+    pub fn abort_if_errors(@self) {
         let s;
-        match self.err_count {
+        match self.err_count.get() {
           0u => return,
           1u => s = ~"aborting due to previous error",
           _  => {
             s = format!("aborting due to {} previous errors",
-                     self.err_count);
+                     self.err_count.get());
           }
         }
         self.fatal(s);
     }
-    pub fn warn(@mut self, msg: &str) {
+    pub fn warn(@self, msg: &str) {
         self.emit.emit(None, msg, warning);
     }
-    pub fn note(@mut self, msg: &str) {
+    pub fn note(@self, msg: &str) {
         self.emit.emit(None, msg, note);
     }
-    pub fn bug(@mut self, msg: &str) -> ! {
+    pub fn bug(@self, msg: &str) -> ! {
         self.fatal(ice_msg(msg));
     }
-    pub fn unimpl(@mut self, msg: &str) -> ! {
+    pub fn unimpl(@self, msg: &str) -> ! {
         self.bug(~"unimplemented " + msg);
     }
-    pub fn emit(@mut self,
+    pub fn emit(@self,
             cmsp: Option<(&codemap::CodeMap, Span)>,
             msg: &str,
             lvl: level) {
@@ -123,22 +124,22 @@ pub fn ice_msg(msg: &str) -> ~str {
             \nWe would appreciate a bug report: {}", msg, BUG_REPORT_URL)
 }
 
-pub fn mk_span_handler(handler: @mut Handler, cm: @codemap::CodeMap)
-                    -> @mut SpanHandler {
-    @mut SpanHandler {
+pub fn mk_span_handler(handler: @Handler, cm: @codemap::CodeMap)
+                       -> @SpanHandler {
+    @SpanHandler {
         handler: handler,
         cm: cm,
     }
 }
 
-pub fn mk_handler(emitter: Option<@Emitter>) -> @mut Handler {
+pub fn mk_handler(emitter: Option<@Emitter>) -> @Handler {
     let emit: @Emitter = match emitter {
         Some(e) => e,
         None => @DefaultEmitter as @Emitter
     };
 
-    @mut Handler {
-        err_count: 0,
+    @Handler {
+        err_count: Cell::new(0),
         emit: emit,
     }
 }
@@ -327,10 +328,7 @@ fn print_macro_backtrace(cm: &codemap::CodeMap, sp: Span) {
     }
 }
 
-pub fn expect<T:Clone>(
-              diag: @mut SpanHandler,
-              opt: Option<T>,
-              msg: || -> ~str)
+pub fn expect<T:Clone>(diag: @SpanHandler, opt: Option<T>, msg: || -> ~str)
               -> T {
     match opt {
        Some(ref t) => (*t).clone(),
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 03e028ea1f1..b4888f1092f 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -284,7 +284,7 @@ pub fn syntax_expander_table() -> SyntaxEnv {
 // when a macro expansion occurs, the resulting nodes have the backtrace()
 // -> expn_info of their expansion context stored into their span.
 pub struct ExtCtxt {
-    parse_sess: @mut parse::ParseSess,
+    parse_sess: @parse::ParseSess,
     cfg: ast::CrateConfig,
     backtrace: Option<@ExpnInfo>,
 
@@ -293,7 +293,7 @@ pub struct ExtCtxt {
 }
 
 impl ExtCtxt {
-    pub fn new(parse_sess: @mut parse::ParseSess, cfg: ast::CrateConfig)
+    pub fn new(parse_sess: @parse::ParseSess, cfg: ast::CrateConfig)
                -> ExtCtxt {
         ExtCtxt {
             parse_sess: parse_sess,
@@ -320,7 +320,7 @@ impl ExtCtxt {
     }
 
     pub fn codemap(&self) -> @CodeMap { self.parse_sess.cm }
-    pub fn parse_sess(&self) -> @mut parse::ParseSess { self.parse_sess }
+    pub fn parse_sess(&self) -> @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 1a3513ab81c..481472e8f0b 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -54,7 +54,7 @@ pub trait AstBuilder {
                lifetime: Option<ast::Lifetime>,
                mutbl: ast::Mutability) -> P<ast::Ty>;
     fn ty_uniq(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty>;
-    fn ty_box(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty>;
+    fn ty_box(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty>;
 
     fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty>;
     fn ty_infer(&self, sp: Span) -> P<ast::Ty>;
@@ -311,12 +311,13 @@ impl AstBuilder for ExtCtxt {
         self.ty(span,
                 ast::ty_rptr(lifetime, self.ty_mt(ty, mutbl)))
     }
+
     fn ty_uniq(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty> {
         self.ty(span, ast::ty_uniq(ty))
     }
-    fn ty_box(&self, span: Span,
-                 ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> {
-        self.ty(span, ast::ty_box(self.ty_mt(ty, mutbl)))
+
+    fn ty_box(&self, span: Span, ty: P<ast::Ty>) -> P<ast::Ty> {
+        self.ty(span, ast::ty_box(ty))
     }
 
     fn ty_option(&self, ty: P<ast::Ty>) -> P<ast::Ty> {
@@ -494,7 +495,7 @@ impl AstBuilder for ExtCtxt {
     }
 
     fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
-        self.expr_unary(sp, ast::UnBox(ast::MutImmutable), e)
+        self.expr_unary(sp, ast::UnBox, e)
     }
 
     fn expr_field_access(&self, sp: Span, expr: @ast::Expr, ident: ast::Ident) -> @ast::Expr {
diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs
index 10e07520a84..89bed626c1e 100644
--- a/src/libsyntax/ext/deriving/ty.rs
+++ b/src/libsyntax/ext/deriving/ty.rs
@@ -24,7 +24,7 @@ use opt_vec::OptVec;
 /// The types of pointers
 pub enum PtrTy<'a> {
     Send, // ~
-    Managed(ast::Mutability), // @[mut]
+    Managed, // @
     Borrowed(Option<&'a str>, ast::Mutability), // &['lifetime] [mut]
 }
 
@@ -138,8 +138,8 @@ impl<'a> Ty<'a> {
                     Send => {
                         cx.ty_uniq(span, raw_ty)
                     }
-                    Managed(mutbl) => {
-                        cx.ty_box(span, raw_ty, mutbl)
+                    Managed => {
+                        cx.ty_box(span, raw_ty)
                     }
                     Borrowed(ref lt, mutbl) => {
                         let lt = mk_lifetime(cx, span, lt);
@@ -251,7 +251,7 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
                 span,
                 match *ptr {
                     Send => ast::sty_uniq(ast::MutImmutable),
-                    Managed(mutbl) => ast::sty_box(mutbl),
+                    Managed => ast::sty_box(ast::MutImmutable),
                     Borrowed(ref lt, mutbl) => {
                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));
                         ast::sty_region(lt, mutbl)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1d9620d405f..aa7c26805c3 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -493,13 +493,14 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
             let mut name_finder = new_name_finder(~[]);
             name_finder.visit_pat(expanded_pat,());
             // generate fresh names, push them to a new pending list
-            let new_pending_renames = @mut ~[];
+            let mut new_pending_renames = ~[];
             for ident in name_finder.ident_accumulator.iter() {
                 let new_name = fresh_name(ident);
                 new_pending_renames.push((*ident,new_name));
             }
             let rewritten_pat = {
-                let mut rename_fld = renames_to_fold(new_pending_renames);
+                let mut rename_fld =
+                    renames_to_fold(&mut new_pending_renames);
                 // rewrite the pattern using the new names (the old ones
                 // have already been applied):
                 rename_fld.fold_pat(expanded_pat)
@@ -889,7 +890,7 @@ impl ast_fold for Injector {
 
 // add a bunch of macros as though they were placed at the head of the
 // program (ick). This should run before cfg stripping.
-pub fn inject_std_macros(parse_sess: @mut parse::ParseSess,
+pub fn inject_std_macros(parse_sess: @parse::ParseSess,
                          cfg: ast::CrateConfig,
                          c: Crate)
                          -> Crate {
@@ -939,7 +940,7 @@ impl<'a> ast_fold for MacroExpander<'a> {
     }
 }
 
-pub fn expand_crate(parse_sess: @mut parse::ParseSess,
+pub fn expand_crate(parse_sess: @parse::ParseSess,
                     cfg: ast::CrateConfig,
                     c: Crate) -> Crate {
     let mut cx = ExtCtxt::new(parse_sess, cfg.clone());
@@ -981,21 +982,6 @@ impl CtxtFn for Renamer {
     }
 }
 
-// a renamer that performs a whole bunch of renames
-pub struct MultiRenamer {
-    renames : @mut ~[(ast::Ident,ast::Name)]
-}
-
-impl CtxtFn for MultiRenamer {
-    fn f(&self, starting_ctxt : ast::SyntaxContext) -> ast::SyntaxContext {
-        // the individual elements are memoized... it would
-        // also be possible to memoize on the whole list at once.
-        self.renames.iter().fold(starting_ctxt,|ctxt,&(from,to)| {
-            new_rename(from,to,ctxt)
-        })
-    }
-}
-
 // a marker adds the given mark to the syntax context
 pub struct Marker { mark : Mrk }
 
@@ -1306,9 +1292,11 @@ mod test {
         let a3_name = gensym("a3");
         // a context that renames from ("a",empty) to "a2" :
         let ctxt2 = new_rename(ast::Ident::new(a_name),a2_name,EMPTY_CTXT);
-        let pending_renames = @mut ~[(ast::Ident::new(a_name),a2_name),
-                                     (ast::Ident{name:a_name,ctxt:ctxt2},a3_name)];
-        let double_renamed = renames_to_fold(pending_renames).fold_crate(item_ast);
+        let mut pending_renames = ~[
+            (ast::Ident::new(a_name),a2_name),
+            (ast::Ident{name:a_name,ctxt:ctxt2},a3_name)
+        ];
+        let double_renamed = renames_to_fold(&mut pending_renames).fold_crate(item_ast);
         let mut path_finder = new_path_finder(~[]);
         visit::walk_crate(&mut path_finder, &double_renamed, ());
         match path_finder.path_accumulator {
@@ -1318,11 +1306,11 @@ mod test {
         }
     }
 
-    fn fake_print_crate(crate: &ast::Crate) {
-        let out = @mut std::io::stderr() as @mut std::io::Writer;
-        let s = pprust::rust_printer(out, get_ident_interner());
-        pprust::print_crate_(s, crate);
-    }
+    //fn fake_print_crate(crate: &ast::Crate) {
+    //    let mut out = ~std::io::stderr() as ~std::io::Writer;
+    //    let mut s = pprust::rust_printer(out, get_ident_interner());
+    //    pprust::print_crate_(&mut s, crate);
+    //}
 
     fn expand_crate_str(crate_str: @str) -> ast::Crate {
         let (crate_ast,ps) = string_to_crate_and_sess(crate_str);
@@ -1516,8 +1504,12 @@ foo_module!()
                          mtwt_resolve(v.segments[0].identifier));
                 let table = get_sctable();
                 println("SC table:");
-                for (idx,val) in table.table.iter().enumerate() {
-                    println!("{:4u} : {:?}",idx,val);
+
+                {
+                    let table = table.table.borrow();
+                    for (idx,val) in table.get().iter().enumerate() {
+                        println!("{:4u} : {:?}",idx,val);
+                    }
                 }
             }
             assert_eq!(mtwt_resolve(v.segments[0].identifier),resolved_binding);
diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs
index 11e7c1c8499..5f634f7f054 100644
--- a/src/libsyntax/ext/source_util.rs
+++ b/src/libsyntax/ext/source_util.rs
@@ -19,6 +19,7 @@ use parse;
 use parse::token::{get_ident_interner};
 use print::pprust;
 
+use std::cell::RefCell;
 use std::io;
 use std::io::File;
 use std::str;
@@ -108,13 +109,14 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::token_tree])
             let s = s.to_managed();
             // Add this input file to the code map to make it available as
             // dependency information
-            cx.parse_sess.cm.files.push(@codemap::FileMap {
+            let mut files = cx.parse_sess.cm.files.borrow_mut();
+            files.get().push(@codemap::FileMap {
                 name: file.display().to_str().to_managed(),
                 substr: codemap::FssNone,
                 src: s,
                 start_pos: codemap::BytePos(0),
-                lines: @mut ~[],
-                multibyte_chars: @mut ~[],
+                lines: RefCell::new(~[]),
+                multibyte_chars: RefCell::new(~[]),
             });
             base::MRExpr(cx.expr_str(sp, s))
         }
diff --git a/src/libsyntax/ext/trace_macros.rs b/src/libsyntax/ext/trace_macros.rs
index 34151377d7b..a7d1d8fb366 100644
--- a/src/libsyntax/ext/trace_macros.rs
+++ b/src/libsyntax/ext/trace_macros.rs
@@ -25,7 +25,7 @@ pub fn expand_trace_macros(cx: &mut ExtCtxt,
     let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
                                None,
                                tt.to_owned());
-    let rdr = tt_rdr as @mut reader;
+    let rdr = tt_rdr as @reader;
     let mut rust_parser = Parser(sess, cfg.clone(), rdr.dup());
 
     if rust_parser.is_keyword(keywords::True) {
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs
index 4d2923f391e..8b22e32262b 100644
--- a/src/libsyntax/ext/tt/macro_parser.rs
+++ b/src/libsyntax/ext/tt/macro_parser.rs
@@ -188,9 +188,9 @@ pub enum named_match {
 
 pub type earley_item = ~MatcherPos;
 
-pub fn nameize(p_s: @mut ParseSess, ms: &[matcher], res: &[@named_match])
+pub fn nameize(p_s: @ParseSess, ms: &[matcher], res: &[@named_match])
             -> HashMap<Ident,@named_match> {
-    fn n_rec(p_s: @mut ParseSess, m: &matcher, res: &[@named_match],
+    fn n_rec(p_s: @ParseSess, m: &matcher, res: &[@named_match],
              ret_val: &mut HashMap<Ident, @named_match>) {
         match *m {
           codemap::Spanned {node: match_tok(_), .. } => (),
@@ -221,12 +221,11 @@ pub enum parse_result {
     error(codemap::Span, ~str)
 }
 
-pub fn parse_or_else(
-    sess: @mut ParseSess,
-    cfg: ast::CrateConfig,
-    rdr: @mut reader,
-    ms: ~[matcher]
-) -> HashMap<Ident, @named_match> {
+pub fn parse_or_else(sess: @ParseSess,
+                     cfg: ast::CrateConfig,
+                     rdr: @reader,
+                     ms: ~[matcher])
+                     -> HashMap<Ident, @named_match> {
     match parse(sess, cfg, rdr, ms) {
       success(m) => m,
       failure(sp, str) => sess.span_diagnostic.span_fatal(sp, str),
@@ -243,12 +242,11 @@ pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
     }
 }
 
-pub fn parse(
-    sess: @mut ParseSess,
-    cfg: ast::CrateConfig,
-    rdr: @mut reader,
-    ms: &[matcher]
-) -> parse_result {
+pub fn parse(sess: @ParseSess,
+             cfg: ast::CrateConfig,
+             rdr: @reader,
+             ms: &[matcher])
+             -> parse_result {
     let mut cur_eis = ~[];
     cur_eis.push(initial_matcher_pos(ms.to_owned(), None, rdr.peek().sp.lo));
 
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index c9827fb54bd..32d9ed1238b 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -130,11 +130,7 @@ fn generic_extension(cx: &ExtCtxt,
         match *lhs {
           @matched_nonterminal(nt_matchers(ref mtcs)) => {
             // `none` is because we're not interpolating
-            let arg_rdr = new_tt_reader(
-                s_d,
-                None,
-                arg.to_owned()
-            ) as @mut reader;
+            let arg_rdr = new_tt_reader(s_d, None, arg.to_owned()) as @reader;
             match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
               success(named_matches) => {
                 let rhs = match rhses[i] {
@@ -154,10 +150,7 @@ fn generic_extension(cx: &ExtCtxt,
                 // rhs has holes ( `$id` and `$(...)` that need filled)
                 let trncbr = new_tt_reader(s_d, Some(named_matches),
                                            rhs);
-                let p = Parser(cx.parse_sess(),
-                               cx.cfg(),
-                               trncbr as @mut reader);
-
+                let p = Parser(cx.parse_sess(), cx.cfg(), trncbr as @reader);
                 // Let the context choose how to interpret the result.
                 // Weird, but useful for X-macros.
                 return MRAny(@ParserAnyMacro {
@@ -218,7 +211,7 @@ pub fn add_new_extension(cx: &mut ExtCtxt,
                                    arg.clone());
     let argument_map = parse_or_else(cx.parse_sess(),
                                      cx.cfg(),
-                                     arg_reader as @mut reader,
+                                     arg_reader as @reader,
                                      argument_gram);
 
     // Extract the arguments:
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index cbce5fb16cb..060f6b8a8b9 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -17,65 +17,66 @@ use parse::token::{EOF, INTERPOLATED, IDENT, Token, nt_ident};
 use parse::token::{ident_to_str};
 use parse::lexer::TokenAndSpan;
 
+use std::cell::{Cell, RefCell};
 use std::hashmap::HashMap;
 use std::option;
 
 ///an unzipping of `token_tree`s
 struct TtFrame {
     forest: @~[ast::token_tree],
-    idx: uint,
+    idx: Cell<uint>,
     dotdotdoted: bool,
     sep: Option<Token>,
-    up: Option<@mut TtFrame>,
+    up: Option<@TtFrame>,
 }
 
 pub struct TtReader {
-    sp_diag: @mut SpanHandler,
+    sp_diag: @SpanHandler,
     // the unzipped tree:
-    stack: @mut TtFrame,
+    priv stack: RefCell<@TtFrame>,
     /* for MBE-style macro transcription */
-    interpolations: HashMap<Ident, @named_match>,
-    repeat_idx: ~[uint],
-    repeat_len: ~[uint],
+    priv interpolations: RefCell<HashMap<Ident, @named_match>>,
+    priv repeat_idx: RefCell<~[uint]>,
+    priv repeat_len: RefCell<~[uint]>,
     /* cached: */
-    cur_tok: Token,
-    cur_span: Span
+    cur_tok: RefCell<Token>,
+    cur_span: RefCell<Span>,
 }
 
 /** This can do Macro-By-Example transcription. On the other hand, if
  *  `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and
  *  should) be none. */
-pub fn new_tt_reader(sp_diag: @mut SpanHandler,
+pub fn new_tt_reader(sp_diag: @SpanHandler,
                      interp: Option<HashMap<Ident,@named_match>>,
                      src: ~[ast::token_tree])
-                  -> @mut TtReader {
-    let r = @mut TtReader {
+                     -> @TtReader {
+    let r = @TtReader {
         sp_diag: sp_diag,
-        stack: @mut TtFrame {
+        stack: RefCell::new(@TtFrame {
             forest: @src,
-            idx: 0u,
+            idx: Cell::new(0u),
             dotdotdoted: false,
             sep: None,
             up: option::None
-        },
+        }),
         interpolations: match interp { /* just a convienience */
-            None => HashMap::new(),
-            Some(x) => x
+            None => RefCell::new(HashMap::new()),
+            Some(x) => RefCell::new(x),
         },
-        repeat_idx: ~[],
-        repeat_len: ~[],
+        repeat_idx: RefCell::new(~[]),
+        repeat_len: RefCell::new(~[]),
         /* dummy values, never read: */
-        cur_tok: EOF,
-        cur_span: DUMMY_SP
+        cur_tok: RefCell::new(EOF),
+        cur_span: RefCell::new(DUMMY_SP),
     };
     tt_next_token(r); /* get cur_tok and cur_span set up */
     return r;
 }
 
-fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame {
-    @mut TtFrame {
+fn dup_tt_frame(f: @TtFrame) -> @TtFrame {
+    @TtFrame {
         forest: @(*f.forest).clone(),
-        idx: f.idx,
+        idx: f.idx.clone(),
         dotdotdoted: f.dotdotdoted,
         sep: f.sep.clone(),
         up: match f.up {
@@ -85,22 +86,21 @@ fn dup_tt_frame(f: @mut TtFrame) -> @mut TtFrame {
     }
 }
 
-pub fn dup_tt_reader(r: @mut TtReader) -> @mut TtReader {
-    @mut TtReader {
+pub fn dup_tt_reader(r: @TtReader) -> @TtReader {
+    @TtReader {
         sp_diag: r.sp_diag,
-        stack: dup_tt_frame(r.stack),
+        stack: RefCell::new(dup_tt_frame(r.stack.get())),
         repeat_idx: r.repeat_idx.clone(),
         repeat_len: r.repeat_len.clone(),
         cur_tok: r.cur_tok.clone(),
-        cur_span: r.cur_span,
+        cur_span: r.cur_span.clone(),
         interpolations: r.interpolations.clone(),
     }
 }
 
 
-fn lookup_cur_matched_by_matched(r: &mut TtReader,
-                                      start: @named_match)
-                                   -> @named_match {
+fn lookup_cur_matched_by_matched(r: &TtReader, start: @named_match)
+                                 -> @named_match {
     fn red(ad: @named_match, idx: &uint) -> @named_match {
         match *ad {
           matched_nonterminal(_) => {
@@ -110,15 +110,21 @@ fn lookup_cur_matched_by_matched(r: &mut TtReader,
           matched_seq(ref ads, _) => ads[*idx]
         }
     }
-    r.repeat_idx.iter().fold(start, red)
+    let repeat_idx = r.repeat_idx.borrow();
+    repeat_idx.get().iter().fold(start, red)
 }
 
-fn lookup_cur_matched(r: &mut TtReader, name: Ident) -> @named_match {
-    match r.interpolations.find_copy(&name) {
+fn lookup_cur_matched(r: &TtReader, name: Ident) -> @named_match {
+    let matched_opt = {
+        let interpolations = r.interpolations.borrow();
+        interpolations.get().find_copy(&name)
+    };
+    match matched_opt {
         Some(s) => lookup_cur_matched_by_matched(r, s),
         None => {
-            r.sp_diag.span_fatal(r.cur_span, format!("unknown macro variable `{}`",
-                                                  ident_to_str(&name)));
+            r.sp_diag.span_fatal(r.cur_span.get(),
+                                 format!("unknown macro variable `{}`",
+                                         ident_to_str(&name)));
         }
     }
 }
@@ -130,7 +136,7 @@ enum lis {
     lis_contradiction(~str),
 }
 
-fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
+fn lockstep_iter_size(t: &token_tree, r: &TtReader) -> lis {
     fn lis_merge(lhs: lis, rhs: lis) -> lis {
         match lhs {
           lis_unconstrained => rhs.clone(),
@@ -166,46 +172,56 @@ fn lockstep_iter_size(t: &token_tree, r: &mut TtReader) -> lis {
 
 // return the next token from the TtReader.
 // EFFECT: advances the reader's token field
-pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
+pub fn tt_next_token(r: &TtReader) -> TokenAndSpan {
     // XXX(pcwalton): Bad copy?
     let ret_val = TokenAndSpan {
-        tok: r.cur_tok.clone(),
-        sp: r.cur_span,
+        tok: r.cur_tok.get(),
+        sp: r.cur_span.get(),
     };
     loop {
         {
-            let stack = &mut *r.stack;
-            if stack.idx < stack.forest.len() {
+            let mut stack = r.stack.borrow_mut();
+            if stack.get().idx.get() < stack.get().forest.len() {
                 break;
             }
         }
 
         /* done with this set; pop or repeat? */
-        if ! r.stack.dotdotdoted
-            || { *r.repeat_idx.last() == *r.repeat_len.last() - 1 } {
+        if !r.stack.get().dotdotdoted || {
+                let repeat_idx = r.repeat_idx.borrow();
+                let repeat_len = r.repeat_len.borrow();
+                *repeat_idx.get().last() == *repeat_len.get().last() - 1
+            } {
 
-            match r.stack.up {
+            match r.stack.get().up {
               None => {
-                r.cur_tok = EOF;
+                r.cur_tok.set(EOF);
                 return ret_val;
               }
               Some(tt_f) => {
-                if r.stack.dotdotdoted {
-                    r.repeat_idx.pop();
-                    r.repeat_len.pop();
+                if r.stack.get().dotdotdoted {
+                    {
+                        let mut repeat_idx = r.repeat_idx.borrow_mut();
+                        let mut repeat_len = r.repeat_len.borrow_mut();
+                        repeat_idx.get().pop();
+                        repeat_len.get().pop();
+                    }
                 }
 
-                r.stack = tt_f;
-                r.stack.idx += 1u;
+                r.stack.set(tt_f);
+                r.stack.get().idx.set(r.stack.get().idx.get() + 1u);
               }
             }
 
         } else { /* repeat */
-            r.stack.idx = 0u;
-            r.repeat_idx[r.repeat_idx.len() - 1u] += 1u;
-            match r.stack.sep.clone() {
+            r.stack.get().idx.set(0u);
+            {
+                let mut repeat_idx = r.repeat_idx.borrow_mut();
+                repeat_idx.get()[repeat_idx.get().len() - 1u] += 1u;
+            }
+            match r.stack.get().sep.clone() {
               Some(tk) => {
-                r.cur_tok = tk; /* repeat same span, I guess */
+                r.cur_tok.set(tk); /* repeat same span, I guess */
                 return ret_val;
               }
               None => ()
@@ -215,21 +231,21 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
     loop { /* because it's easiest, this handles `tt_delim` not starting
     with a `tt_tok`, even though it won't happen */
         // XXX(pcwalton): Bad copy.
-        match r.stack.forest[r.stack.idx].clone() {
+        match r.stack.get().forest[r.stack.get().idx.get()].clone() {
           tt_delim(tts) => {
-            r.stack = @mut TtFrame {
+            r.stack.set(@TtFrame {
                 forest: tts,
-                idx: 0u,
+                idx: Cell::new(0u),
                 dotdotdoted: false,
                 sep: None,
-                up: option::Some(r.stack)
-            };
+                up: option::Some(r.stack.get())
+            });
             // if this could be 0-length, we'd need to potentially recur here
           }
           tt_tok(sp, tok) => {
-            r.cur_span = sp;
-            r.cur_tok = tok;
-            r.stack.idx += 1u;
+            r.cur_span.set(sp);
+            r.cur_tok.set(tok);
+            r.stack.get().idx.set(r.stack.get().idx.get() + 1u);
             return ret_val;
           }
           tt_seq(sp, tts, sep, zerok) => {
@@ -256,18 +272,22 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
                                               once");
                           }
 
-                    r.stack.idx += 1u;
+                    r.stack.get().idx.set(r.stack.get().idx.get() + 1u);
                     return tt_next_token(r);
                 } else {
-                    r.repeat_len.push(len);
-                    r.repeat_idx.push(0u);
-                    r.stack = @mut TtFrame {
-                        forest: tts,
-                        idx: 0u,
-                        dotdotdoted: true,
-                        sep: sep,
-                        up: Some(r.stack)
-                    };
+                    {
+                        let mut repeat_idx = r.repeat_idx.borrow_mut();
+                        let mut repeat_len = r.repeat_len.borrow_mut();
+                        repeat_len.get().push(len);
+                        repeat_idx.get().push(0u);
+                        r.stack.set(@TtFrame {
+                            forest: tts,
+                            idx: Cell::new(0u),
+                            dotdotdoted: true,
+                            sep: sep,
+                            up: Some(r.stack.get())
+                        });
+                    }
                 }
               }
             }
@@ -279,20 +299,21 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
               (a) idents can be in lots of places, so it'd be a pain
               (b) we actually can, since it's a token. */
               matched_nonterminal(nt_ident(~sn,b)) => {
-                r.cur_span = sp; r.cur_tok = IDENT(sn,b);
-                r.stack.idx += 1u;
+                r.cur_span.set(sp);
+                r.cur_tok.set(IDENT(sn,b));
+                r.stack.get().idx.set(r.stack.get().idx.get() + 1u);
                 return ret_val;
               }
               matched_nonterminal(ref other_whole_nt) => {
                 // XXX(pcwalton): Bad copy.
-                r.cur_span = sp;
-                r.cur_tok = INTERPOLATED((*other_whole_nt).clone());
-                r.stack.idx += 1u;
+                r.cur_span.set(sp);
+                r.cur_tok.set(INTERPOLATED((*other_whole_nt).clone()));
+                r.stack.get().idx.set(r.stack.get().idx.get() + 1u);
                 return ret_val;
               }
               matched_seq(..) => {
                 r.sp_diag.span_fatal(
-                    r.cur_span, /* blame the macro writer */
+                    r.cur_span.get(), /* blame the macro writer */
                     format!("variable '{}' is still repeating at this depth",
                          ident_to_str(&ident)));
               }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 4a2adc04fbd..47130a8e355 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -238,7 +238,7 @@ pub trait ast_fold {
     fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
         let node = match t.node {
             ty_nil | ty_bot | ty_infer => t.node.clone(),
-            ty_box(ref mt) => ty_box(fold_mt(mt, self)),
+            ty_box(ty) => ty_box(self.fold_ty(ty)),
             ty_uniq(ty) => ty_uniq(self.fold_ty(ty)),
             ty_vec(ty) => ty_vec(self.fold_ty(ty)),
             ty_ptr(ref mt) => ty_ptr(fold_mt(mt, self)),
@@ -866,7 +866,7 @@ mod test {
     use super::*;
 
     // this version doesn't care about getting comments or docstrings in.
-    fn fake_print_crate(s: @pprust::ps, crate: &ast::Crate) {
+    fn fake_print_crate(s: &mut pprust::ps, crate: &ast::Crate) {
         pprust::print_mod(s, &crate.module, crate.attrs);
     }
 
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index b1390253d19..e0ab7f1535d 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -135,39 +135,44 @@ pub fn strip_doc_comment_decoration(comment: &str) -> ~str {
     fail!("not a doc-comment: {}", comment);
 }
 
-fn read_to_eol(rdr: @mut StringReader) -> ~str {
+fn read_to_eol(rdr: @StringReader) -> ~str {
     let mut val = ~"";
-    while rdr.curr != '\n' && !is_eof(rdr) {
-        val.push_char(rdr.curr);
+    while rdr.curr.get() != '\n' && !is_eof(rdr) {
+        val.push_char(rdr.curr.get());
         bump(rdr);
     }
-    if rdr.curr == '\n' { bump(rdr); }
+    if rdr.curr.get() == '\n' { bump(rdr); }
     return val;
 }
 
-fn read_one_line_comment(rdr: @mut StringReader) -> ~str {
+fn read_one_line_comment(rdr: @StringReader) -> ~str {
     let val = read_to_eol(rdr);
     assert!((val[0] == '/' as u8 && val[1] == '/' as u8) ||
                  (val[0] == '#' as u8 && val[1] == '!' as u8));
     return val;
 }
 
-fn consume_non_eol_whitespace(rdr: @mut StringReader) {
-    while is_whitespace(rdr.curr) && rdr.curr != '\n' && !is_eof(rdr) {
+fn consume_non_eol_whitespace(rdr: @StringReader) {
+    while is_whitespace(rdr.curr.get()) && rdr.curr.get() != '\n' &&
+            !is_eof(rdr) {
         bump(rdr);
     }
 }
 
-fn push_blank_line_comment(rdr: @mut StringReader, comments: &mut ~[cmnt]) {
+fn push_blank_line_comment(rdr: @StringReader, comments: &mut ~[cmnt]) {
     debug!(">>> blank-line comment");
     let v: ~[~str] = ~[];
-    comments.push(cmnt {style: blank_line, lines: v, pos: rdr.last_pos});
+    comments.push(cmnt {
+        style: blank_line,
+        lines: v,
+        pos: rdr.last_pos.get(),
+    });
 }
 
-fn consume_whitespace_counting_blank_lines(rdr: @mut StringReader,
+fn consume_whitespace_counting_blank_lines(rdr: @StringReader,
                                            comments: &mut ~[cmnt]) {
-    while is_whitespace(rdr.curr) && !is_eof(rdr) {
-        if rdr.col == CharPos(0u) && rdr.curr == '\n' {
+    while is_whitespace(rdr.curr.get()) && !is_eof(rdr) {
+        if rdr.col.get() == CharPos(0u) && rdr.curr.get() == '\n' {
             push_blank_line_comment(rdr, &mut *comments);
         }
         bump(rdr);
@@ -175,10 +180,10 @@ fn consume_whitespace_counting_blank_lines(rdr: @mut StringReader,
 }
 
 
-fn read_shebang_comment(rdr: @mut StringReader, code_to_the_left: bool,
+fn read_shebang_comment(rdr: @StringReader, code_to_the_left: bool,
                                             comments: &mut ~[cmnt]) {
     debug!(">>> shebang comment");
-    let p = rdr.last_pos;
+    let p = rdr.last_pos.get();
     debug!("<<< shebang comment");
     comments.push(cmnt {
         style: if code_to_the_left { trailing } else { isolated },
@@ -187,12 +192,12 @@ fn read_shebang_comment(rdr: @mut StringReader, code_to_the_left: bool,
     });
 }
 
-fn read_line_comments(rdr: @mut StringReader, code_to_the_left: bool,
+fn read_line_comments(rdr: @StringReader, code_to_the_left: bool,
                                           comments: &mut ~[cmnt]) {
     debug!(">>> line comments");
-    let p = rdr.last_pos;
+    let p = rdr.last_pos.get();
     let mut lines: ~[~str] = ~[];
-    while rdr.curr == '/' && nextch(rdr) == '/' {
+    while rdr.curr.get() == '/' && nextch(rdr) == '/' {
         let line = read_one_line_comment(rdr);
         debug!("{}", line);
         if is_doc_comment(line) { // doc-comments are not put in comments
@@ -244,22 +249,22 @@ fn trim_whitespace_prefix_and_push_line(lines: &mut ~[~str],
     lines.push(s1);
 }
 
-fn read_block_comment(rdr: @mut StringReader,
+fn read_block_comment(rdr: @StringReader,
                       code_to_the_left: bool,
                       comments: &mut ~[cmnt]) {
     debug!(">>> block comment");
-    let p = rdr.last_pos;
+    let p = rdr.last_pos.get();
     let mut lines: ~[~str] = ~[];
-    let col: CharPos = rdr.col;
+    let col: CharPos = rdr.col.get();
     bump(rdr);
     bump(rdr);
 
     let mut curr_line = ~"/*";
 
     // doc-comments are not really comments, they are attributes
-    if rdr.curr == '*' || rdr.curr == '!' {
-        while !(rdr.curr == '*' && nextch(rdr) == '/') && !is_eof(rdr) {
-            curr_line.push_char(rdr.curr);
+    if rdr.curr.get() == '*' || rdr.curr.get() == '!' {
+        while !(rdr.curr.get() == '*' && nextch(rdr) == '/') && !is_eof(rdr) {
+            curr_line.push_char(rdr.curr.get());
             bump(rdr);
         }
         if !is_eof(rdr) {
@@ -275,22 +280,22 @@ fn read_block_comment(rdr: @mut StringReader,
         while level > 0 {
             debug!("=== block comment level {}", level);
             if is_eof(rdr) {
-                (rdr as @mut reader).fatal(~"unterminated block comment");
+                (rdr as @reader).fatal(~"unterminated block comment");
             }
-            if rdr.curr == '\n' {
+            if rdr.curr.get() == '\n' {
                 trim_whitespace_prefix_and_push_line(&mut lines, curr_line,
                                                      col);
                 curr_line = ~"";
                 bump(rdr);
             } else {
-                curr_line.push_char(rdr.curr);
-                if rdr.curr == '/' && nextch(rdr) == '*' {
+                curr_line.push_char(rdr.curr.get());
+                if rdr.curr.get() == '/' && nextch(rdr) == '*' {
                     bump(rdr);
                     bump(rdr);
                     curr_line.push_char('*');
                     level += 1;
                 } else {
-                    if rdr.curr == '*' && nextch(rdr) == '/' {
+                    if rdr.curr.get() == '*' && nextch(rdr) == '/' {
                         bump(rdr);
                         bump(rdr);
                         curr_line.push_char('/');
@@ -306,28 +311,28 @@ fn read_block_comment(rdr: @mut StringReader,
 
     let mut style = if code_to_the_left { trailing } else { isolated };
     consume_non_eol_whitespace(rdr);
-    if !is_eof(rdr) && rdr.curr != '\n' && lines.len() == 1u {
+    if !is_eof(rdr) && rdr.curr.get() != '\n' && lines.len() == 1u {
         style = mixed;
     }
     debug!("<<< block comment");
     comments.push(cmnt {style: style, lines: lines, pos: p});
 }
 
-fn peeking_at_comment(rdr: @mut StringReader) -> bool {
-    return ((rdr.curr == '/' && nextch(rdr) == '/') ||
-         (rdr.curr == '/' && nextch(rdr) == '*')) ||
-         (rdr.curr == '#' && nextch(rdr) == '!');
+fn peeking_at_comment(rdr: @StringReader) -> bool {
+    return ((rdr.curr.get() == '/' && nextch(rdr) == '/') ||
+         (rdr.curr.get() == '/' && nextch(rdr) == '*')) ||
+         (rdr.curr.get() == '#' && nextch(rdr) == '!');
 }
 
-fn consume_comment(rdr: @mut StringReader,
+fn consume_comment(rdr: @StringReader,
                    code_to_the_left: bool,
                    comments: &mut ~[cmnt]) {
     debug!(">>> consume comment");
-    if rdr.curr == '/' && nextch(rdr) == '/' {
+    if rdr.curr.get() == '/' && nextch(rdr) == '/' {
         read_line_comments(rdr, code_to_the_left, comments);
-    } else if rdr.curr == '/' && nextch(rdr) == '*' {
+    } else if rdr.curr.get() == '/' && nextch(rdr) == '*' {
         read_block_comment(rdr, code_to_the_left, comments);
-    } else if rdr.curr == '#' && nextch(rdr) == '!' {
+    } else if rdr.curr.get() == '#' && nextch(rdr) == '!' {
         read_shebang_comment(rdr, code_to_the_left, comments);
     } else { fail!(); }
     debug!("<<< consume comment");
@@ -342,7 +347,7 @@ pub struct lit {
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
 pub fn gather_comments_and_literals(span_diagnostic:
-                                    @mut diagnostic::SpanHandler,
+                                        @diagnostic::SpanHandler,
                                     path: @str,
                                     srdr: &mut io::Reader)
                                  -> (~[cmnt], ~[lit]) {
@@ -358,7 +363,7 @@ pub fn gather_comments_and_literals(span_diagnostic:
         loop {
             let mut code_to_the_left = !first_read;
             consume_non_eol_whitespace(rdr);
-            if rdr.curr == '\n' {
+            if rdr.curr.get() == '\n' {
                 code_to_the_left = false;
                 consume_whitespace_counting_blank_lines(rdr, &mut comments);
             }
@@ -370,7 +375,7 @@ pub fn gather_comments_and_literals(span_diagnostic:
         }
 
 
-        let bstart = rdr.last_pos;
+        let bstart = rdr.last_pos.get();
         rdr.next_token();
         //discard, and look ahead; we're working with internal state
         let TokenAndSpan {tok: tok, sp: sp} = rdr.peek();
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index be93c962137..3b81b09112b 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -18,6 +18,7 @@ use parse::token;
 use parse::token::{str_to_ident};
 
 use std::cast::transmute;
+use std::cell::{Cell, RefCell};
 use std::char;
 use std::num::from_str_radix;
 use std::util;
@@ -25,12 +26,12 @@ use std::util;
 pub use ext::tt::transcribe::{TtReader, new_tt_reader};
 
 pub trait reader {
-    fn is_eof(@mut self) -> bool;
-    fn next_token(@mut self) -> TokenAndSpan;
-    fn fatal(@mut self, ~str) -> !;
-    fn span_diag(@mut self) -> @mut SpanHandler;
-    fn peek(@mut self) -> TokenAndSpan;
-    fn dup(@mut self) -> @mut reader;
+    fn is_eof(@self) -> bool;
+    fn next_token(@self) -> TokenAndSpan;
+    fn fatal(@self, ~str) -> !;
+    fn span_diag(@self) -> @SpanHandler;
+    fn peek(@self) -> TokenAndSpan;
+    fn dup(@self) -> @reader;
 }
 
 #[deriving(Clone, Eq)]
@@ -40,47 +41,47 @@ pub struct TokenAndSpan {
 }
 
 pub struct StringReader {
-    span_diagnostic: @mut SpanHandler,
+    span_diagnostic: @SpanHandler,
     src: @str,
     // The absolute offset within the codemap of the next character to read
-    pos: BytePos,
+    pos: Cell<BytePos>,
     // The absolute offset within the codemap of the last character read(curr)
-    last_pos: BytePos,
+    last_pos: Cell<BytePos>,
     // The column of the next character to read
-    col: CharPos,
+    col: Cell<CharPos>,
     // The last character to be read
-    curr: char,
+    curr: Cell<char>,
     filemap: @codemap::FileMap,
     /* cached: */
-    peek_tok: token::Token,
-    peek_span: Span
+    peek_tok: RefCell<token::Token>,
+    peek_span: RefCell<Span>,
 }
 
-pub fn new_string_reader(span_diagnostic: @mut SpanHandler,
+pub fn new_string_reader(span_diagnostic: @SpanHandler,
                          filemap: @codemap::FileMap)
-                      -> @mut StringReader {
+                      -> @StringReader {
     let r = new_low_level_string_reader(span_diagnostic, filemap);
     string_advance_token(r); /* fill in peek_* */
     return r;
 }
 
 /* For comments.rs, which hackily pokes into 'pos' and 'curr' */
-pub fn new_low_level_string_reader(span_diagnostic: @mut SpanHandler,
+pub fn new_low_level_string_reader(span_diagnostic: @SpanHandler,
                                    filemap: @codemap::FileMap)
-                                -> @mut StringReader {
+                                -> @StringReader {
     // Force the initial reader bump to start on a fresh line
     let initial_char = '\n';
-    let r = @mut StringReader {
+    let r = @StringReader {
         span_diagnostic: span_diagnostic,
         src: filemap.src,
-        pos: filemap.start_pos,
-        last_pos: filemap.start_pos,
-        col: CharPos(0),
-        curr: initial_char,
+        pos: Cell::new(filemap.start_pos),
+        last_pos: Cell::new(filemap.start_pos),
+        col: Cell::new(CharPos(0)),
+        curr: Cell::new(initial_char),
         filemap: filemap,
         /* dummy values; not read */
-        peek_tok: token::EOF,
-        peek_span: codemap::DUMMY_SP
+        peek_tok: RefCell::new(token::EOF),
+        peek_span: RefCell::new(codemap::DUMMY_SP),
     };
     bump(r);
     return r;
@@ -89,78 +90,84 @@ pub fn new_low_level_string_reader(span_diagnostic: @mut 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: @mut StringReader) -> @mut StringReader {
-    @mut StringReader {
+fn dup_string_reader(r: @StringReader) -> @StringReader {
+    @StringReader {
         span_diagnostic: r.span_diagnostic,
         src: r.src,
-        pos: r.pos,
-        last_pos: r.last_pos,
-        col: r.col,
-        curr: r.curr,
+        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,
         peek_tok: r.peek_tok.clone(),
-        peek_span: r.peek_span
+        peek_span: r.peek_span.clone(),
     }
 }
 
 impl reader for StringReader {
-    fn is_eof(@mut self) -> bool { is_eof(self) }
+    fn is_eof(@self) -> bool { is_eof(self) }
     // return the next token. EFFECT: advances the string_reader.
-    fn next_token(@mut self) -> TokenAndSpan {
-        let ret_val = TokenAndSpan {
-            tok: util::replace(&mut self.peek_tok, token::UNDERSCORE),
-            sp: self.peek_span,
+    fn next_token(@self) -> TokenAndSpan {
+        let ret_val = {
+            let mut peek_tok = self.peek_tok.borrow_mut();
+            TokenAndSpan {
+                tok: util::replace(peek_tok.get(), token::UNDERSCORE),
+                sp: self.peek_span.get(),
+            }
         };
         string_advance_token(self);
         ret_val
     }
-    fn fatal(@mut self, m: ~str) -> ! {
-        self.span_diagnostic.span_fatal(self.peek_span, m)
+    fn fatal(@self, m: ~str) -> ! {
+        self.span_diagnostic.span_fatal(self.peek_span.get(), m)
     }
-    fn span_diag(@mut self) -> @mut SpanHandler { self.span_diagnostic }
-    fn peek(@mut self) -> TokenAndSpan {
+    fn span_diag(@self) -> @SpanHandler { self.span_diagnostic }
+    fn peek(@self) -> TokenAndSpan {
         // XXX(pcwalton): Bad copy!
         TokenAndSpan {
-            tok: self.peek_tok.clone(),
-            sp: self.peek_span,
+            tok: self.peek_tok.get(),
+            sp: self.peek_span.get(),
         }
     }
-    fn dup(@mut self) -> @mut reader { dup_string_reader(self) as @mut reader }
+    fn dup(@self) -> @reader { dup_string_reader(self) as @reader }
 }
 
 impl reader for TtReader {
-    fn is_eof(@mut self) -> bool { self.cur_tok == token::EOF }
-    fn next_token(@mut self) -> TokenAndSpan {
+    fn is_eof(@self) -> bool {
+        let cur_tok = self.cur_tok.borrow();
+        *cur_tok.get() == token::EOF
+    }
+    fn next_token(@self) -> TokenAndSpan {
         let r = tt_next_token(self);
         debug!("TtReader: r={:?}", r);
         return r;
     }
-    fn fatal(@mut self, m: ~str) -> ! {
-        self.sp_diag.span_fatal(self.cur_span, m);
+    fn fatal(@self, m: ~str) -> ! {
+        self.sp_diag.span_fatal(self.cur_span.get(), m);
     }
-    fn span_diag(@mut self) -> @mut SpanHandler { self.sp_diag }
-    fn peek(@mut self) -> TokenAndSpan {
+    fn span_diag(@self) -> @SpanHandler { self.sp_diag }
+    fn peek(@self) -> TokenAndSpan {
         TokenAndSpan {
-            tok: self.cur_tok.clone(),
-            sp: self.cur_span,
+            tok: self.cur_tok.get(),
+            sp: self.cur_span.get(),
         }
     }
-    fn dup(@mut self) -> @mut reader { dup_tt_reader(self) as @mut reader }
+    fn dup(@self) -> @reader { dup_tt_reader(self) as @reader }
 }
 
 // report a lexical error spanning [`from_pos`, `to_pos`)
-fn fatal_span(rdr: @mut StringReader,
+fn fatal_span(rdr: @StringReader,
               from_pos: BytePos,
               to_pos: BytePos,
               m: ~str)
            -> ! {
-    rdr.peek_span = codemap::mk_sp(from_pos, to_pos);
+    rdr.peek_span.set(codemap::mk_sp(from_pos, to_pos));
     rdr.fatal(m);
 }
 
 // report a lexical error spanning [`from_pos`, `to_pos`), appending an
 // escaped character to the error message
-fn fatal_span_char(rdr: @mut StringReader,
+fn fatal_span_char(rdr: @StringReader,
                    from_pos: BytePos,
                    to_pos: BytePos,
                    m: ~str,
@@ -174,7 +181,7 @@ fn fatal_span_char(rdr: @mut StringReader,
 
 // report a lexical error spanning [`from_pos`, `to_pos`), appending the
 // offending string to the error message
-fn fatal_span_verbose(rdr: @mut StringReader,
+fn fatal_span_verbose(rdr: @StringReader,
                       from_pos: BytePos,
                       to_pos: BytePos,
                       m: ~str)
@@ -190,19 +197,20 @@ fn fatal_span_verbose(rdr: @mut StringReader,
 
 // EFFECT: advance peek_tok and peek_span to refer to the next token.
 // EFFECT: update the interner, maybe.
-fn string_advance_token(r: @mut StringReader) {
+fn string_advance_token(r: @StringReader) {
     match (consume_whitespace_and_comments(r)) {
         Some(comment) => {
-            r.peek_span = comment.sp;
-            r.peek_tok = comment.tok;
+            r.peek_span.set(comment.sp);
+            r.peek_tok.set(comment.tok);
         },
         None => {
             if is_eof(r) {
-                r.peek_tok = token::EOF;
+                r.peek_tok.set(token::EOF);
             } else {
-                let start_bytepos = r.last_pos;
-                r.peek_tok = next_token_inner(r);
-                r.peek_span = codemap::mk_sp(start_bytepos, r.last_pos);
+                let start_bytepos = r.last_pos.get();
+                r.peek_tok.set(next_token_inner(r));
+                r.peek_span.set(codemap::mk_sp(start_bytepos,
+                                               r.last_pos.get()));
             };
         }
     }
@@ -216,17 +224,17 @@ fn byte_offset(rdr: &StringReader, pos: BytePos) -> BytePos {
 /// up to but excluding `rdr.last_pos`, meaning the slice does not include
 /// the character `rdr.curr`.
 pub fn with_str_from<T>(
-                     rdr: @mut StringReader,
+                     rdr: @StringReader,
                      start: BytePos,
                      f: |s: &str| -> T)
                      -> T {
-    with_str_from_to(rdr, start, rdr.last_pos, f)
+    with_str_from_to(rdr, start, rdr.last_pos.get(), f)
 }
 
 /// Calls `f` with astring slice of the source text spanning from `start`
 /// up to but excluding `end`.
 fn with_str_from_to<T>(
-                    rdr: @mut StringReader,
+                    rdr: @StringReader,
                     start: BytePos,
                     end: BytePos,
                     f: |s: &str| -> T)
@@ -238,20 +246,22 @@ fn with_str_from_to<T>(
 
 // EFFECT: advance the StringReader by one character. If a newline is
 // discovered, add it to the FileMap's list of line start offsets.
-pub fn bump(rdr: &mut StringReader) {
-    rdr.last_pos = rdr.pos;
-    let current_byte_offset = byte_offset(rdr, rdr.pos).to_uint();
+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.src).len() {
-        assert!(rdr.curr != unsafe { transmute(-1u32) }); // FIXME: #8971: unsound
-        let last_char = rdr.curr;
+        assert!(rdr.curr.get() != unsafe {
+            transmute(-1u32)
+        }); // FIXME: #8971: unsound
+        let last_char = rdr.curr.get();
         let next = rdr.src.char_range_at(current_byte_offset);
         let byte_offset_diff = next.next - current_byte_offset;
-        rdr.pos = rdr.pos + Pos::from_uint(byte_offset_diff);
-        rdr.curr = next.ch;
-        rdr.col = rdr.col + CharPos(1u);
+        rdr.pos.set(rdr.pos.get() + Pos::from_uint(byte_offset_diff));
+        rdr.curr.set(next.ch);
+        rdr.col.set(rdr.col.get() + CharPos(1u));
         if last_char == '\n' {
-            rdr.filemap.next_line(rdr.last_pos);
-            rdr.col = CharPos(0u);
+            rdr.filemap.next_line(rdr.last_pos.get());
+            rdr.col.set(CharPos(0u));
         }
 
         if byte_offset_diff > 1 {
@@ -259,14 +269,14 @@ pub fn bump(rdr: &mut StringReader) {
                 Pos::from_uint(current_byte_offset), byte_offset_diff);
         }
     } else {
-        rdr.curr = unsafe { transmute(-1u32) }; // FIXME: #8971: unsound
+        rdr.curr.set(unsafe { transmute(-1u32) }); // FIXME: #8971: unsound
     }
 }
-pub fn is_eof(rdr: @mut StringReader) -> bool {
-    rdr.curr == unsafe { transmute(-1u32) } // FIXME: #8971: unsound
+pub fn is_eof(rdr: @StringReader) -> bool {
+    rdr.curr.get() == unsafe { transmute(-1u32) } // FIXME: #8971: unsound
 }
-pub fn nextch(rdr: @mut StringReader) -> char {
-    let offset = byte_offset(rdr, rdr.pos).to_uint();
+pub fn nextch(rdr: @StringReader) -> char {
+    let offset = byte_offset(rdr, rdr.pos.get()).to_uint();
     if offset < (rdr.src).len() {
         return rdr.src.char_at(offset);
     } else { return unsafe { transmute(-1u32) }; } // FIXME: #8971: unsound
@@ -296,9 +306,9 @@ fn is_hex_digit(c: char) -> bool {
 
 // EFFECT: eats whitespace and comments.
 // returns a Some(sugared-doc-attr) if one exists, None otherwise.
-fn consume_whitespace_and_comments(rdr: @mut StringReader)
+fn consume_whitespace_and_comments(rdr: @StringReader)
                                 -> Option<TokenAndSpan> {
-    while is_whitespace(rdr.curr) { bump(rdr); }
+    while is_whitespace(rdr.curr.get()) { bump(rdr); }
     return consume_any_line_comment(rdr);
 }
 
@@ -309,17 +319,17 @@ pub fn is_line_non_doc_comment(s: &str) -> bool {
 // PRECONDITION: rdr.curr is not whitespace
 // EFFECT: eats any kind of comment.
 // returns a Some(sugared-doc-attr) if one exists, None otherwise
-fn consume_any_line_comment(rdr: @mut StringReader)
+fn consume_any_line_comment(rdr: @StringReader)
                          -> Option<TokenAndSpan> {
-    if rdr.curr == '/' {
+    if rdr.curr.get() == '/' {
         match nextch(rdr) {
           '/' => {
             bump(rdr);
             bump(rdr);
             // line comments starting with "///" or "//!" are doc-comments
-            if rdr.curr == '/' || rdr.curr == '!' {
-                let start_bpos = rdr.pos - BytePos(3);
-                while rdr.curr != '\n' && !is_eof(rdr) {
+            if rdr.curr.get() == '/' || rdr.curr.get() == '!' {
+                let start_bpos = rdr.pos.get() - BytePos(3);
+                while rdr.curr.get() != '\n' && !is_eof(rdr) {
                     bump(rdr);
                 }
                 let ret = with_str_from(rdr, start_bpos, |string| {
@@ -327,7 +337,7 @@ fn consume_any_line_comment(rdr: @mut StringReader)
                     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)
+                            sp: codemap::mk_sp(start_bpos, rdr.pos.get())
                         })
                     } else {
                         None
@@ -338,7 +348,7 @@ fn consume_any_line_comment(rdr: @mut StringReader)
                     return ret;
                 }
             } else {
-                while rdr.curr != '\n' && !is_eof(rdr) { bump(rdr); }
+                while rdr.curr.get() != '\n' && !is_eof(rdr) { bump(rdr); }
             }
             // Restart whitespace munch.
             return consume_whitespace_and_comments(rdr);
@@ -346,15 +356,18 @@ fn consume_any_line_comment(rdr: @mut StringReader)
           '*' => { bump(rdr); bump(rdr); return consume_block_comment(rdr); }
           _ => ()
         }
-    } else if rdr.curr == '#' {
+    } else if rdr.curr.get() == '#' {
         if nextch(rdr) == '!' {
             // I guess this is the only way to figure out if
             // we're at the beginning of the file...
             let cmap = @CodeMap::new();
-            (*cmap).files.push(rdr.filemap);
-            let loc = cmap.lookup_char_pos_adj(rdr.last_pos);
+            {
+                let mut files = cmap.files.borrow_mut();
+                files.get().push(rdr.filemap);
+            }
+            let loc = cmap.lookup_char_pos_adj(rdr.last_pos.get());
             if loc.line == 1u && loc.col == CharPos(0u) {
-                while rdr.curr != '\n' && !is_eof(rdr) { bump(rdr); }
+                while rdr.curr.get() != '\n' && !is_eof(rdr) { bump(rdr); }
                 return consume_whitespace_and_comments(rdr);
             }
         }
@@ -367,11 +380,10 @@ pub fn is_block_non_doc_comment(s: &str) -> bool {
 }
 
 // might return a sugared-doc-attr
-fn consume_block_comment(rdr: @mut StringReader)
-                      -> Option<TokenAndSpan> {
+fn consume_block_comment(rdr: @StringReader) -> Option<TokenAndSpan> {
     // block comments starting with "/**" or "/*!" are doc-comments
-    let is_doc_comment = rdr.curr == '*' || rdr.curr == '!';
-    let start_bpos = rdr.pos - BytePos(if is_doc_comment {3} else {2});
+    let is_doc_comment = rdr.curr.get() == '*' || rdr.curr.get() == '!';
+    let start_bpos = rdr.pos.get() - BytePos(if is_doc_comment {3} else {2});
 
     let mut level: int = 1;
     while level > 0 {
@@ -381,12 +393,12 @@ fn consume_block_comment(rdr: @mut StringReader)
             } else {
                 ~"unterminated block comment"
             };
-            fatal_span(rdr, start_bpos, rdr.last_pos, msg);
-        } else if rdr.curr == '/' && nextch(rdr) == '*' {
+            fatal_span(rdr, start_bpos, rdr.last_pos.get(), msg);
+        } else if rdr.curr.get() == '/' && nextch(rdr) == '*' {
             level += 1;
             bump(rdr);
             bump(rdr);
-        } else if rdr.curr == '*' && nextch(rdr) == '/' {
+        } else if rdr.curr.get() == '*' && nextch(rdr) == '/' {
             level -= 1;
             bump(rdr);
             bump(rdr);
@@ -401,7 +413,7 @@ fn consume_block_comment(rdr: @mut StringReader)
             if !is_block_non_doc_comment(string) {
                 Some(TokenAndSpan{
                         tok: token::DOC_COMMENT(str_to_ident(string)),
-                        sp: codemap::mk_sp(start_bpos, rdr.pos)
+                        sp: codemap::mk_sp(start_bpos, rdr.pos.get())
                     })
             } else {
                 None
@@ -415,13 +427,13 @@ fn consume_block_comment(rdr: @mut StringReader)
     if res.is_some() { res } else { consume_whitespace_and_comments(rdr) }
 }
 
-fn scan_exponent(rdr: @mut StringReader, start_bpos: BytePos) -> Option<~str> {
-    let mut c = rdr.curr;
+fn scan_exponent(rdr: @StringReader, start_bpos: BytePos) -> Option<~str> {
+    let mut c = rdr.curr.get();
     let mut rslt = ~"";
     if c == 'e' || c == 'E' {
         rslt.push_char(c);
         bump(rdr);
-        c = rdr.curr;
+        c = rdr.curr.get();
         if c == '-' || c == '+' {
             rslt.push_char(c);
             bump(rdr);
@@ -430,16 +442,16 @@ fn scan_exponent(rdr: @mut StringReader, start_bpos: BytePos) -> Option<~str> {
         if exponent.len() > 0u {
             return Some(rslt + exponent);
         } else {
-            fatal_span(rdr, start_bpos, rdr.last_pos,
+            fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                        ~"scan_exponent: bad fp literal");
         }
     } else { return None::<~str>; }
 }
 
-fn scan_digits(rdr: @mut StringReader, radix: uint) -> ~str {
+fn scan_digits(rdr: @StringReader, radix: uint) -> ~str {
     let mut rslt = ~"";
     loop {
-        let c = rdr.curr;
+        let c = rdr.curr.get();
         if c == '_' { bump(rdr); continue; }
         match char::to_digit(c, radix) {
           Some(_) => {
@@ -451,12 +463,12 @@ fn scan_digits(rdr: @mut StringReader, radix: uint) -> ~str {
     };
 }
 
-fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
+fn scan_number(c: char, rdr: @StringReader) -> token::Token {
     let mut num_str;
     let mut base = 10u;
     let mut c = c;
     let mut n = nextch(rdr);
-    let start_bpos = rdr.last_pos;
+    let start_bpos = rdr.last_pos.get();
     if c == '0' && n == 'x' {
         bump(rdr);
         bump(rdr);
@@ -471,7 +483,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
         base = 2u;
     }
     num_str = scan_digits(rdr, base);
-    c = rdr.curr;
+    c = rdr.curr.get();
     nextch(rdr);
     if c == 'u' || c == 'i' {
         enum Result { Signed(ast::int_ty), Unsigned(ast::uint_ty) }
@@ -481,7 +493,7 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
             else { Unsigned(ast::ty_u) }
         };
         bump(rdr);
-        c = rdr.curr;
+        c = rdr.curr.get();
         if c == '8' {
             bump(rdr);
             tp = if signed { Signed(ast::ty_i8) }
@@ -505,12 +517,12 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
                       else { Unsigned(ast::ty_u64) };
         }
         if num_str.len() == 0u {
-            fatal_span(rdr, start_bpos, rdr.last_pos,
+            fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                        ~"no valid digits found for number");
         }
         let parsed = match from_str_radix::<u64>(num_str, base as uint) {
             Some(p) => p,
-            None => fatal_span(rdr, start_bpos, rdr.last_pos,
+            None => fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                                ~"int literal is too large")
         };
 
@@ -520,7 +532,8 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
         }
     }
     let mut is_float = false;
-    if rdr.curr == '.' && !(ident_start(nextch(rdr)) || nextch(rdr) == '.') {
+    if rdr.curr.get() == '.' && !(ident_start(nextch(rdr)) || nextch(rdr) ==
+                                  '.') {
         is_float = true;
         bump(rdr);
         let dec_part = scan_digits(rdr, 10u);
@@ -529,11 +542,11 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
     }
     if is_float {
         match base {
-          16u => fatal_span(rdr, start_bpos, rdr.last_pos,
+          16u => fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                             ~"hexadecimal float literal is not supported"),
-          8u => fatal_span(rdr, start_bpos, rdr.last_pos,
+          8u => fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                            ~"octal float literal is not supported"),
-          2u => fatal_span(rdr, start_bpos, rdr.last_pos,
+          2u => fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                            ~"binary float literal is not supported"),
           _ => ()
         }
@@ -546,9 +559,9 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
       None => ()
     }
 
-    if rdr.curr == 'f' {
+    if rdr.curr.get() == 'f' {
         bump(rdr);
-        c = rdr.curr;
+        c = rdr.curr.get();
         n = nextch(rdr);
         if c == '3' && n == '2' {
             bump(rdr);
@@ -564,19 +577,20 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
             32-bit or 64-bit float, it won't be noticed till the
             back-end.  */
         } else {
-            fatal_span(rdr, start_bpos, rdr.last_pos, ~"expected `f32` or `f64` suffix");
+            fatal_span(rdr, start_bpos, rdr.last_pos.get(),
+                       ~"expected `f32` or `f64` suffix");
         }
     }
     if is_float {
         return token::LIT_FLOAT_UNSUFFIXED(str_to_ident(num_str));
     } else {
         if num_str.len() == 0u {
-            fatal_span(rdr, start_bpos, rdr.last_pos,
+            fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                        ~"no valid digits found for number");
         }
         let parsed = match from_str_radix::<u64>(num_str, base as uint) {
             Some(p) => p,
-            None => fatal_span(rdr, start_bpos, rdr.last_pos,
+            None => fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                                ~"int literal is too large")
         };
 
@@ -585,14 +599,14 @@ fn scan_number(c: char, rdr: @mut StringReader) -> token::Token {
     }
 }
 
-fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> char {
+fn scan_numeric_escape(rdr: @StringReader, n_hex_digits: uint) -> char {
     let mut accum_int = 0;
     let mut i = n_hex_digits;
-    let start_bpos = rdr.last_pos;
+    let start_bpos = rdr.last_pos.get();
     while i != 0u {
-        let n = rdr.curr;
+        let n = rdr.curr.get();
         if !is_hex_digit(n) {
-            fatal_span_char(rdr, rdr.last_pos, rdr.pos,
+            fatal_span_char(rdr, rdr.last_pos.get(), rdr.pos.get(),
                             ~"illegal character in numeric character escape",
                             n);
         }
@@ -603,7 +617,7 @@ fn scan_numeric_escape(rdr: @mut StringReader, n_hex_digits: uint) -> char {
     }
     match char::from_u32(accum_int as u32) {
         Some(x) => x,
-        None => fatal_span(rdr, start_bpos, rdr.last_pos,
+        None => fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                            ~"illegal numeric character escape")
     }
 }
@@ -626,14 +640,14 @@ fn ident_continue(c: char) -> bool {
 // return the next token from the string
 // EFFECT: advances the input past that token
 // EFFECT: updates the interner
-fn next_token_inner(rdr: @mut StringReader) -> token::Token {
-    let c = rdr.curr;
+fn next_token_inner(rdr: @StringReader) -> token::Token {
+    let c = rdr.curr.get();
     if ident_start(c) && nextch(rdr) != '"' && nextch(rdr) != '#' {
         // Note: r as in r" or r#" is part of a raw string literal,
         // not an identifier, and is handled further down.
 
-        let start = rdr.last_pos;
-        while ident_continue(rdr.curr) {
+        let start = rdr.last_pos.get();
+        while ident_continue(rdr.curr.get()) {
             bump(rdr);
         }
 
@@ -641,7 +655,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
             if string == "_" {
                 token::UNDERSCORE
             } else {
-                let is_mod_name = rdr.curr == ':' && nextch(rdr) == ':';
+                let is_mod_name = rdr.curr.get() == ':' && nextch(rdr) == ':';
 
                 // FIXME: perform NFKC normalization here. (Issue #2253)
                 token::IDENT(str_to_ident(string), is_mod_name)
@@ -651,9 +665,9 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
     if is_dec_digit(c) {
         return scan_number(c, rdr);
     }
-    fn binop(rdr: @mut StringReader, op: token::binop) -> token::Token {
+    fn binop(rdr: @StringReader, op: token::binop) -> token::Token {
         bump(rdr);
-        if rdr.curr == '=' {
+        if rdr.curr.get() == '=' {
             bump(rdr);
             return token::BINOPEQ(op);
         } else { return token::BINOP(op); }
@@ -669,9 +683,9 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       ',' => { bump(rdr); return token::COMMA; }
       '.' => {
           bump(rdr);
-          return if rdr.curr == '.' {
+          return if rdr.curr.get() == '.' {
               bump(rdr);
-              if rdr.curr == '.' {
+              if rdr.curr.get() == '.' {
                   bump(rdr);
                   token::DOTDOTDOT
               } else {
@@ -692,7 +706,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       '~' => { bump(rdr); return token::TILDE; }
       ':' => {
         bump(rdr);
-        if rdr.curr == ':' {
+        if rdr.curr.get() == ':' {
             bump(rdr);
             return token::MOD_SEP;
         } else { return token::COLON; }
@@ -707,10 +721,10 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       // Multi-byte tokens.
       '=' => {
         bump(rdr);
-        if rdr.curr == '=' {
+        if rdr.curr.get() == '=' {
             bump(rdr);
             return token::EQEQ;
-        } else if rdr.curr == '>' {
+        } else if rdr.curr.get() == '>' {
             bump(rdr);
             return token::FAT_ARROW;
         } else {
@@ -719,19 +733,19 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       }
       '!' => {
         bump(rdr);
-        if rdr.curr == '=' {
+        if rdr.curr.get() == '=' {
             bump(rdr);
             return token::NE;
         } else { return token::NOT; }
       }
       '<' => {
         bump(rdr);
-        match rdr.curr {
+        match rdr.curr.get() {
           '=' => { bump(rdr); return token::LE; }
           '<' => { return binop(rdr, token::SHL); }
           '-' => {
             bump(rdr);
-            match rdr.curr {
+            match rdr.curr.get() {
               '>' => { bump(rdr); return token::DARROW; }
               _ => { return token::LARROW; }
             }
@@ -741,7 +755,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       }
       '>' => {
         bump(rdr);
-        match rdr.curr {
+        match rdr.curr.get() {
           '=' => { bump(rdr); return token::GE; }
           '>' => { return binop(rdr, token::SHR); }
           _ => { return token::GT; }
@@ -750,14 +764,14 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       '\'' => {
         // Either a character constant 'a' OR a lifetime name 'abc
         bump(rdr);
-        let start = rdr.last_pos;
-        let mut c2 = rdr.curr;
+        let start = rdr.last_pos.get();
+        let mut c2 = rdr.curr.get();
         bump(rdr);
 
         // If the character is an ident start not followed by another single
         // quote, then this is a lifetime name:
-        if ident_start(c2) && rdr.curr != '\'' {
-            while ident_continue(rdr.curr) {
+        if ident_start(c2) && rdr.curr.get() != '\'' {
+            while ident_continue(rdr.curr.get()) {
                 bump(rdr);
             }
             return with_str_from(rdr, start, |lifetime_name| {
@@ -765,11 +779,12 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
                 let tok = &token::IDENT(ident, false);
 
                 if token::is_keyword(token::keywords::Self, tok) {
-                    fatal_span(rdr, start, rdr.last_pos,
+                    fatal_span(rdr, start, rdr.last_pos.get(),
                                ~"invalid lifetime name: 'self is no longer a special lifetime");
                 } else if token::is_any_keyword(tok) &&
                     !token::is_keyword(token::keywords::Static, tok) {
-                    fatal_span(rdr, start, rdr.last_pos, ~"invalid lifetime name");
+                    fatal_span(rdr, start, rdr.last_pos.get(),
+                               ~"invalid lifetime name");
                 } else {
                     token::LIFETIME(ident)
                 }
@@ -780,8 +795,8 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
         match c2 {
             '\\' => {
                 // '\X' for some X must be a character constant:
-                let escaped = rdr.curr;
-                let escaped_pos = rdr.last_pos;
+                let escaped = rdr.curr.get();
+                let escaped_pos = rdr.last_pos.get();
                 bump(rdr);
                 match escaped {
                     'n' => { c2 = '\n'; }
@@ -795,24 +810,24 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
                     'u' => { c2 = scan_numeric_escape(rdr, 4u); }
                     'U' => { c2 = scan_numeric_escape(rdr, 8u); }
                     c2 => {
-                        fatal_span_char(rdr, escaped_pos, rdr.last_pos,
+                        fatal_span_char(rdr, escaped_pos, rdr.last_pos.get(),
                                         ~"unknown character escape", c2);
                     }
                 }
             }
             '\t' | '\n' | '\r' | '\'' => {
-                fatal_span_char(rdr, start, rdr.last_pos,
+                fatal_span_char(rdr, start, rdr.last_pos.get(),
                                 ~"character constant must be escaped", c2);
             }
             _ => {}
         }
-        if rdr.curr != '\'' {
+        if rdr.curr.get() != '\'' {
             fatal_span_verbose(rdr,
                                // Byte offsetting here is okay because the
                                // character before position `start` is an
                                // ascii single quote.
                                start - BytePos(1),
-                               rdr.last_pos,
+                               rdr.last_pos.get(),
                                ~"unterminated character constant");
         }
         bump(rdr); // advance curr past token
@@ -820,20 +835,20 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       }
       '"' => {
         let mut accum_str = ~"";
-        let start_bpos = rdr.last_pos;
+        let start_bpos = rdr.last_pos.get();
         bump(rdr);
-        while rdr.curr != '"' {
+        while rdr.curr.get() != '"' {
             if is_eof(rdr) {
-                fatal_span(rdr, start_bpos, rdr.last_pos,
+                fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                            ~"unterminated double quote string");
             }
 
-            let ch = rdr.curr;
+            let ch = rdr.curr.get();
             bump(rdr);
             match ch {
               '\\' => {
-                let escaped = rdr.curr;
-                let escaped_pos = rdr.last_pos;
+                let escaped = rdr.curr.get();
+                let escaped_pos = rdr.last_pos.get();
                 bump(rdr);
                 match escaped {
                   'n' => accum_str.push_char('\n'),
@@ -854,7 +869,7 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
                     accum_str.push_char(scan_numeric_escape(rdr, 8u));
                   }
                   c2 => {
-                    fatal_span_char(rdr, escaped_pos, rdr.last_pos,
+                    fatal_span_char(rdr, escaped_pos, rdr.last_pos.get(),
                                     ~"unknown string escape", c2);
                   }
                 }
@@ -866,32 +881,32 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
         return token::LIT_STR(str_to_ident(accum_str));
       }
       'r' => {
-        let start_bpos = rdr.last_pos;
+        let start_bpos = rdr.last_pos.get();
         bump(rdr);
         let mut hash_count = 0u;
-        while rdr.curr == '#' {
+        while rdr.curr.get() == '#' {
             bump(rdr);
             hash_count += 1;
         }
-        if rdr.curr != '"' {
-            fatal_span_char(rdr, start_bpos, rdr.last_pos,
+        if rdr.curr.get() != '"' {
+            fatal_span_char(rdr, start_bpos, rdr.last_pos.get(),
                             ~"only `#` is allowed in raw string delimitation; \
                               found illegal character",
-                            rdr.curr);
+                            rdr.curr.get());
         }
         bump(rdr);
-        let content_start_bpos = rdr.last_pos;
+        let content_start_bpos = rdr.last_pos.get();
         let mut content_end_bpos;
         'outer: loop {
             if is_eof(rdr) {
-                fatal_span(rdr, start_bpos, rdr.last_pos,
+                fatal_span(rdr, start_bpos, rdr.last_pos.get(),
                            ~"unterminated raw string");
             }
-            if rdr.curr == '"' {
-                content_end_bpos = rdr.last_pos;
+            if rdr.curr.get() == '"' {
+                content_end_bpos = rdr.last_pos.get();
                 for _ in range(0, hash_count) {
                     bump(rdr);
-                    if rdr.curr != '#' {
+                    if rdr.curr.get() != '#' {
                         continue 'outer;
                     }
                 }
@@ -932,14 +947,14 @@ fn next_token_inner(rdr: @mut StringReader) -> token::Token {
       '^' => { return binop(rdr, token::CARET); }
       '%' => { return binop(rdr, token::PERCENT); }
       c => {
-          fatal_span_char(rdr, rdr.last_pos, rdr.pos,
+          fatal_span_char(rdr, rdr.last_pos.get(), rdr.pos.get(),
                           ~"unknown start of token", c);
       }
     }
 }
 
-fn consume_whitespace(rdr: @mut StringReader) {
-    while is_whitespace(rdr.curr) && !is_eof(rdr) { bump(rdr); }
+fn consume_whitespace(rdr: @StringReader) {
+    while is_whitespace(rdr.curr.get()) && !is_eof(rdr) { bump(rdr); }
 }
 
 #[cfg(test)]
@@ -953,7 +968,7 @@ mod test {
 
     // represents a testing reader (incl. both reader and interner)
     struct Env {
-        string_reader: @mut StringReader
+        string_reader: @StringReader
     }
 
     // open a string reader for the given string
@@ -978,7 +993,7 @@ mod test {
             sp:Span {lo:BytePos(21),hi:BytePos(23),expn_info: None}};
         assert_eq!(tok1,tok2);
         // the 'main' id is already read:
-        assert_eq!(string_reader.last_pos.clone(), BytePos(28));
+        assert_eq!(string_reader.last_pos.get().clone(), BytePos(28));
         // read another token:
         let tok3 = string_reader.next_token();
         let tok4 = TokenAndSpan{
@@ -986,7 +1001,7 @@ mod test {
             sp:Span {lo:BytePos(24),hi:BytePos(28),expn_info: None}};
         assert_eq!(tok3,tok4);
         // the lparen is already read:
-        assert_eq!(string_reader.last_pos.clone(), BytePos(29))
+        assert_eq!(string_reader.last_pos.get().clone(), BytePos(29))
     }
 
     // check that the given reader produces the desired stream
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 5a8444518aa..c20e7f4aaec 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -19,6 +19,7 @@ use parse::attr::parser_attr;
 use parse::lexer::reader;
 use parse::parser::Parser;
 
+use std::cell::RefCell;
 use std::io;
 use std::io::File;
 use std::str;
@@ -41,27 +42,27 @@ 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: @mut 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: ~[Path],
+    included_mod_stack: RefCell<~[Path]>,
 }
 
-pub fn new_parse_sess(demitter: Option<@Emitter>) -> @mut ParseSess {
+pub fn new_parse_sess(demitter: Option<@Emitter>) -> @ParseSess {
     let cm = @CodeMap::new();
-    @mut ParseSess {
+    @ParseSess {
         cm: cm,
         span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
-        included_mod_stack: ~[],
+        included_mod_stack: RefCell::new(~[]),
     }
 }
 
-pub fn new_parse_sess_special_handler(sh: @mut SpanHandler,
+pub fn new_parse_sess_special_handler(sh: @SpanHandler,
                                       cm: @codemap::CodeMap)
-                                   -> @mut ParseSess {
-    @mut ParseSess {
+                                      -> @ParseSess {
+    @ParseSess {
         cm: cm,
         span_diagnostic: sh,
-        included_mod_stack: ~[],
+        included_mod_stack: RefCell::new(~[]),
     }
 }
 
@@ -73,7 +74,7 @@ pub fn new_parse_sess_special_handler(sh: @mut SpanHandler,
 pub fn parse_crate_from_file(
     input: &Path,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> ast::Crate {
     new_parser_from_file(sess, /*bad*/ cfg.clone(), input).parse_crate_mod()
     // why is there no p.abort_if_errors here?
@@ -82,7 +83,7 @@ pub fn parse_crate_from_file(
 pub fn parse_crate_attrs_from_file(
     input: &Path,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> ~[ast::Attribute] {
     let mut parser = new_parser_from_file(sess, cfg, input);
     let (inner, _) = parser.parse_inner_attrs_and_next();
@@ -93,7 +94,7 @@ pub fn parse_crate_from_source_str(
     name: @str,
     source: @str,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> ast::Crate {
     let mut p = new_parser_from_source_str(sess,
                                            /*bad*/ cfg.clone(),
@@ -106,7 +107,7 @@ pub fn parse_crate_attrs_from_source_str(
     name: @str,
     source: @str,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> ~[ast::Attribute] {
     let mut p = new_parser_from_source_str(sess,
                                            /*bad*/ cfg.clone(),
@@ -120,7 +121,7 @@ pub fn parse_expr_from_source_str(
     name: @str,
     source: @str,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> @ast::Expr {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_expr(), p)
@@ -131,7 +132,7 @@ pub fn parse_item_from_source_str(
     source: @str,
     cfg: ast::CrateConfig,
     attrs: ~[ast::Attribute],
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> Option<@ast::item> {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_item(attrs),p)
@@ -141,7 +142,7 @@ pub fn parse_meta_from_source_str(
     name: @str,
     source: @str,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> @ast::MetaItem {
     let mut p = new_parser_from_source_str(sess, cfg, name, source);
     maybe_aborted(p.parse_meta_item(),p)
@@ -152,7 +153,7 @@ pub fn parse_stmt_from_source_str(
     source: @str,
     cfg: ast::CrateConfig,
     attrs: ~[ast::Attribute],
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> @ast::Stmt {
     let mut p = new_parser_from_source_str(
         sess,
@@ -167,7 +168,7 @@ pub fn parse_tts_from_source_str(
     name: @str,
     source: @str,
     cfg: ast::CrateConfig,
-    sess: @mut ParseSess
+    sess: @ParseSess
 ) -> ~[ast::token_tree] {
     let mut p = new_parser_from_source_str(
         sess,
@@ -191,7 +192,7 @@ pub fn parse_from_source_str<T>(
                              ss: codemap::FileSubstr,
                              source: @str,
                              cfg: ast::CrateConfig,
-                             sess: @mut ParseSess)
+                             sess: @ParseSess)
                              -> T {
     let mut p = new_parser_from_source_substr(sess, cfg, name, ss, source);
     let r = f(&mut p);
@@ -202,7 +203,7 @@ pub fn parse_from_source_str<T>(
 }
 
 // Create a new parser from a source string
-pub fn new_parser_from_source_str(sess: @mut ParseSess,
+pub fn new_parser_from_source_str(sess: @ParseSess,
                                   cfg: ast::CrateConfig,
                                   name: @str,
                                   source: @str)
@@ -212,7 +213,7 @@ pub fn new_parser_from_source_str(sess: @mut ParseSess,
 
 // Create a new parser from a source string where the origin
 // is specified as a substring of another file.
-pub fn new_parser_from_source_substr(sess: @mut ParseSess,
+pub fn new_parser_from_source_substr(sess: @ParseSess,
                                   cfg: ast::CrateConfig,
                                   name: @str,
                                   ss: codemap::FileSubstr,
@@ -224,7 +225,7 @@ pub fn new_parser_from_source_substr(sess: @mut ParseSess,
 /// Create a new parser, handling errors as appropriate
 /// if the file doesn't exist
 pub fn new_parser_from_file(
-    sess: @mut ParseSess,
+    sess: @ParseSess,
     cfg: ast::CrateConfig,
     path: &Path
 ) -> Parser {
@@ -235,7 +236,7 @@ pub fn new_parser_from_file(
 /// 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: @mut ParseSess,
+    sess: @ParseSess,
     cfg: ast::CrateConfig,
     path: &Path,
     sp: Span
@@ -244,7 +245,7 @@ pub fn new_sub_parser_from_file(
 }
 
 /// Given a filemap and config, return a parser
-pub fn filemap_to_parser(sess: @mut ParseSess,
+pub fn filemap_to_parser(sess: @ParseSess,
                          filemap: @FileMap,
                          cfg: ast::CrateConfig) -> Parser {
     tts_to_parser(sess,filemap_to_tts(sess,filemap),cfg)
@@ -252,7 +253,7 @@ pub fn filemap_to_parser(sess: @mut ParseSess,
 
 // must preserve old name for now, because quote! from the *existing*
 // compiler expands into it
-pub fn new_parser_from_tts(sess: @mut ParseSess,
+pub fn new_parser_from_tts(sess: @ParseSess,
                      cfg: ast::CrateConfig,
                      tts: ~[ast::token_tree]) -> Parser {
     tts_to_parser(sess,tts,cfg)
@@ -263,7 +264,7 @@ pub fn new_parser_from_tts(sess: @mut 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: @mut ParseSess, path: &Path, spanopt: Option<Span>)
+pub fn file_to_filemap(sess: @ParseSess, path: &Path, spanopt: Option<Span>)
     -> @FileMap {
     let err = |msg: &str| {
         match spanopt {
@@ -292,35 +293,35 @@ pub fn file_to_filemap(sess: @mut 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: @mut ParseSess, source: @str, path: @str)
+pub fn string_to_filemap(sess: @ParseSess, source: @str, path: @str)
     -> @FileMap {
     sess.cm.new_filemap(path, source)
 }
 
 // given a session and a string and a path and a FileSubStr, add
 // the string to the CodeMap and return the new FileMap
-pub fn substring_to_filemap(sess: @mut ParseSess, source: @str, path: @str,
+pub fn substring_to_filemap(sess: @ParseSess, source: @str, path: @str,
                            filesubstr: FileSubstr) -> @FileMap {
     sess.cm.new_filemap_w_substr(path,filesubstr,source)
 }
 
 // given a filemap, produce a sequence of token-trees
-pub fn filemap_to_tts(sess: @mut ParseSess, filemap: @FileMap)
+pub fn filemap_to_tts(sess: @ParseSess, filemap: @FileMap)
     -> ~[ast::token_tree] {
     // 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 = ~[];
     let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap);
-    let mut p1 = Parser(sess, cfg, srdr as @mut reader);
+    let mut p1 = Parser(sess, cfg, srdr as @reader);
     p1.parse_all_token_trees()
 }
 
 // given tts and cfg, produce a parser
-pub fn tts_to_parser(sess: @mut ParseSess,
+pub fn tts_to_parser(sess: @ParseSess,
                      tts: ~[ast::token_tree],
                      cfg: ast::CrateConfig) -> Parser {
     let trdr = lexer::new_tt_reader(sess.span_diagnostic, None, tts);
-    Parser(sess, cfg, trdr as @mut reader)
+    Parser(sess, cfg, trdr as @reader)
 }
 
 // abort if necessary
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2428710087f..40a2ef86e4f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -29,8 +29,7 @@ use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
 use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
 use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc, ExprRepeat};
 use ast::{ExprRet, ExprSelf, ExprStruct, ExprTup, ExprUnary};
-use ast::{ExprVec, ExprVstore, ExprVstoreMutBox};
-use ast::{ExprVstoreSlice, ExprVstoreBox};
+use ast::{ExprVec, ExprVstore, ExprVstoreSlice, ExprVstoreBox};
 use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, extern_fn, Field, fn_decl};
 use ast::{ExprVstoreUniq, Onceness, Once, Many};
 use ast::{foreign_item, foreign_item_static, foreign_item_fn, foreign_mod};
@@ -81,6 +80,7 @@ use parse::{new_sub_parser_from_file, ParseSess};
 use opt_vec;
 use opt_vec::OptVec;
 
+use std::cell::Cell;
 use std::hashmap::HashSet;
 use std::util;
 use std::vec;
@@ -286,8 +286,8 @@ struct ParsedItemsAndViewItems {
 
 /* ident is handled by common.rs */
 
-pub fn Parser(sess: @mut ParseSess, cfg: ast::CrateConfig, rdr: @mut reader)
-           -> Parser {
+pub fn Parser(sess: @ParseSess, cfg: ast::CrateConfig, rdr: @reader)
+              -> Parser {
     let tok0 = rdr.next_token();
     let interner = get_ident_interner();
     let span = tok0.sp;
@@ -324,7 +324,7 @@ pub fn Parser(sess: @mut ParseSess, cfg: ast::CrateConfig, rdr: @mut reader)
 }
 
 pub struct Parser {
-    sess: @mut ParseSess,
+    sess: @ParseSess,
     cfg: CrateConfig,
     // the current token:
     token: token::Token,
@@ -340,7 +340,7 @@ pub struct Parser {
     tokens_consumed: uint,
     restriction: restriction,
     quote_depth: uint, // not (yet) related to the quasiquoter
-    reader: @mut reader,
+    reader: @reader,
     interner: @token::ident_interner,
     /// The set of seen errors about obsolete syntax. Used to suppress
     /// extra detail when the same error is seen twice
@@ -1299,7 +1299,7 @@ impl Parser {
         if sigil == OwnedSigil {
             ty_uniq(self.parse_ty(false))
         } else {
-            ty_box(self.parse_mt())
+            ty_box(self.parse_ty(false))
         }
     }
 
@@ -2185,7 +2185,7 @@ impl Parser {
         // unification of matchers and token_trees would vastly improve
         // the interpolation of matchers
         maybe_whole!(self, nt_matchers);
-        let name_idx = @mut 0u;
+        let name_idx = @Cell::new(0u);
         match self.token {
             token::LBRACE | token::LPAREN | token::LBRACKET => {
                 let other_delimiter = token::flip_delimiter(&self.token);
@@ -2200,7 +2200,7 @@ impl Parser {
     // Otherwise, `$( ( )` would be a valid matcher, and `$( () )` would be
     // invalid. It's similar to common::parse_seq.
     pub fn parse_matcher_subseq_upto(&mut self,
-                                     name_idx: @mut uint,
+                                     name_idx: @Cell<uint>,
                                      ket: &token::Token)
                                      -> ~[matcher] {
         let mut ret_val = ~[];
@@ -2217,13 +2217,13 @@ impl Parser {
         return ret_val;
     }
 
-    pub fn parse_matcher(&mut self, name_idx: @mut uint) -> matcher {
+    pub fn parse_matcher(&mut self, name_idx: @Cell<uint>) -> matcher {
         let lo = self.span.lo;
 
         let m = if self.token == token::DOLLAR {
             self.bump();
             if self.token == token::LPAREN {
-                let name_idx_lo = *name_idx;
+                let name_idx_lo = name_idx.get();
                 self.bump();
                 let ms = self.parse_matcher_subseq_upto(name_idx,
                                                         &token::RPAREN);
@@ -2231,13 +2231,13 @@ impl Parser {
                     self.fatal("repetition body must be nonempty");
                 }
                 let (sep, zerok) = self.parse_sep_and_zerok();
-                match_seq(ms, sep, zerok, name_idx_lo, *name_idx)
+                match_seq(ms, sep, zerok, name_idx_lo, name_idx.get())
             } else {
                 let bound_to = self.parse_ident();
                 self.expect(&token::COLON);
                 let nt_name = self.parse_ident();
-                let m = match_nonterminal(bound_to, nt_name, *name_idx);
-                *name_idx += 1u;
+                let m = match_nonterminal(bound_to, nt_name, name_idx.get());
+                name_idx.set(name_idx.get() + 1u);
                 m
             }
         } else {
@@ -2299,17 +2299,14 @@ impl Parser {
           }
           token::AT => {
             self.bump();
-            let m = self.parse_mutability();
             let e = self.parse_prefix_expr();
             hi = e.span.hi;
             // HACK: turn @[...] into a @-evec
             ex = match e.node {
-              ExprVec(..) | ExprRepeat(..) if m == MutMutable =>
-                ExprVstore(e, ExprVstoreMutBox),
               ExprVec(..) |
               ExprLit(@codemap::Spanned { node: lit_str(..), span: _}) |
-              ExprRepeat(..) if m == MutImmutable => ExprVstore(e, ExprVstoreBox),
-              _ => self.mk_unary(UnBox(m), e)
+              ExprRepeat(..) => ExprVstore(e, ExprVstoreBox),
+              _ => self.mk_unary(UnBox, e)
             };
           }
           token::TILDE => {
@@ -4264,21 +4261,28 @@ impl Parser {
                               path: Path,
                               outer_attrs: ~[ast::Attribute],
                               id_sp: Span) -> (ast::item_, ~[ast::Attribute]) {
-        let maybe_i = self.sess.included_mod_stack.iter().position(|p| *p == path);
-        match maybe_i {
-            Some(i) => {
-                let stack = &self.sess.included_mod_stack;
-                let mut err = ~"circular modules: ";
-                for p in stack.slice(i, stack.len()).iter() {
-                    p.display().with_str(|s| err.push_str(s));
-                    err.push_str(" -> ");
+        {
+            let mut included_mod_stack = self.sess
+                                             .included_mod_stack
+                                             .borrow_mut();
+            let maybe_i = included_mod_stack.get()
+                                            .iter()
+                                            .position(|p| *p == path);
+            match maybe_i {
+                Some(i) => {
+                    let mut err = ~"circular modules: ";
+                    let len = included_mod_stack.get().len();
+                    for p in included_mod_stack.get().slice(i, len).iter() {
+                        p.display().with_str(|s| err.push_str(s));
+                        err.push_str(" -> ");
+                    }
+                    path.display().with_str(|s| err.push_str(s));
+                    self.span_fatal(id_sp, err);
                 }
-                path.display().with_str(|s| err.push_str(s));
-                self.span_fatal(id_sp, err);
+                None => ()
             }
-            None => ()
+            included_mod_stack.get().push(path.clone());
         }
-        self.sess.included_mod_stack.push(path.clone());
 
         let mut p0 =
             new_sub_parser_from_file(self.sess,
@@ -4289,7 +4293,12 @@ impl Parser {
         let mod_attrs = vec::append(outer_attrs, inner);
         let first_item_outer_attrs = next;
         let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs);
-        self.sess.included_mod_stack.pop();
+        {
+            let mut included_mod_stack = self.sess
+                                             .included_mod_stack
+                                             .borrow_mut();
+            included_mod_stack.get().pop();
+        }
         return (ast::item_mod(m0), mod_attrs);
     }
 
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 5138115746e..a6239ab3806 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -148,7 +148,7 @@ pub struct print_stack_elt {
 
 pub static size_infinity: int = 0xffff;
 
-pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> @mut Printer {
+pub fn mk_printer(out: ~io::Writer, linewidth: uint) -> Printer {
     // Yes 3, it makes the ring buffers big enough to never
     // fall behind.
     let n: uint = 3 * linewidth;
@@ -156,7 +156,7 @@ pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> @mut Printer {
     let token: ~[token] = vec::from_elem(n, EOF);
     let size: ~[int] = vec::from_elem(n, 0);
     let scan_stack: ~[uint] = vec::from_elem(n, 0u);
-    @mut Printer {
+    Printer {
         out: out,
         buf_len: n,
         margin: linewidth as int,
@@ -171,7 +171,7 @@ pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> @mut Printer {
         scan_stack_empty: true,
         top: 0,
         bottom: 0,
-        print_stack: @mut ~[],
+        print_stack: ~[],
         pending_indentation: 0
     }
 }
@@ -255,7 +255,7 @@ pub fn mk_printer(out: @mut io::Writer, linewidth: uint) -> @mut Printer {
  * called 'print'.
  */
 pub struct Printer {
-    out: @mut io::Writer,
+    out: ~io::Writer,
     buf_len: uint,
     margin: int, // width of lines we're constrained to
     space: int, // number of spaces left on line
@@ -276,7 +276,7 @@ pub struct Printer {
     top: uint, // index of top of scan_stack
     bottom: uint, // index of bottom of scan_stack
     // stack of blocks-in-progress being flushed by print
-    print_stack: @mut ~[print_stack_elt],
+    print_stack: ~[print_stack_elt],
     // buffered indentation to avoid writing trailing whitespace
     pending_indentation: int,
 }
@@ -461,7 +461,7 @@ impl Printer {
         self.pending_indentation += amount;
     }
     pub fn get_top(&mut self) -> print_stack_elt {
-        let print_stack = &mut *self.print_stack;
+        let print_stack = &mut self.print_stack;
         let n = print_stack.len();
         if n != 0u {
             print_stack[n - 1u]
@@ -506,7 +506,7 @@ impl Printer {
           }
           END => {
             debug!("print END -> pop END");
-            let print_stack = &mut *self.print_stack;
+            let print_stack = &mut self.print_stack;
             assert!((print_stack.len() != 0u));
             print_stack.pop();
           }
@@ -557,47 +557,47 @@ impl Printer {
 // Convenience functions to talk to the printer.
 //
 // "raw box"
-pub fn rbox(p: @mut Printer, indent: uint, b: breaks) {
+pub fn rbox(p: &mut Printer, indent: uint, b: breaks) {
     p.pretty_print(BEGIN(begin_t {
         offset: indent as int,
         breaks: b
     }));
 }
 
-pub fn ibox(p: @mut Printer, indent: uint) { rbox(p, indent, inconsistent); }
+pub fn ibox(p: &mut Printer, indent: uint) { rbox(p, indent, inconsistent); }
 
-pub fn cbox(p: @mut Printer, indent: uint) { rbox(p, indent, consistent); }
+pub fn cbox(p: &mut Printer, indent: uint) { rbox(p, indent, consistent); }
 
-pub fn break_offset(p: @mut Printer, n: uint, off: int) {
+pub fn break_offset(p: &mut Printer, n: uint, off: int) {
     p.pretty_print(BREAK(break_t {
         offset: off,
         blank_space: n as int
     }));
 }
 
-pub fn end(p: @mut Printer) { p.pretty_print(END); }
+pub fn end(p: &mut Printer) { p.pretty_print(END); }
 
-pub fn eof(p: @mut Printer) { p.pretty_print(EOF); }
+pub fn eof(p: &mut Printer) { p.pretty_print(EOF); }
 
-pub fn word(p: @mut Printer, wrd: &str) {
+pub fn word(p: &mut Printer, wrd: &str) {
     p.pretty_print(STRING(/* bad */ wrd.to_managed(), wrd.len() as int));
 }
 
-pub fn huge_word(p: @mut Printer, wrd: &str) {
+pub fn huge_word(p: &mut Printer, wrd: &str) {
     p.pretty_print(STRING(/* bad */ wrd.to_managed(), size_infinity));
 }
 
-pub fn zero_word(p: @mut Printer, wrd: &str) {
+pub fn zero_word(p: &mut Printer, wrd: &str) {
     p.pretty_print(STRING(/* bad */ wrd.to_managed(), 0));
 }
 
-pub fn spaces(p: @mut Printer, n: uint) { break_offset(p, n, 0); }
+pub fn spaces(p: &mut Printer, n: uint) { break_offset(p, n, 0); }
 
-pub fn zerobreak(p: @mut Printer) { spaces(p, 0u); }
+pub fn zerobreak(p: &mut Printer) { spaces(p, 0u); }
 
-pub fn space(p: @mut Printer) { spaces(p, 1u); }
+pub fn space(p: &mut Printer) { spaces(p, 1u); }
 
-pub fn hardbreak(p: @mut Printer) { spaces(p, size_infinity as uint); }
+pub fn hardbreak(p: &mut Printer) { spaces(p, size_infinity as uint); }
 
 pub fn hardbreak_tok_offset(off: int) -> token {
     BREAK(break_t {offset: off, blank_space: size_infinity})
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 79ef9c2cbbe..9725d6e38de 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -27,18 +27,20 @@ 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::Decorator;
 use std::io::mem::MemWriter;
 
-// The @ps is stored here to prevent recursive type.
-pub enum ann_node<'a> {
-    node_block(@ps, &'a ast::Block),
-    node_item(@ps, &'a ast::item),
-    node_expr(@ps, &'a ast::Expr),
-    node_pat(@ps, &'a ast::Pat),
+// The &mut ps is stored here to prevent recursive type.
+pub enum ann_node<'a,'b> {
+    node_block(&'b mut ps, &'a ast::Block),
+    node_item(&'b mut ps, &'a ast::item),
+    node_expr(&'b mut ps, &'a ast::Expr),
+    node_pat(&'b mut ps, &'a ast::Pat),
 }
 
 pub trait pp_ann {
@@ -66,45 +68,51 @@ pub struct CurrentCommentAndLiteral {
 }
 
 pub struct ps {
-    s: @mut pp::Printer,
+    s: pp::Printer,
     cm: Option<@CodeMap>,
     intr: @token::ident_interner,
     comments: Option<~[comments::cmnt]>,
     literals: Option<~[comments::lit]>,
-    cur_cmnt_and_lit: @mut CurrentCommentAndLiteral,
-    boxes: @mut ~[pp::breaks],
+    cur_cmnt_and_lit: CurrentCommentAndLiteral,
+    boxes: RefCell<~[pp::breaks]>,
     ann: @pp_ann
 }
 
-pub fn ibox(s: @ps, u: uint) {
-    s.boxes.push(pp::inconsistent);
-    pp::ibox(s.s, u);
+pub fn ibox(s: &mut ps, u: uint) {
+    {
+        let mut boxes = s.boxes.borrow_mut();
+        boxes.get().push(pp::inconsistent);
+    }
+    pp::ibox(&mut s.s, u);
 }
 
-pub fn end(s: @ps) {
-    s.boxes.pop();
-    pp::end(s.s);
+pub fn end(s: &mut ps) {
+    {
+        let mut boxes = s.boxes.borrow_mut();
+        boxes.get().pop();
+    }
+    pp::end(&mut s.s);
 }
 
-pub fn rust_printer(writer: @mut io::Writer, intr: @ident_interner) -> @ps {
+pub fn rust_printer(writer: ~io::Writer, intr: @ident_interner) -> ps {
     return rust_printer_annotated(writer, intr, @no_ann::new() as @pp_ann);
 }
 
-pub fn rust_printer_annotated(writer: @mut io::Writer,
+pub fn rust_printer_annotated(writer: ~io::Writer,
                               intr: @ident_interner,
                               ann: @pp_ann)
-                              -> @ps {
-    return @ps {
+                              -> ps {
+    return ps {
         s: pp::mk_printer(writer, default_columns),
         cm: None::<@CodeMap>,
         intr: intr,
         comments: None::<~[comments::cmnt]>,
         literals: None::<~[comments::lit]>,
-        cur_cmnt_and_lit: @mut CurrentCommentAndLiteral {
+        cur_cmnt_and_lit: CurrentCommentAndLiteral {
             cur_cmnt: 0,
             cur_lit: 0
         },
-        boxes: @mut ~[],
+        boxes: RefCell::new(~[]),
         ann: ann
     };
 }
@@ -118,11 +126,11 @@ pub static default_columns: uint = 78u;
 // copy forward.
 pub fn print_crate(cm: @CodeMap,
                    intr: @ident_interner,
-                   span_diagnostic: @mut diagnostic::SpanHandler,
+                   span_diagnostic: @diagnostic::SpanHandler,
                    crate: &ast::Crate,
                    filename: @str,
-                   input: @mut io::Reader,
-                   out: @mut io::Writer,
+                   input: &mut io::Reader,
+                   out: ~io::Writer,
                    ann: @pp_ann,
                    is_expanded: bool) {
     let (cmnts, lits) = comments::gather_comments_and_literals(
@@ -130,7 +138,7 @@ pub fn print_crate(cm: @CodeMap,
         filename,
         input
     );
-    let s = @ps {
+    let mut s = ps {
         s: pp::mk_printer(out, default_columns),
         cm: Some(cm),
         intr: intr,
@@ -143,20 +151,20 @@ pub fn print_crate(cm: @CodeMap,
         } else {
             Some(lits)
         },
-        cur_cmnt_and_lit: @mut CurrentCommentAndLiteral {
+        cur_cmnt_and_lit: CurrentCommentAndLiteral {
             cur_cmnt: 0,
             cur_lit: 0
         },
-        boxes: @mut ~[],
+        boxes: RefCell::new(~[]),
         ann: ann
     };
-    print_crate_(s, crate);
+    print_crate_(&mut s, crate);
 }
 
-pub fn print_crate_(s: @ps, crate: &ast::Crate) {
+pub fn print_crate_(s: &mut ps, crate: &ast::Crate) {
     print_mod(s, &crate.module, crate.attrs);
     print_remaining_comments(s);
-    eof(s.s);
+    eof(&mut s.s);
 }
 
 pub fn ty_to_str(ty: &ast::Ty, intr: @ident_interner) -> ~str {
@@ -203,26 +211,30 @@ pub fn path_to_str(p: &ast::Path, intr: @ident_interner) -> ~str {
 pub fn fun_to_str(decl: &ast::fn_decl, purity: ast::purity, name: ast::Ident,
                   opt_explicit_self: Option<ast::explicit_self_>,
                   generics: &ast::Generics, intr: @ident_interner) -> ~str {
-    let wr = @mut MemWriter::new();
-    let s = rust_printer(wr as @mut io::Writer, intr);
-    print_fn(s, decl, Some(purity), AbiSet::Rust(),
+    let wr = ~MemWriter::new();
+    let mut s = rust_printer(wr as ~io::Writer, intr);
+    print_fn(&mut s, decl, Some(purity), AbiSet::Rust(),
              name, generics, opt_explicit_self, ast::inherited);
-    end(s); // Close the head box
-    end(s); // Close the outer box
-    eof(s.s);
-    str::from_utf8_owned(wr.inner_ref().to_owned())
+    end(&mut s); // Close the head box
+    end(&mut s); // Close the outer box
+    eof(&mut s.s);
+    unsafe {
+        get_mem_writer(&mut s.s.out)
+    }
 }
 
 pub fn block_to_str(blk: &ast::Block, intr: @ident_interner) -> ~str {
-    let wr = @mut MemWriter::new();
-    let s = rust_printer(wr as @mut io::Writer, intr);
+    let wr = ~MemWriter::new();
+    let mut s = rust_printer(wr as ~io::Writer, intr);
     // containing cbox, will be closed by print-block at }
-    cbox(s, indent_unit);
+    cbox(&mut s, indent_unit);
     // head-ibox, will be closed by print-block after {
-    ibox(s, 0u);
-    print_block(s, blk);
-    eof(s.s);
-    str::from_utf8_owned(wr.inner_ref().to_owned())
+    ibox(&mut s, 0u);
+    print_block(&mut s, blk);
+    eof(&mut s.s);
+    unsafe {
+        get_mem_writer(&mut s.s.out)
+    }
 }
 
 pub fn meta_item_to_str(mi: &ast::MetaItem, intr: @ident_interner) -> ~str {
@@ -237,28 +249,34 @@ pub fn variant_to_str(var: &ast::variant, intr: @ident_interner) -> ~str {
     to_str(var, print_variant, intr)
 }
 
-pub fn cbox(s: @ps, u: uint) {
-    s.boxes.push(pp::consistent);
-    pp::cbox(s.s, u);
+pub fn cbox(s: &mut ps, u: uint) {
+    {
+        let mut boxes = s.boxes.borrow_mut();
+        boxes.get().push(pp::consistent);
+    }
+    pp::cbox(&mut s.s, u);
 }
 
 // "raw box"
-pub fn rbox(s: @ps, u: uint, b: pp::breaks) {
-    s.boxes.push(b);
-    pp::rbox(s.s, u, b);
+pub fn rbox(s: &mut ps, u: uint, b: pp::breaks) {
+    {
+        let mut boxes = s.boxes.borrow_mut();
+        boxes.get().push(b);
+    }
+    pp::rbox(&mut s.s, u, b);
 }
 
-pub fn nbsp(s: @ps) { word(s.s, " "); }
+pub fn nbsp(s: &mut ps) { word(&mut s.s, " "); }
 
-pub fn word_nbsp(s: @ps, w: &str) { word(s.s, w); nbsp(s); }
+pub fn word_nbsp(s: &mut ps, w: &str) { word(&mut s.s, w); nbsp(s); }
 
-pub fn word_space(s: @ps, w: &str) { word(s.s, w); space(s.s); }
+pub fn word_space(s: &mut ps, w: &str) { word(&mut s.s, w); space(&mut s.s); }
 
-pub fn popen(s: @ps) { word(s.s, "("); }
+pub fn popen(s: &mut ps) { word(&mut s.s, "("); }
 
-pub fn pclose(s: @ps) { word(s.s, ")"); }
+pub fn pclose(s: &mut ps) { word(&mut s.s, ")"); }
 
-pub fn head(s: @ps, w: &str) {
+pub fn head(s: &mut ps, w: &str) {
     // outer-box is consistent
     cbox(s, indent_unit);
     // head-box is inconsistent
@@ -269,49 +287,53 @@ pub fn head(s: @ps, w: &str) {
     }
 }
 
-pub fn bopen(s: @ps) {
-    word(s.s, "{");
+pub fn bopen(s: &mut ps) {
+    word(&mut s.s, "{");
     end(s); // close the head-box
 }
 
-pub fn bclose_(s: @ps, span: codemap::Span, indented: uint) {
+pub fn bclose_(s: &mut ps, span: codemap::Span, indented: uint) {
     bclose_maybe_open(s, span, indented, true);
 }
-pub fn bclose_maybe_open (s: @ps, span: codemap::Span, indented: uint,
+pub fn bclose_maybe_open (s: &mut ps, span: codemap::Span, indented: uint,
                           close_box: bool) {
     maybe_print_comment(s, span.hi);
     break_offset_if_not_bol(s, 1u, -(indented as int));
-    word(s.s, "}");
+    word(&mut s.s, "}");
     if close_box {
         end(s); // close the outer-box
     }
 }
-pub fn bclose(s: @ps, span: codemap::Span) { bclose_(s, span, indent_unit); }
+pub fn bclose(s: &mut ps, span: codemap::Span) { bclose_(s, span, indent_unit); }
 
-pub fn is_begin(s: @ps) -> bool {
+pub fn is_begin(s: &mut ps) -> bool {
     match s.s.last_token() { pp::BEGIN(_) => true, _ => false }
 }
 
-pub fn is_end(s: @ps) -> bool {
+pub fn is_end(s: &mut ps) -> bool {
     match s.s.last_token() { pp::END => true, _ => false }
 }
 
-pub fn is_bol(s: @ps) -> bool {
+pub fn is_bol(s: &mut ps) -> bool {
     return s.s.last_token().is_eof() || s.s.last_token().is_hardbreak_tok();
 }
 
-pub fn in_cbox(s: @ps) -> bool {
-    let boxes = &*s.boxes;
-    let len = boxes.len();
+pub fn in_cbox(s: &mut ps) -> bool {
+    let boxes = s.boxes.borrow();
+    let len = boxes.get().len();
     if len == 0u { return false; }
-    return boxes[len - 1u] == pp::consistent;
+    return boxes.get()[len - 1u] == pp::consistent;
 }
 
-pub fn hardbreak_if_not_bol(s: @ps) { if !is_bol(s) { hardbreak(s.s); } }
-pub fn space_if_not_bol(s: @ps) { if !is_bol(s) { space(s.s); } }
-pub fn break_offset_if_not_bol(s: @ps, n: uint, off: int) {
+pub fn hardbreak_if_not_bol(s: &mut ps) {
     if !is_bol(s) {
-        break_offset(s.s, n, off);
+        hardbreak(&mut s.s)
+    }
+}
+pub fn space_if_not_bol(s: &mut ps) { if !is_bol(s) { space(&mut s.s); } }
+pub fn break_offset_if_not_bol(s: &mut ps, n: uint, off: int) {
+    if !is_bol(s) {
+        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
@@ -324,15 +346,15 @@ pub fn break_offset_if_not_bol(s: @ps, n: uint, off: int) {
 
 // Synthesizes a comment that was not textually present in the original source
 // file.
-pub fn synth_comment(s: @ps, text: ~str) {
-    word(s.s, "/*");
-    space(s.s);
-    word(s.s, text);
-    space(s.s);
-    word(s.s, "*/");
+pub fn synth_comment(s: &mut ps, text: ~str) {
+    word(&mut s.s, "/*");
+    space(&mut s.s);
+    word(&mut s.s, text);
+    space(&mut s.s);
+    word(&mut s.s, "*/");
 }
 
-pub fn commasep<T>(s: @ps, b: breaks, elts: &[T], op: |@ps, &T|) {
+pub fn commasep<T>(s: &mut ps, b: breaks, elts: &[T], op: |&mut ps, &T|) {
     rbox(s, 0u, b);
     let mut first = true;
     for elt in elts.iter() {
@@ -344,10 +366,10 @@ pub fn commasep<T>(s: @ps, b: breaks, elts: &[T], op: |@ps, &T|) {
 
 
 pub fn commasep_cmnt<T>(
-                     s: @ps,
+                     s: &mut ps,
                      b: breaks,
                      elts: &[T],
-                     op: |@ps, &T|,
+                     op: |&mut ps, &T|,
                      get_span: |&T| -> codemap::Span) {
     rbox(s, 0u, b);
     let len = elts.len();
@@ -357,7 +379,7 @@ pub fn commasep_cmnt<T>(
         op(s, elt);
         i += 1u;
         if i < len {
-            word(s.s, ",");
+            word(&mut s.s, ",");
             maybe_print_trailing_comment(s, get_span(elt),
                                          Some(get_span(&elts[i]).hi));
             space_if_not_bol(s);
@@ -366,11 +388,11 @@ pub fn commasep_cmnt<T>(
     end(s);
 }
 
-pub fn commasep_exprs(s: @ps, b: breaks, exprs: &[@ast::Expr]) {
+pub fn commasep_exprs(s: &mut ps, b: breaks, exprs: &[@ast::Expr]) {
     commasep_cmnt(s, b, exprs, |p, &e| print_expr(p, e), |e| e.span);
 }
 
-pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: &[ast::Attribute]) {
+pub fn print_mod(s: &mut ps, _mod: &ast::_mod, attrs: &[ast::Attribute]) {
     print_inner_attributes(s, attrs);
     for vitem in _mod.view_items.iter() {
         print_view_item(s, vitem);
@@ -378,7 +400,7 @@ pub fn print_mod(s: @ps, _mod: &ast::_mod, attrs: &[ast::Attribute]) {
     for item in _mod.items.iter() { print_item(s, *item); }
 }
 
-pub fn print_foreign_mod(s: @ps, nmod: &ast::foreign_mod,
+pub fn print_foreign_mod(s: &mut ps, nmod: &ast::foreign_mod,
                          attrs: &[ast::Attribute]) {
     print_inner_attributes(s, attrs);
     for vitem in nmod.view_items.iter() {
@@ -387,29 +409,29 @@ pub fn print_foreign_mod(s: @ps, nmod: &ast::foreign_mod,
     for item in nmod.items.iter() { print_foreign_item(s, *item); }
 }
 
-pub fn print_opt_lifetime(s: @ps, lifetime: &Option<ast::Lifetime>) {
+pub fn print_opt_lifetime(s: &mut ps, lifetime: &Option<ast::Lifetime>) {
     for l in lifetime.iter() {
         print_lifetime(s, l);
         nbsp(s);
     }
 }
 
-pub fn print_type(s: @ps, ty: &ast::Ty) {
+pub fn print_type(s: &mut ps, ty: &ast::Ty) {
     maybe_print_comment(s, ty.span.lo);
     ibox(s, 0u);
     match ty.node {
-      ast::ty_nil => word(s.s, "()"),
-      ast::ty_bot => word(s.s, "!"),
-      ast::ty_box(ref mt) => { word(s.s, "@"); print_mt(s, mt); }
-      ast::ty_uniq(ty) => { word(s.s, "~"); print_type(s, ty); }
+      ast::ty_nil => word(&mut s.s, "()"),
+      ast::ty_bot => word(&mut s.s, "!"),
+      ast::ty_box(ty) => { word(&mut s.s, "@"); print_type(s, ty); }
+      ast::ty_uniq(ty) => { word(&mut s.s, "~"); print_type(s, ty); }
       ast::ty_vec(ty) => {
-        word(s.s, "[");
+        word(&mut s.s, "[");
         print_type(s, ty);
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
-      ast::ty_ptr(ref mt) => { word(s.s, "*"); print_mt(s, mt); }
+      ast::ty_ptr(ref mt) => { word(&mut s.s, "*"); print_mt(s, mt); }
       ast::ty_rptr(ref lifetime, ref mt) => {
-          word(s.s, "&");
+          word(&mut s.s, "&");
           print_opt_lifetime(s, lifetime);
           print_mt(s, mt);
       }
@@ -417,7 +439,7 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
         popen(s);
         commasep(s, inconsistent, *elts, print_type_ref);
         if elts.len() == 1 {
-            word(s.s, ",");
+            word(&mut s.s, ",");
         }
         pclose(s);
       }
@@ -441,16 +463,16 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
       }
       ast::ty_path(ref path, ref bounds, _) => print_bounded_path(s, path, bounds),
       ast::ty_fixed_length_vec(ty, v) => {
-        word(s.s, "[");
+        word(&mut s.s, "[");
         print_type(s, ty);
-        word(s.s, ", ..");
+        word(&mut s.s, ", ..");
         print_expr(s, v);
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
       ast::ty_typeof(e) => {
-          word(s.s, "typeof(");
+          word(&mut s.s, "typeof(");
           print_expr(s, e);
-          word(s.s, ")");
+          word(&mut s.s, ")");
       }
       ast::ty_infer => {
           fail!("print_type shouldn't see a ty_infer");
@@ -460,11 +482,11 @@ pub fn print_type(s: @ps, ty: &ast::Ty) {
     end(s);
 }
 
-pub fn print_type_ref(s: @ps, ty: &P<ast::Ty>) {
+pub fn print_type_ref(s: &mut ps, ty: &P<ast::Ty>) {
     print_type(s, *ty);
 }
 
-pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
+pub fn print_foreign_item(s: &mut ps, item: &ast::foreign_item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
@@ -473,7 +495,7 @@ pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
         print_fn(s, decl, None, AbiSet::Rust(), item.ident, generics, None,
                  item.vis);
         end(s); // end head-ibox
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the outer fn box
       }
       ast::foreign_item_static(t, m) => {
@@ -484,19 +506,21 @@ pub fn print_foreign_item(s: @ps, item: &ast::foreign_item) {
         print_ident(s, item.ident);
         word_space(s, ":");
         print_type(s, t);
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the head-ibox
         end(s); // end the outer cbox
       }
     }
 }
 
-pub fn print_item(s: @ps, item: &ast::item) {
+pub fn print_item(s: &mut ps, item: &ast::item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
-    let ann_node = node_item(s, item);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_item(s, item);
+        s.ann.pre(ann_node);
+    }
     match item.node {
       ast::item_static(ty, m, expr) => {
         head(s, visibility_qualified(item.vis, "static"));
@@ -506,12 +530,12 @@ pub fn print_item(s: @ps, item: &ast::item) {
         print_ident(s, item.ident);
         word_space(s, ":");
         print_type(s, ty);
-        space(s.s);
+        space(&mut s.s);
         end(s); // end the head-ibox
 
         word_space(s, "=");
         print_expr(s, expr);
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the outer cbox
 
       }
@@ -526,7 +550,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
             None,
             item.vis
         );
-        word(s.s, " ");
+        word(&mut s.s, " ");
         print_block_with_attrs(s, body, item.attrs);
       }
       ast::item_mod(ref _mod) => {
@@ -552,10 +576,10 @@ pub fn print_item(s: @ps, item: &ast::item) {
         print_generics(s, params);
         end(s); // end the inner ibox
 
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "=");
         print_type(s, ty);
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s); // end the outer ibox
       }
       ast::item_enum(ref enum_definition, ref params) => {
@@ -577,13 +601,13 @@ pub fn print_item(s: @ps, item: &ast::item) {
         head(s, visibility_qualified(item.vis, "impl"));
         if generics.is_parameterized() {
             print_generics(s, generics);
-            space(s.s);
+            space(&mut s.s);
         }
 
         match opt_trait {
             &Some(ref t) => {
                 print_trait_ref(s, t);
-                space(s.s);
+                space(&mut s.s);
                 word_space(s, "for");
             }
             &None => ()
@@ -591,7 +615,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
 
         print_type(s, ty);
 
-        space(s.s);
+        space(&mut s.s);
         bopen(s);
         print_inner_attributes(s, item.attrs);
         for meth in methods.iter() {
@@ -604,7 +628,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
         print_ident(s, item.ident);
         print_generics(s, generics);
         if traits.len() != 0u {
-            word(s.s, ":");
+            word(&mut s.s, ":");
             for (i, trait_) in traits.iter().enumerate() {
                 nbsp(s);
                 if i != 0 {
@@ -613,7 +637,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
                 print_path(s, &trait_.path, false);
             }
         }
-        word(s.s, " ");
+        word(&mut s.s, " ");
         bopen(s);
         for meth in methods.iter() {
             print_trait_method(s, meth);
@@ -625,7 +649,7 @@ pub fn print_item(s: @ps, item: &ast::item) {
                                    ..}) => {
         print_visibility(s, item.vis);
         print_path(s, pth, false);
-        word(s.s, "! ");
+        word(&mut s.s, "! ");
         print_ident(s, item.ident);
         cbox(s, indent_unit);
         popen(s);
@@ -634,24 +658,27 @@ pub fn print_item(s: @ps, item: &ast::item) {
         end(s);
       }
     }
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_item(s, item);
+        s.ann.post(ann_node);
+    }
 }
 
-fn print_trait_ref(s: @ps, t: &ast::trait_ref) {
+fn print_trait_ref(s: &mut ps, t: &ast::trait_ref) {
     print_path(s, &t.path, false);
 }
 
-pub fn print_enum_def(s: @ps, enum_definition: &ast::enum_def,
+pub fn print_enum_def(s: &mut ps, enum_definition: &ast::enum_def,
                       generics: &ast::Generics, ident: ast::Ident,
                       span: codemap::Span, visibility: ast::visibility) {
     head(s, visibility_qualified(visibility, "enum"));
     print_ident(s, ident);
     print_generics(s, generics);
-    space(s.s);
+    space(&mut s.s);
     print_variants(s, enum_definition.variants, span);
 }
 
-pub fn print_variants(s: @ps,
+pub fn print_variants(s: &mut ps,
                       variants: &[P<ast::variant>],
                       span: codemap::Span) {
     bopen(s);
@@ -661,7 +688,7 @@ pub fn print_variants(s: @ps,
         print_outer_attributes(s, v.node.attrs);
         ibox(s, indent_unit);
         print_variant(s, v);
-        word(s.s, ",");
+        word(&mut s.s, ",");
         end(s);
         maybe_print_trailing_comment(s, v.span, None);
     }
@@ -683,7 +710,7 @@ pub fn visibility_qualified(vis: ast::visibility, s: &str) -> ~str {
     }
 }
 
-pub fn print_visibility(s: @ps, vis: ast::visibility) {
+pub fn print_visibility(s: &mut ps, vis: ast::visibility) {
     match vis {
         ast::private | ast::public =>
         word_nbsp(s, visibility_to_str(vis)),
@@ -691,7 +718,7 @@ pub fn print_visibility(s: @ps, vis: ast::visibility) {
     }
 }
 
-pub fn print_struct(s: @ps,
+pub fn print_struct(s: &mut ps,
                     struct_def: &ast::struct_def,
                     generics: &ast::Generics,
                     ident: ast::Ident,
@@ -712,7 +739,7 @@ pub fn print_struct(s: @ps,
             });
             pclose(s);
         }
-        word(s.s, ";");
+        word(&mut s.s, ";");
         end(s);
         end(s); // close the outer-box
     } else {
@@ -731,7 +758,7 @@ pub fn print_struct(s: @ps,
                     print_ident(s, ident);
                     word_nbsp(s, ":");
                     print_type(s, field.node.ty);
-                    word(s.s, ",");
+                    word(&mut s.s, ",");
                 }
             }
         }
@@ -747,48 +774,48 @@ pub fn print_struct(s: @ps,
 /// 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: @ps, tt: &ast::token_tree) {
+pub fn print_tt(s: &mut ps, tt: &ast::token_tree) {
     match *tt {
       ast::tt_delim(ref tts) => print_tts(s, &(tts.as_slice())),
       ast::tt_tok(_, ref tk) => {
-          word(s.s, parse::token::to_str(s.intr, tk));
+          word(&mut s.s, parse::token::to_str(s.intr, tk));
       }
       ast::tt_seq(_, ref tts, ref sep, zerok) => {
-        word(s.s, "$(");
+        word(&mut s.s, "$(");
         for tt_elt in (*tts).iter() { print_tt(s, tt_elt); }
-        word(s.s, ")");
+        word(&mut s.s, ")");
         match (*sep) {
-          Some(ref tk) => word(s.s, parse::token::to_str(s.intr, tk)),
+          Some(ref tk) => word(&mut s.s, parse::token::to_str(s.intr, tk)),
           None => ()
         }
-        word(s.s, if zerok { "*" } else { "+" });
+        word(&mut s.s, if zerok { "*" } else { "+" });
       }
       ast::tt_nonterminal(_, name) => {
-        word(s.s, "$");
+        word(&mut s.s, "$");
         print_ident(s, name);
       }
     }
 }
 
-pub fn print_tts(s: @ps, tts: & &[ast::token_tree]) {
+pub fn print_tts(s: &mut ps, tts: & &[ast::token_tree]) {
     ibox(s, 0);
     for (i, tt) in tts.iter().enumerate() {
         if i != 0 {
-            space(s.s);
+            space(&mut s.s);
         }
         print_tt(s, tt);
     }
     end(s);
 }
 
-pub fn print_variant(s: @ps, v: &ast::variant) {
+pub fn print_variant(s: &mut ps, v: &ast::variant) {
     print_visibility(s, v.node.vis);
     match v.node.kind {
         ast::tuple_variant_kind(ref args) => {
             print_ident(s, v.node.name);
             if !args.is_empty() {
                 popen(s);
-                fn print_variant_arg(s: @ps, arg: &ast::variant_arg) {
+                fn print_variant_arg(s: &mut ps, arg: &ast::variant_arg) {
                     print_type(s, arg.ty);
                 }
                 commasep(s, consistent, *args, print_variant_arg);
@@ -803,7 +830,7 @@ pub fn print_variant(s: @ps, v: &ast::variant) {
     }
     match v.node.disr_expr {
       Some(d) => {
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "=");
         print_expr(s, d);
       }
@@ -811,7 +838,7 @@ pub fn print_variant(s: @ps, v: &ast::variant) {
     }
 }
 
-pub fn print_ty_method(s: @ps, m: &ast::TypeMethod) {
+pub fn print_ty_method(s: &mut ps, m: &ast::TypeMethod) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, m.span.lo);
     print_outer_attributes(s, m.attrs);
@@ -826,28 +853,28 @@ pub fn print_ty_method(s: @ps, m: &ast::TypeMethod) {
                 &None,
                 Some(&m.generics),
                 Some(m.explicit_self.node));
-    word(s.s, ";");
+    word(&mut s.s, ";");
 }
 
-pub fn print_trait_method(s: @ps, m: &ast::trait_method) {
+pub fn print_trait_method(s: &mut ps, m: &ast::trait_method) {
     match *m {
         required(ref ty_m) => print_ty_method(s, ty_m),
         provided(m) => print_method(s, m)
     }
 }
 
-pub fn print_method(s: @ps, meth: &ast::method) {
+pub fn print_method(s: &mut ps, meth: &ast::method) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, meth.span.lo);
     print_outer_attributes(s, meth.attrs);
     print_fn(s, meth.decl, Some(meth.purity), AbiSet::Rust(),
              meth.ident, &meth.generics, Some(meth.explicit_self.node),
              meth.vis);
-    word(s.s, " ");
+    word(&mut s.s, " ");
     print_block_with_attrs(s, meth.body, meth.attrs);
 }
 
-pub fn print_outer_attributes(s: @ps, attrs: &[ast::Attribute]) {
+pub fn print_outer_attributes(s: &mut ps, attrs: &[ast::Attribute]) {
     let mut count = 0;
     for attr in attrs.iter() {
         match attr.node.style {
@@ -858,14 +885,14 @@ pub fn print_outer_attributes(s: @ps, attrs: &[ast::Attribute]) {
     if count > 0 { hardbreak_if_not_bol(s); }
 }
 
-pub fn print_inner_attributes(s: @ps, attrs: &[ast::Attribute]) {
+pub fn print_inner_attributes(s: &mut ps, attrs: &[ast::Attribute]) {
     let mut count = 0;
     for attr in attrs.iter() {
         match attr.node.style {
           ast::AttrInner => {
             print_attribute(s, attr);
             if !attr.node.is_sugared_doc {
-                word(s.s, ";");
+                word(&mut s.s, ";");
             }
             count += 1;
           }
@@ -875,21 +902,21 @@ pub fn print_inner_attributes(s: @ps, attrs: &[ast::Attribute]) {
     if count > 0 { hardbreak_if_not_bol(s); }
 }
 
-pub fn print_attribute(s: @ps, attr: &ast::Attribute) {
+pub fn print_attribute(s: &mut ps, attr: &ast::Attribute) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, attr.span.lo);
     if attr.node.is_sugared_doc {
         let comment = attr.value_str().unwrap();
-        word(s.s, comment);
+        word(&mut s.s, comment);
     } else {
-        word(s.s, "#[");
+        word(&mut s.s, "#[");
         print_meta_item(s, attr.meta());
-        word(s.s, "]");
+        word(&mut s.s, "]");
     }
 }
 
 
-pub fn print_stmt(s: @ps, st: &ast::Stmt) {
+pub fn print_stmt(s: &mut ps, st: &ast::Stmt) {
     maybe_print_comment(s, st.span.lo);
     match st.node {
       ast::StmtDecl(decl, _) => {
@@ -902,33 +929,33 @@ pub fn print_stmt(s: @ps, st: &ast::Stmt) {
       ast::StmtSemi(expr, _) => {
         space_if_not_bol(s);
         print_expr(s, expr);
-        word(s.s, ";");
+        word(&mut s.s, ";");
       }
       ast::StmtMac(ref mac, semi) => {
         space_if_not_bol(s);
         print_mac(s, mac);
-        if semi { word(s.s, ";"); }
+        if semi { word(&mut s.s, ";"); }
       }
     }
-    if parse::classify::stmt_ends_with_semi(st) { word(s.s, ";"); }
+    if parse::classify::stmt_ends_with_semi(st) { word(&mut s.s, ";"); }
     maybe_print_trailing_comment(s, st.span, None);
 }
 
-pub fn print_block(s: @ps, blk: &ast::Block) {
+pub fn print_block(s: &mut ps, blk: &ast::Block) {
     print_possibly_embedded_block(s, blk, block_normal, indent_unit);
 }
 
-pub fn print_block_unclosed(s: @ps, blk: &ast::Block) {
+pub fn print_block_unclosed(s: &mut ps, blk: &ast::Block) {
     print_possibly_embedded_block_(s, blk, block_normal, indent_unit, &[],
                                  false);
 }
 
-pub fn print_block_unclosed_indent(s: @ps, blk: &ast::Block, indented: uint) {
+pub fn print_block_unclosed_indent(s: &mut ps, blk: &ast::Block, indented: uint) {
     print_possibly_embedded_block_(s, blk, block_normal, indented, &[],
                                    false);
 }
 
-pub fn print_block_with_attrs(s: @ps,
+pub fn print_block_with_attrs(s: &mut ps,
                               blk: &ast::Block,
                               attrs: &[ast::Attribute]) {
     print_possibly_embedded_block_(s, blk, block_normal, indent_unit, attrs,
@@ -937,7 +964,7 @@ pub fn print_block_with_attrs(s: @ps,
 
 pub enum embed_type { block_block_fn, block_normal, }
 
-pub fn print_possibly_embedded_block(s: @ps,
+pub fn print_possibly_embedded_block(s: &mut ps,
                                      blk: &ast::Block,
                                      embedded: embed_type,
                                      indented: uint) {
@@ -945,7 +972,7 @@ pub fn print_possibly_embedded_block(s: @ps,
         s, blk, embedded, indented, &[], true);
 }
 
-pub fn print_possibly_embedded_block_(s: @ps,
+pub fn print_possibly_embedded_block_(s: &mut ps,
                                       blk: &ast::Block,
                                       embedded: embed_type,
                                       indented: uint,
@@ -956,8 +983,10 @@ pub fn print_possibly_embedded_block_(s: @ps,
       ast::DefaultBlock => ()
     }
     maybe_print_comment(s, blk.span.lo);
-    let ann_node = node_block(s, blk);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_block(s, blk);
+        s.ann.pre(ann_node);
+    }
     match embedded {
       block_block_fn => end(s),
       block_normal => bopen(s)
@@ -978,17 +1007,20 @@ pub fn print_possibly_embedded_block_(s: @ps,
       _ => ()
     }
     bclose_maybe_open(s, blk.span, indented, close_box);
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_block(s, blk);
+        s.ann.post(ann_node);
+    }
 }
 
-pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
+pub fn print_if(s: &mut ps, test: &ast::Expr, blk: &ast::Block,
                 elseopt: Option<@ast::Expr>, chk: bool) {
     head(s, "if");
     if chk { word_nbsp(s, "check"); }
     print_expr(s, test);
-    space(s.s);
+    space(&mut s.s);
     print_block(s, blk);
-    fn do_else(s: @ps, els: Option<@ast::Expr>) {
+    fn do_else(s: &mut ps, els: Option<@ast::Expr>) {
         match els {
           Some(_else) => {
             match _else.node {
@@ -996,9 +1028,9 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
               ast::ExprIf(i, t, e) => {
                 cbox(s, indent_unit - 1u);
                 ibox(s, 0u);
-                word(s.s, " else if ");
+                word(&mut s.s, " else if ");
                 print_expr(s, i);
-                space(s.s);
+                space(&mut s.s);
                 print_block(s, t);
                 do_else(s, e);
               }
@@ -1006,7 +1038,7 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
               ast::ExprBlock(b) => {
                 cbox(s, indent_unit - 1u);
                 ibox(s, 0u);
-                word(s.s, " else ");
+                word(&mut s.s, " else ");
                 print_block(s, b);
               }
               // BLEAH, constraints would be great here
@@ -1021,12 +1053,12 @@ pub fn print_if(s: @ps, test: &ast::Expr, blk: &ast::Block,
     do_else(s, elseopt);
 }
 
-pub fn print_mac(s: @ps, m: &ast::mac) {
+pub fn print_mac(s: &mut ps, m: &ast::mac) {
     match m.node {
       // I think it's reasonable to hide the ctxt here:
       ast::mac_invoc_tt(ref pth, ref tts, _) => {
         print_path(s, pth, false);
-        word(s.s, "!");
+        word(&mut s.s, "!");
         popen(s);
         print_tts(s, &tts.as_slice());
         pclose(s);
@@ -1034,36 +1066,32 @@ pub fn print_mac(s: @ps, m: &ast::mac) {
     }
 }
 
-pub fn print_vstore(s: @ps, t: ast::Vstore) {
+pub fn print_vstore(s: &mut ps, t: ast::Vstore) {
     match t {
-        ast::VstoreFixed(Some(i)) => word(s.s, format!("{}", i)),
-        ast::VstoreFixed(None) => word(s.s, "_"),
-        ast::VstoreUniq => word(s.s, "~"),
-        ast::VstoreBox => word(s.s, "@"),
+        ast::VstoreFixed(Some(i)) => word(&mut s.s, format!("{}", i)),
+        ast::VstoreFixed(None) => word(&mut s.s, "_"),
+        ast::VstoreUniq => word(&mut s.s, "~"),
+        ast::VstoreBox => word(&mut s.s, "@"),
         ast::VstoreSlice(ref r) => {
-            word(s.s, "&");
+            word(&mut s.s, "&");
             print_opt_lifetime(s, r);
         }
     }
 }
 
-pub fn print_expr_vstore(s: @ps, t: ast::ExprVstore) {
+pub fn print_expr_vstore(s: &mut ps, t: ast::ExprVstore) {
     match t {
-      ast::ExprVstoreUniq => word(s.s, "~"),
-      ast::ExprVstoreBox => word(s.s, "@"),
-      ast::ExprVstoreMutBox => {
-        word(s.s, "@");
-        word(s.s, "mut");
-      }
-      ast::ExprVstoreSlice => word(s.s, "&"),
+      ast::ExprVstoreUniq => word(&mut s.s, "~"),
+      ast::ExprVstoreBox => word(&mut s.s, "@"),
+      ast::ExprVstoreSlice => word(&mut s.s, "&"),
       ast::ExprVstoreMutSlice => {
-        word(s.s, "&");
-        word(s.s, "mut");
+        word(&mut s.s, "&");
+        word(&mut s.s, "mut");
       }
     }
 }
 
-pub fn print_call_pre(s: @ps,
+pub fn print_call_pre(s: &mut ps,
                       sugar: ast::CallSugar,
                       base_args: &mut ~[@ast::Expr])
                    -> Option<@ast::Expr> {
@@ -1080,7 +1108,7 @@ pub fn print_call_pre(s: @ps,
     }
 }
 
-pub fn print_call_post(s: @ps,
+pub fn print_call_post(s: &mut ps,
                        sugar: ast::CallSugar,
                        blk: &Option<@ast::Expr>,
                        base_args: &mut ~[@ast::Expr]) {
@@ -1107,8 +1135,8 @@ pub fn print_call_post(s: @ps,
     }
 }
 
-pub fn print_expr(s: @ps, expr: &ast::Expr) {
-    fn print_field(s: @ps, field: &ast::Field) {
+pub fn print_expr(s: &mut ps, expr: &ast::Expr) {
+    fn print_field(s: &mut ps, field: &ast::Field) {
         ibox(s, indent_unit);
         print_ident(s, field.ident.node);
         word_space(s, ":");
@@ -1119,8 +1147,10 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
 
     maybe_print_comment(s, expr.span.lo);
     ibox(s, indent_unit);
-    let ann_node = node_expr(s, expr);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_expr(s, expr);
+        s.ann.pre(ann_node);
+    }
     match expr.node {
         ast::ExprVstore(e, v) => {
             print_expr_vstore(s, v);
@@ -1128,53 +1158,53 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         },
       ast::ExprVec(ref exprs, mutbl) => {
         ibox(s, indent_unit);
-        word(s.s, "[");
+        word(&mut s.s, "[");
         if mutbl == ast::MutMutable {
-            word(s.s, "mut");
+            word(&mut s.s, "mut");
             if exprs.len() > 0u { nbsp(s); }
         }
         commasep_exprs(s, inconsistent, *exprs);
-        word(s.s, "]");
+        word(&mut s.s, "]");
         end(s);
       }
 
       ast::ExprRepeat(element, count, mutbl) => {
         ibox(s, indent_unit);
-        word(s.s, "[");
+        word(&mut s.s, "[");
         if mutbl == ast::MutMutable {
-            word(s.s, "mut");
+            word(&mut s.s, "mut");
             nbsp(s);
         }
         print_expr(s, element);
-        word(s.s, ",");
-        word(s.s, "..");
+        word(&mut s.s, ",");
+        word(&mut s.s, "..");
         print_expr(s, count);
-        word(s.s, "]");
+        word(&mut s.s, "]");
         end(s);
       }
 
       ast::ExprStruct(ref path, ref fields, wth) => {
         print_path(s, path, true);
-        word(s.s, "{");
+        word(&mut s.s, "{");
         commasep_cmnt(s, consistent, (*fields), print_field, get_span);
         match wth {
             Some(expr) => {
                 ibox(s, indent_unit);
-                word(s.s, ",");
-                space(s.s);
-                word(s.s, "..");
+                word(&mut s.s, ",");
+                space(&mut s.s);
+                word(&mut s.s, "..");
                 print_expr(s, expr);
                 end(s);
             }
-            _ => (word(s.s, ","))
+            _ => (word(&mut s.s, ","))
         }
-        word(s.s, "}");
+        word(&mut s.s, "}");
       }
       ast::ExprTup(ref exprs) => {
         popen(s);
         commasep_exprs(s, inconsistent, *exprs);
         if exprs.len() == 1 {
-            word(s.s, ",");
+            word(&mut s.s, ",");
         }
         pclose(s);
       }
@@ -1188,31 +1218,31 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         let mut base_args = (*args).clone();
         let blk = print_call_pre(s, sugar, &mut base_args);
         print_expr(s, func);
-        word(s.s, ".");
+        word(&mut s.s, ".");
         print_ident(s, ident);
         if tys.len() > 0u {
-            word(s.s, "::<");
+            word(&mut s.s, "::<");
             commasep(s, inconsistent, *tys, print_type_ref);
-            word(s.s, ">");
+            word(&mut s.s, ">");
         }
         print_call_post(s, sugar, &blk, &mut base_args);
       }
       ast::ExprBinary(_, op, lhs, rhs) => {
         print_expr(s, lhs);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, ast_util::binop_to_str(op));
         print_expr(s, rhs);
       }
       ast::ExprUnary(_, op, expr) => {
-        word(s.s, ast_util::unop_to_str(op));
+        word(&mut s.s, ast_util::unop_to_str(op));
         print_expr(s, expr);
       }
       ast::ExprAddrOf(m, expr) => {
-        word(s.s, "&");
+        word(&mut s.s, "&");
         print_mutability(s, m);
         // Avoid `& &e` => `&&e`.
         match (m, &expr.node) {
-            (ast::MutImmutable, &ast::ExprAddrOf(..)) => space(s.s),
+            (ast::MutImmutable, &ast::ExprAddrOf(..)) => space(&mut s.s),
             _ => { }
         }
         print_expr(s, expr);
@@ -1220,7 +1250,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
       ast::ExprLit(lit) => print_literal(s, lit),
       ast::ExprCast(expr, ty) => {
         print_expr(s, expr);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "as");
         print_type(s, ty);
       }
@@ -1230,31 +1260,31 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
       ast::ExprWhile(test, blk) => {
         head(s, "while");
         print_expr(s, test);
-        space(s.s);
+        space(&mut s.s);
         print_block(s, blk);
       }
       ast::ExprForLoop(pat, iter, blk, opt_ident) => {
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_ident(s, *ident);
             word_space(s, ":");
         }
         head(s, "for");
         print_pat(s, pat);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "in");
         print_expr(s, iter);
-        space(s.s);
+        space(&mut s.s);
         print_block(s, blk);
       }
       ast::ExprLoop(blk, opt_ident) => {
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_ident(s, *ident);
             word_space(s, ":");
         }
         head(s, "loop");
-        space(s.s);
+        space(&mut s.s);
         print_block(s, blk);
       }
       ast::ExprMatch(expr, ref arms) => {
@@ -1262,26 +1292,26 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         ibox(s, 4);
         word_nbsp(s, "match");
         print_expr(s, expr);
-        space(s.s);
+        space(&mut s.s);
         bopen(s);
         let len = arms.len();
         for (i, arm) in arms.iter().enumerate() {
-            space(s.s);
+            space(&mut s.s);
             cbox(s, indent_unit);
             ibox(s, 0u);
             let mut first = true;
             for p in arm.pats.iter() {
                 if first {
                     first = false;
-                } else { space(s.s); word_space(s, "|"); }
+                } else { space(&mut s.s); word_space(s, "|"); }
                 print_pat(s, *p);
             }
-            space(s.s);
+            space(&mut s.s);
             match arm.guard {
               Some(e) => {
                 word_space(s, "if");
                 print_expr(s, e);
-                space(s.s);
+                space(&mut s.s);
               }
               None => ()
             }
@@ -1309,7 +1339,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
                         }
                         if !expr_is_simple_block(expr)
                             && i < len - 1 {
-                            word(s.s, ",");
+                            word(&mut s.s, ",");
                         }
                         end(s); // close enclosing cbox
                     }
@@ -1329,7 +1359,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         //
         // if !decl.inputs.is_empty() {
         print_fn_block_args(s, decl);
-        space(s.s);
+        space(&mut s.s);
         // }
         assert!(body.stmts.is_empty());
         assert!(body.expr.is_some());
@@ -1356,7 +1386,7 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
         //
         // if !decl.inputs.is_empty() {
         print_proc_args(s, decl);
-        space(s.s);
+        space(&mut s.s);
         // }
         assert!(body.stmts.is_empty());
         assert!(body.expr.is_some());
@@ -1388,70 +1418,70 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
       }
       ast::ExprAssign(lhs, rhs) => {
         print_expr(s, lhs);
-        space(s.s);
+        space(&mut s.s);
         word_space(s, "=");
         print_expr(s, rhs);
       }
       ast::ExprAssignOp(_, op, lhs, rhs) => {
         print_expr(s, lhs);
-        space(s.s);
-        word(s.s, ast_util::binop_to_str(op));
+        space(&mut s.s);
+        word(&mut s.s, ast_util::binop_to_str(op));
         word_space(s, "=");
         print_expr(s, rhs);
       }
       ast::ExprField(expr, id, ref tys) => {
         print_expr(s, expr);
-        word(s.s, ".");
+        word(&mut s.s, ".");
         print_ident(s, id);
         if tys.len() > 0u {
-            word(s.s, "::<");
+            word(&mut s.s, "::<");
             commasep(s, inconsistent, *tys, print_type_ref);
-            word(s.s, ">");
+            word(&mut s.s, ">");
         }
       }
       ast::ExprIndex(_, expr, index) => {
         print_expr(s, expr);
-        word(s.s, "[");
+        word(&mut s.s, "[");
         print_expr(s, index);
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
       ast::ExprPath(ref path) => print_path(s, path, true),
-      ast::ExprSelf => word(s.s, "self"),
+      ast::ExprSelf => word(&mut s.s, "self"),
       ast::ExprBreak(opt_ident) => {
-        word(s.s, "break");
-        space(s.s);
+        word(&mut s.s, "break");
+        space(&mut s.s);
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_name(s, *ident);
-            space(s.s);
+            space(&mut s.s);
         }
       }
       ast::ExprAgain(opt_ident) => {
-        word(s.s, "continue");
-        space(s.s);
+        word(&mut s.s, "continue");
+        space(&mut s.s);
         for ident in opt_ident.iter() {
-            word(s.s, "'");
+            word(&mut s.s, "'");
             print_name(s, *ident);
-            space(s.s)
+            space(&mut s.s)
         }
       }
       ast::ExprRet(result) => {
-        word(s.s, "return");
+        word(&mut s.s, "return");
         match result {
-          Some(expr) => { word(s.s, " "); print_expr(s, expr); }
+          Some(expr) => { word(&mut s.s, " "); print_expr(s, expr); }
           _ => ()
         }
       }
       ast::ExprLogLevel => {
-        word(s.s, "__log_level");
+        word(&mut s.s, "__log_level");
         popen(s);
         pclose(s);
       }
       ast::ExprInlineAsm(ref a) => {
         if a.volatile {
-            word(s.s, "__volatile__ asm!");
+            word(&mut s.s, "__volatile__ asm!");
         } else {
-            word(s.s, "asm!");
+            word(&mut s.s, "asm!");
         }
         popen(s);
         print_string(s, a.asm, a.asm_str_style);
@@ -1482,11 +1512,14 @@ pub fn print_expr(s: @ps, expr: &ast::Expr) {
           pclose(s);
       }
     }
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_expr(s, expr);
+        s.ann.post(ann_node);
+    }
     end(s);
 }
 
-pub fn print_local_decl(s: @ps, loc: &ast::Local) {
+pub fn print_local_decl(s: &mut ps, loc: &ast::Local) {
     print_pat(s, loc.pat);
     match loc.ty.node {
       ast::ty_infer => (),
@@ -1494,7 +1527,7 @@ pub fn print_local_decl(s: @ps, loc: &ast::Local) {
     }
 }
 
-pub fn print_decl(s: @ps, decl: &ast::Decl) {
+pub fn print_decl(s: &mut ps, decl: &ast::Decl) {
     maybe_print_comment(s, decl.span.lo);
     match decl.node {
       ast::DeclLocal(ref loc) => {
@@ -1502,7 +1535,7 @@ pub fn print_decl(s: @ps, decl: &ast::Decl) {
         ibox(s, indent_unit);
         word_nbsp(s, "let");
 
-        fn print_local(s: @ps, loc: &ast::Local) {
+        fn print_local(s: &mut ps, loc: &ast::Local) {
             ibox(s, indent_unit);
             print_local_decl(s, loc);
             end(s);
@@ -1523,28 +1556,28 @@ pub fn print_decl(s: @ps, decl: &ast::Decl) {
     }
 }
 
-pub fn print_ident(s: @ps, ident: ast::Ident) {
-    word(s.s, ident_to_str(&ident));
+pub fn print_ident(s: &mut ps, ident: ast::Ident) {
+    word(&mut s.s, ident_to_str(&ident));
 }
 
-pub fn print_name(s: @ps, name: ast::Name) {
-    word(s.s, interner_get(name));
+pub fn print_name(s: &mut ps, name: ast::Name) {
+    word(&mut s.s, interner_get(name));
 }
 
-pub fn print_for_decl(s: @ps, loc: &ast::Local, coll: &ast::Expr) {
+pub fn print_for_decl(s: &mut ps, loc: &ast::Local, coll: &ast::Expr) {
     print_local_decl(s, loc);
-    space(s.s);
+    space(&mut s.s);
     word_space(s, "in");
     print_expr(s, coll);
 }
 
-fn print_path_(s: @ps,
+fn print_path_(s: &mut ps,
                path: &ast::Path,
                colons_before_params: bool,
                opt_bounds: &Option<OptVec<ast::TyParamBound>>) {
     maybe_print_comment(s, path.span.lo);
     if path.global {
-        word(s.s, "::");
+        word(&mut s.s, "::");
     }
 
     let mut first = true;
@@ -1552,7 +1585,7 @@ fn print_path_(s: @ps,
         if first {
             first = false
         } else {
-            word(s.s, "::")
+            word(&mut s.s, "::")
         }
 
         print_ident(s, segment.identifier);
@@ -1567,9 +1600,9 @@ fn print_path_(s: @ps,
 
         if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
             if colons_before_params {
-                word(s.s, "::")
+                word(&mut s.s, "::")
             }
-            word(s.s, "<");
+            word(&mut s.s, "<");
 
             let mut comma = false;
             for lifetime in segment.lifetimes.iter() {
@@ -1590,29 +1623,31 @@ fn print_path_(s: @ps,
                          print_type_ref);
             }
 
-            word(s.s, ">")
+            word(&mut s.s, ">")
         }
     }
 }
 
-pub fn print_path(s: @ps, path: &ast::Path, colons_before_params: bool) {
+pub fn print_path(s: &mut ps, path: &ast::Path, colons_before_params: bool) {
     print_path_(s, path, colons_before_params, &None)
 }
 
-pub fn print_bounded_path(s: @ps, path: &ast::Path,
+pub fn print_bounded_path(s: &mut ps, path: &ast::Path,
                           bounds: &Option<OptVec<ast::TyParamBound>>) {
     print_path_(s, path, false, bounds)
 }
 
-pub fn print_pat(s: @ps, pat: &ast::Pat) {
+pub fn print_pat(s: &mut ps, pat: &ast::Pat) {
     maybe_print_comment(s, pat.span.lo);
-    let ann_node = node_pat(s, pat);
-    s.ann.pre(ann_node);
+    {
+        let ann_node = node_pat(s, pat);
+        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 => word(s.s, "_"),
-      ast::PatWildMulti => word(s.s, ".."),
+      ast::PatWild => word(&mut s.s, "_"),
+      ast::PatWildMulti => word(&mut s.s, ".."),
       ast::PatIdent(binding_mode, ref path, sub) => {
           match binding_mode {
               ast::BindByRef(mutbl) => {
@@ -1627,7 +1662,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
           print_path(s, path, true);
           match sub {
               Some(p) => {
-                  word(s.s, "@");
+                  word(&mut s.s, "@");
                   print_pat(s, p);
               }
               None => ()
@@ -1636,7 +1671,7 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
       ast::PatEnum(ref path, ref args_) => {
         print_path(s, path, true);
         match *args_ {
-          None => word(s.s, "(..)"),
+          None => word(&mut s.s, "(..)"),
           Some(ref args) => {
             if !args.is_empty() {
               popen(s);
@@ -1649,8 +1684,8 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
       }
       ast::PatStruct(ref path, ref fields, etc) => {
         print_path(s, path, true);
-        word(s.s, "{");
-        fn print_field(s: @ps, f: &ast::FieldPat) {
+        word(&mut s.s, "{");
+        fn print_field(s: &mut ps, f: &ast::FieldPat) {
             cbox(s, indent_unit);
             print_ident(s, f.ident);
             word_space(s, ":");
@@ -1663,39 +1698,39 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
                       get_span);
         if etc {
             if fields.len() != 0u { word_space(s, ","); }
-            word(s.s, "..");
+            word(&mut s.s, "..");
         }
-        word(s.s, "}");
+        word(&mut s.s, "}");
       }
       ast::PatTup(ref elts) => {
         popen(s);
         commasep(s, inconsistent, *elts, |s, &p| print_pat(s, p));
         if elts.len() == 1 {
-            word(s.s, ",");
+            word(&mut s.s, ",");
         }
         pclose(s);
       }
       ast::PatBox(inner) => {
-          word(s.s, "@");
+          word(&mut s.s, "@");
           print_pat(s, inner);
       }
       ast::PatUniq(inner) => {
-          word(s.s, "~");
+          word(&mut s.s, "~");
           print_pat(s, inner);
       }
       ast::PatRegion(inner) => {
-          word(s.s, "&");
+          word(&mut s.s, "&");
           print_pat(s, inner);
       }
       ast::PatLit(e) => print_expr(s, e),
       ast::PatRange(begin, end) => {
         print_expr(s, begin);
-        space(s.s);
-        word(s.s, "..");
+        space(&mut s.s);
+        word(&mut s.s, "..");
         print_expr(s, end);
       }
       ast::PatVec(ref before, slice, ref after) => {
-        word(s.s, "[");
+        word(&mut s.s, "[");
         commasep(s, inconsistent, *before, |s, &p| print_pat(s, p));
         for &p in slice.iter() {
             if !before.is_empty() { word_space(s, ","); }
@@ -1703,16 +1738,19 @@ pub fn print_pat(s: @ps, pat: &ast::Pat) {
                 @ast::Pat { node: ast::PatWildMulti, .. } => {
                     // this case is handled by print_pat
                 }
-                _ => word(s.s, ".."),
+                _ => word(&mut s.s, ".."),
             }
             print_pat(s, p);
             if !after.is_empty() { word_space(s, ","); }
         }
         commasep(s, inconsistent, *after, |s, &p| print_pat(s, p));
-        word(s.s, "]");
+        word(&mut s.s, "]");
       }
     }
-    s.ann.post(ann_node);
+    {
+        let ann_node = node_pat(s, pat);
+        s.ann.post(ann_node);
+    }
 }
 
 pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_interner) -> ~str {
@@ -1720,31 +1758,31 @@ pub fn explicit_self_to_str(explicit_self: &ast::explicit_self_, intr: @ident_in
 }
 
 // Returns whether it printed anything
-pub fn print_explicit_self(s: @ps, explicit_self: ast::explicit_self_) -> bool {
+pub fn print_explicit_self(s: &mut ps, explicit_self: ast::explicit_self_) -> bool {
     match explicit_self {
         ast::sty_static => { return false; }
         ast::sty_value(m) => {
             print_mutability(s, m);
-            word(s.s, "self");
+            word(&mut s.s, "self");
         }
         ast::sty_uniq(m) => {
             print_mutability(s, m);
-            word(s.s, "~self");
+            word(&mut s.s, "~self");
         }
         ast::sty_region(ref lt, m) => {
-            word(s.s, "&");
+            word(&mut s.s, "&");
             print_opt_lifetime(s, lt);
             print_mutability(s, m);
-            word(s.s, "self");
+            word(&mut s.s, "self");
         }
         ast::sty_box(m) => {
-            word(s.s, "@"); print_mutability(s, m); word(s.s, "self");
+            word(&mut s.s, "@"); print_mutability(s, m); word(&mut s.s, "self");
         }
     }
     return true;
 }
 
-pub fn print_fn(s: @ps,
+pub fn print_fn(s: &mut ps,
                 decl: &ast::fn_decl,
                 purity: Option<ast::purity>,
                 abis: AbiSet,
@@ -1760,7 +1798,7 @@ pub fn print_fn(s: @ps,
     print_fn_args_and_ret(s, decl, opt_explicit_self);
 }
 
-pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
+pub fn print_fn_args(s: &mut ps, decl: &ast::fn_decl,
                  opt_explicit_self: Option<ast::explicit_self_>) {
     // It is unfortunate to duplicate the commasep logic, but we want the
     // self type and the args all in the same box.
@@ -1778,12 +1816,12 @@ pub fn print_fn_args(s: @ps, decl: &ast::fn_decl,
     end(s);
 }
 
-pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl,
+pub fn print_fn_args_and_ret(s: &mut ps, decl: &ast::fn_decl,
                              opt_explicit_self: Option<ast::explicit_self_>) {
     popen(s);
     print_fn_args(s, decl, opt_explicit_self);
     if decl.variadic {
-        word(s.s, ", ...");
+        word(&mut s.s, ", ...");
     }
     pclose(s);
 
@@ -1798,10 +1836,10 @@ pub fn print_fn_args_and_ret(s: @ps, decl: &ast::fn_decl,
     }
 }
 
-pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
-    word(s.s, "|");
+pub fn print_fn_block_args(s: &mut ps, decl: &ast::fn_decl) {
+    word(&mut s.s, "|");
     print_fn_args(s, decl, None);
-    word(s.s, "|");
+    word(&mut s.s, "|");
 
     match decl.output.node {
         ast::ty_infer => {}
@@ -1815,11 +1853,11 @@ pub fn print_fn_block_args(s: @ps, decl: &ast::fn_decl) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
-pub fn print_proc_args(s: @ps, decl: &ast::fn_decl) {
-    word(s.s, "proc");
-    word(s.s, "(");
+pub fn print_proc_args(s: &mut ps, decl: &ast::fn_decl) {
+    word(&mut s.s, "proc");
+    word(&mut s.s, "(");
     print_fn_args(s, decl, None);
-    word(s.s, ")");
+    word(&mut s.s, ")");
 
     match decl.output.node {
         ast::ty_infer => {}
@@ -1833,10 +1871,10 @@ pub fn print_proc_args(s: @ps, decl: &ast::fn_decl) {
     maybe_print_comment(s, decl.output.span.lo);
 }
 
-pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>,
+pub fn print_bounds(s: &mut ps, bounds: &OptVec<ast::TyParamBound>,
                     print_colon_anyway: bool) {
     if !bounds.is_empty() {
-        word(s.s, ":");
+        word(&mut s.s, ":");
         let mut first = true;
         for bound in bounds.iter() {
             nbsp(s);
@@ -1848,24 +1886,24 @@ pub fn print_bounds(s: @ps, bounds: &OptVec<ast::TyParamBound>,
 
             match *bound {
                 TraitTyParamBound(ref tref) => print_trait_ref(s, tref),
-                RegionTyParamBound => word(s.s, "'static"),
+                RegionTyParamBound => word(&mut s.s, "'static"),
             }
         }
     } else if print_colon_anyway {
-        word(s.s, ":");
+        word(&mut s.s, ":");
     }
 }
 
-pub fn print_lifetime(s: @ps, lifetime: &ast::Lifetime) {
-    word(s.s, "'");
+pub fn print_lifetime(s: &mut ps, lifetime: &ast::Lifetime) {
+    word(&mut s.s, "'");
     print_ident(s, lifetime.ident);
 }
 
-pub fn print_generics(s: @ps, generics: &ast::Generics) {
+pub fn print_generics(s: &mut ps, generics: &ast::Generics) {
     let total = generics.lifetimes.len() + generics.ty_params.len();
     if total > 0 {
-        word(s.s, "<");
-        fn print_item(s: @ps, generics: &ast::Generics, idx: uint) {
+        word(&mut s.s, "<");
+        fn print_item(s: &mut ps, generics: &ast::Generics, idx: uint) {
             if idx < generics.lifetimes.len() {
                 let lifetime = generics.lifetimes.get(idx);
                 print_lifetime(s, lifetime);
@@ -1884,21 +1922,21 @@ pub fn print_generics(s: @ps, generics: &ast::Generics) {
 
         commasep(s, inconsistent, ints,
                  |s, &i| print_item(s, generics, i));
-        word(s.s, ">");
+        word(&mut s.s, ">");
     }
 }
 
-pub fn print_meta_item(s: @ps, item: &ast::MetaItem) {
+pub fn print_meta_item(s: &mut ps, item: &ast::MetaItem) {
     ibox(s, indent_unit);
     match item.node {
-      ast::MetaWord(name) => word(s.s, name),
+      ast::MetaWord(name) => word(&mut s.s, name),
       ast::MetaNameValue(name, value) => {
         word_space(s, name);
         word_space(s, "=");
         print_literal(s, &value);
       }
       ast::MetaList(name, ref items) => {
-        word(s.s, name);
+        word(&mut s.s, name);
         popen(s);
         commasep(s,
                  consistent,
@@ -1910,13 +1948,13 @@ pub fn print_meta_item(s: @ps, item: &ast::MetaItem) {
     end(s);
 }
 
-pub fn print_view_path(s: @ps, vp: &ast::view_path) {
+pub fn print_view_path(s: &mut ps, vp: &ast::view_path) {
     match vp.node {
       ast::view_path_simple(ident, ref path, _) => {
         // FIXME(#6993) can't compare identifiers directly here
         if path.segments.last().identifier.name != ident.name {
             print_ident(s, ident);
-            space(s.s);
+            space(&mut s.s);
             word_space(s, "=");
         }
         print_path(s, path, false);
@@ -1924,29 +1962,29 @@ pub fn print_view_path(s: @ps, vp: &ast::view_path) {
 
       ast::view_path_glob(ref path, _) => {
         print_path(s, path, false);
-        word(s.s, "::*");
+        word(&mut s.s, "::*");
       }
 
       ast::view_path_list(ref path, ref idents, _) => {
         if path.segments.is_empty() {
-            word(s.s, "{");
+            word(&mut s.s, "{");
         } else {
             print_path(s, path, false);
-            word(s.s, "::{");
+            word(&mut s.s, "::{");
         }
         commasep(s, inconsistent, (*idents), |s, w| {
             print_ident(s, w.node.name);
         });
-        word(s.s, "}");
+        word(&mut s.s, "}");
       }
     }
 }
 
-pub fn print_view_paths(s: @ps, vps: &[@ast::view_path]) {
+pub fn print_view_paths(s: &mut ps, vps: &[@ast::view_path]) {
     commasep(s, inconsistent, vps, |p, &vp| print_view_path(p, vp));
 }
 
-pub fn print_view_item(s: @ps, item: &ast::view_item) {
+pub fn print_view_item(s: &mut ps, item: &ast::view_item) {
     hardbreak_if_not_bol(s);
     maybe_print_comment(s, item.span.lo);
     print_outer_attributes(s, item.attrs);
@@ -1956,9 +1994,9 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) {
             head(s, "extern mod");
             print_ident(s, id);
             for &(ref p, style) in optional_path.iter() {
-                space(s.s);
-                word(s.s, "=");
-                space(s.s);
+                space(&mut s.s);
+                word(&mut s.s, "=");
+                space(&mut s.s);
                 print_string(s, *p, style);
             }
         }
@@ -1968,24 +2006,24 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) {
             print_view_paths(s, *vps);
         }
     }
-    word(s.s, ";");
+    word(&mut s.s, ";");
     end(s); // end inner head-block
     end(s); // end outer head-block
 }
 
-pub fn print_mutability(s: @ps, mutbl: ast::Mutability) {
+pub fn print_mutability(s: &mut ps, mutbl: ast::Mutability) {
     match mutbl {
       ast::MutMutable => word_nbsp(s, "mut"),
       ast::MutImmutable => {/* nothing */ }
     }
 }
 
-pub fn print_mt(s: @ps, mt: &ast::mt) {
+pub fn print_mt(s: &mut ps, mt: &ast::mt) {
     print_mutability(s, mt.mutbl);
     print_type(s, mt.ty);
 }
 
-pub fn print_arg(s: @ps, input: &ast::arg) {
+pub fn print_arg(s: &mut ps, input: &ast::arg) {
     ibox(s, indent_unit);
     match input.ty.node {
       ast::ty_infer => print_pat(s, input.pat),
@@ -1999,8 +2037,8 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
             }
             _ => {
                 print_pat(s, input.pat);
-                word(s.s, ":");
-                space(s.s);
+                word(&mut s.s, ":");
+                space(&mut s.s);
             }
         }
         print_type(s, input.ty);
@@ -2009,7 +2047,7 @@ pub fn print_arg(s: @ps, input: &ast::arg) {
     end(s);
 }
 
-pub fn print_ty_fn(s: @ps,
+pub fn print_ty_fn(s: &mut ps,
                    opt_abis: Option<AbiSet>,
                    opt_sigil: Option<ast::Sigil>,
                    opt_region: &Option<ast::Lifetime>,
@@ -2025,7 +2063,7 @@ pub fn print_ty_fn(s: @ps,
     // 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 {
-        word(s.s, "proc");
+        word(&mut s.s, "proc");
     } else if opt_sigil == Some(ast::BorrowedSigil) {
         print_extern_opt_abis(s, opt_abis);
         for lifetime in opt_region.iter() {
@@ -2039,20 +2077,20 @@ pub fn print_ty_fn(s: @ps,
         print_opt_lifetime(s, opt_region);
         print_purity(s, purity);
         print_onceness(s, onceness);
-        word(s.s, "fn");
+        word(&mut s.s, "fn");
     }
 
-    match id { Some(id) => { word(s.s, " "); print_ident(s, id); } _ => () }
+    match id { Some(id) => { word(&mut s.s, " "); 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) => print_generics(s, g), _ => () }
-    zerobreak(s.s);
+    zerobreak(&mut s.s);
 
     if opt_sigil == Some(ast::BorrowedSigil) {
-        word(s.s, "|");
+        word(&mut s.s, "|");
     } else {
         popen(s);
     }
@@ -2071,12 +2109,12 @@ pub fn print_ty_fn(s: @ps,
     end(s);
 
     if opt_sigil == Some(ast::BorrowedSigil) {
-        word(s.s, "|");
+        word(&mut s.s, "|");
 
         opt_bounds.as_ref().map(|bounds| print_bounds(s, bounds, true));
     } else {
         if decl.variadic {
-            word(s.s, ", ...");
+            word(&mut s.s, ", ...");
         }
         pclose(s);
     }
@@ -2098,7 +2136,7 @@ pub fn print_ty_fn(s: @ps,
     end(s);
 }
 
-pub fn maybe_print_trailing_comment(s: @ps, span: codemap::Span,
+pub fn maybe_print_trailing_comment(s: &mut ps, span: codemap::Span,
                                     next_pos: Option<BytePos>) {
     let cm;
     match s.cm { Some(ccm) => cm = ccm, _ => return }
@@ -2119,10 +2157,10 @@ pub fn maybe_print_trailing_comment(s: @ps, span: codemap::Span,
     }
 }
 
-pub fn print_remaining_comments(s: @ps) {
+pub fn print_remaining_comments(s: &mut ps) {
     // 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() { hardbreak(s.s); }
+    if next_comment(s).is_none() { hardbreak(&mut s.s); }
     loop {
         match next_comment(s) {
           Some(ref cmnt) => {
@@ -2134,11 +2172,11 @@ pub fn print_remaining_comments(s: @ps) {
     }
 }
 
-pub fn print_literal(s: @ps, lit: &ast::lit) {
+pub fn print_literal(s: &mut ps, lit: &ast::lit) {
     maybe_print_comment(s, lit.span.lo);
     match next_lit(s, lit.span.lo) {
       Some(ref ltrl) => {
-        word(s.s, (*ltrl).lit);
+        word(&mut s.s, (*ltrl).lit);
         return;
       }
       _ => ()
@@ -2149,45 +2187,45 @@ pub fn print_literal(s: @ps, lit: &ast::lit) {
           let mut res = ~"'";
           char::from_u32(ch).unwrap().escape_default(|c| res.push_char(c));
           res.push_char('\'');
-          word(s.s, res);
+          word(&mut s.s, res);
       }
       ast::lit_int(i, t) => {
         if i < 0_i64 {
-            word(s.s,
+            word(&mut s.s,
                  ~"-" + (-i as u64).to_str_radix(10u)
                  + ast_util::int_ty_to_str(t));
         } else {
-            word(s.s,
+            word(&mut s.s,
                  (i as u64).to_str_radix(10u)
                  + ast_util::int_ty_to_str(t));
         }
       }
       ast::lit_uint(u, t) => {
-        word(s.s,
+        word(&mut s.s,
              u.to_str_radix(10u)
              + ast_util::uint_ty_to_str(t));
       }
       ast::lit_int_unsuffixed(i) => {
         if i < 0_i64 {
-            word(s.s, ~"-" + (-i as u64).to_str_radix(10u));
+            word(&mut s.s, ~"-" + (-i as u64).to_str_radix(10u));
         } else {
-            word(s.s, (i as u64).to_str_radix(10u));
+            word(&mut s.s, (i as u64).to_str_radix(10u));
         }
       }
       ast::lit_float(f, t) => {
-        word(s.s, f.to_owned() + ast_util::float_ty_to_str(t));
+        word(&mut s.s, f.to_owned() + ast_util::float_ty_to_str(t));
       }
-      ast::lit_float_unsuffixed(f) => word(s.s, f),
-      ast::lit_nil => word(s.s, "()"),
+      ast::lit_float_unsuffixed(f) => word(&mut s.s, f),
+      ast::lit_nil => word(&mut s.s, "()"),
       ast::lit_bool(val) => {
-        if val { word(s.s, "true"); } else { word(s.s, "false"); }
+        if val { word(&mut s.s, "true"); } else { word(&mut s.s, "false"); }
       }
       ast::lit_binary(arr) => {
         ibox(s, indent_unit);
-        word(s.s, "[");
-        commasep_cmnt(s, inconsistent, arr, |s, u| word(s.s, format!("{}", *u)),
+        word(&mut s.s, "[");
+        commasep_cmnt(s, inconsistent, arr, |s, u| word(&mut s.s, format!("{}", *u)),
                       |_| lit.span);
-        word(s.s, "]");
+        word(&mut s.s, "]");
         end(s);
       }
     }
@@ -2197,7 +2235,7 @@ pub fn lit_to_str(l: &ast::lit) -> ~str {
     return to_str(l, print_literal, parse::token::mk_fake_ident_interner());
 }
 
-pub fn next_lit(s: @ps, pos: BytePos) -> Option<comments::lit> {
+pub fn next_lit(s: &mut ps, pos: BytePos) -> Option<comments::lit> {
     match s.literals {
       Some(ref lits) => {
         while s.cur_cmnt_and_lit.cur_lit < lits.len() {
@@ -2212,7 +2250,7 @@ pub fn next_lit(s: @ps, pos: BytePos) -> Option<comments::lit> {
     }
 }
 
-pub fn maybe_print_comment(s: @ps, pos: BytePos) {
+pub fn maybe_print_comment(s: &mut ps, pos: BytePos) {
     loop {
         match next_comment(s) {
           Some(ref cmnt) => {
@@ -2226,33 +2264,33 @@ pub fn maybe_print_comment(s: @ps, pos: BytePos) {
     }
 }
 
-pub fn print_comment(s: @ps, cmnt: &comments::cmnt) {
+pub fn print_comment(s: &mut ps, cmnt: &comments::cmnt) {
     match cmnt.style {
       comments::mixed => {
         assert_eq!(cmnt.lines.len(), 1u);
-        zerobreak(s.s);
-        word(s.s, cmnt.lines[0]);
-        zerobreak(s.s);
+        zerobreak(&mut s.s);
+        word(&mut s.s, cmnt.lines[0]);
+        zerobreak(&mut s.s);
       }
       comments::isolated => {
         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() { word(s.s, *line); }
-            hardbreak(s.s);
+            if !line.is_empty() { word(&mut s.s, *line); }
+            hardbreak(&mut s.s);
         }
       }
       comments::trailing => {
-        word(s.s, " ");
+        word(&mut s.s, " ");
         if cmnt.lines.len() == 1u {
-            word(s.s, cmnt.lines[0]);
-            hardbreak(s.s);
+            word(&mut s.s, cmnt.lines[0]);
+            hardbreak(&mut s.s);
         } else {
             ibox(s, 0u);
             for line in cmnt.lines.iter() {
-                if !line.is_empty() { word(s.s, *line); }
-                hardbreak(s.s);
+                if !line.is_empty() { word(&mut s.s, *line); }
+                hardbreak(&mut s.s);
             }
             end(s);
         }
@@ -2264,30 +2302,42 @@ pub fn print_comment(s: @ps, cmnt: &comments::cmnt) {
               pp::STRING(s, _) => ";" == s,
               _ => false
             };
-        if is_semi || is_begin(s) || is_end(s) { hardbreak(s.s); }
-        hardbreak(s.s);
+        if is_semi || is_begin(s) || is_end(s) { hardbreak(&mut s.s); }
+        hardbreak(&mut s.s);
       }
     }
 }
 
-pub fn print_string(s: @ps, st: &str, style: ast::StrStyle) {
+pub fn print_string(s: &mut ps, st: &str, style: ast::StrStyle) {
     let st = match style {
         ast::CookedStr => format!("\"{}\"", st.escape_default()),
         ast::RawStr(n) => format!("r{delim}\"{string}\"{delim}",
                                   delim="#".repeat(n), string=st)
     };
-    word(s.s, st);
+    word(&mut s.s, st);
 }
 
-pub fn to_str<T>(t: &T, f: |@ps, &T|, intr: @ident_interner) -> ~str {
-    let wr = @mut MemWriter::new();
-    let s = rust_printer(wr as @mut io::Writer, intr);
-    f(s, t);
-    eof(s.s);
-    str::from_utf8_owned(wr.inner_ref().to_owned())
+// XXX(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.inner_ref().to_owned());
+    cast::forget(wr);
+    result
 }
 
-pub fn next_comment(s: @ps) -> Option<comments::cmnt> {
+pub fn to_str<T>(t: &T, f: |&mut ps, &T|, intr: @ident_interner) -> ~str {
+    let wr = ~MemWriter::new();
+    let mut s = rust_printer(wr as ~io::Writer, intr);
+    f(&mut s, t);
+    eof(&mut s.s);
+    unsafe {
+        get_mem_writer(&mut s.s.out)
+    }
+}
+
+pub fn next_comment(s: &mut ps) -> Option<comments::cmnt> {
     match s.comments {
       Some(ref cmnts) => {
         if s.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
@@ -2300,7 +2350,7 @@ pub fn next_comment(s: @ps) -> Option<comments::cmnt> {
     }
 }
 
-pub fn print_opt_purity(s: @ps, opt_purity: Option<ast::purity>) {
+pub fn print_opt_purity(s: &mut ps, opt_purity: Option<ast::purity>) {
     match opt_purity {
         Some(ast::impure_fn) => { }
         Some(purity) => {
@@ -2310,7 +2360,7 @@ pub fn print_opt_purity(s: @ps, opt_purity: Option<ast::purity>) {
     }
 }
 
-pub fn print_opt_abis_and_extern_if_nondefault(s: @ps,
+pub fn print_opt_abis_and_extern_if_nondefault(s: &mut ps,
                                                opt_abis: Option<AbiSet>) {
     match opt_abis {
         Some(abis) if !abis.is_rust() => {
@@ -2321,7 +2371,7 @@ pub fn print_opt_abis_and_extern_if_nondefault(s: @ps,
     };
 }
 
-pub fn print_extern_opt_abis(s: @ps, opt_abis: Option<AbiSet>) {
+pub fn print_extern_opt_abis(s: &mut ps, opt_abis: Option<AbiSet>) {
     match opt_abis {
         Some(abis) => {
             word_nbsp(s, "extern");
@@ -2331,23 +2381,23 @@ pub fn print_extern_opt_abis(s: @ps, opt_abis: Option<AbiSet>) {
     };
 }
 
-pub fn print_opt_sigil(s: @ps, opt_sigil: Option<ast::Sigil>) {
+pub fn print_opt_sigil(s: &mut ps, opt_sigil: Option<ast::Sigil>) {
     match opt_sigil {
-        Some(ast::BorrowedSigil) => { word(s.s, "&"); }
-        Some(ast::OwnedSigil) => { word(s.s, "~"); }
-        Some(ast::ManagedSigil) => { word(s.s, "@"); }
+        Some(ast::BorrowedSigil) => { word(&mut s.s, "&"); }
+        Some(ast::OwnedSigil) => { word(&mut s.s, "~"); }
+        Some(ast::ManagedSigil) => { word(&mut s.s, "@"); }
         None => {}
     };
 }
 
-pub fn print_fn_header_info(s: @ps,
+pub fn print_fn_header_info(s: &mut ps,
                             _opt_explicit_self: Option<ast::explicit_self_>,
                             opt_purity: Option<ast::purity>,
                             abis: AbiSet,
                             onceness: ast::Onceness,
                             opt_sigil: Option<ast::Sigil>,
                             vis: ast::visibility) {
-    word(s.s, visibility_qualified(vis, ""));
+    word(&mut s.s, visibility_qualified(vis, ""));
 
     if abis != AbiSet::Rust() {
         word_nbsp(s, "extern");
@@ -2361,7 +2411,7 @@ pub fn print_fn_header_info(s: @ps,
     }
 
     print_onceness(s, onceness);
-    word(s.s, "fn");
+    word(&mut s.s, "fn");
     print_opt_sigil(s, opt_sigil);
 }
 
@@ -2380,14 +2430,14 @@ pub fn onceness_to_str(o: ast::Onceness) -> &'static str {
     }
 }
 
-pub fn print_purity(s: @ps, p: ast::purity) {
+pub fn print_purity(s: &mut ps, p: ast::purity) {
     match p {
       ast::impure_fn => (),
       _ => word_nbsp(s, purity_to_str(p))
     }
 }
 
-pub fn print_onceness(s: @ps, o: ast::Onceness) {
+pub fn print_onceness(s: &mut ps, o: ast::Onceness) {
     match o {
         ast::Once => { word_nbsp(s, "once"); }
         ast::Many => {}
@@ -2403,12 +2453,6 @@ mod test {
     use codemap;
     use parse::token;
 
-    fn string_check<T:Eq> (given : &T, expected: &T) {
-        if !(given == expected) {
-            fail!("given {:?}, expected {:?}", given, expected);
-        }
-    }
-
     #[test]
     fn test_fun_to_str() {
         let abba_ident = token::str_to_ident("abba");
diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs
index c144b36a86f..b694e1f702b 100644
--- a/src/libsyntax/util/interner.rs
+++ b/src/libsyntax/util/interner.rs
@@ -14,20 +14,21 @@
 
 use ast::Name;
 
+use std::cell::RefCell;
 use std::cmp::Equiv;
 use std::hashmap::HashMap;
 
 pub struct Interner<T> {
-    priv map: @mut HashMap<T, Name>,
-    priv vect: @mut ~[T],
+    priv map: @RefCell<HashMap<T, Name>>,
+    priv vect: @RefCell<~[T]>,
 }
 
 // when traits can extend traits, we should extend index<Name,T> to get []
 impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
-            map: @mut HashMap::new(),
-            vect: @mut ~[],
+            map: @RefCell::new(HashMap::new()),
+            vect: @RefCell::new(~[]),
         }
     }
 
@@ -40,37 +41,41 @@ impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
     }
 
     pub fn intern(&self, val: T) -> Name {
-        match self.map.find(&val) {
+        let mut map = self.map.borrow_mut();
+        match map.get().find(&val) {
             Some(&idx) => return idx,
             None => (),
         }
 
-        let vect = &mut *self.vect;
-        let new_idx = vect.len() as Name;
-        self.map.insert(val.clone(), new_idx);
-        vect.push(val);
+        let mut vect = self.vect.borrow_mut();
+        let new_idx = vect.get().len() as Name;
+        map.get().insert(val.clone(), new_idx);
+        vect.get().push(val);
         new_idx
     }
 
     pub fn gensym(&self, val: T) -> Name {
-        let new_idx = {
-            let vect = &*self.vect;
-            vect.len() as Name
-        };
+        let mut vect = self.vect.borrow_mut();
+        let new_idx = vect.get().len() as Name;
         // leave out of .map to avoid colliding
-        self.vect.push(val);
+        vect.get().push(val);
         new_idx
     }
 
     pub fn get(&self, idx: Name) -> T {
-        self.vect[idx].clone()
+        let vect = self.vect.borrow();
+        vect.get()[idx].clone()
     }
 
-    pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }
+    pub fn len(&self) -> uint {
+        let vect = self.vect.borrow();
+        vect.get().len()
+    }
 
     pub fn find_equiv<Q:Hash + IterBytes + Equiv<T>>(&self, val: &Q)
                                               -> Option<Name> {
-        match self.map.find_equiv(val) {
+        let map = self.map.borrow();
+        match map.get().find_equiv(val) {
             Some(v) => Some(*v),
             None => None,
         }
@@ -80,16 +85,16 @@ impl<T:Eq + IterBytes + Hash + Freeze + Clone + 'static> Interner<T> {
 // A StrInterner differs from Interner<String> in that it accepts
 // borrowed pointers rather than @ ones, resulting in less allocation.
 pub struct StrInterner {
-    priv map: @mut HashMap<@str, Name>,
-    priv vect: @mut ~[@str],
+    priv map: @RefCell<HashMap<@str, Name>>,
+    priv vect: @RefCell<~[@str]>,
 }
 
 // when traits can extend traits, we should extend index<Name,T> to get []
 impl StrInterner {
     pub fn new() -> StrInterner {
         StrInterner {
-            map: @mut HashMap::new(),
-            vect: @mut ~[],
+            map: @RefCell::new(HashMap::new()),
+            vect: @RefCell::new(~[]),
         }
     }
 
@@ -100,22 +105,25 @@ impl StrInterner {
     }
 
     pub fn intern(&self, val: &str) -> Name {
-        match self.map.find_equiv(&val) {
+        let mut map = self.map.borrow_mut();
+        match map.get().find_equiv(&val) {
             Some(&idx) => return idx,
             None => (),
         }
 
         let new_idx = self.len() as Name;
         let val = val.to_managed();
-        self.map.insert(val, new_idx);
-        self.vect.push(val);
+        map.get().insert(val, new_idx);
+        let mut vect = self.vect.borrow_mut();
+        vect.get().push(val);
         new_idx
     }
 
     pub fn gensym(&self, val: &str) -> Name {
         let new_idx = self.len() as Name;
         // leave out of .map to avoid colliding
-        self.vect.push(val.to_managed());
+        let mut vect = self.vect.borrow_mut();
+        vect.get().push(val.to_managed());
         new_idx
     }
 
@@ -132,17 +140,26 @@ impl StrInterner {
     pub fn gensym_copy(&self, idx : Name) -> Name {
         let new_idx = self.len() as Name;
         // leave out of map to avoid colliding
-        self.vect.push(self.vect[idx]);
+        let mut vect = self.vect.borrow_mut();
+        let existing = vect.get()[idx];
+        vect.get().push(existing);
         new_idx
     }
 
-    pub fn get(&self, idx: Name) -> @str { self.vect[idx] }
+    pub fn get(&self, idx: Name) -> @str {
+        let vect = self.vect.borrow();
+        vect.get()[idx]
+    }
 
-    pub fn len(&self) -> uint { let vect = &*self.vect; vect.len() }
+    pub fn len(&self) -> uint {
+        let vect = self.vect.borrow();
+        vect.get().len()
+    }
 
     pub fn find_equiv<Q:Hash + IterBytes + Equiv<@str>>(&self, val: &Q)
                                                          -> Option<Name> {
-        match self.map.find_equiv(val) {
+        let map = self.map.borrow();
+        match map.get().find_equiv(val) {
             Some(v) => Some(*v),
             None => None,
         }
diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs
index 01e050c1ffe..dc546c7610f 100644
--- a/src/libsyntax/util/parser_testing.rs
+++ b/src/libsyntax/util/parser_testing.rs
@@ -17,7 +17,7 @@ use parse::token;
 
 // map a string to tts, using a made-up filename: return both the token_trees
 // and the ParseSess
-pub fn string_to_tts_and_sess (source_str : @str) -> (~[ast::token_tree],@mut ParseSess) {
+pub fn string_to_tts_and_sess (source_str : @str) -> (~[ast::token_tree],@ParseSess) {
     let ps = new_parse_sess(None);
     (filemap_to_tts(ps,string_to_filemap(ps,source_str,@"bogofile")),ps)
 }
@@ -28,7 +28,7 @@ pub fn string_to_tts(source_str : @str) -> ~[ast::token_tree] {
     tts
 }
 
-pub fn string_to_parser_and_sess(source_str: @str) -> (Parser,@mut ParseSess) {
+pub fn string_to_parser_and_sess(source_str: @str) -> (Parser,@ParseSess) {
     let ps = new_parse_sess(None);
     (new_parser_from_source_str(ps,~[],@"bogofile",source_str),ps)
 }
@@ -54,7 +54,7 @@ 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,@mut 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)
 }
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 2e83a038c58..29567ab9442 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -302,10 +302,10 @@ pub fn skip_ty<E, V:Visitor<E>>(_: &mut V, _: &Ty, _: E) {
 
 pub fn walk_ty<E:Clone, V:Visitor<E>>(visitor: &mut V, typ: &Ty, env: E) {
     match typ.node {
-        ty_uniq(ty) | ty_vec(ty) => {
+        ty_uniq(ty) | ty_vec(ty) | ty_box(ty) => {
             visitor.visit_ty(ty, env)
         }
-        ty_box(ref mutable_type) | ty_ptr(ref mutable_type) => {
+        ty_ptr(ref mutable_type) => {
             visitor.visit_ty(mutable_type.ty, env)
         }
         ty_rptr(ref lifetime, ref mutable_type) => {
diff --git a/src/test/auxiliary/cci_nested_lib.rs b/src/test/auxiliary/cci_nested_lib.rs
index 72ce66c20bd..90b01f8888b 100644
--- a/src/test/auxiliary/cci_nested_lib.rs
+++ b/src/test/auxiliary/cci_nested_lib.rs
@@ -10,6 +10,8 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 pub struct Entry<A,B> {
     key: A,
     value: B
@@ -17,11 +19,12 @@ pub struct Entry<A,B> {
 
 pub struct alist<A,B> {
     eq_fn: extern "Rust" fn(A,A) -> bool,
-    data: @mut ~[Entry<A,B>]
+    data: @RefCell<~[Entry<A,B>]>,
 }
 
 pub fn alist_add<A:'static,B:'static>(lst: &alist<A,B>, k: A, v: B) {
-    lst.data.push(Entry{key:k, value:v});
+    let mut data = lst.data.borrow_mut();
+    data.get().push(Entry{key:k, value:v});
 }
 
 pub fn alist_get<A:Clone + 'static,
@@ -30,7 +33,8 @@ pub fn alist_get<A:Clone + 'static,
                  k: A)
                  -> B {
     let eq_fn = lst.eq_fn;
-    for entry in lst.data.iter() {
+    let data = lst.data.borrow();
+    for entry in data.get().iter() {
         if eq_fn(entry.key.clone(), k.clone()) {
             return entry.value.clone();
         }
@@ -41,12 +45,18 @@ pub fn alist_get<A:Clone + 'static,
 #[inline]
 pub fn new_int_alist<B:'static>() -> alist<int, B> {
     fn eq_int(a: int, b: int) -> bool { a == b }
-    return alist {eq_fn: eq_int, data: @mut ~[]};
+    return alist {
+        eq_fn: eq_int,
+        data: @RefCell::new(~[]),
+    };
 }
 
 #[inline]
 pub fn new_int_alist_2<B:'static>() -> alist<int, B> {
     #[inline]
     fn eq_int(a: int, b: int) -> bool { a == b }
-    return alist {eq_fn: eq_int, data: @mut ~[]};
+    return alist {
+        eq_fn: eq_int,
+        data: @RefCell::new(~[]),
+    };
 }
diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs
index f5d2fb9ffd2..15dde899ce3 100644
--- a/src/test/auxiliary/issue-2631-a.rs
+++ b/src/test/auxiliary/issue-2631-a.rs
@@ -14,11 +14,12 @@
 
 extern mod extra;
 
+use std::cell::RefCell;
 use std::hashmap::HashMap;
 
-pub type header_map = HashMap<~str, @mut ~[@~str]>;
+pub type header_map = HashMap<~str, @RefCell<~[@~str]>>;
 
 // the unused ty param is necessary so this gets monomorphized
 pub fn request<T>(req: &header_map) {
-  let _x = (*((**req.get(&~"METHOD")).clone())[0u]).clone();
+  let _x = (*((**req.get(&~"METHOD")).clone()).get()[0u]).clone();
 }
diff --git a/src/test/bench/sudoku.rs b/src/test/bench/sudoku.rs
index 39bcfde2826..75587f17b10 100644
--- a/src/test/bench/sudoku.rs
+++ b/src/test/bench/sudoku.rs
@@ -86,7 +86,7 @@ impl Sudoku {
         return Sudoku::new(g)
     }
 
-    pub fn write(&self, writer: @mut io::Writer) {
+    pub fn write(&self, writer: &mut io::Writer) {
         for row in range(0u8, 9u8) {
             write!(writer, "{}", self.grid[row][0]);
             for col in range(1u8, 9u8) {
@@ -280,5 +280,5 @@ fn main() {
         Sudoku::read(BufferedReader::new(io::stdin()))
     };
     sudoku.solve();
-    sudoku.write(@mut io::stdout() as @mut io::Writer);
+    sudoku.write(&mut io::stdout());
 }
diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
index bfc1884ac5a..9d628c1f6c7 100644
--- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
+++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
@@ -49,13 +49,5 @@ fn b() {
     q.x += 1; // and OK to mutate it
 }
 
-fn c() {
-    // Here the receiver is in aliased memory but due to write
-    // barriers we can still consider it immutable.
-    let q = @mut Point {x: 3, y: 4};
-    *q + 3;
-    q.times(3);
-}
-
 fn main() {
 }
diff --git a/src/test/compile-fail/borrowck-loan-rcvr.rs b/src/test/compile-fail/borrowck-loan-rcvr.rs
index 5c6f7082ed0..a0071938ce4 100644
--- a/src/test/compile-fail/borrowck-loan-rcvr.rs
+++ b/src/test/compile-fail/borrowck-loan-rcvr.rs
@@ -48,16 +48,5 @@ fn b() {
     l.x += 1;
 }
 
-fn c() {
-    // Loaning @mut as & is considered legal due to dynamic checks...
-    let q = @mut point {x: 3, y: 4};
-    q.impurem();
-
-    // ...but we still detect errors statically when we can.
-    q.blockm(|| {
-        q.x = 10; //~ ERROR cannot assign
-    })
-}
-
 fn main() {
 }
diff --git a/src/test/compile-fail/borrowck-mut-boxed-vec.rs b/src/test/compile-fail/borrowck-mut-boxed-vec.rs
deleted file mode 100644
index 84c2db8bd57..00000000000
--- a/src/test/compile-fail/borrowck-mut-boxed-vec.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-fn main() {
-    let v = @mut [ 1, 2, 3 ];
-    for _x in v.iter() {
-        v[1] = 4; //~ ERROR cannot assign
-    }
-}
diff --git a/src/test/compile-fail/borrowck-mut-deref-comp.rs b/src/test/compile-fail/borrowck-mut-deref-comp.rs
index 7cf2e57ab80..77318e6a636 100644
--- a/src/test/compile-fail/borrowck-mut-deref-comp.rs
+++ b/src/test/compile-fail/borrowck-mut-deref-comp.rs
@@ -12,7 +12,7 @@
 
 struct foo(~int);
 
-fn borrow(x: @mut foo) {
+fn borrow(x: @foo) {
     let _y = &***x;
     *x = foo(~4); //~ ERROR cannot assign
 }
diff --git a/src/test/compile-fail/borrowck-object-mutability.rs b/src/test/compile-fail/borrowck-object-mutability.rs
index e6cb8d62d04..1d1b993f5d1 100644
--- a/src/test/compile-fail/borrowck-object-mutability.rs
+++ b/src/test/compile-fail/borrowck-object-mutability.rs
@@ -30,11 +30,6 @@ fn managed_receiver(x: @Foo) {
     x.borrowed_mut(); //~ ERROR cannot borrow
 }
 
-fn managed_mut_receiver(x: @mut Foo) {
-    x.borrowed();
-    x.borrowed_mut();
-}
-
 fn owned_receiver(x: ~Foo) {
     x.borrowed();
     x.borrowed_mut(); //~ ERROR cannot borrow
diff --git a/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-2.rs b/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-2.rs
deleted file mode 100644
index 451f023f5fc..00000000000
--- a/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-2.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-fn main() {
-    let mut b = ~3;
-    let _x = &mut *b;
-    let _y = &mut *b; //~ ERROR cannot borrow
-}
diff --git a/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-3.rs b/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-3.rs
deleted file mode 100644
index c455de888a3..00000000000
--- a/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail-3.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-fn main() {
-    let mut a = ~3;
-    let mut b = &mut a;
-    let _c = &mut *b;
-    let mut d = /*move*/ a; //~ ERROR cannot move out
-    *d += 1;
-}
diff --git a/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail.rs b/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail.rs
deleted file mode 100644
index e18808dfe53..00000000000
--- a/src/test/compile-fail/borrowck-wg-borrow-mut-to-imm-fail.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let mut b = ~3;
-    let _x = &mut *b;
-    let mut y = /*move*/ b; //~ ERROR cannot move out
-    *y += 1;
-}
diff --git a/src/test/compile-fail/borrowck-wg-move-base-2.rs b/src/test/compile-fail/borrowck-wg-move-base-2.rs
deleted file mode 100644
index 4050b4c5971..00000000000
--- a/src/test/compile-fail/borrowck-wg-move-base-2.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-fn foo(x: &mut int) {
-    let mut a = 3;
-    let mut _y = &mut *x;
-    let _z = &mut *_y;
-    _y = &mut a; //~ ERROR cannot assign
-}
-
-fn main() {
-}
diff --git a/src/test/compile-fail/cast-immutable-mutable-trait.rs b/src/test/compile-fail/cast-immutable-mutable-trait.rs
deleted file mode 100644
index 817696c6d20..00000000000
--- a/src/test/compile-fail/cast-immutable-mutable-trait.rs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-trait T {
-    fn foo(@mut self);
-}
-
-struct S {
-    unused: int
-}
-
-impl T for S {
-    fn foo(@mut self) {
-    }
-}
-
-fn main() {
-    let s = @S { unused: 0 };
-    let _s2 = s as @mut T; //~ error: types differ in mutability
-    let _s3 = &s as &mut T; //~ error: types differ in mutability
-}
diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs
index a4ebfef1774..2277f7080af 100644
--- a/src/test/compile-fail/fn-variance-1.rs
+++ b/src/test/compile-fail/fn-variance-1.rs
@@ -8,19 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[feature(managed_boxes)];
+fn takes_imm(x: &int) { }
 
-fn takes_mut(x: @mut int) { }
-fn takes_imm(x: @int) { }
+fn takes_mut(x: &mut int) { }
 
 fn apply<T>(t: T, f: |T|) {
     f(t)
 }
 
 fn main() {
-    apply(@3, takes_mut); //~ ERROR (values differ in mutability)
-    apply(@3, takes_imm);
+    apply(&3, takes_mut); //~ ERROR (values differ in mutability)
+    apply(&3, takes_imm);
 
-    apply(@mut 3, takes_mut);
-    apply(@mut 3, takes_imm); //~ ERROR (values differ in mutability)
+    apply(&mut 3, takes_mut);
+    apply(&mut 3, takes_imm); //~ ERROR (values differ in mutability)
 }
diff --git a/src/test/compile-fail/issue-10487.rs b/src/test/compile-fail/issue-10487.rs
index d116b7b67ca..302e883942e 100644
--- a/src/test/compile-fail/issue-10487.rs
+++ b/src/test/compile-fail/issue-10487.rs
@@ -12,6 +12,5 @@
 
 static x: ~[int] = ~[123, 456]; //~ ERROR: cannot allocate vectors in constant expressions
 static y: @[int] = @[123, 456]; //~ ERROR: cannot allocate vectors in constant expressions
-static z: @mut [int] = @mut [123, 456]; //~ ERROR: cannot allocate vectors in constant expressions
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-2548.rs b/src/test/compile-fail/issue-2548.rs
index 21b6959692f..def712d9e8d 100644
--- a/src/test/compile-fail/issue-2548.rs
+++ b/src/test/compile-fail/issue-2548.rs
@@ -12,10 +12,10 @@
 
 // A test case for #2548.
 
-struct foo {
-    x: @mut int,
-
+use std::cell::Cell;
 
+struct foo {
+    x: @Cell<int>,
 }
 
 #[unsafe_destructor]
@@ -23,17 +23,17 @@ impl Drop for foo {
     fn drop(&mut self) {
         unsafe {
             println("Goodbye, World!");
-            *self.x += 1;
+            self.x.set(self.x.get() + 1);
         }
     }
 }
 
-fn foo(x: @mut int) -> foo {
+fn foo(x: @Cell<int>) -> foo {
     foo { x: x }
 }
 
 fn main() {
-    let x = @mut 0;
+    let x = @Cell::new(0);
 
     {
         let mut res = foo(x);
@@ -43,5 +43,5 @@ fn main() {
         assert_eq!(v.len(), 2);
     }
 
-    assert_eq!(*x, 1);
+    assert_eq!(x.get(), 1);
 }
diff --git a/src/test/compile-fail/issue-3668.rs b/src/test/compile-fail/issue-3668.rs
index 4665687db85..fe57d7171a6 100644
--- a/src/test/compile-fail/issue-3668.rs
+++ b/src/test/compile-fail/issue-3668.rs
@@ -10,7 +10,7 @@
 
 #[feature(managed_boxes)];
 
-struct P { child: Option<@mut P> }
+struct P { child: Option<@P> }
 trait PTrait {
    fn getChildOption(&self) -> Option<@P>;
 }
diff --git a/src/test/compile-fail/kindck-destructor-owned.rs b/src/test/compile-fail/kindck-destructor-owned.rs
index 2ea12ab9fdc..de277b4c36e 100644
--- a/src/test/compile-fail/kindck-destructor-owned.rs
+++ b/src/test/compile-fail/kindck-destructor-owned.rs
@@ -1,12 +1,11 @@
 #[feature(managed_boxes)];
 
 struct Foo {
-    f: @mut int,
+    f: @int,
 }
 
 impl Drop for Foo { //~ ERROR cannot implement a destructor on a structure that does not satisfy Send
     fn drop(&mut self) {
-        *self.f = 10;
     }
 }
 
diff --git a/src/test/compile-fail/lub-in-args.rs b/src/test/compile-fail/lub-in-args.rs
deleted file mode 100644
index 0ce8ee40d3b..00000000000
--- a/src/test/compile-fail/lub-in-args.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-fn two_args<T>(x: T, y: T) { }
-
-fn main() {
-    let a: @mut int = @mut 3;
-    let b: @int = @3;
-
-    // NOTE:
-    //
-    // The fact that this test fails to compile reflects a known
-    // shortcoming of the current inference algorithm.  These errors
-    // are *not* desirable.
-
-    two_args(a, b); //~ ERROR (values differ in mutability)
-}
diff --git a/src/test/compile-fail/object-pointer-types.rs b/src/test/compile-fail/object-pointer-types.rs
index a1a577a1856..2270cb6f498 100644
--- a/src/test/compile-fail/object-pointer-types.rs
+++ b/src/test/compile-fail/object-pointer-types.rs
@@ -15,7 +15,6 @@ trait Foo {
     fn borrowed_mut(&mut self);
 
     fn managed(@self);
-    fn managed_mut(@mut self);
 
     fn owned(~self);
 }
@@ -24,7 +23,6 @@ fn borrowed_receiver(x: &Foo) {
     x.borrowed();
     x.borrowed_mut(); // See [1]
     x.managed(); //~ ERROR does not implement any method
-    x.managed_mut(); //~ ERROR does not implement any method
     x.owned(); //~ ERROR does not implement any method
 }
 
@@ -32,7 +30,6 @@ fn borrowed_mut_receiver(x: &mut Foo) {
     x.borrowed();
     x.borrowed_mut();
     x.managed(); //~ ERROR does not implement any method
-    x.managed_mut(); //~ ERROR does not implement any method
     x.owned(); //~ ERROR does not implement any method
 }
 
@@ -40,15 +37,6 @@ fn managed_receiver(x: @Foo) {
     x.borrowed();
     x.borrowed_mut(); // See [1]
     x.managed();
-    x.managed_mut();  //~ ERROR does not implement any method
-    x.owned(); //~ ERROR does not implement any method
-}
-
-fn managed_mut_receiver(x: @mut Foo) {
-    x.borrowed();
-    x.borrowed_mut();
-    x.managed();  //~ ERROR does not implement any method
-    x.managed_mut();
     x.owned(); //~ ERROR does not implement any method
 }
 
@@ -56,7 +44,6 @@ fn owned_receiver(x: ~Foo) {
     x.borrowed();
     x.borrowed_mut(); // See [1]
     x.managed();  //~ ERROR does not implement any method
-    x.managed_mut();  //~ ERROR does not implement any method
     x.owned();
 }
 
diff --git a/src/test/compile-fail/pinned-deep-copy.rs b/src/test/compile-fail/pinned-deep-copy.rs
index 6c19ef9700f..9c9b4a9f4d5 100644
--- a/src/test/compile-fail/pinned-deep-copy.rs
+++ b/src/test/compile-fail/pinned-deep-copy.rs
@@ -10,20 +10,22 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 struct r {
-  i: @mut int,
+  i: @Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for r {
     fn drop(&mut self) {
         unsafe {
-            *(self.i) = *(self.i) + 1;
+            self.i.set(self.i.get() + 1);
         }
     }
 }
 
-fn r(i: @mut int) -> r {
+fn r(i: @Cell<int>) -> r {
     r {
         i: i
     }
@@ -34,7 +36,7 @@ struct A {
 }
 
 fn main() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         // Can't do this copy
         let x = ~~~A {y: r(i)};
diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
index 6a6b8f95e63..b36933c4957 100644
--- a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
+++ b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-3.rs
@@ -11,7 +11,7 @@
 #[feature(managed_boxes)];
 
 struct invariant<'a> {
-    f: 'static |x: @mut &'a int|
+    f: 'static |x: &mut &'a int|
 }
 
 fn to_same_lifetime<'r>(bi: invariant<'r>) {
diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
index 4210c52e7f6..449cbc6970f 100644
--- a/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
+++ b/src/test/compile-fail/regions-infer-invariance-due-to-mutability-4.rs
@@ -11,7 +11,7 @@
 #[feature(managed_boxes)];
 
 struct invariant<'a> {
-    f: 'static || -> @mut &'a int
+    f: 'static || -> &mut &'a int
 }
 
 fn to_same_lifetime<'r>(bi: invariant<'r>) {
diff --git a/src/test/compile-fail/unique-vec-res.rs b/src/test/compile-fail/unique-vec-res.rs
index 9771fea04ef..c604e66507e 100644
--- a/src/test/compile-fail/unique-vec-res.rs
+++ b/src/test/compile-fail/unique-vec-res.rs
@@ -10,15 +10,17 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 struct r {
-  i: @mut int,
+  i: @Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for r {
     fn drop(&mut self) {
         unsafe {
-            *(self.i) = *(self.i) + 1;
+            self.i.set(self.i.get() + 1);
         }
     }
 }
@@ -27,12 +29,12 @@ fn f<T>(_i: ~[T], _j: ~[T]) {
 }
 
 fn main() {
-    let i1 = @mut 0;
-    let i2 = @mut 1;
+    let i1 = @Cell::new(0);
+    let i2 = @Cell::new(1);
     let r1 = ~[~r { i: i1 }];
     let r2 = ~[~r { i: i2 }];
     f(r1.clone(), r2.clone());
     //~^ ERROR failed to find an implementation of
-    info!("{:?}", (r2, *i1));
-    info!("{:?}", (r1, *i2));
+    info!("{:?}", (r2, i1.get()));
+    info!("{:?}", (r1, i2.get()));
 }
diff --git a/src/test/pretty/block-disambig.rs b/src/test/pretty/block-disambig.rs
index 8d6eaef8b34..3f789fa456a 100644
--- a/src/test/pretty/block-disambig.rs
+++ b/src/test/pretty/block-disambig.rs
@@ -14,6 +14,8 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 fn test1() { let val = @0; { } *val; }
 
 fn test2() -> int { let val = @0; { } *val }
@@ -21,9 +23,9 @@ fn test2() -> int { let val = @0; { } *val }
 struct S { eax: int }
 
 fn test3() {
-    let regs = @mut S {eax: 0};
+    let regs = @Cell::new(S {eax: 0});
     match true { true => { } _ => { } }
-    (*regs).eax = 1;
+    regs.set(S {eax: 1});
 }
 
 fn test4() -> bool { let regs = @true; if true { } *regs || false }
@@ -51,10 +53,13 @@ fn test8() -> int {
     }
 }
 
-fn test9() { let regs = @mut 0; match true { true => { } _ => { } } *regs += 1; }
+fn test9() {
+    let regs = @Cell::new(0);
+    match true { true => { } _ => { } } regs.set(regs.get() + 1);
+}
 
 fn test10() -> int {
-    let regs = @mut ~[0];
+    let regs = @~[0];
     match true { true => { } _ => { } }
     (*regs)[0]
 }
diff --git a/src/test/run-fail/borrowck-wg-autoderef-and-autoborrowvec-combined-fail-issue-6272.rs b/src/test/run-fail/borrowck-wg-autoderef-and-autoborrowvec-combined-fail-issue-6272.rs
deleted file mode 100644
index c9bc061995d..00000000000
--- a/src/test/run-fail/borrowck-wg-autoderef-and-autoborrowvec-combined-fail-issue-6272.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-// error-pattern:borrowed
-
-// Issue #6272. Tests that freezing correctly accounts for all the
-// implicit derefs that can occur and freezes the innermost box. See
-// the companion test
-//
-//     run-pass/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs
-//
-// for a detailed explanation of what is going on here.
-
-#[feature(managed_boxes)];
-
-fn main() {
-    let a = @mut [3i];
-    let b = @mut [a];
-    let c = @mut b;
-
-    // this should freeze `a` only
-    let _x: &mut [int] = c[0];
-
-    // hence this should fail
-    a[0] = a[0];
-}
diff --git a/src/test/run-fail/borrowck-wg-fail-2.rs b/src/test/run-fail/borrowck-wg-fail-2.rs
deleted file mode 100644
index 284882ff6f5..00000000000
--- a/src/test/run-fail/borrowck-wg-fail-2.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// error-pattern:borrowed
-
-// Test that write guards trigger when there is a write to a field
-// of a frozen structure.
-
-#[feature(managed_boxes)];
-
-struct S {
-    x: int
-}
-
-fn main() {
-    let x = @mut S { x: 3 };
-    let _y: &S = x;
-    let z = x;
-    z.x = 5;
-}
diff --git a/src/test/run-fail/borrowck-wg-fail-3.rs b/src/test/run-fail/borrowck-wg-fail-3.rs
deleted file mode 100644
index 2643ed261f9..00000000000
--- a/src/test/run-fail/borrowck-wg-fail-3.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// error-pattern:borrowed
-
-// Test that write guards trigger when there is a write to a directly
-// frozen @mut box.
-
-#[feature(managed_boxes)];
-
-fn main() {
-    let x = @mut 3;
-    let _y: &mut int = x;
-    let z = x;
-    *z = 5;
-}
diff --git a/src/test/run-fail/borrowck-wg-fail-object-arg.rs b/src/test/run-fail/borrowck-wg-fail-object-arg.rs
deleted file mode 100644
index 4a5664d08b6..00000000000
--- a/src/test/run-fail/borrowck-wg-fail-object-arg.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-#[feature(managed_boxes)];
-
-// error-pattern:borrowed
-
-trait Foo {
-    fn foo(&self, @mut int);
-}
-
-impl Foo for int {
-    fn foo(&self, x: @mut int) {
-        *x += *self;
-    }
-}
-
-fn it_takes_two(_f: &Foo, _g: &mut Foo) {
-}
-
-fn main() {
-    let x = @mut 3_i;
-    let y = x as @mut Foo;
-    let z = y;
-
-    it_takes_two(y, z);
-}
diff --git a/src/test/run-fail/borrowck-wg-fail-object.rs b/src/test/run-fail/borrowck-wg-fail-object.rs
deleted file mode 100644
index 9e32dbf6420..00000000000
--- a/src/test/run-fail/borrowck-wg-fail-object.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-#[feature(managed_boxes)];
-
-// error-pattern:borrowed
-
-trait Foo {
-    fn foo(&self, @mut int);
-}
-
-impl Foo for int {
-    fn foo(&self, x: @mut int) {
-        *x += *self;
-    }
-}
-
-fn main() {
-    let x = @mut 3_i;
-    let y = x as @mut Foo;
-
-    // The call to `y.foo(...)` should freeze `y` (and thus also `x`,
-    // since `x === y`). It is thus an error when `foo` tries to
-    // mutate `x`.
-    y.foo(x);
-}
diff --git a/src/test/run-fail/borrowck-wg-fail.rs b/src/test/run-fail/borrowck-wg-fail.rs
deleted file mode 100644
index e1273381e93..00000000000
--- a/src/test/run-fail/borrowck-wg-fail.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#[feature(managed_boxes)];
-
-// error-pattern:borrowed
-
-// Test that write guards trigger when mut box is frozen
-// as part of argument coercion.
-
-fn f(_x: &int, y: @mut int) {
-    *y = 2;
-}
-
-fn main() {
-    let x = @mut 3;
-    f(x, x);
-}
diff --git a/src/test/run-fail/borrowck-wg-imm-then-mut.rs b/src/test/run-fail/borrowck-wg-imm-then-mut.rs
deleted file mode 100644
index c41b9b37bb5..00000000000
--- a/src/test/run-fail/borrowck-wg-imm-then-mut.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#[feature(managed_boxes)];
-
-// error-pattern:borrowed
-
-// Test that if you imm borrow then mut borrow it fails.
-
-fn add1(a:@mut int)
-{
-    add2(a); // already frozen
-}
-
-fn add2(_:&mut int)
-{
-}
-
-pub fn main()
-{
-    let a = @mut 3;
-    let _b = &*a; // freezes a
-    add1(a);
-}
diff --git a/src/test/run-fail/borrowck-wg-mut-then-imm.rs b/src/test/run-fail/borrowck-wg-mut-then-imm.rs
deleted file mode 100644
index aceadb0459c..00000000000
--- a/src/test/run-fail/borrowck-wg-mut-then-imm.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-#[feature(managed_boxes)];
-
-// error-pattern:borrowed
-
-// Test that if you mut borrow then imm borrow it fails.
-
-fn add1(a:@mut int)
-{
-    add2(a); // already frozen
-}
-
-fn add2(_:&int)
-{
-}
-
-pub fn main()
-{
-    let a = @mut 3;
-    let _b = &mut *a; // freezes a
-    add1(a);
-}
diff --git a/src/test/run-fail/borrowck-wg-one-mut-one-imm-slice-method.rs b/src/test/run-fail/borrowck-wg-one-mut-one-imm-slice-method.rs
deleted file mode 100644
index d33e39e09a8..00000000000
--- a/src/test/run-fail/borrowck-wg-one-mut-one-imm-slice-method.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-// error-pattern:borrowed
-
-// Test that write guards trigger when there is a coercion to
-// a slice on the receiver of a method.
-
-#[feature(managed_boxes)];
-
-trait MyMutSlice {
-    fn my_mut_slice(self) -> Self;
-}
-
-impl<'a, T> MyMutSlice for &'a mut [T] {
-    fn my_mut_slice(self) -> &'a mut [T] {
-        self
-    }
-}
-
-trait MySlice {
-    fn my_slice(self) -> Self;
-}
-
-impl<'a, T> MySlice for &'a [T] {
-    fn my_slice(self) -> &'a [T] {
-        self
-    }
-}
-
-fn add(x:&mut [int], y:&[int])
-{
-    x[0] = x[0] + y[0];
-}
-
-pub fn main()
-{
-    let z = @mut [1,2,3];
-    let z2 = z;
-    add(z.my_mut_slice(), z2.my_slice());
-    println!("{}", z[0]);
-}
diff --git a/src/test/run-fail/borrowck-wg-one-mut-one-imm-slices.rs b/src/test/run-fail/borrowck-wg-one-mut-one-imm-slices.rs
deleted file mode 100644
index 63287981bdc..00000000000
--- a/src/test/run-fail/borrowck-wg-one-mut-one-imm-slices.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// error-pattern:borrowed
-
-// Test that write guards trigger when arguments are coerced to slices.
-
-#[feature(managed_boxes)];
-
-fn add(x:&mut [int], y:&[int])
-{
-    x[0] = x[0] + y[0];
-}
-
-pub fn main()
-{
-    let z = @mut [1,2,3];
-    let z2 = z;
-    add(z, z2);
-    println!("{}", z[0]);
-}
diff --git a/src/test/run-fail/borrowck-wg-one-mut-one-imm.rs b/src/test/run-fail/borrowck-wg-one-mut-one-imm.rs
deleted file mode 100644
index 0820b94e181..00000000000
--- a/src/test/run-fail/borrowck-wg-one-mut-one-imm.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// error-pattern:borrowed
-
-// Test that write guards trigger when we are indexing into
-// an @mut vector.
-
-#[feature(managed_boxes)];
-
-fn add(x:&mut int, y:&int)
-{
-    *x = *x + *y;
-}
-
-pub fn main()
-{
-    let z = @mut [1,2,3];
-    let z2 = z;
-    add(&mut z[0], &z2[0]);
-    println!("{}", z[0]);
-}
diff --git a/src/test/run-fail/borrowck-wg-two-array-indices.rs b/src/test/run-fail/borrowck-wg-two-array-indices.rs
deleted file mode 100644
index 5ee9cd37e87..00000000000
--- a/src/test/run-fail/borrowck-wg-two-array-indices.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// error-pattern:borrowed
-
-// Test that arguments trigger when there are *two mutable* borrows
-// of indices.
-
-#[feature(managed_boxes)];
-
-fn add(x:&mut int, y:&mut int)
-{
-    *x = *x + *y;
-}
-
-pub fn main()
-{
-    let z = @mut [1,2,3];
-    let z2 = z;
-    add(&mut z[0], &mut z2[0]);
-    println!("{}", z[0]);
-}
diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs
index b87303467ce..09e7d0bc28c 100644
--- a/src/test/run-fail/unwind-misc-1.rs
+++ b/src/test/run-fail/unwind-misc-1.rs
@@ -14,7 +14,7 @@
 #[feature(managed_boxes)];
 
 fn main() {
-    let _count = @mut 0u;
+    let _count = @0u;
     let mut map = std::hashmap::HashMap::new();
     let mut arr = ~[];
     for _i in range(0u, 10u) {
diff --git a/src/test/run-pass/alignment-gep-tup-like-2.rs b/src/test/run-pass/alignment-gep-tup-like-2.rs
index 8f7f8c4fa58..02ce1fd4b26 100644
--- a/src/test/run-pass/alignment-gep-tup-like-2.rs
+++ b/src/test/run-pass/alignment-gep-tup-like-2.rs
@@ -10,6 +10,8 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 struct Pair<A,B> {
     a: A, b: B
 }
@@ -17,12 +19,15 @@ struct Pair<A,B> {
 struct RecEnum<A>(Rec<A>);
 struct Rec<A> {
     val: A,
-    rec: Option<@mut RecEnum<A>>
+    rec: Option<@RefCell<RecEnum<A>>>
 }
 
 fn make_cycle<A:'static>(a: A) {
-    let g: @mut RecEnum<A> = @mut RecEnum(Rec {val: a, rec: None});
-    g.rec = Some(g);
+    let g: @RefCell<RecEnum<A>> = @RefCell::new(RecEnum(Rec {val: a, rec: None}));
+    {
+        let mut gb = g.borrow_mut();
+        gb.get().rec = Some(g);
+    }
 }
 
 struct Invoker<A,B> {
diff --git a/src/test/run-pass/auto-encode.rs b/src/test/run-pass/auto-encode.rs
index 1810f33eadb..8058556a469 100644
--- a/src/test/run-pass/auto-encode.rs
+++ b/src/test/run-pass/auto-encode.rs
@@ -35,8 +35,8 @@ fn test_ebml<'a, A:
     Encodable<EBWriter::Encoder> +
     Decodable<EBReader::Decoder<'a>>
 >(a1: &A) {
-    let mut wr = @mut std::io::mem::MemWriter::new();
-    let mut ebml_w = EBWriter::Encoder(wr);
+    let mut wr = std::io::mem::MemWriter::new();
+    let mut ebml_w = EBWriter::Encoder(&mut wr);
     a1.encode(&mut ebml_w);
     let bytes = wr.inner_ref().as_slice();
 
diff --git a/src/test/compile-fail/borrowck-assign-to-subfield.rs b/src/test/run-pass/borrowck-assign-to-subfield.rs
index 40db36787bb..10b5825cdd6 100644
--- a/src/test/compile-fail/borrowck-assign-to-subfield.rs
+++ b/src/test/run-pass/borrowck-assign-to-subfield.rs
@@ -8,14 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[feature(managed_boxes)];
-
-fn main() {
+pub fn main() {
     struct A {
         a: int,
         w: B,
-        x: @B,
-        z: @mut B
     }
     struct B {
         a: int
@@ -23,8 +19,6 @@ fn main() {
     let mut p = A {
         a: 1,
         w: B {a: 1},
-        x: @B {a: 1},
-        z: @mut B {a: 1}
     };
 
     // even though `x` is not declared as a mutable field,
@@ -33,9 +27,4 @@ fn main() {
 
     // this is true for an interior field too
     p.w.a = 2;
-
-    // in these cases we pass through a box, so the mut
-    // of the box is dominant
-    p.x.a = 2;     //~ ERROR cannot assign to immutable field
-    p.z.a = 2;
 }
diff --git a/src/test/run-pass/borrowck-nested-calls.rs b/src/test/run-pass/borrowck-nested-calls.rs
index 50e9b6d81b5..7402f087508 100644
--- a/src/test/run-pass/borrowck-nested-calls.rs
+++ b/src/test/run-pass/borrowck-nested-calls.rs
@@ -24,7 +24,7 @@ impl Foo {
     }
 }
 
-fn main() {
+pub fn main() {
     let mut f = Foo {a: 22, b: 23};
     f.inc_a(f.next_b());
     assert_eq!(f.a, 22+23);
diff --git a/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs b/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs
index 3f6bcb4d5b7..8871035908b 100644
--- a/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs
+++ b/src/test/run-pass/borrowck-preserve-box-in-arm-not-taken.rs
@@ -12,15 +12,18 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 pub fn main() {
-    let x: @mut @Option<~int> = @mut @None;
-    match x {
-      @@Some(ref _y) => {
+    let x: @RefCell<@Option<~int>> = @RefCell::new(@None);
+    let mut xb = x.borrow_mut();
+    match *xb.get() {
+      @Some(ref _y) => {
         // here, the refcount of `*x` is bumped so
         // `_y` remains valid even if `*x` is modified.
-        *x = @None;
+        *xb.get() = @None;
       }
-      @@None => {
+      @None => {
         // here, no bump of the ref count of `*x` is needed, but in
         // fact a bump occurs anyway because of how pattern marching
         // works.
diff --git a/src/test/run-pass/borrowck-preserve-box-in-pat.rs b/src/test/run-pass/borrowck-preserve-box-in-pat.rs
index 2fd2c689a3c..b333bcae582 100644
--- a/src/test/run-pass/borrowck-preserve-box-in-pat.rs
+++ b/src/test/run-pass/borrowck-preserve-box-in-pat.rs
@@ -12,23 +12,25 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
 use std::ptr;
 
 struct F { f: ~int }
 
 pub fn main() {
-    let x = @mut @F {f: ~3};
-    match x {
-      @@F{f: ref b_x} => {
+    let x = @RefCell::new(@F {f: ~3});
+    let mut xb = x.borrow_mut();
+    match *xb.get() {
+      @F{f: ref b_x} => {
         assert_eq!(**b_x, 3);
-        assert_eq!(ptr::to_unsafe_ptr(&(x.f)), ptr::to_unsafe_ptr(b_x));
+        assert_eq!(ptr::to_unsafe_ptr(&(xb.get().f)), ptr::to_unsafe_ptr(b_x));
 
-        *x = @F {f: ~4};
+        *xb.get() = @F {f: ~4};
 
         info!("ptr::to_unsafe_ptr(*b_x) = {:x}",
                ptr::to_unsafe_ptr(&(**b_x)) as uint);
         assert_eq!(**b_x, 3);
-        assert!(ptr::to_unsafe_ptr(&(*x.f)) != ptr::to_unsafe_ptr(&(**b_x)));
+        assert!(ptr::to_unsafe_ptr(&(*xb.get().f)) != ptr::to_unsafe_ptr(&(**b_x)));
       }
     }
 }
diff --git a/src/test/run-pass/borrowck-root-while-cond-2.rs b/src/test/run-pass/borrowck-root-while-cond-2.rs
index 19b87584e2d..9511d1b40e6 100644
--- a/src/test/run-pass/borrowck-root-while-cond-2.rs
+++ b/src/test/run-pass/borrowck-root-while-cond-2.rs
@@ -14,6 +14,6 @@ struct F { f: @G }
 struct G { g: ~[int] }
 
 pub fn main() {
-    let rec = @mut F {f: @G {g: ~[1, 2, 3]}};
+    let rec = @F {f: @G {g: ~[1, 2, 3]}};
     while rec.f.g.len() == 23 {}
 }
diff --git a/src/test/run-pass/borrowck-root-while-cond.rs b/src/test/run-pass/borrowck-root-while-cond.rs
index 35ab64584f5..a2d4991abc0 100644
--- a/src/test/run-pass/borrowck-root-while-cond.rs
+++ b/src/test/run-pass/borrowck-root-while-cond.rs
@@ -15,6 +15,6 @@ fn borrow<'r,T>(x: &'r T) -> &'r T {x}
 struct Rec { f: @int }
 
 pub fn main() {
-    let rec = @mut Rec {f: @22};
+    let rec = @Rec {f: @22};
     while *borrow(rec.f) == 23 {}
 }
diff --git a/src/test/run-pass/borrowck-univariant-enum.rs b/src/test/run-pass/borrowck-univariant-enum.rs
index aaa08ea49b3..97d92f421c1 100644
--- a/src/test/run-pass/borrowck-univariant-enum.rs
+++ b/src/test/run-pass/borrowck-univariant-enum.rs
@@ -10,6 +10,8 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 enum newtype {
     newtype(int)
 }
@@ -19,12 +21,12 @@ pub fn main() {
     // Test that borrowck treats enums with a single variant
     // specially.
 
-    let x = @mut 5;
-    let y = @mut newtype(3);
-    let z = match *y {
+    let x = @Cell::new(5);
+    let y = @Cell::new(newtype(3));
+    let z = match y.get() {
       newtype(b) => {
-        *x += 1;
-        *x * b
+        x.set(x.get() + 1);
+        x.get() * b
       }
     };
     assert_eq!(z, 18);
diff --git a/src/test/run-pass/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs b/src/test/run-pass/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs
deleted file mode 100644
index 27d337a28bf..00000000000
--- a/src/test/run-pass/borrowck-wg-autoderef-and-autoborrowvec-combined-issue-6272.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Issue #6272. Tests that freezing correctly accounts for all the
-// implicit derefs that can occur.
-//
-// In this particular case, the expression:
-//
-//    let x: &mut [int] = c[0];
-//
-// is seen by borrowck as this sequence of derefs
-// and pointer offsets:
-//
-//    &*((**c)[0])
-//
-// or, written using `x.*` for `*x` (so that everything
-// is a postfix operation):
-//
-//    &c.*.*.[0].*
-//       ^    ^
-//       |    |
-//       b    a
-//
-// Here I also indicated where the evaluation yields the boxes `a` and
-// `b`. It is important then that we only freeze the innermost box
-// (`a`), and not the other ones (`b`, `c`).
-//
-// Also see the companion test:
-//
-// run-fail/borrowck-wg-autoderef-and-autoborrowvec-combined-fail-issue-6272.rs
-
-#[feature(managed_boxes)];
-
-pub fn main() {
-    let a = @mut 3i;
-    let b = @mut [a];
-    let c = @mut [3];
-
-    // this should freeze `a` only
-    let _x: &mut int = a;
-
-    // hence these writes should not fail:
-    b[0] = b[0];
-    c[0] = c[0];
-}
diff --git a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-2.rs b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-2.rs
deleted file mode 100644
index d721704ba55..00000000000
--- a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-2.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-struct Cat;
-
-fn bar(_: &Cat) {
-}
-
-fn foo(cat: &mut Cat) {
-    bar(&*cat);
-}
-
-pub fn main() {
-    let mut mimi = ~Cat;
-    foo(mimi);
-}
diff --git a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs
deleted file mode 100644
index dcf497e81f7..00000000000
--- a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm-3.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-struct Wizard {
-    spells: ~[&'static str]
-}
-
-impl Wizard {
-    pub fn cast(&mut self) {
-        for &spell in self.spells.iter() {
-            println(spell);
-        }
-    }
-}
-
-pub fn main() {
-    let mut harry = Wizard {
-        spells: ~[ "expelliarmus", "expecto patronum", "incendio" ]
-    };
-    harry.cast();
-}
diff --git a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs b/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs
deleted file mode 100644
index 668f602b3d3..00000000000
--- a/src/test/run-pass/borrowck-wg-borrow-mut-to-imm.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-fn g(x: &Option<int>) {
-    println(x.unwrap().to_str());
-}
-
-fn f(x: &mut Option<int>) {
-    g(&*x);
-}
-
-pub fn main() {
-    let mut x = ~Some(3);
-    f(x);
-}
diff --git a/src/test/run-pass/borrowck-wg-simple.rs b/src/test/run-pass/borrowck-wg-simple.rs
deleted file mode 100644
index f561dba2423..00000000000
--- a/src/test/run-pass/borrowck-wg-simple.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#[feature(managed_boxes)];
-
-fn f(x: &int) {
-    println(x.to_str());
-}
-
-pub fn main() {
-    let x = @mut 3;
-    f(x);
-}
diff --git a/src/test/run-pass/borrowck-wg-two-imm-borrows.rs b/src/test/run-pass/borrowck-wg-two-imm-borrows.rs
deleted file mode 100644
index efd0572c8c6..00000000000
--- a/src/test/run-pass/borrowck-wg-two-imm-borrows.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Test that we can borrow the same @mut box twice, so long as both are imm.
-
-#[feature(managed_boxes)];
-
-fn add(x:&int, y:&int)
-{
-    *x + *y;
-}
-
-pub fn main()
-{
-    let z = @mut [1,2,3];
-    let z2 = z;
-    add(&z[0], &z2[0]);
-    println!("{}", z[0]);
-}
diff --git a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs
index f94d1af84f6..54c4e0dce8b 100644
--- a/src/test/run-pass/builtin-superkinds-capabilities-xc.rs
+++ b/src/test/run-pass/builtin-superkinds-capabilities-xc.rs
@@ -28,7 +28,7 @@ fn foo<T: RequiresRequiresFreezeAndSend>(val: T, chan: Chan<T>) {
     chan.send(val);
 }
 
-fn main() {
+pub fn main() {
     let (p,c) = Chan::new();
     foo(X(31337), c);
     assert!(p.recv() == X(31337));
diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs
index f285275f5e2..55edc135190 100644
--- a/src/test/run-pass/builtin-superkinds-in-metadata.rs
+++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs
@@ -26,4 +26,4 @@ impl <T:Freeze+Send> RequiresRequiresFreezeAndSend for X<T> { }
 
 impl <T:Pod> RequiresPod for X<T> { }
 
-fn main() { }
+pub fn main() { }
diff --git a/src/test/run-pass/cast-mutable-trait.rs b/src/test/run-pass/cast-mutable-trait.rs
deleted file mode 100644
index 09d10502b84..00000000000
--- a/src/test/run-pass/cast-mutable-trait.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-trait T {
-    fn foo(@mut self);
-}
-
-struct S {
-    unused: int
-}
-
-impl T for S {
-    fn foo(@mut self) {
-    }
-}
-
-fn bar(t: @mut T) {
-    t.foo();
-}
-
-pub fn main() {
-    let s = @mut S { unused: 0 };
-    let s2 = s as @mut T;
-    s2.foo();
-    bar(s2);
-    bar(s as @mut T);
-}
diff --git a/src/test/run-pass/cfg-macros-foo.rs b/src/test/run-pass/cfg-macros-foo.rs
index 224df80d08e..49e36ca5c63 100644
--- a/src/test/run-pass/cfg-macros-foo.rs
+++ b/src/test/run-pass/cfg-macros-foo.rs
@@ -32,6 +32,6 @@ mod foo {
     }
 }
 
-fn main() {
+pub fn main() {
     assert!(bar!())
 }
diff --git a/src/test/run-pass/cfg-macros-notfoo.rs b/src/test/run-pass/cfg-macros-notfoo.rs
index 5aa94bb1fbd..88244135ff7 100644
--- a/src/test/run-pass/cfg-macros-notfoo.rs
+++ b/src/test/run-pass/cfg-macros-notfoo.rs
@@ -32,6 +32,6 @@ mod foo {
     }
 }
 
-fn main() {
+pub fn main() {
     assert!(!bar!())
 }
diff --git a/src/test/run-pass/cfg_inner_static.rs b/src/test/run-pass/cfg_inner_static.rs
index 2d06a10a05f..58f094c5987 100644
--- a/src/test/run-pass/cfg_inner_static.rs
+++ b/src/test/run-pass/cfg_inner_static.rs
@@ -13,6 +13,6 @@
 
 extern mod cfg_inner_static;
 
-fn main() {
+pub fn main() {
     cfg_inner_static::foo();
 }
diff --git a/src/test/run-pass/cfgs-on-items.rs b/src/test/run-pass/cfgs-on-items.rs
index 237fa3f7ea9..496770bc325 100644
--- a/src/test/run-pass/cfgs-on-items.rs
+++ b/src/test/run-pass/cfgs-on-items.rs
@@ -25,7 +25,7 @@ fn foo2() -> int { 2 }
 fn foo2() -> int { 3 }
 
 
-fn main() {
+pub fn main() {
     assert_eq!(1, foo1());
     assert_eq!(3, foo2());
 }
diff --git a/src/test/run-pass/class-cast-to-trait-multiple-types.rs b/src/test/run-pass/class-cast-to-trait-multiple-types.rs
index e44d7c41931..8c142768944 100644
--- a/src/test/run-pass/class-cast-to-trait-multiple-types.rs
+++ b/src/test/run-pass/class-cast-to-trait-multiple-types.rs
@@ -11,86 +11,92 @@
 #[feature(managed_boxes)];
 
 trait noisy {
-  fn speak(&self) -> int;
+  fn speak(&mut self) -> int;
 }
 
 struct dog {
-  priv barks : @mut uint,
+  priv barks: uint,
 
-  volume : @mut int,
+  volume: int,
 }
 
 impl dog {
-    fn bark(&self) -> int {
-      info!("Woof {} {}", *self.barks, *self.volume);
-      *self.barks += 1u;
-      if *self.barks % 3u == 0u {
-          *self.volume += 1;
+    fn bark(&mut self) -> int {
+      info!("Woof {} {}", self.barks, self.volume);
+      self.barks += 1u;
+      if self.barks % 3u == 0u {
+          self.volume += 1;
       }
-      if *self.barks % 10u == 0u {
-          *self.volume -= 2;
+      if self.barks % 10u == 0u {
+          self.volume -= 2;
       }
-      info!("Grrr {} {}", *self.barks, *self.volume);
-      *self.volume
+      info!("Grrr {} {}", self.barks, self.volume);
+      self.volume
     }
 }
 
 impl noisy for dog {
-  fn speak(&self) -> int { self.bark() }
+    fn speak(&mut self) -> int {
+        self.bark()
+    }
 }
 
 fn dog() -> dog {
     dog {
-        volume: @mut 0,
-        barks: @mut 0u
+        volume: 0,
+        barks: 0u
     }
 }
 
 #[deriving(Clone)]
 struct cat {
-  priv meows : @mut uint,
+  priv meows: uint,
 
-  how_hungry : @mut int,
-  name : ~str,
+  how_hungry: int,
+  name: ~str,
 }
 
 impl noisy for cat {
-  fn speak(&self) -> int { self.meow() as int }
+    fn speak(&mut self) -> int {
+        self.meow() as int
+    }
 }
 
 impl cat {
-  pub fn meow_count(&self) -> uint { *self.meows }
+    pub fn meow_count(&self) -> uint {
+        self.meows
+    }
 }
 
 impl cat {
-    fn meow(&self) -> uint {
-      info!("Meow");
-      *self.meows += 1u;
-      if *self.meows % 5u == 0u {
-          *self.how_hungry += 1;
-      }
-      *self.meows
+    fn meow(&mut self) -> uint {
+        info!("Meow");
+        self.meows += 1u;
+        if self.meows % 5u == 0u {
+            self.how_hungry += 1;
+        }
+        self.meows
     }
 }
 
-fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
+fn cat(in_x: uint, in_y: int, in_name: ~str) -> cat {
     cat {
-        meows: @mut in_x,
-        how_hungry: @mut in_y,
+        meows: in_x,
+        how_hungry: in_y,
         name: in_name
     }
 }
 
 
-fn annoy_neighbors(critter: @noisy) {
+fn annoy_neighbors(critter: &mut noisy) {
     for _i in range(0u, 10) { critter.speak(); }
 }
 
 pub fn main() {
-  let nyan : cat  = cat(0u, 2, ~"nyan");
-  let whitefang : dog = dog();
-  annoy_neighbors(@nyan.clone() as @noisy);
-  annoy_neighbors(@whitefang as @noisy);
+  let mut nyan: cat = cat(0u, 2, ~"nyan");
+  let mut whitefang: dog = dog();
+  annoy_neighbors(&mut nyan);
+  annoy_neighbors(&mut whitefang);
   assert_eq!(nyan.meow_count(), 10u);
-  assert_eq!(*whitefang.volume, 1);
+  assert_eq!(whitefang.volume, 1);
 }
diff --git a/src/test/run-pass/class-cast-to-trait.rs b/src/test/run-pass/class-cast-to-trait.rs
index cc723f8037d..86764df6ae0 100644
--- a/src/test/run-pass/class-cast-to-trait.rs
+++ b/src/test/run-pass/class-cast-to-trait.rs
@@ -58,6 +58,7 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
 
 
 pub fn main() {
-  let nyan: @mut noisy = @mut cat(0u, 2, ~"nyan") as @mut noisy;
-  nyan.speak();
+    let mut nyan = cat(0u, 2, ~"nyan");
+    let mut nyan: &mut noisy = &mut nyan;
+    nyan.speak();
 }
diff --git a/src/test/run-pass/conditional-debug-macro-off.rs b/src/test/run-pass/conditional-debug-macro-off.rs
index 1648b198999..54626f9ffff 100644
--- a/src/test/run-pass/conditional-debug-macro-off.rs
+++ b/src/test/run-pass/conditional-debug-macro-off.rs
@@ -12,7 +12,7 @@
 // compile-flags: --cfg ndebug
 // exec-env:RUST_LOG=conditional-debug-macro-off=4
 
-fn main() {
+pub fn main() {
     // only fails if debug! evaluates its argument.
     debug!("{:?}", { if true { fail!() } });
 }
diff --git a/src/test/run-pass/conditional-debug-macro-on.rs b/src/test/run-pass/conditional-debug-macro-on.rs
index 3842d480327..0599d199dc0 100644
--- a/src/test/run-pass/conditional-debug-macro-on.rs
+++ b/src/test/run-pass/conditional-debug-macro-on.rs
@@ -11,7 +11,7 @@
 // xfail-fast compile-flags directive doesn't work for check-fast
 // exec-env:RUST_LOG=conditional-debug-macro-on=4
 
-fn main() {
+pub fn main() {
     // exits early if debug! evaluates its arguments, otherwise it
     // will hit the fail.
     debug!("{:?}", { if true { return; } });
diff --git a/src/test/run-pass/const-cross-crate-const.rs b/src/test/run-pass/const-cross-crate-const.rs
index 607d0c72b89..9d85689d4ad 100644
--- a/src/test/run-pass/const-cross-crate-const.rs
+++ b/src/test/run-pass/const-cross-crate-const.rs
@@ -16,7 +16,7 @@ static foo: &'static str = cci_const::foopy;
 static a: uint = cci_const::uint_val;
 static b: uint = cci_const::uint_expr + 5;
 
-fn main() {
+pub fn main() {
     assert_eq!(a, 12);
     let foo2 = a;
     assert_eq!(foo2, cci_const::uint_val);
diff --git a/src/test/run-pass/cross-crate-const-pat.rs b/src/test/run-pass/cross-crate-const-pat.rs
index 0a0e2356f44..f6516d2b826 100644
--- a/src/test/run-pass/cross-crate-const-pat.rs
+++ b/src/test/run-pass/cross-crate-const-pat.rs
@@ -13,7 +13,7 @@
 
 extern mod cci_const;
 
-fn main() {
+pub fn main() {
     let x = cci_const::uint_val;
     match x {
         cci_const::uint_val => {}
diff --git a/src/test/run-pass/cross-crate-newtype-struct-pat.rs b/src/test/run-pass/cross-crate-newtype-struct-pat.rs
index 37d5c5c700b..db767151bd4 100644
--- a/src/test/run-pass/cross-crate-newtype-struct-pat.rs
+++ b/src/test/run-pass/cross-crate-newtype-struct-pat.rs
@@ -13,7 +13,7 @@
 
 extern mod newtype_struct_xc;
 
-fn main() {
+pub fn main() {
     let x = newtype_struct_xc::Au(21);
     match x {
         newtype_struct_xc::Au(n) => assert_eq!(n, 21)
diff --git a/src/test/run-pass/cycle-collection.rs b/src/test/run-pass/cycle-collection.rs
index 29a972ae30e..ca1e18eb87b 100644
--- a/src/test/run-pass/cycle-collection.rs
+++ b/src/test/run-pass/cycle-collection.rs
@@ -10,14 +10,16 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 enum taggy {
-    cons(@mut taggy),
+    cons(@RefCell<taggy>),
     nil,
 }
 
 fn f() {
-    let a_box = @mut nil;
-    *a_box = cons(a_box);
+    let a_box = @RefCell::new(nil);
+    a_box.set(cons(a_box));
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/cycle-collection2.rs b/src/test/run-pass/cycle-collection2.rs
deleted file mode 100644
index f10592bf800..00000000000
--- a/src/test/run-pass/cycle-collection2.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-struct foo {
-    z: Option<@Invokable>,
-}
-
-struct Thing {
-    w: @mut foo,
-}
-
-trait Invokable {
-    fn f(&self);
-}
-
-impl Invokable for Thing {
-    fn f(&self) {
-        nop_foo(self.w);
-    }
-}
-
-fn nop() { }
-fn nop_foo(_x : @mut foo) { }
-
-pub fn main() {
-    let w = @mut foo {
-        z: None,
-    };
-    let x = @Thing {
-        w: w,
-    } as @Invokable;
-    w.z = Some(x);
-}
diff --git a/src/test/run-pass/deref-lval.rs b/src/test/run-pass/deref-lval.rs
index 997e2f03abd..914805c126f 100644
--- a/src/test/run-pass/deref-lval.rs
+++ b/src/test/run-pass/deref-lval.rs
@@ -10,4 +10,10 @@
 
 #[feature(managed_boxes)];
 
-pub fn main() { let x = @mut 5; *x = 1000; info!("{:?}", *x); }
+use std::cell::Cell;
+
+pub fn main() {
+    let x = @Cell::new(5);
+    x.set(1000);
+    info!("{:?}", x.get());
+}
diff --git a/src/test/run-pass/deriving-encodable-decodable.rs b/src/test/run-pass/deriving-encodable-decodable.rs
index 4f4e9c9ce00..9194304a376 100644
--- a/src/test/run-pass/deriving-encodable-decodable.rs
+++ b/src/test/run-pass/deriving-encodable-decodable.rs
@@ -58,8 +58,8 @@ struct G<T> {
 fn roundtrip<'a, T: Rand + Eq + Encodable<Encoder> +
                     Decodable<Decoder<'a>>>() {
     let obj: T = random();
-    let w = @mut MemWriter::new();
-    let mut e = Encoder(w);
+    let mut w = MemWriter::new();
+    let mut e = Encoder(&mut w);
     obj.encode(&mut e);
     let doc = ebml::reader::Doc(@w.inner_ref().to_owned());
     let mut dec = Decoder(doc);
diff --git a/src/test/run-pass/deriving-global.rs b/src/test/run-pass/deriving-global.rs
index 37487c1b6d7..ce51e2dcd70 100644
--- a/src/test/run-pass/deriving-global.rs
+++ b/src/test/run-pass/deriving-global.rs
@@ -39,4 +39,4 @@ mod submod {
 
 }
 
-fn main() {}
+pub fn main() {}
diff --git a/src/test/run-pass/deriving-rand.rs b/src/test/run-pass/deriving-rand.rs
index 9a28ed70088..58ef613b7cd 100644
--- a/src/test/run-pass/deriving-rand.rs
+++ b/src/test/run-pass/deriving-rand.rs
@@ -32,7 +32,7 @@ enum D {
     D2 { x: (), y: () }
 }
 
-fn main() {
+pub fn main() {
     // check there's no segfaults
     20.times(|| {
         rand::random::<A>();
diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs
index 0cff8e8a3f8..d28e54d57ad 100644
--- a/src/test/run-pass/deriving-zero.rs
+++ b/src/test/run-pass/deriving-zero.rs
@@ -30,7 +30,7 @@ struct Lots {
     e: char,
     f: f64,
     g: (f32, char),
-    h: @mut (int, int),
+    h: @(int, int),
     i: bool,
     j: (),
 }
diff --git a/src/test/run-pass/dupe-first-attr.rc b/src/test/run-pass/dupe-first-attr.rc
index 9bd63a8d646..c3c22cb26d2 100644
--- a/src/test/run-pass/dupe-first-attr.rc
+++ b/src/test/run-pass/dupe-first-attr.rc
@@ -26,4 +26,4 @@ mod hello;
 #[cfg(target_os = "android")]
 mod hello;
 
-fn main() { }
\ No newline at end of file
+pub fn main() { }
diff --git a/src/test/run-pass/explicit-self-closures.rs b/src/test/run-pass/explicit-self-closures.rs
index ce662bafd49..c7e5681c0c1 100644
--- a/src/test/run-pass/explicit-self-closures.rs
+++ b/src/test/run-pass/explicit-self-closures.rs
@@ -18,9 +18,6 @@ impl Box {
     pub fn set_many(&mut self, xs: &[uint]) {
         for x in xs.iter() { self.x = *x; }
     }
-    pub fn set_many2(@mut self, xs: &[uint]) {
-        for x in xs.iter() { self.x = *x; }
-    }
 }
 
 pub fn main() {}
diff --git a/src/test/run-pass/expr-repeat-vstore.rs b/src/test/run-pass/expr-repeat-vstore.rs
index 2831740deaf..e1be481099c 100644
--- a/src/test/run-pass/expr-repeat-vstore.rs
+++ b/src/test/run-pass/expr-repeat-vstore.rs
@@ -13,10 +13,4 @@ pub fn main() {
     println(v[2].to_str());
     println(v[3].to_str());
     println(v[4].to_str());
-    let v: @mut [int] = @mut [ 3, ..5 ];
-    println((v[0]).to_str());
-    println((v[1]).to_str());
-    println((v[2]).to_str());
-    println((v[3]).to_str());
-    println((v[4]).to_str());
 }
diff --git a/src/test/run-pass/exterior.rs b/src/test/run-pass/exterior.rs
index 27f30fb8ba9..d9505e01de9 100644
--- a/src/test/run-pass/exterior.rs
+++ b/src/test/run-pass/exterior.rs
@@ -10,15 +10,21 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 struct Point {x: int, y: int, z: int}
 
-fn f(p: @mut Point) { assert!((p.z == 12)); p.z = 13; assert!((p.z == 13)); }
+fn f(p: @Cell<Point>) {
+    assert!((p.get().z == 12));
+    p.set(Point {x: 10, y: 11, z: 13});
+    assert!((p.get().z == 13));
+}
 
 pub fn main() {
     let a: Point = Point {x: 10, y: 11, z: 12};
-    let b: @mut Point = @mut a;
-    assert_eq!(b.z, 12);
+    let b: @Cell<Point> = @Cell::new(a);
+    assert_eq!(b.get().z, 12);
     f(b);
     assert_eq!(a.z, 12);
-    assert_eq!(b.z, 13);
+    assert_eq!(b.get().z, 13);
 }
diff --git a/src/test/run-pass/extern-calling-convention-test.rs b/src/test/run-pass/extern-calling-convention-test.rs
index e8609a8b60b..5a5ed2e02c1 100644
--- a/src/test/run-pass/extern-calling-convention-test.rs
+++ b/src/test/run-pass/extern-calling-convention-test.rs
@@ -15,6 +15,6 @@ extern mod extern_calling_convention;
 
 use extern_calling_convention::foo;
 
-fn main() {
+pub fn main() {
     foo(1, 2, 3, 4);
 }
diff --git a/src/test/run-pass/extern-fn-reachable.rs b/src/test/run-pass/extern-fn-reachable.rs
index 7af832a7bac..c1af0c2b373 100644
--- a/src/test/run-pass/extern-fn-reachable.rs
+++ b/src/test/run-pass/extern-fn-reachable.rs
@@ -27,7 +27,7 @@ pub mod bar {
 
 #[no_mangle] pub fn fun5() {}
 
-fn main() {
+pub fn main() {
     unsafe {
         let a = DynamicLibrary::open(None).unwrap();
         assert!(a.symbol::<int>("fun1").is_ok());
diff --git a/src/test/run-pass/extern-mod-ordering-exe.rs b/src/test/run-pass/extern-mod-ordering-exe.rs
index 5836245ff78..17731d9ec94 100644
--- a/src/test/run-pass/extern-mod-ordering-exe.rs
+++ b/src/test/run-pass/extern-mod-ordering-exe.rs
@@ -5,6 +5,6 @@ extern mod extern_mod_ordering_lib;
 
 use extern_mod_ordering_lib::extern_mod_ordering_lib;
 
-fn main() {
+pub fn main() {
     extern_mod_ordering_lib::f();
 }
diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs
index 49aa8d18e90..905fa42635b 100644
--- a/src/test/run-pass/hashmap-memory.rs
+++ b/src/test/run-pass/hashmap-memory.rs
@@ -40,7 +40,7 @@ mod map_reduce {
     }
 
     fn map_task(ctrl: SharedChan<ctrl_proto>, input: ~str) {
-        let intermediates = @mut HashMap::new();
+        let mut intermediates = HashMap::new();
 
         fn emit(im: &mut HashMap<~str, int>,
                 ctrl: SharedChan<ctrl_proto>, key: ~str,
@@ -58,7 +58,7 @@ mod map_reduce {
         }
 
         let ctrl_clone = ctrl.clone();
-        ::map(input, |a,b| emit(intermediates, ctrl.clone(), a, b) );
+        ::map(input, |a,b| emit(&mut intermediates, ctrl.clone(), a, b) );
         ctrl_clone.send(mapper_done);
     }
 
diff --git a/src/test/run-pass/init-res-into-things.rs b/src/test/run-pass/init-res-into-things.rs
index 5181ec6f71d..ede67275ba9 100644
--- a/src/test/run-pass/init-res-into-things.rs
+++ b/src/test/run-pass/init-res-into-things.rs
@@ -10,11 +10,13 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 // Resources can't be copied, but storing into data structures counts
 // as a move unless the stored thing is used afterwards.
 
 struct r {
-  i: @mut int,
+    i: @Cell<int>,
 }
 
 struct Box { x: r }
@@ -22,30 +24,30 @@ struct Box { x: r }
 #[unsafe_destructor]
 impl Drop for r {
     fn drop(&mut self) {
-        *(self.i) = *(self.i) + 1;
+        self.i.set(self.i.get() + 1)
     }
 }
 
-fn r(i: @mut int) -> r {
+fn r(i: @Cell<int>) -> r {
     r {
         i: i
     }
 }
 
 fn test_box() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         let _a = @r(i);
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
 
 fn test_rec() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         let _a = Box {x: r(i)};
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
 
 fn test_tag() {
@@ -53,37 +55,37 @@ fn test_tag() {
         t0(r),
     }
 
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         let _a = t0(r(i));
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
 
 fn test_tup() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         let _a = (r(i), 0);
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
 
 fn test_unique() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         let _a = ~r(i);
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
 
 fn test_box_rec() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     {
         let _a = @Box {
             x: r(i)
         };
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
 
 pub fn main() {
diff --git a/src/test/run-pass/issue-10626.rs b/src/test/run-pass/issue-10626.rs
index f6c0b73387d..020db44bb87 100644
--- a/src/test/run-pass/issue-10626.rs
+++ b/src/test/run-pass/issue-10626.rs
@@ -16,7 +16,7 @@
 use std::os;
 use std::io::process;
 
-fn main () {
+pub fn main () {
     let args = os::args();
     if args.len() > 1 && args[1] == ~"child" {
         for _ in range(0, 1000) {
diff --git a/src/test/run-pass/issue-10806.rs b/src/test/run-pass/issue-10806.rs
index 3ee3f30e00f..046b2884a0e 100644
--- a/src/test/run-pass/issue-10806.rs
+++ b/src/test/run-pass/issue-10806.rs
@@ -38,7 +38,7 @@ pub mod waldo {
     }
 }
 
-fn main() {
+pub fn main() {
     let _x = baz::quux();
     let _y = grault::garply();
     let _z = waldo::plugh();
diff --git a/src/test/run-pass/issue-11085.rs b/src/test/run-pass/issue-11085.rs
index 9d7eab050d8..c0686d91fb9 100644
--- a/src/test/run-pass/issue-11085.rs
+++ b/src/test/run-pass/issue-11085.rs
@@ -43,7 +43,7 @@ enum Bar3 {
     }
 }
 
-fn main() {
+pub fn main() {
     let _f = Foo { foo: 3 };
     let _f = Foo2 { foo: 3 };
 
diff --git a/src/test/run-pass/issue-11224.rs b/src/test/run-pass/issue-11224.rs
index bf412ceab28..da92428f258 100644
--- a/src/test/run-pass/issue-11224.rs
+++ b/src/test/run-pass/issue-11224.rs
@@ -13,4 +13,4 @@
 
 extern mod unused = "issue-11224";
 
-fn main() {}
+pub fn main() {}
diff --git a/src/test/run-pass/issue-11225-1.rs b/src/test/run-pass/issue-11225-1.rs
index ad8cb1e79ab..d8724b5ba8d 100644
--- a/src/test/run-pass/issue-11225-1.rs
+++ b/src/test/run-pass/issue-11225-1.rs
@@ -13,6 +13,6 @@
 
 extern mod foo = "issue-11225-1";
 
-fn main() {
+pub fn main() {
     foo::foo(1);
 }
diff --git a/src/test/run-pass/issue-11225-2.rs b/src/test/run-pass/issue-11225-2.rs
index e572e56362b..86e4232880c 100644
--- a/src/test/run-pass/issue-11225-2.rs
+++ b/src/test/run-pass/issue-11225-2.rs
@@ -13,6 +13,6 @@
 
 extern mod foo = "issue-11225-2";
 
-fn main() {
+pub fn main() {
     foo::foo(1);
 }
diff --git a/src/test/run-pass/issue-2631-b.rs b/src/test/run-pass/issue-2631-b.rs
index bc76fa74dbd..dc46bef4ed4 100644
--- a/src/test/run-pass/issue-2631-b.rs
+++ b/src/test/run-pass/issue-2631-b.rs
@@ -16,11 +16,12 @@
 extern mod req;
 
 use req::request;
+use std::cell::RefCell;
 use std::hashmap::HashMap;
 
 pub fn main() {
   let v = ~[@~"hi"];
   let mut m: req::header_map = HashMap::new();
-  m.insert(~"METHOD", @mut v);
+  m.insert(~"METHOD", @RefCell::new(v));
   request::<int>(&m);
 }
diff --git a/src/test/run-pass/issue-2735-2.rs b/src/test/run-pass/issue-2735-2.rs
index 85b6e80be7c..44222315dcd 100644
--- a/src/test/run-pass/issue-2735-2.rs
+++ b/src/test/run-pass/issue-2735-2.rs
@@ -10,26 +10,28 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 // This test should behave exactly like issue-2735-3
 struct defer {
-    b: @mut bool,
+    b: @Cell<bool>,
 }
 
 #[unsafe_destructor]
 impl Drop for defer {
     fn drop(&mut self) {
-        *self.b = true;
+        self.b.set(true);
     }
 }
 
-fn defer(b: @mut bool) -> defer {
+fn defer(b: @Cell<bool>) -> defer {
     defer {
         b: b
     }
 }
 
 pub fn main() {
-    let dtor_ran = @mut false;
+    let dtor_ran = @Cell::new(false);
     let _  = defer(dtor_ran);
-    assert!(*dtor_ran);
+    assert!(dtor_ran.get());
 }
diff --git a/src/test/run-pass/issue-2735-3.rs b/src/test/run-pass/issue-2735-3.rs
index 401a43f8b25..f48e763966b 100644
--- a/src/test/run-pass/issue-2735-3.rs
+++ b/src/test/run-pass/issue-2735-3.rs
@@ -10,26 +10,28 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 // This test should behave exactly like issue-2735-2
 struct defer {
-    b: @mut bool,
+    b: @Cell<bool>,
 }
 
 #[unsafe_destructor]
 impl Drop for defer {
     fn drop(&mut self) {
-        *self.b = true;
+        self.b.set(true);
     }
 }
 
-fn defer(b: @mut bool) -> defer {
+fn defer(b: @Cell<bool>) -> defer {
     defer {
         b: b
     }
 }
 
 pub fn main() {
-    let dtor_ran = @mut false;
+    let dtor_ran = @Cell::new(false);
     defer(dtor_ran);
-    assert!(*dtor_ran);
+    assert!(dtor_ran.get());
 }
diff --git a/src/test/run-pass/issue-2904.rs b/src/test/run-pass/issue-2904.rs
index 5208995a0c7..dc2f59f1481 100644
--- a/src/test/run-pass/issue-2904.rs
+++ b/src/test/run-pass/issue-2904.rs
@@ -62,8 +62,8 @@ fn square_from_char(c: char) -> square {
     }
 }
 
-fn read_board_grid<rdr:'static + io::Reader>(input: rdr) -> ~[~[square]] {
-    let input = @mut input as @mut io::Reader;
+fn read_board_grid<rdr:'static + io::Reader>(mut input: rdr) -> ~[~[square]] {
+    let mut input: &mut io::Reader = &mut input;
     let mut grid = ~[];
     let mut line = [0, ..10];
     input.read(line);
diff --git a/src/test/run-pass/issue-3290.rs b/src/test/run-pass/issue-3290.rs
index 5cdc4238eaf..c6b48ad636f 100644
--- a/src/test/run-pass/issue-3290.rs
+++ b/src/test/run-pass/issue-3290.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // xfail-test FIXME #3290
-fn main() {
+pub fn main() {
    let mut x = ~3;
    x = x;
    assert_eq!(*x, 3);
diff --git a/src/test/run-pass/issue-3447.rs b/src/test/run-pass/issue-3447.rs
index 7ae3e43c579..3d56abb3de6 100644
--- a/src/test/run-pass/issue-3447.rs
+++ b/src/test/run-pass/issue-3447.rs
@@ -10,11 +10,13 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 static S: &'static str = "str";
 
 struct list<T> {
     element: T,
-    next: Option<@mut list<T>>
+    next: Option<@RefCell<list<T>>>
 }
 
 impl<T:'static> list<T> {
@@ -24,7 +26,7 @@ impl<T:'static> list<T> {
             next: None
         };
 
-        self.next = Some(@mut newList);
+        self.next = Some(@RefCell::new(newList));
     }
 }
 
diff --git a/src/test/run-pass/issue-3796.rs b/src/test/run-pass/issue-3796.rs
index a7c6f86b453..df8820c5623 100644
--- a/src/test/run-pass/issue-3796.rs
+++ b/src/test/run-pass/issue-3796.rs
@@ -10,7 +10,7 @@
 
 // xfail-test FIXME #3796
 #[deny(dead_assignment)];
-fn main() {
+pub fn main() {
     let mut x = 1;
     let f: || -> int = || { x + 20 };
     assert_eq!(f(), 21);
diff --git a/src/test/run-pass/issue-3860.rs b/src/test/run-pass/issue-3860.rs
deleted file mode 100644
index 8a30cc96748..00000000000
--- a/src/test/run-pass/issue-3860.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-struct Foo { x: int }
-
-impl Foo {
-    pub fn stuff<'a>(&'a mut self) -> &'a mut Foo {
-        return self;
-    }
-}
-
-pub fn main() {
-    let x = @mut Foo { x: 3 };
-    // Neither of the next two lines should cause an error
-    let _ = x.stuff();
-    x.stuff();
-}
diff --git a/src/test/run-pass/issue-4208.rs b/src/test/run-pass/issue-4208.rs
index 92b3f6274d5..4a4c263f938 100644
--- a/src/test/run-pass/issue-4208.rs
+++ b/src/test/run-pass/issue-4208.rs
@@ -16,4 +16,4 @@ use numeric::{sin, Angle};
 
 fn foo<T, A:Angle<T>>(theta: A) -> T { sin(&theta) }
 
-fn main() {}
+pub fn main() {}
diff --git a/src/test/run-pass/issue-4241.rs b/src/test/run-pass/issue-4241.rs
index b53036d091f..7a09741acb1 100644
--- a/src/test/run-pass/issue-4241.rs
+++ b/src/test/run-pass/issue-4241.rs
@@ -127,5 +127,5 @@ fn query2(cmd: ~[~str]) -> Result {
 }
 
 
-fn main() {
+pub fn main() {
 }
diff --git a/src/test/run-pass/issue-4252.rs b/src/test/run-pass/issue-4252.rs
index c7ba345517c..9fd1a1c81eb 100644
--- a/src/test/run-pass/issue-4252.rs
+++ b/src/test/run-pass/issue-4252.rs
@@ -31,7 +31,7 @@ impl<T: X> Drop for Z<T> {
     }
 }
 
-fn main() {
+pub fn main() {
     let y = Y;
     let _z = Z{x: y};
 }
diff --git a/src/test/run-pass/issue-4545.rs b/src/test/run-pass/issue-4545.rs
index dfee437ba35..6c018b5cd2f 100644
--- a/src/test/run-pass/issue-4545.rs
+++ b/src/test/run-pass/issue-4545.rs
@@ -12,4 +12,4 @@
 // aux-build:issue-4545.rs
 
 extern mod somelib = "issue-4545";
-fn main() { somelib::mk::<int>(); }
+pub fn main() { somelib::mk::<int>(); }
diff --git a/src/test/run-pass/issue-5275.rs b/src/test/run-pass/issue-5275.rs
deleted file mode 100644
index 088376c1068..00000000000
--- a/src/test/run-pass/issue-5275.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-// Regression test for issue #5275
-
-fn foo(self_: &A) -> int {
-    if true {
-        fail!()
-    } else {
-        *bar(self_.bar)
-    }
-}
-
-fn bar<'r>(_: &'r mut int) -> &'r int {
-    fail!()
-}
-
-struct A {
-    bar: @mut int,
-}
-
-pub fn main() {}
diff --git a/src/test/run-pass/issue-5517.rs b/src/test/run-pass/issue-5517.rs
deleted file mode 100644
index a5c318a20f4..00000000000
--- a/src/test/run-pass/issue-5517.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-pub fn main() {
-    let box1 = @mut 42;
-    let _x = *(&mut *box1) == 42 || *(&mut *box1) == 31337;
-}
diff --git a/src/test/run-pass/issue-5950.rs b/src/test/run-pass/issue-5950.rs
index b169d2d4804..9cef8b5685f 100644
--- a/src/test/run-pass/issue-5950.rs
+++ b/src/test/run-pass/issue-5950.rs
@@ -14,4 +14,4 @@ pub use local_alias = local;
 
 mod local { }
 
-fn main() {}
+pub fn main() {}
diff --git a/src/test/run-pass/issue-6334.rs b/src/test/run-pass/issue-6334.rs
index 740a2212726..38934c6e763 100644
--- a/src/test/run-pass/issue-6334.rs
+++ b/src/test/run-pass/issue-6334.rs
@@ -48,7 +48,7 @@ fn use_c<S:C, T:B+A>(s: &S, t: &T) -> uint {
     s.combine(t)
 }
 
-fn main() {
+pub fn main() {
     let foo = Foo;
     let bar = Bar;
     let r = use_c(&bar, &foo);
diff --git a/src/test/run-pass/issue-7178.rs b/src/test/run-pass/issue-7178.rs
index 3d635b87777..39afbd1c3ec 100644
--- a/src/test/run-pass/issue-7178.rs
+++ b/src/test/run-pass/issue-7178.rs
@@ -13,6 +13,6 @@
 
 extern mod cross_crate_self = "issue-7178";
 
-fn main() {
+pub fn main() {
     let _ = cross_crate_self::Foo::new(&1i);
 }
diff --git a/src/test/run-pass/issue-8044.rs b/src/test/run-pass/issue-8044.rs
index 15d490e98d6..5ad355dbd4c 100644
--- a/src/test/run-pass/issue-8044.rs
+++ b/src/test/run-pass/issue-8044.rs
@@ -14,6 +14,6 @@
 extern mod minimal = "issue-8044";
 use minimal::{BTree, leaf};
 
-fn main() {
+pub fn main() {
     BTree::<int> { node: leaf(1) };
 }
diff --git a/src/test/run-pass/issue-8259.rs b/src/test/run-pass/issue-8259.rs
index 3e9007b5e36..3533f336b42 100644
--- a/src/test/run-pass/issue-8259.rs
+++ b/src/test/run-pass/issue-8259.rs
@@ -14,4 +14,4 @@
 extern mod other = "issue-8259";
 static a: other::Foo<'static> = other::A;
 
-fn main() {}
+pub fn main() {}
diff --git a/src/test/run-pass/issue-8498.rs b/src/test/run-pass/issue-8498.rs
index 247b74e4643..fc7e24ccd7a 100644
--- a/src/test/run-pass/issue-8498.rs
+++ b/src/test/run-pass/issue-8498.rs
@@ -10,7 +10,7 @@
 
 // xfail-test
 
-fn main() {
+pub fn main() {
 // This is ok
     match &[(~5,~7)] {
         ps => {
diff --git a/src/test/run-pass/issue-9188.rs b/src/test/run-pass/issue-9188.rs
index e3e09394bd6..d3455af4e2c 100644
--- a/src/test/run-pass/issue-9188.rs
+++ b/src/test/run-pass/issue-9188.rs
@@ -13,7 +13,7 @@
 
 extern mod issue_9188;
 
-fn main() {
+pub fn main() {
     let a = issue_9188::bar();
     let b = issue_9188::foo::<int>();
     assert_eq!(*a, *b);
diff --git a/src/test/run-pass/issue-979.rs b/src/test/run-pass/issue-979.rs
index 08d8abc1d50..ca83e783268 100644
--- a/src/test/run-pass/issue-979.rs
+++ b/src/test/run-pass/issue-979.rs
@@ -10,28 +10,30 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 struct r {
-  b: @mut int,
+    b: @Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for r {
     fn drop(&mut self) {
-        *(self.b) += 1;
+        self.b.set(self.b.get() + 1);
     }
 }
 
-fn r(b: @mut int) -> r {
+fn r(b: @Cell<int>) -> r {
     r {
         b: b
     }
 }
 
 pub fn main() {
-    let b = @mut 0;
+    let b = @Cell::new(0);
     {
         let _p = Some(r(b));
     }
 
-    assert_eq!(*b, 1);
+    assert_eq!(b.get(), 1);
 }
diff --git a/src/test/run-pass/issue-980.rs b/src/test/run-pass/issue-980.rs
index 2f94dc77690..f6dc4adcf9b 100644
--- a/src/test/run-pass/issue-980.rs
+++ b/src/test/run-pass/issue-980.rs
@@ -10,16 +10,20 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 enum maybe_pointy {
     no_pointy,
-    yes_pointy(@mut Pointy),
+    yes_pointy(@RefCell<Pointy>),
 }
 
 struct Pointy {
-    x : maybe_pointy
+    x: maybe_pointy
 }
 
 pub fn main() {
-    let m = @mut Pointy { x : no_pointy };
-    m.x = yes_pointy(m);
+    let m = @RefCell::new(Pointy { x : no_pointy });
+    m.set(Pointy {
+        x: yes_pointy(m)
+    });
 }
diff --git a/src/test/run-pass/issue-9906.rs b/src/test/run-pass/issue-9906.rs
index e44374cb23a..6a604058663 100644
--- a/src/test/run-pass/issue-9906.rs
+++ b/src/test/run-pass/issue-9906.rs
@@ -13,7 +13,7 @@
 
 extern mod testmod = "issue-9906";
 
-fn main() {
+pub fn main() {
     testmod::foo();
     testmod::FooBar::new(1);
 }
diff --git a/src/test/run-pass/issue-9968.rs b/src/test/run-pass/issue-9968.rs
index 4ea5aba91da..f23729537eb 100644
--- a/src/test/run-pass/issue-9968.rs
+++ b/src/test/run-pass/issue-9968.rs
@@ -15,7 +15,7 @@ extern mod lib = "issue-9968";
 
 use lib::{Trait, Struct};
 
-fn main()
+pub fn main()
 {
     Struct::init().test();
 }
diff --git a/src/test/run-pass/issue_9155.rs b/src/test/run-pass/issue_9155.rs
index ae0bfe2babe..3fbdf57e348 100644
--- a/src/test/run-pass/issue_9155.rs
+++ b/src/test/run-pass/issue_9155.rs
@@ -15,6 +15,6 @@ extern mod issue_9155;
 
 struct Baz;
 
-fn main() {
+pub fn main() {
     issue_9155::Foo::new(Baz);
 }
diff --git a/src/test/run-pass/lambda-infer-unresolved.rs b/src/test/run-pass/lambda-infer-unresolved.rs
index a499c148025..65f95f78ea8 100644
--- a/src/test/run-pass/lambda-infer-unresolved.rs
+++ b/src/test/run-pass/lambda-infer-unresolved.rs
@@ -11,12 +11,10 @@
 // This should typecheck even though the type of e is not fully
 // resolved when we finish typechecking the ||.
 
-#[feature(managed_boxes)];
-
 struct Refs { refs: ~[int], n: int }
 
 pub fn main() {
-    let e = @mut Refs{refs: ~[], n: 0};
+    let mut e = Refs{refs: ~[], n: 0};
     let _f: || = || error!("{}", e.n);
     e.refs.push(1);
 }
diff --git a/src/test/run-pass/linkage-visibility.rs b/src/test/run-pass/linkage-visibility.rs
index 438fd21e810..bbfbdb1cdf0 100644
--- a/src/test/run-pass/linkage-visibility.rs
+++ b/src/test/run-pass/linkage-visibility.rs
@@ -15,7 +15,7 @@
 
 extern mod foo = "linkage-visibility";
 
-fn main() {
+pub fn main() {
     foo::test();
     foo::foo2::<int>();
     foo::foo();
diff --git a/src/test/run-pass/log-linearized.rs b/src/test/run-pass/log-linearized.rs
deleted file mode 100644
index e4dd3b56fca..00000000000
--- a/src/test/run-pass/log-linearized.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-// Tests that shapes respect linearize_ty_params().
-
-enum option<T> {
-    none,
-    some(T),
-}
-
-struct Smallintmap<T> {v: ~[option<T>]}
-
-struct V<T> { v: ~[option<T>] }
-
-fn mk<T:'static>() -> @mut Smallintmap<T> {
-    let v: ~[option<T>] = ~[];
-    return @mut Smallintmap {v: v};
-}
-
-fn f<T,U:'static>() {
-    let sim = mk::<U>();
-    error!("{:?}", sim);
-}
-
-pub fn main() {
-    f::<int,int>();
-}
diff --git a/src/test/run-pass/logging-enabled-debug.rs b/src/test/run-pass/logging-enabled-debug.rs
index 4bfdbc5563a..98fe46357ba 100644
--- a/src/test/run-pass/logging-enabled-debug.rs
+++ b/src/test/run-pass/logging-enabled-debug.rs
@@ -14,7 +14,7 @@
 
 use std::logging;
 
-fn main() {
+pub fn main() {
     if log_enabled!(logging::DEBUG) {
         fail!("what?! debugging?");
     }
diff --git a/src/test/run-pass/logging-enabled.rs b/src/test/run-pass/logging-enabled.rs
index 1fc38ac30c2..43f039569b2 100644
--- a/src/test/run-pass/logging-enabled.rs
+++ b/src/test/run-pass/logging-enabled.rs
@@ -13,7 +13,7 @@
 
 use std::logging;
 
-fn main() {
+pub fn main() {
     if log_enabled!(logging::DEBUG) {
         fail!("what?! debugging?");
     }
diff --git a/src/test/run-pass/logging-only-prints-once.rs b/src/test/run-pass/logging-only-prints-once.rs
index 6a88b804c22..fb352ea0708 100644
--- a/src/test/run-pass/logging-only-prints-once.rs
+++ b/src/test/run-pass/logging-only-prints-once.rs
@@ -11,25 +11,24 @@
 // xfail-fast
 // exec-env:RUST_LOG=debug
 
-#[feature(managed_boxes)];
-
+use std::cell::Cell;
 use std::fmt;
 
-struct Foo(@mut int);
+struct Foo(Cell<int>);
 
 impl fmt::Default for Foo {
     fn fmt(f: &Foo, _fmt: &mut fmt::Formatter) {
-        assert!(***f == 0);
-        ***f = 1;
+        assert!(f.get() == 0);
+        f.set(1);
     }
 }
 
 pub fn main() {
     let (p,c) = Chan::new();
     do spawn {
-        let f = Foo(@mut 0);
+        let mut f = Foo(Cell::new(0));
         debug!("{}", f);
-        assert!(**f == 1);
+        assert!(f.get() == 1);
         c.send(());
     }
     p.recv();
diff --git a/src/test/run-pass/logging-right-crate.rs b/src/test/run-pass/logging-right-crate.rs
index 21b45cec235..3e6978a6fa7 100644
--- a/src/test/run-pass/logging-right-crate.rs
+++ b/src/test/run-pass/logging-right-crate.rs
@@ -24,7 +24,7 @@
 
 extern mod logging_right_crate;
 
-fn main() {
+pub fn main() {
     // this function fails if logging is turned on
     logging_right_crate::foo::<int>();
 }
diff --git a/src/test/run-pass/logging_before_rt_started.rs b/src/test/run-pass/logging_before_rt_started.rs
index 61d48c6800d..7bbe7f72a2c 100644
--- a/src/test/run-pass/logging_before_rt_started.rs
+++ b/src/test/run-pass/logging_before_rt_started.rs
@@ -17,4 +17,4 @@
 // this test will trigger "output during runtime initialization" to make sure
 // that the bug isn't re-introduced.
 
-fn main() {}
+pub fn main() {}
diff --git a/src/test/run-pass/macro-with-attrs1.rs b/src/test/run-pass/macro-with-attrs1.rs
index 5a5091c3856..6d6d8f2cc21 100644
--- a/src/test/run-pass/macro-with-attrs1.rs
+++ b/src/test/run-pass/macro-with-attrs1.rs
@@ -19,6 +19,6 @@ macro_rules! foo( () => (1) )
 #[cfg(not(foo))]
 macro_rules! foo( () => (2) )
 
-fn main() {
+pub fn main() {
     assert_eq!(foo!(), 1);
 }
diff --git a/src/test/run-pass/mlist-cycle.rs b/src/test/run-pass/mlist-cycle.rs
deleted file mode 100644
index 66e7fc4265b..00000000000
--- a/src/test/run-pass/mlist-cycle.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// xfail-test
-extern mod std;
-use std::gc;
-use std::gc::rustrt;
-
-struct cell {c: @list}
-
-enum list { link(@mut cell), nil, }
-
-pub fn main() {
-    let first: @cell = @mut cell{c: @nil()};
-    let second: @cell = @mut cell{c: @link(first)};
-    first._0 = @link(second);
-    rustrt::gc();
-    let third: @cell = @mut cell{c: @nil()};
-}
diff --git a/src/test/run-pass/native-print-no-runtime.rs b/src/test/run-pass/native-print-no-runtime.rs
index b468b53d2f7..7dbd895b476 100644
--- a/src/test/run-pass/native-print-no-runtime.rs
+++ b/src/test/run-pass/native-print-no-runtime.rs
@@ -13,7 +13,7 @@
 #[no_uv];
 
 #[start]
-fn main(_: int, _: **u8) -> int {
+pub fn main(_: int, _: **u8) -> int {
     println!("hello");
     0
 }
diff --git a/src/test/run-pass/new-vstore-mut-box-syntax.rs b/src/test/run-pass/new-vstore-mut-box-syntax.rs
deleted file mode 100644
index 4a2756f5446..00000000000
--- a/src/test/run-pass/new-vstore-mut-box-syntax.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-pub fn main() {
-    let _x: @mut [int] = @mut [ 1, 2, 3 ];
-
-}
diff --git a/src/test/run-pass/newtype-struct-drop-run.rs b/src/test/run-pass/newtype-struct-drop-run.rs
index 8d1333941f7..f190a5102d2 100644
--- a/src/test/run-pass/newtype-struct-drop-run.rs
+++ b/src/test/run-pass/newtype-struct-drop-run.rs
@@ -12,19 +12,21 @@
 
 // Make sure the destructor is run for newtype structs.
 
-struct Foo(@mut int);
+use std::cell::Cell;
+
+struct Foo(@Cell<int>);
 
 #[unsafe_destructor]
 impl Drop for Foo {
     fn drop(&mut self) {
-        ***self = 23;
+        self.set(23);
     }
 }
 
 pub fn main() {
-    let y = @mut 32;
+    let y = @Cell::new(32);
     {
         let _x = Foo(y);
     }
-    assert_eq!(*y, 23);
+    assert_eq!(y.get(), 23);
 }
diff --git a/src/test/run-pass/no-std-xcrate.rs b/src/test/run-pass/no-std-xcrate.rs
index f69f53cecd4..d4341ccf7dc 100644
--- a/src/test/run-pass/no-std-xcrate.rs
+++ b/src/test/run-pass/no-std-xcrate.rs
@@ -16,6 +16,6 @@
 
 extern mod no_std_crate;
 
-fn main() {
+pub fn main() {
     no_std_crate::foo();
 }
diff --git a/src/test/run-pass/no-std-xcrate2.rs b/src/test/run-pass/no-std-xcrate2.rs
index e393eb3a5c9..f164d8609fc 100644
--- a/src/test/run-pass/no-std-xcrate2.rs
+++ b/src/test/run-pass/no-std-xcrate2.rs
@@ -29,7 +29,7 @@ pub mod linkhack {
 }
 
 #[start]
-fn main(_: int, _: **u8, _: *u8) -> int {
+pub fn main(_: int, _: **u8, _: *u8) -> int {
     no_std_crate::foo();
     0
 }
diff --git a/src/test/run-pass/objects-coerce-from-managed-to-borrowed.rs b/src/test/run-pass/objects-coerce-from-managed-to-borrowed.rs
index f0955ab8efa..52792c8c427 100644
--- a/src/test/run-pass/objects-coerce-from-managed-to-borrowed.rs
+++ b/src/test/run-pass/objects-coerce-from-managed-to-borrowed.rs
@@ -14,24 +14,12 @@
 
 trait Foo {
     fn foo(&self) -> uint;
-    fn bar(&mut self) -> uint;
 }
 
 impl Foo for uint {
     fn foo(&self) -> uint {
         *self
     }
-
-    fn bar(&mut self) -> uint {
-        *self += 1;
-        *self
-    }
-}
-
-fn do_it_mut(obj: &mut Foo) {
-    let x = obj.bar();
-    let y = obj.foo();
-    assert_eq!(x, y);
 }
 
 fn do_it_imm(obj: &Foo, v: uint) {
@@ -40,7 +28,6 @@ fn do_it_imm(obj: &Foo, v: uint) {
 }
 
 pub fn main() {
-    let x = @mut 22u as @mut Foo;
-    do_it_mut(x);
-    do_it_imm(x, 23u);
+    let x = @22u as @Foo;
+    do_it_imm(x, 22u);
 }
diff --git a/src/test/run-pass/once-move-out-on-heap.rs b/src/test/run-pass/once-move-out-on-heap.rs
index 4b09506b65f..8c3f889c176 100644
--- a/src/test/run-pass/once-move-out-on-heap.rs
+++ b/src/test/run-pass/once-move-out-on-heap.rs
@@ -20,7 +20,7 @@ fn foo(blk: proc()) {
     blk();
 }
 
-fn main() {
+pub fn main() {
     let x = arc::Arc::new(true);
     do foo {
         assert!(*x.get());
diff --git a/src/test/run-pass/once-move-out-on-stack.rs b/src/test/run-pass/once-move-out-on-stack.rs
index c7b2cc6124b..07dd5175a0f 100644
--- a/src/test/run-pass/once-move-out-on-stack.rs
+++ b/src/test/run-pass/once-move-out-on-stack.rs
@@ -20,7 +20,7 @@ fn foo(blk: once ||) {
     blk();
 }
 
-fn main() {
+pub fn main() {
     let x = arc::Arc::new(true);
     foo(|| {
         assert!(*x.get());
diff --git a/src/test/run-pass/option-unwrap.rs b/src/test/run-pass/option-unwrap.rs
index ab9d5b9d2bf..0806bcd185e 100644
--- a/src/test/run-pass/option-unwrap.rs
+++ b/src/test/run-pass/option-unwrap.rs
@@ -10,16 +10,17 @@
 
 #[feature(managed_boxes)];
 
-struct dtor {
-    x: @mut int,
+use std::cell::Cell;
 
+struct dtor {
+    x: @Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for dtor {
     fn drop(&mut self) {
         // abuse access to shared mutable state to write this code
-        *self.x -= 1;
+        self.x.set(self.x.get() - 1);
     }
 }
 
@@ -31,12 +32,12 @@ fn unwrap<T>(o: Option<T>) -> T {
 }
 
 pub fn main() {
-    let x = @mut 1;
+    let x = @Cell::new(1);
 
     {
         let b = Some(dtor { x:x });
         let _c = unwrap(b);
     }
 
-    assert_eq!(*x, 0);
+    assert_eq!(x.get(), 0);
 }
diff --git a/src/test/run-pass/osx-frameworks.rs b/src/test/run-pass/osx-frameworks.rs
index cfb7a8e43be..5e45386353b 100644
--- a/src/test/run-pass/osx-frameworks.rs
+++ b/src/test/run-pass/osx-frameworks.rs
@@ -17,7 +17,7 @@ extern {
 }
 
 #[cfg(target_os = "macos")]
-fn main() {
+pub fn main() {
     unsafe { CFRunLoopGetTypeID(); }
 }
 
diff --git a/src/test/run-pass/packed-struct-generic-size.rs b/src/test/run-pass/packed-struct-generic-size.rs
index 1d3d8cf736f..cba923ef646 100644
--- a/src/test/run-pass/packed-struct-generic-size.rs
+++ b/src/test/run-pass/packed-struct-generic-size.rs
@@ -22,6 +22,6 @@ pub fn main() {
 
     assert_eq!(mem::size_of::<S<u64, u16>>(), 11);
 
-    assert_eq!(mem::size_of::<S<~str, @mut [int]>>(),
-               1 + mem::size_of::<~str>() + mem::size_of::<@mut [int]>());
+    assert_eq!(mem::size_of::<S<~str, @[int]>>(),
+               1 + mem::size_of::<~str>() + mem::size_of::<@[int]>());
 }
diff --git a/src/test/run-pass/packed-struct-size-xc.rs b/src/test/run-pass/packed-struct-size-xc.rs
index 5b4426d314b..336df24586a 100644
--- a/src/test/run-pass/packed-struct-size-xc.rs
+++ b/src/test/run-pass/packed-struct-size-xc.rs
@@ -5,6 +5,6 @@ extern mod packed;
 
 use std::mem;
 
-fn main() {
+pub fn main() {
     assert_eq!(mem::size_of::<packed::S>(), 5);
 }
diff --git a/src/test/run-pass/packed-struct-size.rs b/src/test/run-pass/packed-struct-size.rs
index c6550f24d5c..f694cc98ad3 100644
--- a/src/test/run-pass/packed-struct-size.rs
+++ b/src/test/run-pass/packed-struct-size.rs
@@ -49,7 +49,7 @@ struct S7_Option {
     a: f32,
     b: u8,
     c: u16,
-    d: Option<@mut f64>
+    d: Option<@f64>
 }
 
 // Placing packed structs in statics should work
@@ -63,5 +63,5 @@ pub fn main() {
     assert_eq!(mem::size_of::<S5>(), 5);
     assert_eq!(mem::size_of::<S13_str>(), 13 + mem::size_of::<~str>());
     assert_eq!(mem::size_of::<S3_Foo>(), 3 + mem::size_of::<Foo>());
-    assert_eq!(mem::size_of::<S7_Option>(), 7 + mem::size_of::<Option<@mut f64>>());
+    assert_eq!(mem::size_of::<S7_Option>(), 7 + mem::size_of::<Option<@f64>>());
 }
diff --git a/src/test/run-pass/packed-tuple-struct-size.rs b/src/test/run-pass/packed-tuple-struct-size.rs
index ad83de6ef48..7d2be73edc3 100644
--- a/src/test/run-pass/packed-tuple-struct-size.rs
+++ b/src/test/run-pass/packed-tuple-struct-size.rs
@@ -30,7 +30,7 @@ enum Foo {
 struct S3_Foo(u8, u16, Foo);
 
 #[packed]
-struct S7_Option(f32, u8, u16, Option<@mut f64>);
+struct S7_Option(f32, u8, u16, Option<@f64>);
 
 pub fn main() {
     assert_eq!(mem::size_of::<S4>(), 4);
@@ -44,5 +44,5 @@ pub fn main() {
                3 + mem::size_of::<Foo>());
 
     assert_eq!(mem::size_of::<S7_Option>(),
-              7 + mem::size_of::<Option<@mut f64>>());
+              7 + mem::size_of::<Option<@f64>>());
 }
diff --git a/src/test/run-pass/priv-impl-prim-ty.rs b/src/test/run-pass/priv-impl-prim-ty.rs
index 0c722e1ede5..a61b30dd480 100644
--- a/src/test/run-pass/priv-impl-prim-ty.rs
+++ b/src/test/run-pass/priv-impl-prim-ty.rs
@@ -13,7 +13,7 @@
 
 extern mod bar = "priv-impl-prim-ty";
 
-fn main() {
+pub fn main() {
     bar::frob(1i);
 
 }
diff --git a/src/test/run-pass/privacy-reexport.rs b/src/test/run-pass/privacy-reexport.rs
index eedc47ca0ad..6e0e1d6ef9e 100644
--- a/src/test/run-pass/privacy-reexport.rs
+++ b/src/test/run-pass/privacy-reexport.rs
@@ -13,6 +13,6 @@
 
 extern mod privacy_reexport;
 
-fn main() {
+pub fn main() {
     privacy_reexport::bar::frob();
 }
diff --git a/src/test/run-pass/rcvr-borrowed-to-region.rs b/src/test/run-pass/rcvr-borrowed-to-region.rs
index d6d015d4785..8c1be0a6219 100644
--- a/src/test/run-pass/rcvr-borrowed-to-region.rs
+++ b/src/test/run-pass/rcvr-borrowed-to-region.rs
@@ -24,7 +24,7 @@ impl<'a> get for &'a int {
 }
 
 pub fn main() {
-    let x = @mut 6;
+    let x = @6;
     let y = x.get();
     assert_eq!(y, 6);
 
diff --git a/src/test/run-pass/reexport-should-still-link.rs b/src/test/run-pass/reexport-should-still-link.rs
index fcfcc30c988..1cd8e80ba93 100644
--- a/src/test/run-pass/reexport-should-still-link.rs
+++ b/src/test/run-pass/reexport-should-still-link.rs
@@ -13,6 +13,6 @@
 
 extern mod foo = "reexport-should-still-link";
 
-fn main() {
+pub fn main() {
     foo::bar();
 }
diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs
index 6e5aa1aaf8b..0d4277d2e1d 100644
--- a/src/test/run-pass/reflect-visit-data.rs
+++ b/src/test/run-pass/reflect-visit-data.rs
@@ -12,6 +12,7 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
 use std::libc::c_void;
 use std::ptr;
 use std::mem;
@@ -458,8 +459,9 @@ impl<V:TyVisitor + movable_ptr> TyVisitor for ptr_visit_adaptor<V> {
     }
 }
 
-struct my_visitor(@mut Stuff);
+struct my_visitor(@RefCell<Stuff>);
 
+#[deriving(Clone)]
 struct Stuff {
     ptr1: *c_void,
     ptr2: *c_void,
@@ -469,7 +471,7 @@ struct Stuff {
 impl my_visitor {
     pub fn get<T:Clone>(&mut self, f: |T|) {
         unsafe {
-            f((*(self.ptr1 as *T)).clone());
+            f((*((**self).get().ptr1 as *T)).clone());
         }
     }
 
@@ -487,8 +489,9 @@ struct Inner<V> { inner: V }
 
 impl movable_ptr for my_visitor {
     fn move_ptr(&mut self, adjustment: |*c_void| -> *c_void) {
-        self.ptr1 = adjustment(self.ptr1);
-        self.ptr2 = adjustment(self.ptr2);
+        let mut this = self.borrow_mut();
+        this.get().ptr1 = adjustment(this.get().ptr1);
+        this.get().ptr2 = adjustment(this.get().ptr2);
     }
 }
 
@@ -497,11 +500,17 @@ impl TyVisitor for my_visitor {
     fn visit_bot(&mut self) -> bool { true }
     fn visit_nil(&mut self) -> bool { true }
     fn visit_bool(&mut self) -> bool {
-        self.get::<bool>(|b| self.vals.push(b.to_str()));
+        self.get::<bool>(|b| {
+            let mut this = self.borrow_mut();
+            this.get().vals.push(b.to_str());
+        });
         true
     }
     fn visit_int(&mut self) -> bool {
-        self.get::<int>(|i| self.vals.push(i.to_str()));
+        self.get::<int>(|i| {
+            let mut this = self.borrow_mut();
+            this.get().vals.push(i.to_str());
+        });
         true
     }
     fn visit_i8(&mut self) -> bool { true }
@@ -622,21 +631,22 @@ pub fn main() {
     unsafe {
         let r = (1,2,3,true,false, Triple {x:5,y:4,z:3}, (12,));
         let p = ptr::to_unsafe_ptr(&r) as *c_void;
-        let u = my_visitor(@mut Stuff {ptr1: p,
-                                       ptr2: p,
-                                       vals: ~[]});
+        let u = my_visitor(@RefCell::new(Stuff {ptr1: p,
+                                                ptr2: p,
+                                                vals: ~[]}));
         let mut v = ptr_visit_adaptor(Inner {inner: u});
         let td = get_tydesc_for(r);
         error!("tydesc sz: {}, align: {}",
                (*td).size, (*td).align);
         visit_tydesc(td, &mut v as &mut TyVisitor);
 
-        let r = u.vals.clone();
+        let mut ub = u.borrow_mut();
+        let r = ub.get().vals.clone();
         for s in r.iter() {
             println!("val: {}", *s);
         }
-        error!("{:?}", u.vals.clone());
-        assert_eq!(u.vals.clone(),
+        error!("{:?}", ub.get().vals.clone());
+        assert_eq!(ub.get().vals.clone(),
                    ~[ ~"1", ~"2", ~"3", ~"true", ~"false", ~"5", ~"4", ~"3", ~"12"]);
     }
 }
diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs
index 03722cd0fbf..5acb072fd2d 100644
--- a/src/test/run-pass/reflect-visit-type.rs
+++ b/src/test/run-pass/reflect-visit-type.rs
@@ -13,7 +13,7 @@
 use std::unstable::intrinsics::{TyDesc, get_tydesc, visit_tydesc, TyVisitor, Disr, Opaque};
 
 struct MyVisitor {
-    types: @mut ~[~str],
+    types: ~[~str],
 }
 
 impl TyVisitor for MyVisitor {
@@ -153,7 +153,7 @@ fn visit_ty<T>(v: &mut MyVisitor) {
 }
 
 pub fn main() {
-    let mut v = MyVisitor {types: @mut ~[]};
+    let mut v = MyVisitor {types: ~[]};
 
     visit_ty::<bool>(&mut v);
     visit_ty::<int>(&mut v);
@@ -164,5 +164,5 @@ pub fn main() {
     for s in v.types.iter() {
         println!("type: {}", (*s).clone());
     }
-    assert_eq!((*v.types).clone(), ~[~"bool", ~"int", ~"i8", ~"i16", ~"[", ~"int", ~"]"]);
+    assert_eq!(v.types.clone(), ~[~"bool", ~"int", ~"i8", ~"i16", ~"[", ~"int", ~"]"]);
 }
diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs
index fa4321451db..1e5dfe21cbe 100644
--- a/src/test/run-pass/rename-directory.rs
+++ b/src/test/run-pass/rename-directory.rs
@@ -55,4 +55,4 @@ fn rename_directory() {
     }
 }
 
-fn main() { rename_directory() }
+pub fn main() { rename_directory() }
diff --git a/src/test/run-pass/resource-assign-is-not-copy.rs b/src/test/run-pass/resource-assign-is-not-copy.rs
index 3025032fec1..bec101a6d45 100644
--- a/src/test/run-pass/resource-assign-is-not-copy.rs
+++ b/src/test/run-pass/resource-assign-is-not-copy.rs
@@ -10,25 +10,27 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 struct r {
-  i: @mut int,
+    i: @Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for r {
     fn drop(&mut self) {
-        *(self.i) += 1;
+        self.i.set(self.i.get() + 1);
     }
 }
 
-fn r(i: @mut int) -> r {
+fn r(i: @Cell<int>) -> r {
     r {
         i: i
     }
 }
 
 pub fn main() {
-    let i = @mut 0;
+    let i = @Cell::new(0);
     // Even though these look like copies, they are guaranteed not to be
     {
         let a = r(i);
@@ -36,5 +38,5 @@ pub fn main() {
         let (c, _d) = b;
         info!("{:?}", c);
     }
-    assert_eq!(*i, 1);
+    assert_eq!(i.get(), 1);
 }
diff --git a/src/test/run-pass/resource-cycle.rs b/src/test/run-pass/resource-cycle.rs
deleted file mode 100644
index 898f6327aeb..00000000000
--- a/src/test/run-pass/resource-cycle.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-// Don't leak the unique pointers
-
-use std::cast;
-
-struct r {
-  v: *int,
-}
-
-impl Drop for r {
-    fn drop(&mut self) {
-        unsafe {
-            info!("r's dtor: self = {:x}, self.v = {:x}, self.v's value = {:x}",
-              cast::transmute::<*mut r, uint>(self),
-              cast::transmute::<**int, uint>(&(self.v)),
-              cast::transmute::<*int, uint>(self.v));
-            let _v2: ~int = cast::transmute(self.v);
-        }
-    }
-}
-
-fn r(v: *int) -> r {
-    r {
-        v: v
-    }
-}
-
-struct t(Node);
-
-struct Node {
-    next: Option<@mut t>,
-    r: r
-}
-
-pub fn main() {
-    unsafe {
-        let i1 = ~0;
-        let i1p = cast::transmute_copy(&i1);
-        cast::forget(i1);
-        let i2 = ~0;
-        let i2p = cast::transmute_copy(&i2);
-        cast::forget(i2);
-
-        let x1 = @mut t(Node{
-            next: None,
-              r: {
-              let rs = r(i1p);
-              info!("r = {:x}", cast::transmute::<*r, uint>(&rs));
-              rs }
-        });
-
-        info!("x1 = {:x}, x1.r = {:x}",
-               cast::transmute::<@mut t, uint>(x1),
-               cast::transmute::<*r, uint>(&x1.r));
-
-        let x2 = @mut t(Node{
-            next: None,
-              r: {
-              let rs = r(i2p);
-              info!("r2 = {:x}", cast::transmute::<*r, uint>(&rs));
-              rs
-                }
-        });
-
-        info!("x2 = {:x}, x2.r = {:x}",
-               cast::transmute::<@mut t, uint>(x2),
-               cast::transmute::<*r, uint>(&(x2.r)));
-
-        x1.next = Some(x2);
-        x2.next = Some(x1);
-    }
-}
diff --git a/src/test/run-pass/resource-cycle2.rs b/src/test/run-pass/resource-cycle2.rs
deleted file mode 100644
index c7ad9711ed4..00000000000
--- a/src/test/run-pass/resource-cycle2.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-// Don't leak the unique pointers
-
-use std::cast;
-
-struct U {
-    a: int,
-    b: int,
-    c: *int
-}
-
-struct r {
-  v: U,
-}
-
-impl Drop for r {
-    fn drop(&mut self) {
-        unsafe {
-            let _v2: ~int = cast::transmute(self.v.c);
-        }
-    }
-}
-
-fn r(v: U) -> r {
-    r {
-        v: v
-    }
-}
-
-struct t(Node);
-
-struct Node {
-    next: Option<@mut t>,
-    r: r
-}
-
-pub fn main() {
-    unsafe {
-        let i1 = ~0xA;
-        let i1p = cast::transmute_copy(&i1);
-        cast::forget(i1);
-        let i2 = ~0xA;
-        let i2p = cast::transmute_copy(&i2);
-        cast::forget(i2);
-
-        let u1 = U {a: 0xB, b: 0xC, c: i1p};
-        let u2 = U {a: 0xB, b: 0xC, c: i2p};
-
-        let x1 = @mut t(Node {
-            next: None,
-            r: r(u1)
-        });
-        let x2 = @mut t(Node {
-            next: None,
-            r: r(u2)
-        });
-        x1.next = Some(x2);
-        x2.next = Some(x1);
-    }
-}
diff --git a/src/test/run-pass/resource-cycle3.rs b/src/test/run-pass/resource-cycle3.rs
deleted file mode 100644
index 8d11eca4492..00000000000
--- a/src/test/run-pass/resource-cycle3.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-// same as resource-cycle2, but be sure to give r multiple fields...
-
-// Don't leak the unique pointers
-
-use std::cast;
-
-struct U {
-    a: int,
-    b: int,
-    c: *int
-}
-
-struct R {
-  v: U,
-  w: int,
-  x: *int,
-}
-
-impl Drop for R {
-    fn drop(&mut self) {
-        unsafe {
-            let _v2: ~int = cast::transmute(self.v.c);
-            // let _v3: ~int = cast::transmute_copy(self.x);
-        }
-    }
-}
-
-fn r(v: U, w: int, _x: *int) -> R {
-    unsafe {
-        R {
-            v: v,
-            w: w,
-            x: cast::transmute(0)
-        }
-    }
-}
-
-struct t(Node);
-
-struct Node {
-    next: Option<@mut t>,
-    r: R
-}
-
-pub fn main() {
-    unsafe {
-        let i1 = ~0xA;
-        let i1p = cast::transmute_copy(&i1);
-        cast::forget(i1);
-        let i2 = ~0xA;
-        let i2p = cast::transmute_copy(&i2);
-        cast::forget(i2);
-
-        let u1 = U {a: 0xB, b: 0xC, c: i1p};
-        let u2 = U {a: 0xB, b: 0xC, c: i2p};
-
-        let x1 = @mut t(Node{
-            next: None,
-            r: r(u1, 42, i1p)
-        });
-        let x2 = @mut t(Node{
-            next: None,
-            r: r(u2, 42, i2p)
-        });
-        x1.next = Some(x2);
-        x2.next = Some(x1);
-    }
-}
diff --git a/src/test/run-pass/resource-destruct.rs b/src/test/run-pass/resource-destruct.rs
index d85759dff19..93183f8dba4 100644
--- a/src/test/run-pass/resource-destruct.rs
+++ b/src/test/run-pass/resource-destruct.rs
@@ -10,30 +10,32 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 struct shrinky_pointer {
-  i: @@mut int,
+  i: @@Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for shrinky_pointer {
     fn drop(&mut self) {
-        error!("Hello!"); **(self.i) -= 1;
+        error!("Hello!"); self.i.set(self.i.get() - 1);
     }
 }
 
 impl shrinky_pointer {
-    pub fn look_at(&self) -> int { return **(self.i); }
+    pub fn look_at(&self) -> int { return self.i.get(); }
 }
 
-fn shrinky_pointer(i: @@mut int) -> shrinky_pointer {
+fn shrinky_pointer(i: @@Cell<int>) -> shrinky_pointer {
     shrinky_pointer {
         i: i
     }
 }
 
 pub fn main() {
-    let my_total = @@mut 10;
+    let my_total = @@Cell::new(10);
     { let pt = shrinky_pointer(my_total); assert!((pt.look_at() == 10)); }
-    error!("my_total = {}", **my_total);
-    assert_eq!(**my_total, 9);
+    error!("my_total = {}", my_total.get());
+    assert_eq!(my_total.get(), 9);
 }
diff --git a/src/test/run-pass/resource-in-struct.rs b/src/test/run-pass/resource-in-struct.rs
index c76a9659c26..1c5ad9ce525 100644
--- a/src/test/run-pass/resource-in-struct.rs
+++ b/src/test/run-pass/resource-in-struct.rs
@@ -13,7 +13,9 @@
 // Ensures that class dtors run if the object is inside an enum
 // variant
 
-type closable = @mut bool;
+use std::cell::Cell;
+
+type closable = @Cell<bool>;
 
 struct close_res {
   i: closable,
@@ -23,7 +25,7 @@ struct close_res {
 #[unsafe_destructor]
 impl Drop for close_res {
     fn drop(&mut self) {
-        *(self.i) = false;
+        self.i.set(false);
     }
 }
 
@@ -38,8 +40,8 @@ enum option<T> { none, some(T), }
 fn sink(_res: option<close_res>) { }
 
 pub fn main() {
-    let c = @mut true;
+    let c = @Cell::new(true);
     sink(none);
     sink(some(close_res(c)));
-    assert!((!*c));
+    assert!(!c.get());
 }
diff --git a/src/test/run-pass/signal-exit-status.rs b/src/test/run-pass/signal-exit-status.rs
index c26c79112fe..dc74e9fb470 100644
--- a/src/test/run-pass/signal-exit-status.rs
+++ b/src/test/run-pass/signal-exit-status.rs
@@ -13,7 +13,7 @@
 use std::{os, run};
 use std::io::process;
 
-fn main() {
+pub fn main() {
     let args = os::args();
     if args.len() >= 2 && args[1] == ~"signal" {
         // Raise a segfault.
diff --git a/src/test/run-pass/smallest-hello-world.rs b/src/test/run-pass/smallest-hello-world.rs
index 92513caf87d..11cef9d480a 100644
--- a/src/test/run-pass/smallest-hello-world.rs
+++ b/src/test/run-pass/smallest-hello-world.rs
@@ -32,7 +32,7 @@ extern "rust-intrinsic" {
 }
 
 #[start]
-fn main(_: int, _: **u8, _: *u8) -> int {
+pub fn main(_: int, _: **u8, _: *u8) -> int {
     unsafe {
         let (ptr, _): (*u8, uint) = transmute("Hello!");
         puts(ptr);
diff --git a/src/test/run-pass/spawning-with-debug.rs b/src/test/run-pass/spawning-with-debug.rs
index f8094f9fdb9..c14ef147bc7 100644
--- a/src/test/run-pass/spawning-with-debug.rs
+++ b/src/test/run-pass/spawning-with-debug.rs
@@ -15,7 +15,7 @@
 
 use std::task;
 
-fn main() {
+pub fn main() {
     let mut t = task::task();
     t.spawn(proc() ());
 }
diff --git a/src/test/run-pass/static-function-pointer-xc.rs b/src/test/run-pass/static-function-pointer-xc.rs
index 61790e93584..4c72c3075ff 100644
--- a/src/test/run-pass/static-function-pointer-xc.rs
+++ b/src/test/run-pass/static-function-pointer-xc.rs
@@ -14,7 +14,7 @@ extern mod aux = "static-function-pointer-aux";
 
 fn f(x: int) -> int { x }
 
-fn main() {
+pub fn main() {
     assert_eq!(aux::F(42), -42);
     unsafe {
         assert_eq!(aux::MutF(42), -42);
diff --git a/src/test/run-pass/struct_variant_xc.rs b/src/test/run-pass/struct_variant_xc.rs
index 2dd7887cfcd..dc56cdf3a34 100644
--- a/src/test/run-pass/struct_variant_xc.rs
+++ b/src/test/run-pass/struct_variant_xc.rs
@@ -14,6 +14,6 @@ extern mod struct_variant_xc_aux;
 
 use struct_variant_xc_aux::Variant;
 
-fn main() {
+pub fn main() {
     let _ = Variant { arg: 1 };
 }
diff --git a/src/test/run-pass/syntax-extension-cfg.rs b/src/test/run-pass/syntax-extension-cfg.rs
index 321929207f7..5f85ac1bd55 100644
--- a/src/test/run-pass/syntax-extension-cfg.rs
+++ b/src/test/run-pass/syntax-extension-cfg.rs
@@ -11,7 +11,7 @@
 // xfail-fast compile-flags doesn't work with fast-check
 // compile-flags: --cfg foo --cfg bar(baz) --cfg qux="foo"
 
-fn main() {
+pub fn main() {
     // check
     if ! cfg!(foo) { fail!() }
     if   cfg!(not(foo)) { fail!() }
diff --git a/src/test/run-pass/task-killjoin-rsrc.rs b/src/test/run-pass/task-killjoin-rsrc.rs
index a490cc6020f..16e9cb53891 100644
--- a/src/test/run-pass/task-killjoin-rsrc.rs
+++ b/src/test/run-pass/task-killjoin-rsrc.rs
@@ -13,12 +13,14 @@
 // A port of task-killjoin to use a class with a dtor to manage
 // the join.
 
+use std::cell::Cell;
 use std::comm::*;
 use std::ptr;
 use std::task;
 
 struct notify {
-    ch: Chan<bool>, v: @mut bool,
+    ch: Chan<bool>,
+    v: @Cell<bool>,
 }
 
 #[unsafe_destructor]
@@ -36,7 +38,7 @@ impl Drop for notify {
     }
 }
 
-fn notify(ch: Chan<bool>, v: @mut bool) -> notify {
+fn notify(ch: Chan<bool>, v: @Cell<bool>) -> notify {
     notify {
         ch: ch,
         v: v
@@ -45,10 +47,10 @@ fn notify(ch: Chan<bool>, v: @mut bool) -> notify {
 
 fn joinable(f: proc()) -> Port<bool> {
     fn wrapper(c: Chan<bool>, f: ||) {
-        let b = @mut false;
+        let b = @Cell::new(false);
         error!("wrapper: task=%? allocated v=%x",
                0,
-               ptr::to_unsafe_ptr(&(*b)) as uint);
+               ptr::to_unsafe_ptr(&b) as uint);
         let _r = notify(c, b);
         f();
         *b = true;
diff --git a/src/test/run-pass/tempfile.rs b/src/test/run-pass/tempfile.rs
index d3bb8128a3b..eb055342acd 100644
--- a/src/test/run-pass/tempfile.rs
+++ b/src/test/run-pass/tempfile.rs
@@ -141,7 +141,7 @@ fn in_tmpdir(f: ||) {
     f();
 }
 
-fn main() {
+pub fn main() {
     in_tmpdir(test_tempdir);
     in_tmpdir(test_rm_tempdir);
     in_tmpdir(recursive_mkdir_rel);
diff --git a/src/test/run-pass/trait-bounds-in-arc.rs b/src/test/run-pass/trait-bounds-in-arc.rs
index 7e13d960947..b99e6a03bcb 100644
--- a/src/test/run-pass/trait-bounds-in-arc.rs
+++ b/src/test/run-pass/trait-bounds-in-arc.rs
@@ -60,7 +60,7 @@ impl Pet for Goldfyshe {
     fn of_good_pedigree(&self) -> bool { self.swim_speed >= 500 }
 }
 
-fn main() {
+pub fn main() {
     let catte = Catte { num_whiskers: 7, name: ~"alonzo_church" };
     let dogge1 = Dogge { bark_decibels: 100, tricks_known: 42, name: ~"alan_turing" };
     let dogge2 = Dogge { bark_decibels: 55,  tricks_known: 11, name: ~"albert_einstein" };
diff --git a/src/test/run-pass/trait-cast.rs b/src/test/run-pass/trait-cast.rs
index e5d91608997..bf8b0b5522d 100644
--- a/src/test/run-pass/trait-cast.rs
+++ b/src/test/run-pass/trait-cast.rs
@@ -12,7 +12,9 @@
 
 // Test cyclic detector when using trait instances.
 
-struct Tree(@mut TreeR);
+use std::cell::RefCell;
+
+struct Tree(@RefCell<TreeR>);
 struct TreeR {
     left: Option<Tree>,
     right: Option<Tree>,
@@ -38,8 +40,9 @@ impl to_str for int {
 
 impl to_str for Tree {
     fn to_str_(&self) -> ~str {
-        let (l, r) = (self.left, self.right);
-        let val = &self.val;
+        let this = self.borrow();
+        let (l, r) = (this.get().left, this.get().right);
+        let val = &this.get().val;
         format!("[{}, {}, {}]", val.to_str_(), l.to_str_(), r.to_str_())
     }
 }
@@ -47,14 +50,18 @@ impl to_str for Tree {
 fn foo<T:to_str>(x: T) -> ~str { x.to_str_() }
 
 pub fn main() {
-    let t1 = Tree(@mut TreeR{left: None,
-                             right: None,
-                             val: ~1 as ~to_str });
-    let t2 = Tree(@mut TreeR{left: Some(t1),
-                             right: Some(t1),
-                             val: ~2 as ~to_str });
+    let t1 = Tree(@RefCell::new(TreeR{left: None,
+                                      right: None,
+                                      val: ~1 as ~to_str}));
+    let t2 = Tree(@RefCell::new(TreeR{left: Some(t1),
+                                      right: Some(t1),
+                                      val: ~2 as ~to_str}));
     let expected = ~"[2, some([1, none, none]), some([1, none, none])]";
     assert!(t2.to_str_() == expected);
     assert!(foo(t2) == expected);
-    t1.left = Some(t2); // create cycle
+
+    {
+        let mut t1 = t1.borrow_mut();
+        t1.get().left = Some(t2); // create cycle
+    }
 }
diff --git a/src/test/run-pass/trait-default-method-xc-2.rs b/src/test/run-pass/trait-default-method-xc-2.rs
index 171971e73e0..58066adc4bd 100644
--- a/src/test/run-pass/trait-default-method-xc-2.rs
+++ b/src/test/run-pass/trait-default-method-xc-2.rs
@@ -9,7 +9,7 @@ use aux::A;
 use aux2::{a_struct, welp};
 
 
-fn main () {
+pub fn main () {
 
     let a = a_struct { x: 0 };
     let b = a_struct { x: 1 };
diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs
index 9813864724c..3323b3c952a 100644
--- a/src/test/run-pass/trait-default-method-xc.rs
+++ b/src/test/run-pass/trait-default-method-xc.rs
@@ -44,7 +44,7 @@ impl TestEquality for stuff::thing {
 }
 
 
-fn main () {
+pub fn main () {
     // Some tests of random things
     f(0);
 
diff --git a/src/test/run-pass/tydesc-name.rs b/src/test/run-pass/tydesc-name.rs
index 44a6a5750de..55360608bca 100644
--- a/src/test/run-pass/tydesc-name.rs
+++ b/src/test/run-pass/tydesc-name.rs
@@ -16,7 +16,7 @@ struct Foo<T> {
     x: T
 }
 
-fn main() {
+pub fn main() {
     unsafe {
         assert_eq!((*get_tydesc::<int>()).name, "int");
         assert_eq!((*get_tydesc::<~[int]>()).name, "~[int]");
diff --git a/src/test/run-pass/typeid-intrinsic.rs b/src/test/run-pass/typeid-intrinsic.rs
index a500e167a8b..d7feb4f4a01 100644
--- a/src/test/run-pass/typeid-intrinsic.rs
+++ b/src/test/run-pass/typeid-intrinsic.rs
@@ -21,7 +21,7 @@ use std::unstable::intrinsics::TypeId;
 struct A;
 struct Test;
 
-fn main() {
+pub fn main() {
     unsafe {
         assert_eq!(intrinsics::type_id::<other1::A>(), other1::id_A());
         assert_eq!(intrinsics::type_id::<other1::B>(), other1::id_B());
diff --git a/src/test/run-pass/uniq-cc-generic.rs b/src/test/run-pass/uniq-cc-generic.rs
index ebf3da60db8..53836a6e17d 100644
--- a/src/test/run-pass/uniq-cc-generic.rs
+++ b/src/test/run-pass/uniq-cc-generic.rs
@@ -10,11 +10,12 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
 use std::ptr;
 
 enum maybe_pointy {
     none,
-    p(@mut Pointy),
+    p(@RefCell<Pointy>),
 }
 
 struct Pointy {
@@ -27,14 +28,17 @@ fn make_uniq_closure<A:Send>(a: A) -> proc() -> uint {
     result
 }
 
-fn empty_pointy() -> @mut Pointy {
-    return @mut Pointy {
+fn empty_pointy() -> @RefCell<Pointy> {
+    return @RefCell::new(Pointy {
         a : none,
         d : make_uniq_closure(~"hi")
-    }
+    })
 }
 
 pub fn main() {
     let v = empty_pointy();
-    v.a = p(v);
+    {
+        let mut vb = v.borrow_mut();
+        vb.get().a = p(v);
+    }
 }
diff --git a/src/test/run-pass/uniq-cc.rs b/src/test/run-pass/uniq-cc.rs
index 20b5761e6bd..23a27dece46 100644
--- a/src/test/run-pass/uniq-cc.rs
+++ b/src/test/run-pass/uniq-cc.rs
@@ -10,9 +10,11 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::RefCell;
+
 enum maybe_pointy {
     none,
-    p(@mut Pointy),
+    p(@RefCell<Pointy>),
 }
 
 struct Pointy {
@@ -21,15 +23,18 @@ struct Pointy {
     d : proc()->(),
 }
 
-fn empty_pointy() -> @mut Pointy {
-    return @mut Pointy {
+fn empty_pointy() -> @RefCell<Pointy> {
+    return @RefCell::new(Pointy {
         a : none,
         c : ~22,
         d : proc() {},
-    }
+    })
 }
 
 pub fn main() {
     let v = empty_pointy();
-    v.a = p(v);
+    {
+        let mut vb = v.borrow_mut();
+        vb.get().a = p(v);
+    }
 }
diff --git a/src/test/run-pass/unique-pinned-nocopy-2.rs b/src/test/run-pass/unique-pinned-nocopy-2.rs
deleted file mode 100644
index a7c326ba11c..00000000000
--- a/src/test/run-pass/unique-pinned-nocopy-2.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[feature(managed_boxes)];
-
-struct r {
-  i: @mut int,
-}
-
-#[unsafe_destructor]
-impl Drop for r {
-    fn drop(&mut self) {
-        *(self.i) = *(self.i) + 1;
-    }
-}
-
-fn r(i: @mut int) -> r {
-    r {
-        i: i
-    }
-}
-
-pub fn main() {
-    let i = @mut 0;
-    {
-        let _j = ~r(i);
-    }
-    assert_eq!(*i, 1);
-}
diff --git a/src/test/run-pass/use_inline_dtor.rs b/src/test/run-pass/use_inline_dtor.rs
index 73b7013742b..239416adfe0 100644
--- a/src/test/run-pass/use_inline_dtor.rs
+++ b/src/test/run-pass/use_inline_dtor.rs
@@ -13,6 +13,6 @@
 
 extern mod inline_dtor;
 
-fn main() {
+pub fn main() {
     let _x = inline_dtor::Foo;
 }
diff --git a/src/test/run-pass/vec-slice-drop.rs b/src/test/run-pass/vec-slice-drop.rs
index c8493f0cb15..f8e28dc792c 100644
--- a/src/test/run-pass/vec-slice-drop.rs
+++ b/src/test/run-pass/vec-slice-drop.rs
@@ -10,29 +10,31 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
+
 // Make sure that destructors get run on slice literals
 struct foo {
-    x: @mut int,
+    x: @Cell<int>,
 }
 
 #[unsafe_destructor]
 impl Drop for foo {
     fn drop(&mut self) {
-        *self.x += 1;
+        self.x.set(self.x.get() + 1);
     }
 }
 
-fn foo(x: @mut int) -> foo {
+fn foo(x: @Cell<int>) -> foo {
     foo {
         x: x
     }
 }
 
 pub fn main() {
-    let x = @mut 0;
+    let x = @Cell::new(0);
     {
         let l = &[foo(x)];
-        assert_eq!(*l[0].x, 0);
+        assert_eq!(l[0].x.get(), 0);
     }
-    assert_eq!(*x, 1);
+    assert_eq!(x.get(), 1);
 }
diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs
index 70803c9bd55..f62ab6f59a0 100644
--- a/src/test/run-pass/weird-exprs.rs
+++ b/src/test/run-pass/weird-exprs.rs
@@ -10,6 +10,7 @@
 
 #[feature(managed_boxes)];
 
+use std::cell::Cell;
 use std::util;
 
 // Just a grab bag of stuff that you wouldn't want to actually write.
@@ -22,11 +23,13 @@ fn funny() {
 }
 
 fn what() {
-    fn the(x: @mut bool) { return while !*x { *x = true; }; }
-    let i = @mut false;
+    fn the(x: @Cell<bool>) {
+        return while !x.get() { x.set(true); };
+    }
+    let i = @Cell::new(false);
     let dont = {||the(i)};
     dont();
-    assert!((*i));
+    assert!((i.get()));
 }
 
 fn zombiejesus() {
diff --git a/src/test/run-pass/xcrate-address-insignificant.rs b/src/test/run-pass/xcrate-address-insignificant.rs
index 8a5a4a0cfe5..872c94e05fd 100644
--- a/src/test/run-pass/xcrate-address-insignificant.rs
+++ b/src/test/run-pass/xcrate-address-insignificant.rs
@@ -13,6 +13,6 @@
 
 extern mod foo = "xcrate_address_insignificant";
 
-fn main() {
+pub fn main() {
     assert_eq!(foo::foo::<f64>(), foo::bar());
 }
diff --git a/src/test/run-pass/xcrate-unit-struct.rs b/src/test/run-pass/xcrate-unit-struct.rs
index 79740c7b5a5..10f3a2b037f 100644
--- a/src/test/run-pass/xcrate-unit-struct.rs
+++ b/src/test/run-pass/xcrate-unit-struct.rs
@@ -21,7 +21,7 @@ static s4: xcrate_unit_struct::Unit = xcrate_unit_struct::Argument(s1);
 fn f1(_: xcrate_unit_struct::Struct) {}
 fn f2(_: xcrate_unit_struct::Unit) {}
 
-fn main() {
+pub fn main() {
     f1(xcrate_unit_struct::Struct);
     f2(xcrate_unit_struct::Unit);
     f2(xcrate_unit_struct::Argument(xcrate_unit_struct::Struct));