about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/doc/full-toc.inc7
-rw-r--r--src/doc/guide-lifetimes.md4
-rw-r--r--src/doc/guide-tasks.md2
-rw-r--r--src/doc/po/ja/tutorial.md.po24
-rw-r--r--src/doc/rust.css125
-rw-r--r--src/doc/rust.md34
-rw-r--r--src/doc/tutorial.md33
-rw-r--r--src/libcollections/btree.rs4
-rw-r--r--src/libcollections/hashmap.rs288
-rw-r--r--src/libcollections/lru_cache.rs93
-rw-r--r--src/libcollections/treemap.rs2
-rw-r--r--src/libcollections/trie.rs2
-rw-r--r--src/libgreen/basic.rs2
-rw-r--r--src/libgreen/context.rs2
-rw-r--r--src/libgreen/lib.rs8
-rw-r--r--src/libgreen/sched.rs2
-rw-r--r--src/libgreen/simple.rs2
-rw-r--r--src/libgreen/task.rs10
-rw-r--r--src/libnum/lib.rs2
-rw-r--r--src/librustc/back/link.rs6
-rw-r--r--src/librustc/back/svh.rs2
-rw-r--r--src/librustc/driver/driver.rs34
-rw-r--r--src/librustc/lib/llvm.rs51
-rw-r--r--src/librustc/metadata/creader.rs25
-rw-r--r--src/librustc/metadata/csearch.rs78
-rw-r--r--src/librustc/metadata/cstore.rs18
-rw-r--r--src/librustc/metadata/decoder.rs108
-rw-r--r--src/librustc/metadata/encoder.rs287
-rw-r--r--src/librustc/metadata/loader.rs4
-rw-r--r--src/librustc/metadata/tydecode.rs5
-rw-r--r--src/librustc/metadata/tyencode.rs81
-rw-r--r--src/librustc/middle/astencode.rs92
-rw-r--r--src/librustc/middle/borrowck/check_loans.rs130
-rw-r--r--src/librustc/middle/borrowck/gather_loans/gather_moves.rs26
-rw-r--r--src/librustc/middle/borrowck/gather_loans/lifetime.rs47
-rw-r--r--src/librustc/middle/borrowck/gather_loans/mod.rs49
-rw-r--r--src/librustc/middle/borrowck/gather_loans/move_error.rs10
-rw-r--r--src/librustc/middle/borrowck/gather_loans/restrictions.rs26
-rw-r--r--src/librustc/middle/borrowck/mod.rs190
-rw-r--r--src/librustc/middle/borrowck/move_data.rs60
-rw-r--r--src/librustc/middle/check_const.rs26
-rw-r--r--src/librustc/middle/check_match.rs6
-rw-r--r--src/librustc/middle/const_eval.rs10
-rw-r--r--src/librustc/middle/dataflow.rs5
-rw-r--r--src/librustc/middle/dead.rs25
-rw-r--r--src/librustc/middle/effect.rs9
-rw-r--r--src/librustc/middle/freevars.rs48
-rw-r--r--src/librustc/middle/kind.rs29
-rw-r--r--src/librustc/middle/lang_items.rs4
-rw-r--r--src/librustc/middle/lint.rs30
-rw-r--r--src/librustc/middle/liveness.rs23
-rw-r--r--src/librustc/middle/mem_categorization.rs225
-rw-r--r--src/librustc/middle/moves.rs69
-rw-r--r--src/librustc/middle/pat_util.rs14
-rw-r--r--src/librustc/middle/privacy.rs16
-rw-r--r--src/librustc/middle/reachable.rs11
-rw-r--r--src/librustc/middle/region.rs6
-rw-r--r--src/librustc/middle/resolve.rs1096
-rw-r--r--src/librustc/middle/subst.rs2
-rw-r--r--src/librustc/middle/trans/_match.rs264
-rw-r--r--src/librustc/middle/trans/adt.rs28
-rw-r--r--src/librustc/middle/trans/base.rs117
-rw-r--r--src/librustc/middle/trans/callee.rs72
-rw-r--r--src/librustc/middle/trans/closure.rs4
-rw-r--r--src/librustc/middle/trans/common.rs130
-rw-r--r--src/librustc/middle/trans/consts.rs29
-rw-r--r--src/librustc/middle/trans/context.rs31
-rw-r--r--src/librustc/middle/trans/debuginfo.rs55
-rw-r--r--src/librustc/middle/trans/expr.rs35
-rw-r--r--src/librustc/middle/trans/glue.rs34
-rw-r--r--src/librustc/middle/trans/intrinsic.rs8
-rw-r--r--src/librustc/middle/trans/meth.rs159
-rw-r--r--src/librustc/middle/trans/monomorphize.rs154
-rw-r--r--src/librustc/middle/trans/reflect.rs24
-rw-r--r--src/librustc/middle/trans/type_of.rs12
-rw-r--r--src/librustc/middle/trans/write_guard.rs2
-rw-r--r--src/librustc/middle/ty.rs456
-rw-r--r--src/librustc/middle/typeck/astconv.rs32
-rw-r--r--src/librustc/middle/typeck/check/_match.rs6
-rw-r--r--src/librustc/middle/typeck/check/method.rs92
-rw-r--r--src/librustc/middle/typeck/check/mod.rs111
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs164
-rw-r--r--src/librustc/middle/typeck/check/vtable.rs103
-rw-r--r--src/librustc/middle/typeck/check/writeback.rs151
-rw-r--r--src/librustc/middle/typeck/coherence.rs174
-rw-r--r--src/librustc/middle/typeck/collect.rs92
-rw-r--r--src/librustc/middle/typeck/infer/coercion.rs34
-rw-r--r--src/librustc/middle/typeck/infer/combine.rs14
-rw-r--r--src/librustc/middle/typeck/infer/error_reporting.rs19
-rw-r--r--src/librustc/middle/typeck/infer/glb.rs18
-rw-r--r--src/librustc/middle/typeck/infer/lattice.rs32
-rw-r--r--src/librustc/middle/typeck/infer/lub.rs18
-rw-r--r--src/librustc/middle/typeck/infer/mod.rs28
-rw-r--r--src/librustc/middle/typeck/infer/region_inference/mod.rs22
-rw-r--r--src/librustc/middle/typeck/infer/resolve.rs2
-rw-r--r--src/librustc/middle/typeck/infer/sub.rs18
-rw-r--r--src/librustc/middle/typeck/mod.rs37
-rw-r--r--src/librustc/middle/typeck/variance.rs15
-rw-r--r--src/librustc/util/nodemap.rs18
-rw-r--r--src/librustc/util/ppaux.rs12
-rw-r--r--src/librustc/util/sha2.rs4
-rw-r--r--src/librustdoc/html/layout.rs13
-rw-r--r--src/librustdoc/html/render.rs2
-rw-r--r--src/librustdoc/html/static/main.css40
-rw-r--r--src/librustuv/net.rs9
-rw-r--r--src/libstd/cast.rs5
-rw-r--r--src/libstd/cmp.rs4
-rw-r--r--src/libstd/iter.rs2
-rw-r--r--src/libstd/macros.rs2
-rw-r--r--src/libstd/ptr.rs2
-rw-r--r--src/libstd/raw.rs2
-rw-r--r--src/libstd/result.rs4
-rw-r--r--src/libstd/rt/local_ptr.rs2
-rw-r--r--src/libstd/str.rs6
-rw-r--r--src/libstd/strbuf.rs2
-rw-r--r--src/libstd/vec.rs4
-rw-r--r--src/libsyntax/util/small_vector.rs9
-rw-r--r--src/test/bench/shootout-chameneos-redux.rs178
-rw-r--r--src/test/compile-fail/issue-13599.rs23
-rw-r--r--src/test/compile-fail/typeck-unsafe-always-share.rs43
120 files changed, 3252 insertions, 3559 deletions
diff --git a/src/doc/full-toc.inc b/src/doc/full-toc.inc
index 35681f1796d..604a65dc8a9 100644
--- a/src/doc/full-toc.inc
+++ b/src/doc/full-toc.inc
@@ -1,6 +1,11 @@
 <style>
   /* Display the full TOC */
-  #TOC ul ul {
+  nav {
+    column-count: auto;
+    -moz-column-count: auto;
+    -webkit-column-count: auto;
+  }
+  nav ul ul {
     display: block;
     padding-left: 2em;
   }
diff --git a/src/doc/guide-lifetimes.md b/src/doc/guide-lifetimes.md
index 7f58e276ad5..59818922d1e 100644
--- a/src/doc/guide-lifetimes.md
+++ b/src/doc/guide-lifetimes.md
@@ -236,7 +236,7 @@ it. It would violate memory safety for the box that was originally
 assigned to `x` to be garbage-collected, since a non-heap
 pointer *`y`* still points into it.
 
-> ***Note:*** Our current implementation implements the garbage collector
+> *Note:* Our current implementation implements the garbage collector
 > using reference counting and cycle detection.
 
 For this reason, whenever an `&` expression borrows the interior of a
@@ -674,7 +674,7 @@ Named lifetime notation can also be used to control the flow of execution:
 }
 ~~~
 
-> ***Note:*** Labelled breaks are not currently supported within `while` loops.
+> *Note:* Labelled breaks are not currently supported within `while` loops.
 
 Named labels are hygienic and can be used safely within macros.
 See the macros guide section on hygiene for more details.
diff --git a/src/doc/guide-tasks.md b/src/doc/guide-tasks.md
index ed5384830d9..26e5c053372 100644
--- a/src/doc/guide-tasks.md
+++ b/src/doc/guide-tasks.md
@@ -456,7 +456,7 @@ an `Error` result.
 
 [`Result`]: std/result/index.html
 
-> ***Note:*** A failed task does not currently produce a useful error
+> *Note:* A failed task does not currently produce a useful error
 > value (`try` always returns `Err(())`). In the
 > future, it may be possible for tasks to intercept the value passed to
 > `fail!()`.
diff --git a/src/doc/po/ja/tutorial.md.po b/src/doc/po/ja/tutorial.md.po
index ebd08e8ae63..721b5b2b659 100644
--- a/src/doc/po/ja/tutorial.md.po
+++ b/src/doc/po/ja/tutorial.md.po
@@ -196,11 +196,11 @@ msgstr ""
 #. type: Plain text
 #: src/doc/tutorial.md:57
 msgid ""
-"> ***Warning:*** Rust is a language under ongoing development. Notes > about "
+"> *Warning:* Rust is a language under ongoing development. Notes > about "
 "potential changes to the language, implementation > deficiencies, and other "
 "caveats appear offset in blockquotes."
 msgstr ""
-"> ***警告:*** Rust は開発途上の言語です。将来予定されている言語への変更や、実"
+"> *警告:* Rust は開発途上の言語です。将来予定されている言語への変更や、実"
 "装上の不備、その他の注意事項など、 blockquote の段落 (この段落もそうです) に"
 "注意してください。"
 
@@ -287,13 +287,13 @@ msgstr ""
 #. type: Plain text
 #: src/doc/tutorial.md:88
 msgid ""
-"> ***Note:*** Windows users should read the detailed > \"[getting started]"
+"> *Note:* Windows users should read the detailed > \"[getting started]"
 "[wiki-start]\" notes on the wiki. Even when using > the binary installer, "
 "the Windows build requires a MinGW installation, > the precise details of "
 "which are not discussed here. Finally, `rustc` may > need to be [referred to "
 "as `rustc.exe`][bug-3319]. It's a bummer, we > know."
 msgstr ""
-"> ***注意:*** Windows ユーザーは wiki の [getting started][wiki-start] の記事"
+"> *注意:* Windows ユーザーは wiki の [getting started][wiki-start] の記事"
 "を読んでください。 本書では詳細を説明しませんが、インストーラを利用する場合で"
 "も、MinGW のインストールなど、追加の手順が必要です。また、コンパイラは "
 "`rustc` ではなく、 [`rustc.exe` として呼び出す必要がある][bug-3319] かもしれ"
@@ -1254,11 +1254,11 @@ msgstr ""
 #. type: Plain text
 #: src/doc/tutorial.md:504
 msgid ""
-"> ***Note:*** The following code makes use of tuples (`(f64, f64)`) which > "
+"> *Note:* The following code makes use of tuples (`(f64, f64)`) which > "
 "are explained in section 5.3. For now you can think of tuples as a list of > "
 "items."
 msgstr ""
-"> ***注意:*** 以下のコード例では5.3 節で説明されるタプル (`(f64, f64)`) を"
+"> *注意:* 以下のコード例では5.3 節で説明されるタプル (`(f64, f64)`) を"
 "使っています。現時点では、タプルは項目のリストのようなものだとみなしてくださ"
 "い。"
 
@@ -3005,11 +3005,11 @@ msgstr ""
 #. type: Plain text
 #: src/doc/tutorial.md:1774
 msgid ""
-"> ***Note:*** Both the syntax and the semantics will be changing > in small "
+"> *Note:* Both the syntax and the semantics will be changing > in small "
 "ways. At the moment they can be unsound in some > scenarios, particularly "
 "with non-copyable types."
 msgstr ""
-"> ***注意*** コードの文法と意味は将来的に変更されるかもしれません。現時点では"
+"> *注意* コードの文法と意味は将来的に変更されるかもしれません。現時点では"
 "いくつかの状況、特にコピーできない型が関連するケースにおいて望ましくない振る"
 "舞いが起こされる場合があります。"
 
@@ -3660,10 +3660,10 @@ msgstr ""
 #. type: Plain text
 #: src/doc/tutorial.md:2099
 msgid ""
-"> ***Note:*** These two traits were referred to as 'kinds' in earlier > "
+"> *Note:* These two traits were referred to as 'kinds' in earlier > "
 "iterations of the language, and often still are."
 msgstr ""
-"> ***注意*** これら2つのトレイトは、以前は 「種」 (kind) と呼ばれており、現在"
+"> *注意* これら2つのトレイトは、以前は 「種」 (kind) と呼ばれており、現在"
 "でもそう呼ばれる場合があります。"
 
 #. type: Plain text
@@ -4374,9 +4374,9 @@ msgstr ""
 
 #. type: Plain text
 #: src/doc/tutorial.md:2511
-msgid "> ***Note:*** Trait inheritance does not actually work with objects yet"
+msgid "> *Note:* Trait inheritance does not actually work with objects yet"
 msgstr ""
-"> ***注意*** トレイトの継承は、実際にはまだオブジェクトに対しては動作しませ"
+"> *注意* トレイトの継承は、実際にはまだオブジェクトに対しては動作しませ"
 "ん。"
 
 #. type: Plain text
diff --git a/src/doc/rust.css b/src/doc/rust.css
index c69b59855a7..b581dc2cce8 100644
--- a/src/doc/rust.css
+++ b/src/doc/rust.css
@@ -10,13 +10,43 @@
  * option. This file may not be copied, modified, or distributed
  * except according to those terms.
  */
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: normal;
+    font-weight: 400;
+    src: local('Fira Sans'), url("http://www.rust-lang.org/fonts/FiraSans-Regular.woff") format('woff');
+}
+@font-face {
+    font-family: 'Fira Sans';
+    font-style: normal;
+    font-weight: 500;
+    src: local('Fira Sans Medium'), url("http://www.rust-lang.org/fonts/FiraSans-Medium.woff") format('woff');
+}
+@font-face {
+    font-family: 'Heuristica';
+    font-style: normal;
+    font-weight: 400;
+    src: local('Heuristica Regular'), url("http://www.rust-lang.org/fonts/Heuristica-Regular.woff") format('woff');
+}
+@font-face {
+    font-family: 'Heuristica';
+    font-style: italic;
+    font-weight: 400;
+    src: local('Heuristica Italic'), url("http://www.rust-lang.org/fonts/Heuristica-Italic.woff") format('woff');
+}
+@font-face {
+    font-family: 'Heuristica';
+    font-style: normal;
+    font-weight: 700;
+    src: local('Heuristica Bold'), url("http://www.rust-lang.org/fonts/Heuristica-Bold.woff") format('woff');
+}
 /* Global page semantics
    ========================================================================== */
 body {
     margin: 0 auto;
     padding: 0 15px;
-    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-    font-size: 14px;
+    font-family: "Heuristica", "Helvetica Neue", Helvetica, Arial, sans-serif;
+    font-size: 18px;
     color: #333;
     line-height: 1.428571429;
 }
@@ -26,33 +56,51 @@ body {
     }
 }
 
+h1, h2, h3, h4, h5, h6, nav, #versioninfo {
+    font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
 h1, h2, h3, h4, h5, h6 {
     color: black;
-    font-weight: 500;
+    font-weight: 400;
     line-height: 1.1;
 }
 h1, h2, h3 {
     margin-top: 20px;
-    margin-bottom: 10px;
+    margin-bottom: 15px;
+}
+h1 {
+    margin-bottom: 20px;
+}
+@media (min-width: 1170px) {
+    h1 {
+        margin-top: 40px;
+        margin-bottom: 30px;
+    }
+    h1, h2, h3 {
+        margin-top: 30px;
+        margin-bottom: 15px;
+    }
 }
 h4, h5, h6 {
     margin-top: 12px;
     margin-bottom: 10px;
-    padding: .2em .8em;
+    padding: 5px 10px;
+}
+h5, h6 {
     text-decoration: underline;
 }
 
 h1 {
-    font-size: 36px;
+    font-size: 28px;
+    font-weight: 500;
     padding: .1em .4em;
-    margin: 0.67em 0;
     border-bottom: 2px solid #ddd;
 }
 h1.title {
     line-height: 1.5em;
 }
 h2 {
-    font-size: 30px;
+    font-size: 26px;
     padding: .2em .5em;
     border-bottom: 1px solid #ddd;
 }
@@ -62,17 +110,34 @@ h3 {
     border-bottom: 1px solid #DDE8FC;
 }
 h4 {
-    font-size: 18px;
+    font-size: 22px;
 }
 h5 {
-    font-size: 16px;
+    font-size: 20px;
 }
 h6 {
-    font-size: 14px;
+    font-size: 18px;
+}
+@media (min-width: 992px) {
+    h1 {
+        font-size: 36px;
+    }
+    h2 {
+        font-size: 30px;
+    }
+    h3 {
+        font-size: 26px;
+    }
 }
 
+nav {
+    column-count: 2;
+    -moz-column-count: 2;
+    -webkit-column-count: 2;
+    font-size: 15px;
+}
 p {
-    margin: 0 0 10px;
+    margin: 0 0 1em 0;
 }
 
 strong {
@@ -85,10 +150,10 @@ em {
 
 footer {
     border-top: 1px solid #ddd;
-    font-size: 12px;
+    font-size: 14.3px;
     font-style: italic;
-    padding-top: 4px;
-    margin-top: 4em;
+    padding-top: 5px;
+    margin-top: 3em;
     margin-bottom: 1em;
 }
 
@@ -130,16 +195,14 @@ pre {
     border-radius: 0.5em;
     white-space: pre-wrap;
     padding: 9.5px;
-    margin: 10px 0;
+    margin: 20px 0;
     font-size: 13px;
     word-break: break-all;
     word-wrap: break-word;
 }
 code {
-    padding: 2px 4px;
-    font-size: 90%;
-    color: #C7254E;
-    background-color: #F9F2F4;
+    padding: 0 2px;
+    color: #8D1A38;
     white-space: nowrap;
 }
 pre code {
@@ -170,7 +233,7 @@ pre.rust .lifetime { color: #B76514; }
     margin: 0.5em;
     font-size: 1.1em;
 }
-@media only screen, handheld and (min-width: 768px) {
+@media only screen and (min-width: 768px) {
     #versioninfo {
         position: fixed;
         bottom: 0px;
@@ -185,7 +248,7 @@ pre.rust .lifetime { color: #B76514; }
 }
 #versioninfo a.hash {
     color: gray;
-    font-size: 70%;
+    font-size: 80%;
 }
 
 blockquote {
@@ -197,21 +260,16 @@ blockquote {
 blockquote p {
     font-size: 17px;
     font-weight: 300;
-    line-height: 1.25;
+    line-height: 1.4;
 }
 blockquote p:last-child {
     margin-bottom: 0;
 }
 
-ul,
-ol {
-    margin-top: 0;
-    margin-bottom: 10px;
+ul, ol {
+    padding-left: 25px;
 }
-ul ul,
-ol ul,
-ul ol,
-ol ol {
+ul ul, ol ul, ul ol, ol ol {
     margin-bottom: 0;
 }
 dl {
@@ -221,13 +279,14 @@ dd {
     margin-left: 0;
 }
 
-#TOC ul {
+nav ul {
     list-style-type: none;
+    margin: 0;
     padding-left: 0px;
 }
 
 /* Only display one level of hierarchy in the TOC */
-#TOC ul ul {
+nav ul ul {
     display: none;
 }
 
diff --git a/src/doc/rust.md b/src/doc/rust.md
index 46a4756ce84..aeda95aa261 100644
--- a/src/doc/rust.md
+++ b/src/doc/rust.md
@@ -96,9 +96,9 @@ The section [Special Unicode Productions](#special-unicode-productions) lists th
 
 ## String table productions
 
-Some rules in the grammar -- notably [unary
+Some rules in the grammar &mdash; notably [unary
 operators](#unary-operator-expressions), [binary
-operators](#binary-operator-expressions), and [keywords](#keywords) --
+operators](#binary-operator-expressions), and [keywords](#keywords) &mdash;
 are given in a simplified form: as a listing of a table of unquoted,
 printable whitespace-separated strings. These cases form a subset of
 the rules regarding the [token](#tokens) rule, and are assumed to be
@@ -645,7 +645,7 @@ The processing of that source file may result in other source files being loaded
 Source files have the extension `.rs`.
 
 A Rust source file describes a module, the name and
-location of which -- in the module tree of the current crate -- are defined
+location of which &mdash; in the module tree of the current crate &mdash; are defined
 from outside the source file: either by an explicit `mod_item` in
 a referencing source file, or by the name of the crate itself.
 
@@ -709,7 +709,7 @@ Some items form an implicit scope for the declaration of sub-items. In other
 words, within a function or module, declarations of items can (in many cases)
 be mixed with the statements, control blocks, and similar artifacts that
 otherwise compose the item body. The meaning of these scoped items is the same
-as if the item was declared outside the scope -- it is still a static item --
+as if the item was declared outside the scope &mdash; it is still a static item &mdash;
 except that the item's *path name* within the module namespace is qualified by
 the name of the enclosing item, or is private to the enclosing item (in the
 case of functions).
@@ -1348,7 +1348,6 @@ Traits are implemented for specific types through separate [implementations](#im
 ~~~~
 # type Surface = int;
 # type BoundingBox = int;
-
 trait Shape {
     fn draw(&self, Surface);
     fn bounding_box(&self) -> BoundingBox;
@@ -1379,7 +1378,6 @@ For example:
 ~~~~
 # type Surface = int;
 # trait Shape { fn draw(&self, Surface); }
-
 fn draw_twice<T: Shape>(surface: Surface, sh: T) {
     sh.draw(surface);
     sh.draw(surface);
@@ -1395,7 +1393,6 @@ to pointers to the trait name, used as a type.
 # trait Shape { }
 # impl Shape for int { }
 # let mycircle = 0;
-
 let myshape: ~Shape = ~mycircle as ~Shape;
 ~~~~
 
@@ -1456,7 +1453,6 @@ Likewise, supertrait methods may also be called on trait objects.
 # impl Shape for int { fn area(&self) -> f64 { 0.0 } }
 # impl Circle for int { fn radius(&self) -> f64 { 0.0 } }
 # let mycircle = 0;
-
 let mycircle: Circle = ~mycircle as ~Circle;
 let nonsense = mycircle.radius() * mycircle.area();
 ~~~~
@@ -1473,7 +1469,6 @@ Implementations are defined with the keyword `impl`.
 # struct BoundingBox {x: f64, y: f64, width: f64, height: f64};
 # trait Shape { fn draw(&self, Surface); fn bounding_box(&self) -> BoundingBox; }
 # fn do_draw_circle(s: Surface, c: Circle) { }
-
 struct Circle {
     radius: f64,
     center: Point,
@@ -1506,7 +1501,6 @@ Implementation parameters are written after the `impl` keyword.
 
 ~~~~
 # trait Seq<T> { }
-
 impl<T> Seq<T> for ~[T] {
    /* ... */
 }
@@ -1746,7 +1740,7 @@ attr : ident [ '=' literal
              | '(' attr_list ')' ] ? ;
 ~~~~
 
-Static entities in Rust -- crates, modules and items -- may have _attributes_
+Static entities in Rust &mdash; crates, modules and items &mdash; may have _attributes_
 applied to them. Attributes in Rust are modeled on Attributes in ECMA-335,
 with the syntax coming from ECMA-334 (C#). An attribute is a general,
 free-form metadatum that is interpreted according to name, convention, and
@@ -2368,8 +2362,8 @@ The declared names may denote new slots or new items.
 #### Item declarations
 
 An _item declaration statement_ has a syntactic form identical to an
-[item](#items) declaration within a module. Declaring an item -- a function,
-enumeration, structure, type, static, trait, implementation or module -- locally
+[item](#items) declaration within a module. Declaring an item &mdash; a function,
+enumeration, structure, type, static, trait, implementation or module &mdash; locally
 within a statement block is simply a way of restricting its scope to a narrow
 region containing all of its uses; it is otherwise identical in meaning to
 declaring the item outside the statement block.
@@ -3398,7 +3392,7 @@ but must be denoted by named reference to an [`enum` item](#enumerations).
 
 ### Recursive types
 
-Nominal types -- [enumerations](#enumerated-types) and [structures](#structure-types) -- may be recursive.
+Nominal types &mdash; [enumerations](#enumerated-types) and [structures](#structure-types) &mdash; may be recursive.
 That is, each `enum` constructor or `struct` field may refer, directly or indirectly, to the enclosing `enum` or `struct` type itself.
 Such recursion has restrictions:
 
@@ -3708,7 +3702,7 @@ entry to each function as the task executes. A stack allocation is reclaimed
 when control leaves the frame containing it.
 
 The _heap_ is a general term that describes two separate sets of boxes:
-managed boxes -- which may be subject to garbage collection -- and owned
+managed boxes &mdash; which may be subject to garbage collection &mdash; and owned
 boxes.  The lifetime of an allocation in the heap depends on the lifetime of
 the box values pointing to it. Since box values may themselves be passed in
 and out of frames, or stored in the heap, heap allocations may outlive the
@@ -3774,7 +3768,7 @@ initialized; this is enforced by the compiler.
 ### Owned boxes
 
 An  _owned box_ is a reference to a heap allocation holding another value, which is constructed
-by the prefix *tilde* sigil `~`
+by the prefix *tilde* sigil `~`.
 
 An example of an owned box type and value:
 
@@ -3809,7 +3803,7 @@ The runtime scheduler maps tasks to a certain number of operating-system threads
 By default, the scheduler chooses the number of threads based on
 the number of concurrent physical CPUs detected at startup.
 It's also possible to override this choice at runtime.
-When the number of tasks exceeds the number of threads -- which is likely --
+When the number of tasks exceeds the number of threads &mdash; which is likely &mdash;
 the scheduler multiplexes the tasks onto threads.^[
 This is an M:N scheduler,
 which is known to give suboptimal results for CPU-bound concurrency problems.
@@ -3848,14 +3842,14 @@ that cause transitions between the states. The lifecycle states of a task are:
 * failing
 * dead
 
-A task begins its lifecycle -- once it has been spawned -- in the *running*
+A task begins its lifecycle &mdash; once it has been spawned &mdash; in the *running*
 state. In this state it executes the statements of its entry function, and any
 functions called by the entry function.
 
 A task may transition from the *running* state to the *blocked*
 state any time it makes a blocking communication call. When the
-call can be completed -- when a message arrives at a sender, or a
-buffer opens to receive a message -- then the blocked task will
+call can be completed &mdash; when a message arrives at a sender, or a
+buffer opens to receive a message &mdash; then the blocked task will
 unblock and transition back to *running*.
 
 A task may transition to the *failing* state at any time, due being
diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md
index bd0851f9700..9f15fd1934f 100644
--- a/src/doc/tutorial.md
+++ b/src/doc/tutorial.md
@@ -33,7 +33,7 @@ pleasant high-level features include:
 This is an introductory tutorial for the Rust programming language. It
 covers the fundamentals of the language, including the syntax, the
 type system and memory model, generics, and modules. [Additional
-tutorials](#what-next) cover specific language features in greater
+tutorials](#what-next?) cover specific language features in greater
 depth.
 
 This tutorial assumes that the reader is already familiar with one or
@@ -51,13 +51,13 @@ fragments of programs that don't compile on their own. To try them
 out, you might have to wrap them in `fn main() { ... }`, and make sure
 they don't contain references to names that aren't actually defined.
 
-> ***Warning:*** Rust is a language under ongoing development. Notes
+> *Warning:* Rust is a language under ongoing development. Notes
 > about potential changes to the language, implementation
 > deficiencies, and other caveats appear offset in blockquotes.
 
 # Getting started
 
-> ***Warning:*** The tarball and installer links are for the most recent
+> *Warning:* The tarball and installer links are for the most recent
 > release, not master. To use master, you **must** build from [git].
 
 The Rust compiler currently must be built from a [tarball] or [git], unless
@@ -79,7 +79,7 @@ Snapshot binaries are currently built and tested on several platforms:
 You may find that other platforms work, but these are our "tier 1"
 supported build environments that are most likely to work.
 
-> ***Note:*** Windows users should read the detailed
+> *Note:* Windows users should read the detailed
 > [Getting started][wiki-start] notes on the wiki. Even when using
 > the binary installer, the Windows build requires a MinGW installation,
 > the precise details of which are not discussed here.
@@ -130,7 +130,7 @@ fn main() {
     println!("hello?");
 }
 ~~~~
-> ***Note:*** An identifier followed by an exclamation point, like
+> *Note:* An identifier followed by an exclamation point, like
 > `println!`, is a macro invocation.  Macros are explained
 > [later](#syntax-extensions); for now just remember to include the
 > exclamation point.
@@ -498,7 +498,7 @@ omitted.
 A powerful application of pattern matching is *destructuring*:
 matching in order to bind names to the contents of data types.
 
-> ***Note:*** The following code makes use of tuples (`(f64, f64)`) which
+> *Note:* The following code makes use of tuples (`(f64, f64)`) which
 > are explained in section 5.3. For now you can think of tuples as a list of
 > items.
 
@@ -781,7 +781,7 @@ fn area(sh: Shape) -> f64 {
 }
 ~~~~
 
-> ***Note:*** This feature of the compiler is currently gated behind the
+> *Note:* This feature of the compiler is currently gated behind the
 > `#[feature(struct_variant)]` directive. More about these directives can be
 > found in the manual.
 
@@ -841,7 +841,6 @@ values can be extracted with pattern matching:
 
 ~~~
 # struct Inches(int);
-
 let length_with_unit = Inches(10);
 let Inches(integer_length) = length_with_unit;
 println!("length is {} inches", integer_length);
@@ -1061,7 +1060,7 @@ list -> | Cons | 1 | ~ | -> | Cons | 2 | ~ | -> | Cons | 3 | ~ | -> | Nil
         +--------------+    +--------------+    +--------------+    +--------------+
 ~~~
 
-> ***Note:*** the above diagram shows the logical contents of the enum. The actual
+> *Note:* the above diagram shows the logical contents of the enum. The actual
 > memory layout of the enum may vary. For example, for the `List` enum shown
 > above, Rust guarantees that there will be no enum tag field in the actual
 > structure. See the language reference for more details.
@@ -1209,7 +1208,7 @@ let ys = Cons(5, ~Cons(10, ~Nil));
 assert!(eq(&xs, &ys));
 ~~~
 
-> ***Note:*** Rust doesn't guarantee [tail-call](http://en.wikipedia.org/wiki/Tail_call) optimization,
+> *Note:* Rust doesn't guarantee [tail-call](http://en.wikipedia.org/wiki/Tail_call) optimization,
 > but LLVM is able to handle a simple case like this with optimizations enabled.
 
 ## Lists of other types
@@ -1220,7 +1219,7 @@ element type.
 
 The `u32` in the previous definition can be substituted with a type parameter:
 
-> ***Note:*** The following code introduces generics, which are explained in a
+> *Note:* The following code introduces generics, which are explained in a
 > [dedicated section](#generics).
 
 ~~~
@@ -1794,7 +1793,7 @@ spawn(proc() {
 });
 ~~~~
 
-> ***Note:*** If you want to see the output of `debug!` statements, you will need to turn on
+> *Note:* If you want to see the output of `debug!` statements, you will need to turn on
 > `debug!` logging.  To enable `debug!` logging, set the RUST_LOG environment
 > variable to the name of your crate, which, for a file named `foo.rs`, will be
 > `foo` (e.g., with bash, `export RUST_LOG=foo`).
@@ -1816,7 +1815,7 @@ call_twice(closure);
 call_twice(function);
 ~~~~
 
-> ***Note:*** Both the syntax and the semantics will be changing
+> *Note:* Both the syntax and the semantics will be changing
 > in small ways. At the moment they can be unsound in some
 > scenarios, particularly with non-copyable types.
 
@@ -2011,7 +2010,7 @@ a function that returns `Option<T>` instead of `T`.
 fn radius(shape: Shape) -> Option<f64> {
     match shape {
         Circle(_, radius) => Some(radius),
-        Rectangle(..)      => None
+        Rectangle(..)     => None
     }
 }
 ~~~~
@@ -2101,7 +2100,7 @@ references, or types where the only contained references
 have the `'static` lifetime. (For more on named lifetimes and their uses,
 see the [references and lifetimes guide][lifetimes].)
 
-> ***Note:*** These built-in traits were referred to as 'kinds' in earlier
+> *Note:* These built-in traits were referred to as 'kinds' in earlier
 > iterations of the language, and often still are.
 
 Additionally, the `Drop` trait is used to define destructors. This
@@ -2512,7 +2511,7 @@ let mycircle: ~Circle = concrete as ~Circle;
 let nonsense = mycircle.radius() * mycircle.area();
 ~~~
 
-> ***Note:*** Trait inheritance does not actually work with objects yet
+> *Note:* Trait inheritance does not actually work with objects yet
 
 ## Deriving implementations for traits
 
@@ -2966,7 +2965,7 @@ use farm::*;
 # fn main() { cow(); chicken() }
 ~~~
 
-> ***Note:*** This feature of the compiler is currently gated behind the
+> *Note:* This feature of the compiler is currently gated behind the
 > `#[feature(globs)]` directive. More about these directives can be found in
 > the manual.
 
diff --git a/src/libcollections/btree.rs b/src/libcollections/btree.rs
index a258cf8b175..b6dc790ea88 100644
--- a/src/libcollections/btree.rs
+++ b/src/libcollections/btree.rs
@@ -659,13 +659,13 @@ impl<K: fmt::Show + TotalOrd, V: fmt::Show> fmt::Show for Branch<K, V> {
     }
 }
 
-//A LeafElt containts no left child, but a key-value pair.
+//A LeafElt contains no left child, but a key-value pair.
 struct LeafElt<K, V> {
     key: K,
     value: V
 }
 
-//A BranchElt has a left child in insertition to a key-value pair.
+//A BranchElt has a left child in insertion to a key-value pair.
 struct BranchElt<K, V> {
     left: ~Node<K, V>,
     key: K,
diff --git a/src/libcollections/hashmap.rs b/src/libcollections/hashmap.rs
index 03b486e628c..f6a2b1c6250 100644
--- a/src/libcollections/hashmap.rs
+++ b/src/libcollections/hashmap.rs
@@ -43,7 +43,8 @@ mod table {
     use std::ptr;
     use std::ptr::RawPtr;
     use std::rt::global_heap;
-    use std::intrinsics::{size_of, min_align_of, transmute, move_val_init};
+    use std::intrinsics::{size_of, min_align_of, transmute};
+    use std::intrinsics::{move_val_init, set_memory};
     use std::iter::{Iterator, range_step_inclusive};
 
     static EMPTY_BUCKET: u64 = 0u64;
@@ -52,15 +53,15 @@ mod table {
     /// optimized arrays of hashes, keys, and values.
     ///
     /// This design uses less memory and is a lot faster than the naive
-    /// `~[Option<u64, K, V>]`, because we don't pay for the overhead of an
+    /// `Vec<Option<u64, K, V>>`, because we don't pay for the overhead of an
     /// option on every element, and we get a generally more cache-aware design.
     ///
     /// Key invariants of this structure:
     ///
     ///   - if hashes[i] == EMPTY_BUCKET, then keys[i] and vals[i] have
     ///     'undefined' contents. Don't read from them. This invariant is
-    ///     enforced outside this module with the [EmptyIndex], [FullIndex],
-    ///     and [SafeHash] types/concepts.
+    ///     enforced outside this module with the `EmptyIndex`, `FullIndex`,
+    ///     and `SafeHash` types.
     ///
     ///   - An `EmptyIndex` is only constructed for a bucket at an index with
     ///     a hash of EMPTY_BUCKET.
@@ -69,8 +70,9 @@ mod table {
     ///     non-EMPTY_BUCKET hash.
     ///
     ///   - A `SafeHash` is only constructed for non-`EMPTY_BUCKET` hash. We get
-    ///     around hashes of zero by changing them to 0x800_0000, which will
-    ///     likely hash to the same bucket, but not be represented as "empty".
+    ///     around hashes of zero by changing them to 0x8000_0000_0000_0000,
+    ///     which will likely map to the same bucket, while not being confused
+    ///     with "empty".
     ///
     ///   - All three "arrays represented by pointers" are the same length:
     ///     `capacity`. This is set at creation and never changes. The arrays
@@ -111,25 +113,27 @@ mod table {
 
     /// Represents an index into a `RawTable` with no key or value in it.
     pub struct EmptyIndex {
-        idx:   int,
+        idx:    int,
         nocopy: marker::NoCopy,
     }
 
     /// Represents an index into a `RawTable` with a key, value, and hash
     /// in it.
     pub struct FullIndex {
-        idx:   int,
-        hash:  SafeHash,
+        idx:    int,
+        hash:   SafeHash,
         nocopy: marker::NoCopy,
     }
 
     impl FullIndex {
         /// Since we get the hash for free whenever we check the bucket state,
-        /// this function is provided for fast access, letting us avoid making
+        /// this function is provided for fast access, letting us avoid
         /// redundant trips back to the hashtable.
+        #[inline(always)]
         pub fn hash(&self) -> SafeHash { self.hash }
 
         /// Same comment as with `hash`.
+        #[inline(always)]
         pub fn raw_index(&self) -> uint { self.idx as uint }
     }
 
@@ -141,7 +145,8 @@ mod table {
         Full(FullIndex),
     }
 
-    /// A hash that is not zero, since we use that to represent empty buckets.
+    /// A hash that is not zero, since we use a hash of zero to represent empty
+    /// buckets.
     #[deriving(Eq)]
     pub struct SafeHash {
         hash: u64,
@@ -149,6 +154,7 @@ mod table {
 
     impl SafeHash {
         /// Peek at the hash value, which is guaranteed to be non-zero.
+        #[inline(always)]
         pub fn inspect(&self) -> u64 { self.hash }
     }
 
@@ -171,12 +177,16 @@ mod table {
 
     #[test]
     fn test_rounding() {
-        assert!(round_up_to_next(0, 4) == 0);
-        assert!(round_up_to_next(1, 4) == 4);
-        assert!(round_up_to_next(2, 4) == 4);
-        assert!(round_up_to_next(3, 4) == 4);
-        assert!(round_up_to_next(4, 4) == 4);
-        assert!(round_up_to_next(5, 4) == 8);
+        assert_eq!(round_up_to_next(0, 4), 0);
+        assert_eq!(round_up_to_next(1, 4), 4);
+        assert_eq!(round_up_to_next(2, 4), 4);
+        assert_eq!(round_up_to_next(3, 4), 4);
+        assert_eq!(round_up_to_next(4, 4), 4);
+        assert_eq!(round_up_to_next(5, 4), 8);
+    }
+
+    fn has_alignment(n: uint, alignment: uint) -> bool {
+        round_up_to_next(n, alignment) == n
     }
 
     // Returns a tuple of (minimum required malloc alignment, hash_offset,
@@ -200,6 +210,13 @@ mod table {
         (min_align, hash_offset, keys_offset, vals_offset, end_of_vals)
     }
 
+    #[test]
+    fn test_offset_calculation() {
+        assert_eq!(calculate_offsets(128, 8, 15, 1, 4, 4 ), (8, 0, 128, 144, 148));
+        assert_eq!(calculate_offsets(3,   1, 2,  1, 1, 1 ), (1, 0, 3,   5,   6));
+        assert_eq!(calculate_offsets(6,   2, 12, 4, 24, 8), (8, 0, 8,   24,  48));
+    }
+
     impl<K, V> RawTable<K, V> {
 
         /// Does not initialize the buckets. The caller should ensure they,
@@ -213,9 +230,9 @@ mod table {
                 capacity.checked_mul(&size_of::< V >()).expect("capacity overflow");
 
             // Allocating hashmaps is a little tricky. We need to allocate three
-            // arrays here, but since we know their sizes and alignments up front,
-            // we could theoretically allocate only a single array, and then have
-            // the subarrays just point into it.
+            // arrays, but since we know their sizes and alignments up front,
+            // we just allocate a single array, and then have the subarrays
+            // point into it.
             //
             // This is great in theory, but in practice getting the alignment
             // right is a little subtle. Therefore, calculating offsets has been
@@ -231,8 +248,7 @@ mod table {
             // FIXME #13094: If malloc was not at as aligned as we expected,
             // our offset calculations are just plain wrong. We could support
             // any alignment if we switched from `malloc` to `posix_memalign`.
-            assert!(round_up_to_next(buffer as uint, malloc_alignment)
-                == (buffer as uint));
+            assert!(has_alignment(buffer as uint, malloc_alignment));
 
             let hashes = buffer.offset(hash_offset as int) as *mut u64;
             let keys   = buffer.offset(keys_offset as int) as *mut K;
@@ -247,26 +263,20 @@ mod table {
             }
         }
 
-
-
         /// Creates a new raw table from a given capacity. All buckets are
         /// initially empty.
         pub fn new(capacity: uint) -> RawTable<K, V> {
             unsafe {
                 let ret = RawTable::new_uninitialized(capacity);
-
-                for i in range(0, ret.capacity() as int) {
-                    *ret.hashes.offset(i) = EMPTY_BUCKET;
-                }
-
+                set_memory(ret.hashes, 0u8, capacity);
                 ret
             }
         }
 
         /// Reads a bucket at a given index, returning an enum indicating whether
         /// there's anything there or not. You need to match on this enum to get
-        /// the appropriate types to pass on to most of the rest of the functions
-        /// in this module.
+        /// the appropriate types to pass on to most of the other functions in
+        /// this module.
         pub fn peek(&self, index: uint) -> BucketState {
             // FIXME #12049
             if cfg!(test) { assert!(index < self.capacity) }
@@ -279,13 +289,13 @@ mod table {
             match hash {
                 EMPTY_BUCKET =>
                     Empty(EmptyIndex {
-                        idx: idx,
+                        idx:    idx,
                         nocopy: nocopy
                     }),
                 full_hash =>
                     Full(FullIndex {
-                        idx:   idx,
-                        hash:  SafeHash { hash: full_hash },
+                        idx:    idx,
+                        hash:   SafeHash { hash: full_hash },
                         nocopy: nocopy,
                     })
             }
@@ -321,13 +331,6 @@ mod table {
             -> (&'a mut SafeHash, &'a mut K, &'a mut V) {
             let idx = index.idx;
 
-            // I'm totally abusing the fact that a pointer to any u64 in the
-            // hashtable at a full index is a safe hash. Thanks to `SafeHash`
-            // just being a wrapper around u64, this is true. It's just really
-            // really really really unsafe. However, the exposed API is now
-            // impossible to get wrong. You cannot insert an empty hash into
-            // this slot now.
-
             unsafe {
                 // FIXME #12049
                 if cfg!(test) { assert!(*self.hashes.offset(idx) != EMPTY_BUCKET) }
@@ -340,8 +343,8 @@ mod table {
         /// Puts a key and value pair, along with the key's hash, into a given
         /// index in the hashtable. Note how the `EmptyIndex` is 'moved' into this
         /// function, because that slot will no longer be empty when we return!
-        /// Because we know this, a FullIndex is returned for later use, pointing
-        /// to the newly-filled slot in the hashtable.
+        /// A FullIndex is returned for later use, pointing to the newly-filled
+        /// slot in the hashtable.
         ///
         /// Use `make_hash` to construct a `SafeHash` to pass to this function.
         pub fn put(&mut self, index: EmptyIndex, hash: SafeHash, k: K, v: V) -> FullIndex {
@@ -349,7 +352,7 @@ mod table {
 
             unsafe {
                 // FIXME #12049
-                if cfg!(test) { assert!(*self.hashes.offset(idx) == EMPTY_BUCKET) }
+                if cfg!(test) { assert_eq!(*self.hashes.offset(idx), EMPTY_BUCKET) }
                 *self.hashes.offset(idx) = hash.inspect();
                 move_val_init(&mut *self.keys.offset(idx), k);
                 move_val_init(&mut *self.vals.offset(idx), v);
@@ -371,9 +374,7 @@ mod table {
                 // FIXME #12049
                 if cfg!(test) { assert!(*self.hashes.offset(idx) != EMPTY_BUCKET) }
 
-                let hash_ptr = self.hashes.offset(idx);
-
-                *hash_ptr = EMPTY_BUCKET;
+                *self.hashes.offset(idx) = EMPTY_BUCKET;
 
                 // Drop the mutable constraint.
                 let keys = self.keys as *K;
@@ -400,31 +401,48 @@ mod table {
         }
 
         pub fn iter<'a>(&'a self) -> Entries<'a, K, V> {
-            Entries { table: self, idx: 0 }
+            Entries { table: self, idx: 0, elems_seen: 0 }
         }
 
         pub fn mut_iter<'a>(&'a mut self) -> MutEntries<'a, K, V> {
-            MutEntries { table: self, idx: 0 }
+            MutEntries { table: self, idx: 0, elems_seen: 0 }
         }
 
         pub fn move_iter(self) -> MoveEntries<K, V> {
-            MoveEntries { table: self, idx: 0 }
+            MoveEntries { table: self, idx: 0, elems_seen: 0 }
         }
     }
 
+    // `read_all_mut` casts a `*u64` to a `*SafeHash`. Since we statically
+    // ensure that a `FullIndex` points to an index with a non-zero hash,
+    // and a `SafeHash` is just a `u64` with a different name, this is
+    // safe.
+    //
+    // This test ensures that a `SafeHash` really IS the same size as a
+    // `u64`. If you need to change the size of `SafeHash` (and
+    // consequently made this test fail), `read_all_mut` needs to be
+    // modified to no longer assume this.
+    #[test]
+    fn can_alias_safehash_as_u64() {
+        unsafe { assert_eq!(size_of::<SafeHash>(), size_of::<u64>()) };
+    }
+
     pub struct Entries<'a, K, V> {
         table: &'a RawTable<K, V>,
         idx: uint,
+        elems_seen: uint,
     }
 
     pub struct MutEntries<'a, K, V> {
         table: &'a mut RawTable<K, V>,
         idx: uint,
+        elems_seen: uint,
     }
 
     pub struct MoveEntries<K, V> {
         table: RawTable<K, V>,
         idx: uint,
+        elems_seen: uint,
     }
 
     impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
@@ -435,7 +453,10 @@ mod table {
 
                 match self.table.peek(i) {
                     Empty(_)  => {},
-                    Full(idx) => return Some(self.table.read(&idx))
+                    Full(idx) => {
+                        self.elems_seen += 1;
+                        return Some(self.table.read(&idx));
+                    }
                 }
             }
 
@@ -443,7 +464,7 @@ mod table {
         }
 
         fn size_hint(&self) -> (uint, Option<uint>) {
-            let size = self.table.size() - self.idx;
+            let size = self.table.size() - self.elems_seen;
             (size, Some(size))
         }
     }
@@ -460,7 +481,8 @@ mod table {
                     // error: lifetime of `self` is too short to guarantee its contents
                     //        can be safely reborrowed
                     Full(idx) => unsafe {
-                        return Some(transmute(self.table.read_mut(&idx)))
+                        self.elems_seen += 1;
+                        return Some(transmute(self.table.read_mut(&idx)));
                     }
                 }
             }
@@ -469,7 +491,7 @@ mod table {
         }
 
         fn size_hint(&self) -> (uint, Option<uint>) {
-            let size = self.table.size() - self.idx;
+            let size = self.table.size() - self.elems_seen;
             (size, Some(size))
         }
     }
@@ -526,18 +548,14 @@ mod table {
         }
     }
 
-
-
     #[unsafe_destructor]
     impl<K, V> Drop for RawTable<K, V> {
         fn drop(&mut self) {
-            // Ideally, this should be in reverse, since we're likely to have
-            // partially taken some elements out with `.move_iter()` from the
-            // front.
+            // This is in reverse because we're likely to have partially taken
+            // some elements out with `.move_iter()` from the front.
             for i in range_step_inclusive(self.capacity as int - 1, 0, -1) {
                 // Check if the size is 0, so we don't do a useless scan when
                 // dropping empty tables such as on resize.
-
                 if self.size == 0 { break }
 
                 match self.peek(i as uint) {
@@ -546,7 +564,7 @@ mod table {
                 }
             }
 
-            assert!(self.size == 0);
+            assert_eq!(self.size, 0);
 
             unsafe {
                 libc::free(self.hashes as *mut libc::c_void);
@@ -587,7 +605,7 @@ static INITIAL_LOAD_FACTOR: Fraction = (9, 10);
 //
 // > Why a load factor of 90%?
 //
-// In general, all the distances to inital buckets will converge on the mean.
+// In general, all the distances to initial buckets will converge on the mean.
 // At a load factor of α, the odds of finding the target bucket after k
 // probes is approximately 1-α^k. If we set this equal to 50% (since we converge
 // on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round
@@ -600,7 +618,7 @@ static INITIAL_LOAD_FACTOR: Fraction = (9, 10);
 // > Wait, what? Where did you get 1-α^k from?
 //
 // On the first probe, your odds of a collision with an existing element is α.
-// The odds of doing this twice in a row is approximatelly α^2. For three times,
+// The odds of doing this twice in a row is approximately α^2. For three times,
 // α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT
 // colliding after k tries is 1-α^k.
 //
@@ -637,19 +655,12 @@ static INITIAL_LOAD_FACTOR: Fraction = (9, 10);
 // This would definitely be an avenue worth exploring if people start complaining
 // about the size of rust executables.
 //
-// There's also two optimizations that have been omitted regarding how the
-// hashtable allocates. The first is that a hashtable which never has an element
-// inserted should not allocate. I'm suspicious of this one, because supporting
-// that internally gains no performance over just using an
-// `Option<HashMap<K, V>>`, and is significantly more complicated.
-//
-// The second omitted allocation optimization is that right now we allocate three
-// arrays to back the hashtable. This is wasteful. In theory, we only need one
-// array, and each of the three original arrays can just be slices of it. This
-// would reduce the pressure on the allocator, and will play much nicer with the
-// rest of the system. An initial implementation is commented out in
-// `table::RawTable::new`, but I'm not confident it works for all sane alignments,
-// especially if a type needs more alignment than `malloc` provides.
+// There's also an "optimization" that has been omitted regarding how the
+// hashtable allocates. The vector type has set the expectation that a hashtable
+// which never has an element inserted should not allocate. I'm suspicious of
+// implementing this for hashtables, because supporting it has no performance
+// benefit over using an `Option<HashMap<K, V>>`, and is significantly more
+// complicated.
 
 /// A hash map implementation which uses linear probing with Robin
 /// Hood bucket stealing.
@@ -681,7 +692,7 @@ static INITIAL_LOAD_FACTOR: Fraction = (9, 10);
 /// let mut book_reviews = HashMap::new();
 ///
 /// // review some books.
-/// book_reviews.insert("Adventures of Hucklebury Fin",      "My favorite book.");
+/// book_reviews.insert("Adventures of Huckleberry Finn",    "My favorite book.");
 /// book_reviews.insert("Grimms' Fairy Tales",               "Masterpiece.");
 /// book_reviews.insert("Pride and Prejudice",               "Very enjoyable.");
 /// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
@@ -745,7 +756,7 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     // This exploits the power-of-two size of the hashtable. As long as this
     // is always true, we can use a bitmask of cap-1 to do modular arithmetic.
     //
-    // Prefer to use this with increasing values of `idx` rather than repeatedly
+    // Prefer using this with increasing values of `idx` rather than repeatedly
     // calling `probe_next`. This reduces data-dependencies between loops, which
     // can help the optimizer, and certainly won't hurt it. `probe_next` is
     // simply for convenience, and is no more efficient than `probe`.
@@ -756,7 +767,7 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         ((hash.inspect() as uint) + idx) & hash_mask
     }
 
-    // Generate the next probe in a sequence. Prefer to use 'probe' by itself,
+    // Generate the next probe in a sequence. Prefer using 'probe' by itself,
     // but this can sometimes be useful.
     fn probe_next(&self, probe: uint) -> uint {
         let hash_mask = self.table.capacity() - 1;
@@ -771,7 +782,7 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// from its 'ideal' location.
     ///
     /// In the cited blog posts above, this is called the "distance to
-    /// inital bucket", or DIB.
+    /// initial bucket", or DIB.
     fn bucket_distance(&self, index_of_elem: &table::FullIndex) -> uint {
         // where the hash of the element that happens to reside at
         // `index_of_elem` tried to place itself first.
@@ -804,7 +815,7 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
             if self.bucket_distance(&idx) < num_probes { return None }
 
             // If the hash doesn't match, it can't be this one..
-            if hash != &idx.hash() { continue }
+            if *hash != idx.hash() { continue }
 
             let (k, _) = self.table.read(&idx);
 
@@ -1087,7 +1098,7 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     ///   2) Ensure new_capacity is a power of two.
     fn resize(&mut self, new_capacity: uint) {
         assert!(self.table.size() <= new_capacity);
-        assert!((new_capacity - 1) & new_capacity == 0);
+        assert!(num::is_power_of_two(new_capacity));
 
         self.grow_at = grow_at(new_capacity, self.load_factor);
 
@@ -1095,7 +1106,7 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         let old_size  = old_table.size();
 
         for (h, k, v) in old_table.move_iter() {
-            self.manual_insert_hashed_nocheck(h, k, v);
+            self.insert_hashed_nocheck(h, k, v);
         }
 
         assert_eq!(self.table.size(), old_size);
@@ -1171,13 +1182,13 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         }
     }
 
-    /// Manually insert a pre-hashed key-value pair, without first checking
+    /// Insert a pre-hashed key-value pair, without first checking
     /// that there's enough room in the buckets. Returns a reference to the
     /// newly insert value.
     ///
     /// If the key already exists, the hashtable will be returned untouched
     /// and a reference to the existing element will be returned.
-    fn manual_insert_hashed_nocheck<'a>(
+    fn insert_hashed_nocheck<'a>(
         &'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
 
         for dib in range_inclusive(0u, self.table.size()) {
@@ -1226,28 +1237,25 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
         fail!("Internal HashMap error: Out of space.");
     }
 
-    fn manual_insert_hashed<'a>(&'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
+    /// Inserts an element which has already been hashed, returning a reference
+    /// to that element inside the hashtable. This is more efficient that using
+    /// `insert`, since the key will not be rehashed.
+    fn insert_hashed<'a>(&'a mut self, hash: table::SafeHash, k: K, v: V) -> &'a mut V {
         let potential_new_size = self.table.size() + 1;
         self.make_some_room(potential_new_size);
-        self.manual_insert_hashed_nocheck(hash, k, v)
-    }
-
-    /// Inserts an element, returning a reference to that element inside the
-    /// hashtable.
-    fn manual_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
-        let hash = self.make_hash(&k);
-        self.manual_insert_hashed(hash, k, v)
+        self.insert_hashed_nocheck(hash, k, v)
     }
 
     /// Return the value corresponding to the key in the map, or insert
     /// and return the value if it doesn't exist.
     pub fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a mut V {
-        match self.search(&k) {
+        let hash = self.make_hash(&k);
+        match self.search_hashed(&hash, &k) {
             Some(idx) => {
                 let (_, v_ref) = self.table.read_mut(&idx);
                 v_ref
             },
-            None => self.manual_insert(k, v)
+            None => self.insert_hashed(hash, k, v)
         }
     }
 
@@ -1255,14 +1263,15 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// insert, and return a new value if it doesn't exist.
     pub fn find_or_insert_with<'a>(&'a mut self, k: K, f: |&K| -> V)
                                -> &'a mut V {
-        match self.search(&k) {
+        let hash = self.make_hash(&k);
+        match self.search_hashed(&hash, &k) {
             Some(idx) => {
                 let (_, v_ref) = self.table.read_mut(&idx);
                 v_ref
             },
-            None      => {
+            None => {
                 let v = f(&k);
-                self.manual_insert(k, v)
+                self.insert_hashed(hash, k, v)
             }
         }
     }
@@ -1276,8 +1285,9 @@ impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
                                  v: V,
                                  f: |&K, &mut V|)
                                  -> &'a mut V {
-        match self.search(&k) {
-            None      => self.manual_insert(k, v),
+        let hash = self.make_hash(&k);
+        match self.search_hashed(&hash, &k) {
+            None      => self.insert_hashed(hash, k, v),
             Some(idx) => {
                 let (_, v_ref) = self.table.read_mut(&idx);
                 f(&k, v_ref);
@@ -1369,7 +1379,8 @@ impl<K: TotalEq + Hash<S>, V: Eq, S, H: Hasher<S>> Eq for HashMap<K, V, H> {
     fn eq(&self, other: &HashMap<K, V, H>) -> bool {
         if self.len() != other.len() { return false; }
 
-        self.iter().all(|(key, value)| {
+        self.iter()
+          .all(|(key, value)| {
             match other.find(key) {
                 None    => false,
                 Some(v) => *value == *v
@@ -1393,7 +1404,7 @@ impl<K: TotalEq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K,
 
 impl<K: TotalEq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
     fn default() -> HashMap<K, V, H> {
-        HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, Default::default())
+        HashMap::with_hasher(Default::default())
     }
 }
 
@@ -1449,13 +1460,10 @@ pub struct HashSet<T, H = sip::SipHasher> {
 }
 
 impl<T: TotalEq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {
-    // FIXME #11998: Since the value is a (), and `find` returns a Some(&()),
-    // we trigger #11998 when matching on it. I've fallen back to manual
-    // iteration until this is fixed.
     fn eq(&self, other: &HashSet<T, H>) -> bool {
         if self.len() != other.len() { return false; }
 
-        self.iter().all(|key| other.map.contains_key(key))
+        self.iter().all(|key| other.contains(key))
     }
 }
 
@@ -1468,7 +1476,7 @@ impl<T: TotalEq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
 }
 
 impl<T: TotalEq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
-    fn contains(&self, value: &T) -> bool { self.map.search(value).is_some() }
+    fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
 
     fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
         self.iter().all(|v| !other.contains(v))
@@ -1540,8 +1548,7 @@ impl<T: TotalEq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
 
     /// Visit the values representing the difference
     pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a, T, H> {
-        Repeat::new(other)
-            .zip(self.iter())
+        Repeat::new(other).zip(self.iter())
             .filter_map(|(other, elt)| {
                 if !other.contains(elt) { Some(elt) } else { None }
             })
@@ -1556,8 +1563,7 @@ impl<T: TotalEq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// Visit the values representing the intersection
     pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
         -> SetAlgebraItems<'a, T, H> {
-        Repeat::new(other)
-            .zip(self.iter())
+        Repeat::new(other).zip(self.iter())
             .filter_map(|(other, elt)| {
                 if other.contains(elt) { Some(elt) } else { None }
             })
@@ -1568,7 +1574,6 @@ impl<T: TotalEq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
         -> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
         self.iter().chain(other.difference(self))
     }
-
 }
 
 impl<T: TotalEq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
@@ -1953,7 +1958,7 @@ mod test_map {
         m.insert(1, 2);
         match m.find(&1) {
             None => fail!(),
-            Some(v) => assert!(*v == 2)
+            Some(v) => assert_eq!(*v, 2)
         }
     }
 
@@ -2020,6 +2025,32 @@ mod test_map {
             assert_eq!(map.find(&k), Some(&v));
         }
     }
+
+    #[test]
+    fn test_size_hint() {
+        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+        let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+        let mut iter = map.iter();
+
+        for _ in iter.by_ref().take(3) {}
+
+        assert_eq!(iter.size_hint(), (3, Some(3)));
+    }
+
+    #[test]
+    fn test_mut_size_hint() {
+        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+        let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+        let mut iter = map.mut_iter();
+
+        for _ in iter.by_ref().take(3) {}
+
+        assert_eq!(iter.size_hint(), (3, Some(3)));
+    }
 }
 
 #[cfg(test)]
@@ -2271,6 +2302,27 @@ mod bench {
     use std::iter::{range_inclusive};
 
     #[bench]
+    fn new_drop(b : &mut Bencher) {
+        use super::HashMap;
+
+        b.iter(|| {
+            let m : HashMap<int, int> = HashMap::new();
+            assert_eq!(m.len(), 0);
+        })
+    }
+
+    #[bench]
+    fn new_insert_drop(b : &mut Bencher) {
+        use super::HashMap;
+
+        b.iter(|| {
+            let mut m = HashMap::new();
+            m.insert(0, 0);
+            assert_eq!(m.len(), 1);
+        })
+    }
+
+    #[bench]
     fn insert(b: &mut Bencher) {
         use super::HashMap;
 
@@ -2299,7 +2351,9 @@ mod bench {
         }
 
         b.iter(|| {
-            m.contains_key(&412);
+            for i in range_inclusive(1, 1000) {
+                m.contains_key(&i);
+            }
         });
     }
 
@@ -2314,7 +2368,9 @@ mod bench {
         }
 
         b.iter(|| {
-            m.contains_key(&2048);
+            for i in range_inclusive(1001, 2000) {
+                m.contains_key(&i);
+            }
         });
     }
 
diff --git a/src/libcollections/lru_cache.rs b/src/libcollections/lru_cache.rs
index fc95ba6d95a..097513c6c57 100644
--- a/src/libcollections/lru_cache.rs
+++ b/src/libcollections/lru_cache.rs
@@ -41,6 +41,7 @@ use std::cast;
 use std::container::Container;
 use std::hash::Hash;
 use std::fmt;
+use std::mem;
 use std::ptr;
 
 use HashMap;
@@ -48,10 +49,10 @@ use HashMap;
 struct KeyRef<K> { k: *K }
 
 struct LruEntry<K, V> {
-    key: Option<K>,
-    value: Option<V>,
     next: *mut LruEntry<K, V>,
     prev: *mut LruEntry<K, V>,
+    key: K,
+    value: V,
 }
 
 /// An LRU Cache.
@@ -59,7 +60,6 @@ pub struct LruCache<K, V> {
     map: HashMap<KeyRef<K>, ~LruEntry<K, V>>,
     max_size: uint,
     head: *mut LruEntry<K, V>,
-    tail: *mut LruEntry<K, V>,
 }
 
 impl<S, K: Hash<S>> Hash<S> for KeyRef<K> {
@@ -77,19 +77,10 @@ impl<K: Eq> Eq for KeyRef<K> {
 impl<K: TotalEq> TotalEq for KeyRef<K> {}
 
 impl<K, V> LruEntry<K, V> {
-    fn new() -> LruEntry<K, V> {
+    fn new(k: K, v: V) -> LruEntry<K, V> {
         LruEntry {
-            key: None,
-            value: None,
-            next: ptr::mut_null(),
-            prev: ptr::mut_null(),
-        }
-    }
-
-    fn with_key_value(k: K, v: V) -> LruEntry<K, V> {
-        LruEntry {
-            key: Some(k),
-            value: Some(v),
+            key: k,
+            value: v,
             next: ptr::mut_null(),
             prev: ptr::mut_null(),
         }
@@ -102,41 +93,42 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
         let cache = LruCache {
             map: HashMap::new(),
             max_size: capacity,
-            head: unsafe{ cast::transmute(~LruEntry::<K, V>::new()) },
-            tail: unsafe{ cast::transmute(~LruEntry::<K, V>::new()) },
+            head: unsafe{ cast::transmute(~mem::uninit::<LruEntry<K, V>>()) },
         };
         unsafe {
-            (*cache.head).next = cache.tail;
-            (*cache.tail).prev = cache.head;
+            (*cache.head).next = cache.head;
+            (*cache.head).prev = cache.head;
         }
         return cache;
     }
 
     /// Put a key-value pair into cache.
     pub fn put(&mut self, k: K, v: V) {
-        let mut key_existed = false;
         let (node_ptr, node_opt) = match self.map.find_mut(&KeyRef{k: &k}) {
             Some(node) => {
-                key_existed = true;
-                node.value = Some(v);
+                node.value = v;
                 let node_ptr: *mut LruEntry<K, V> = &mut **node;
                 (node_ptr, None)
             }
             None => {
-                let mut node = ~LruEntry::with_key_value(k, v);
+                let mut node = ~LruEntry::new(k, v);
                 let node_ptr: *mut LruEntry<K, V> = &mut *node;
                 (node_ptr, Some(node))
             }
         };
-        if key_existed {
-            self.detach(node_ptr);
-            self.attach(node_ptr);
-        } else {
-            let keyref = unsafe { (*node_ptr).key.as_ref().unwrap() };
-            self.map.swap(KeyRef{k: keyref}, node_opt.unwrap());
-            self.attach(node_ptr);
-            if self.len() > self.capacity() {
-                self.remove_lru();
+        match node_opt {
+            None => {
+                // Existing node, just update LRU position
+                self.detach(node_ptr);
+                self.attach(node_ptr);
+            }
+            Some(node) => {
+                let keyref = unsafe { &(*node_ptr).key };
+                self.map.swap(KeyRef{k: keyref}, node);
+                self.attach(node_ptr);
+                if self.len() > self.capacity() {
+                    self.remove_lru();
+                }
             }
         }
     }
@@ -147,12 +139,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
             None => (None, None),
             Some(node) => {
                 let node_ptr: *mut LruEntry<K, V> = &mut **node;
-                unsafe {
-                    match (*node_ptr).value {
-                        None => (None, None),
-                        Some(ref value) => (Some(value), Some(node_ptr))
-                    }
-                }
+                (Some(unsafe { &(*node_ptr).value }), Some(node_ptr))
             }
         };
         match node_ptr_opt {
@@ -169,7 +156,7 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
     pub fn pop(&mut self, k: &K) -> Option<V> {
         match self.map.pop(&KeyRef{k: k}) {
             None => None,
-            Some(lru_entry) => lru_entry.value
+            Some(lru_entry) => Some(lru_entry.value)
         }
     }
 
@@ -190,14 +177,9 @@ impl<K: Hash + TotalEq, V> LruCache<K, V> {
     #[inline]
     fn remove_lru(&mut self) {
         if self.len() > 0 {
-            let lru = unsafe { (*self.tail).prev };
+            let lru = unsafe { (*self.head).prev };
             self.detach(lru);
-            unsafe {
-                match (*lru).key {
-                    None => (),
-                    Some(ref k) => { self.map.pop(&KeyRef{k: k}); }
-                }
-            }
+            self.map.pop(&KeyRef{k: unsafe { &(*lru).key }});
         }
     }
 
@@ -230,19 +212,11 @@ impl<A: fmt::Show + Hash + TotalEq, B: fmt::Show> fmt::Show for LruCache<A, B> {
             if i > 0 { try!(write!(f.buf, ", ")) }
             unsafe {
                 cur = (*cur).next;
-                match (*cur).key {
-                    // should never print nil
-                    None => try!(write!(f.buf, "nil")),
-                    Some(ref k) => try!(write!(f.buf, "{}", *k)),
-                }
+                try!(write!(f.buf, "{}", (*cur).key));
             }
             try!(write!(f.buf, ": "));
             unsafe {
-                match (*cur).value {
-                    // should never print nil
-                    None => try!(write!(f.buf, "nil")),
-                    Some(ref value) => try!(write!(f.buf, "{}", *value)),
-                }
+                try!(write!(f.buf, "{}", (*cur).value));
             }
         }
         write!(f.buf, r"\}")
@@ -267,8 +241,11 @@ impl<K: Hash + TotalEq, V> Mutable for LruCache<K, V> {
 impl<K, V> Drop for LruCache<K, V> {
     fn drop(&mut self) {
         unsafe {
-            let _: ~LruEntry<K, V> = cast::transmute(self.head);
-            let _: ~LruEntry<K, V> = cast::transmute(self.tail);
+            let node: ~LruEntry<K, V> = cast::transmute(self.head);
+            // Prevent compiler from trying to drop the un-initialized field in the sigil node.
+            let ~LruEntry { key: k, value: v, .. } = node;
+            cast::forget(k);
+            cast::forget(v);
         }
     }
 }
diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs
index 3db12b5a538..dc8e64ed86b 100644
--- a/src/libcollections/treemap.rs
+++ b/src/libcollections/treemap.rs
@@ -308,7 +308,7 @@ pub struct RevMutEntries<'a, K, V> {
 // (with many different `x`) below, so we need to optionally pass mut
 // as a tt, but the only thing we can do with a `tt` is pass them to
 // other macros, so this takes the `& <mutability> <operand>` token
-// sequence and forces their evalutation as an expression.
+// sequence and forces their evaluation as an expression.
 macro_rules! addr { ($e:expr) => { $e }}
 // putting an optional mut into type signatures
 macro_rules! item { ($i:item) => { $i }}
diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs
index e831b394b9c..e040bb0a9e5 100644
--- a/src/libcollections/trie.rs
+++ b/src/libcollections/trie.rs
@@ -141,7 +141,7 @@ impl<T> TrieMap<T> {
 // (with many different `x`) below, so we need to optionally pass mut
 // as a tt, but the only thing we can do with a `tt` is pass them to
 // other macros, so this takes the `& <mutability> <operand>` token
-// sequence and forces their evalutation as an expression. (see also
+// sequence and forces their evaluation as an expression. (see also
 // `item!` below.)
 macro_rules! addr { ($e:expr) => { $e } }
 
diff --git a/src/libgreen/basic.rs b/src/libgreen/basic.rs
index 2877768dd8b..3aa3d6742eb 100644
--- a/src/libgreen/basic.rs
+++ b/src/libgreen/basic.rs
@@ -243,7 +243,7 @@ mod test {
         })
     }
 
-    fn run(f: proc()) {
+    fn run(f: proc():Send) {
         let mut pool = pool();
         pool.spawn(TaskOpts::new(), f);
         pool.shutdown();
diff --git a/src/libgreen/context.rs b/src/libgreen/context.rs
index a521c9bee87..0a3d6a78034 100644
--- a/src/libgreen/context.rs
+++ b/src/libgreen/context.rs
@@ -46,7 +46,7 @@ impl Context {
     /// FIXME: this is basically an awful the interface. The main reason for
     ///        this is to reduce the number of allocations made when a green
     ///        task is spawned as much as possible
-    pub fn new(init: InitFn, arg: uint, start: proc(),
+    pub fn new(init: InitFn, arg: uint, start: proc():Send,
                stack: &mut Stack) -> Context {
 
         let sp: *uint = stack.end();
diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs
index dd897b9db4b..77715b1f5fb 100644
--- a/src/libgreen/lib.rs
+++ b/src/libgreen/lib.rs
@@ -289,7 +289,7 @@ macro_rules! green_start( ($f:ident) => (
 /// error.
 pub fn start(argc: int, argv: **u8,
              event_loop_factory: fn() -> ~rtio::EventLoop:Send,
-             main: proc()) -> int {
+             main: proc():Send) -> int {
     rt::init(argc, argv);
     let mut main = Some(main);
     let mut ret = None;
@@ -310,7 +310,7 @@ pub fn start(argc: int, argv: **u8,
 /// This function will not return until all schedulers in the associated pool
 /// have returned.
 pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop:Send,
-           main: proc()) -> int {
+           main: proc():Send) -> int {
     // Create a scheduler pool and spawn the main task into this pool. We will
     // get notified over a channel when the main task exits.
     let mut cfg = PoolConfig::new();
@@ -445,7 +445,7 @@ impl SchedPool {
     /// This is useful to create a task which can then be sent to a specific
     /// scheduler created by `spawn_sched` (and possibly pin it to that
     /// scheduler).
-    pub fn task(&mut self, opts: TaskOpts, f: proc()) -> ~GreenTask {
+    pub fn task(&mut self, opts: TaskOpts, f: proc():Send) -> ~GreenTask {
         GreenTask::configure(&mut self.stack_pool, opts, f)
     }
 
@@ -455,7 +455,7 @@ impl SchedPool {
     /// New tasks are spawned in a round-robin fashion to the schedulers in this
     /// pool, but tasks can certainly migrate among schedulers once they're in
     /// the pool.
-    pub fn spawn(&mut self, opts: TaskOpts, f: proc()) {
+    pub fn spawn(&mut self, opts: TaskOpts, f: proc():Send) {
         let task = self.task(opts, f);
 
         // Figure out someone to send this task to
diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs
index 922a5905faf..74872086b35 100644
--- a/src/libgreen/sched.rs
+++ b/src/libgreen/sched.rs
@@ -1027,7 +1027,7 @@ mod test {
         })
     }
 
-    fn run(f: proc()) {
+    fn run(f: proc():Send) {
         let mut pool = pool();
         pool.spawn(TaskOpts::new(), f);
         pool.shutdown();
diff --git a/src/libgreen/simple.rs b/src/libgreen/simple.rs
index 75a53b0bbd3..4f2f0c1addb 100644
--- a/src/libgreen/simple.rs
+++ b/src/libgreen/simple.rs
@@ -72,7 +72,7 @@ impl Runtime for SimpleTask {
     // feet and running.
     fn yield_now(~self, _cur_task: ~Task) { fail!() }
     fn maybe_yield(~self, _cur_task: ~Task) { fail!() }
-    fn spawn_sibling(~self, _cur_task: ~Task, _opts: TaskOpts, _f: proc()) {
+    fn spawn_sibling(~self, _cur_task: ~Task, _opts: TaskOpts, _f: proc():Send) {
         fail!()
     }
     fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs
index 534e9f8401e..150e2704c59 100644
--- a/src/libgreen/task.rs
+++ b/src/libgreen/task.rs
@@ -129,7 +129,7 @@ impl GreenTask {
     /// and will not have any contained Task structure.
     pub fn new(stack_pool: &mut StackPool,
                stack_size: Option<uint>,
-               start: proc()) -> ~GreenTask {
+               start: proc():Send) -> ~GreenTask {
         GreenTask::new_homed(stack_pool, stack_size, AnySched, start)
     }
 
@@ -137,7 +137,7 @@ impl GreenTask {
     pub fn new_homed(stack_pool: &mut StackPool,
                      stack_size: Option<uint>,
                      home: Home,
-                     start: proc()) -> ~GreenTask {
+                     start: proc():Send) -> ~GreenTask {
         // Allocate ourselves a GreenTask structure
         let mut ops = GreenTask::new_typed(None, TypeGreen(Some(home)));
 
@@ -175,7 +175,7 @@ impl GreenTask {
     /// new stack for this task.
     pub fn configure(pool: &mut StackPool,
                      opts: TaskOpts,
-                     f: proc()) -> ~GreenTask {
+                     f: proc():Send) -> ~GreenTask {
         let TaskOpts {
             notify_chan, name, stack_size,
             stderr, stdout,
@@ -443,7 +443,7 @@ impl Runtime for GreenTask {
         }
     }
 
-    fn spawn_sibling(mut ~self, cur_task: ~Task, opts: TaskOpts, f: proc()) {
+    fn spawn_sibling(mut ~self, cur_task: ~Task, opts: TaskOpts, f: proc():Send) {
         self.put_task(cur_task);
 
         // Spawns a task into the current scheduler. We allocate the new task's
@@ -490,7 +490,7 @@ mod tests {
     use super::super::{PoolConfig, SchedPool};
     use super::GreenTask;
 
-    fn spawn_opts(opts: TaskOpts, f: proc()) {
+    fn spawn_opts(opts: TaskOpts, f: proc():Send) {
         let mut pool = SchedPool::new(PoolConfig {
             threads: 1,
             event_loop_factory: ::rustuv::event_loop,
diff --git a/src/libnum/lib.rs b/src/libnum/lib.rs
index 986ba9e9a5c..e68c5f22728 100644
--- a/src/libnum/lib.rs
+++ b/src/libnum/lib.rs
@@ -171,7 +171,7 @@ macro_rules! impl_integer_for_int {
             /// `other`.
             #[inline]
             fn lcm(&self, other: &$T) -> $T {
-                // should not have to recaluculate abs
+                // should not have to recalculate abs
                 ((*self * *other) / self.gcd(other)).abs()
             }
 
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 9211827e6a6..9fd3894d794 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -1171,7 +1171,7 @@ fn link_args(sess: &Session,
         // actually creates "invalid" objects [1] [2], but only for some
         // introspection tools, not in terms of whether it can be loaded.
         //
-        // Long story shory, passing this flag forces the linker to *not*
+        // Long story short, passing this flag forces the linker to *not*
         // truncate section names (so we can find the metadata section after
         // it's compiled). The real kicker is that rust compiled just fine on
         // windows for quite a long time *without* this flag, so I have no idea
@@ -1491,7 +1491,7 @@ fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
 }
 
 // Link in all of our upstream crates' native dependencies. Remember that
-// all of these upstream native depenencies are all non-static
+// all of these upstream native dependencies are all non-static
 // dependencies. We've got two cases then:
 //
 // 1. The upstream crate is an rlib. In this case we *must* link in the
@@ -1509,7 +1509,7 @@ fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
 // be instantiated in the target crate, meaning that the native symbol must
 // also be resolved in the target crate.
 fn add_upstream_native_libraries(args: &mut Vec<~str>, sess: &Session) {
-    // Be sure to use a topological sorting of crates becuase there may be
+    // Be sure to use a topological sorting of crates because there may be
     // interdependencies between native libraries. When passing -nodefaultlibs,
     // for example, almost all native libraries depend on libc, so we have to
     // make sure that's all the way at the right (liblibc is near the base of
diff --git a/src/librustc/back/svh.rs b/src/librustc/back/svh.rs
index a2c579d13f4..633850f3718 100644
--- a/src/librustc/back/svh.rs
+++ b/src/librustc/back/svh.rs
@@ -20,7 +20,7 @@
 //! such.
 //!
 //! The core of this problem is when an upstream dependency changes and
-//! downstream dependants are not recompiled. This causes compile errors because
+//! downstream dependents are not recompiled. This causes compile errors because
 //! the upstream crate's metadata has changed but the downstream crates are
 //! still referencing the older crate's metadata.
 //!
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 7da9d6f82bc..cf0e7e161c1 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -299,7 +299,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         last_private_map: last_private_map
     } =
         time(time_passes, "resolution", (), |_|
-             middle::resolve::resolve_crate(&sess, lang_items, krate));
+             middle::resolve::resolve_crate(&sess, &lang_items, krate));
 
     // Discard MTWT tables that aren't required past resolution.
     syntax::ext::mtwt::clear_tables();
@@ -316,7 +316,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
                 sess.diagnostic(), krate)));
 
     let freevars = time(time_passes, "freevar finding", (), |_|
-                        freevars::annotate_freevars(def_map, krate));
+                        freevars::annotate_freevars(&def_map, krate));
 
     let region_map = time(time_passes, "region resolution", (), |_|
                           middle::region::resolve_crate(&sess, krate));
@@ -328,7 +328,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
                             freevars, region_map, lang_items);
 
     // passes are timed inside typeck
-    let (method_map, vtable_map) = typeck::check_crate(&ty_cx, trait_map, krate);
+    typeck::check_crate(&ty_cx, trait_map, krate);
 
     time(time_passes, "check static items", (), |_|
          middle::check_static::check_crate(&ty_cx, krate));
@@ -338,56 +338,52 @@ pub fn phase_3_run_analysis_passes(sess: Session,
          middle::const_eval::process_crate(krate, &ty_cx));
 
     time(time_passes, "const checking", (), |_|
-         middle::check_const::check_crate(krate, def_map, method_map, &ty_cx));
+         middle::check_const::check_crate(krate, &ty_cx));
 
     let maps = (external_exports, last_private_map);
     let (exported_items, public_items) =
             time(time_passes, "privacy checking", maps, |(a, b)|
-                 middle::privacy::check_crate(&ty_cx, &method_map, &exp_map2,
-                                              a, b, krate));
+                 middle::privacy::check_crate(&ty_cx, &exp_map2, a, b, krate));
 
     time(time_passes, "effect checking", (), |_|
-         middle::effect::check_crate(&ty_cx, method_map, krate));
+         middle::effect::check_crate(&ty_cx, krate));
 
     let middle::moves::MoveMaps {moves_map, moved_variables_set,
                                  capture_map} =
         time(time_passes, "compute moves", (), |_|
-             middle::moves::compute_moves(&ty_cx, method_map, krate));
+             middle::moves::compute_moves(&ty_cx, krate));
 
     time(time_passes, "match checking", (), |_|
-         middle::check_match::check_crate(&ty_cx, method_map,
-                                          &moves_map, krate));
+         middle::check_match::check_crate(&ty_cx, &moves_map, krate));
 
     time(time_passes, "liveness checking", (), |_|
-         middle::liveness::check_crate(&ty_cx, method_map,
-                                       &capture_map, krate));
+         middle::liveness::check_crate(&ty_cx, &capture_map, krate));
 
     let root_map =
         time(time_passes, "borrow checking", (), |_|
-             middle::borrowck::check_crate(&ty_cx, method_map,
-                                           &moves_map, &moved_variables_set,
+             middle::borrowck::check_crate(&ty_cx, &moves_map,
+                                           &moved_variables_set,
                                            &capture_map, krate));
 
     drop(moves_map);
     drop(moved_variables_set);
 
     time(time_passes, "kind checking", (), |_|
-         kind::check_crate(&ty_cx, method_map, krate));
+         kind::check_crate(&ty_cx, krate));
 
     let reachable_map =
         time(time_passes, "reachability checking", (), |_|
-             reachable::find_reachable(&ty_cx, method_map, &exported_items));
+             reachable::find_reachable(&ty_cx, &exported_items));
 
     time(time_passes, "death checking", (), |_| {
         middle::dead::check_crate(&ty_cx,
-                                  method_map,
                                   &exported_items,
                                   &reachable_map,
                                   krate)
     });
 
     time(time_passes, "lint checking", (), |_|
-         lint::check_crate(&ty_cx, method_map, &exported_items, krate));
+         lint::check_crate(&ty_cx, &exported_items, krate));
 
     CrateAnalysis {
         exp_map2: exp_map2,
@@ -396,8 +392,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
         public_items: public_items,
         maps: astencode::Maps {
             root_map: root_map,
-            method_map: method_map,
-            vtable_map: vtable_map,
             capture_map: RefCell::new(capture_map)
         },
         reachable: reachable_map
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 9e652536f6d..ba7c5054794 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1882,37 +1882,23 @@ impl TypeNames {
 
 /* Memory-managed interface to target data. */
 
-pub struct target_data_res {
-    pub td: TargetDataRef,
+pub struct TargetData {
+    pub lltd: TargetDataRef
 }
 
-impl Drop for target_data_res {
+impl Drop for TargetData {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeTargetData(self.td);
+            llvm::LLVMDisposeTargetData(self.lltd);
         }
     }
 }
 
-pub fn target_data_res(td: TargetDataRef) -> target_data_res {
-    target_data_res {
-        td: td
-    }
-}
-
-pub struct TargetData {
-    pub lltd: TargetDataRef,
-    dtor: @target_data_res
-}
-
 pub fn mk_target_data(string_rep: &str) -> TargetData {
-    let lltd = string_rep.with_c_str(|buf| {
-        unsafe { llvm::LLVMCreateTargetData(buf) }
-    });
-
     TargetData {
-        lltd: lltd,
-        dtor: @target_data_res(lltd)
+        lltd: string_rep.with_c_str(|buf| {
+            unsafe { llvm::LLVMCreateTargetData(buf) }
+        })
     }
 }
 
@@ -1949,35 +1935,22 @@ impl Drop for ObjectFile {
 
 /* Memory-managed interface to section iterators. */
 
-pub struct section_iter_res {
-    pub si: SectionIteratorRef,
+pub struct SectionIter {
+    pub llsi: SectionIteratorRef
 }
 
-impl Drop for section_iter_res {
+impl Drop for SectionIter {
     fn drop(&mut self) {
         unsafe {
-            llvm::LLVMDisposeSectionIterator(self.si);
+            llvm::LLVMDisposeSectionIterator(self.llsi);
         }
     }
 }
 
-pub fn section_iter_res(si: SectionIteratorRef) -> section_iter_res {
-    section_iter_res {
-        si: si
-    }
-}
-
-pub struct SectionIter {
-    pub llsi: SectionIteratorRef,
-    dtor: @section_iter_res
-}
-
 pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
     unsafe {
-        let llsi = llvm::LLVMGetSections(llof);
         SectionIter {
-            llsi: llsi,
-            dtor: @section_iter_res(llsi)
+            llsi: llvm::LLVMGetSections(llof)
         }
     }
 }
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index 799da4150c5..efbfce1b2bb 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -23,7 +23,6 @@ use metadata::loader;
 use metadata::loader::Os;
 use metadata::loader::CratePaths;
 
-use std::cell::RefCell;
 use std::rc::Rc;
 use collections::HashMap;
 use syntax::ast;
@@ -280,7 +279,7 @@ fn resolve_crate<'a>(e: &mut Env,
                      hash: Option<&Svh>,
                      should_link: bool,
                      span: Span)
-                     -> (ast::CrateNum, @cstore::crate_metadata,
+                     -> (ast::CrateNum, Rc<cstore::crate_metadata>,
                          cstore::CrateSource) {
     match existing_match(e, crate_id, hash) {
         None => {
@@ -317,7 +316,7 @@ fn resolve_crate<'a>(e: &mut Env,
             let cnum_map = if should_link {
                 resolve_crate_deps(e, root, metadata.as_slice(), span)
             } else {
-                @RefCell::new(HashMap::new())
+                HashMap::new()
             };
 
             // Claim this crate number and cache it if we're linking to the
@@ -331,13 +330,13 @@ fn resolve_crate<'a>(e: &mut Env,
                 -1
             };
 
-            let cmeta = @cstore::crate_metadata {
+            let cmeta = Rc::new(cstore::crate_metadata {
                 name: load_ctxt.crate_id.name.to_owned(),
                 data: metadata,
                 cnum_map: cnum_map,
                 cnum: cnum,
                 span: span,
-            };
+            });
 
             let source = cstore::CrateSource {
                 dylib: dylib,
@@ -346,7 +345,7 @@ fn resolve_crate<'a>(e: &mut Env,
             };
 
             if should_link {
-                e.sess.cstore.set_crate_data(cnum, cmeta);
+                e.sess.cstore.set_crate_data(cnum, cmeta.clone());
                 e.sess.cstore.add_used_crate_source(source.clone());
             }
             (cnum, cmeta, source)
@@ -365,10 +364,7 @@ fn resolve_crate_deps(e: &mut Env,
     debug!("resolving deps of external crate");
     // The map from crate numbers in the crate we're resolving to local crate
     // numbers
-    let mut cnum_map = HashMap::new();
-    let r = decoder::get_crate_deps(cdata);
-    for dep in r.iter() {
-        let extrn_cnum = dep.cnum;
+    decoder::get_crate_deps(cdata).iter().map(|dep| {
         debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
         let (local_cnum, _, _) = resolve_crate(e, root,
                                                dep.crate_id.name.as_slice(),
@@ -376,9 +372,8 @@ fn resolve_crate_deps(e: &mut Env,
                                                Some(&dep.hash),
                                                true,
                                                span);
-        cnum_map.insert(extrn_cnum, local_cnum);
-    }
-    return @RefCell::new(cnum_map);
+        (dep.cnum, local_cnum)
+    }).collect()
 }
 
 pub struct Loader<'a> {
@@ -407,8 +402,8 @@ impl<'a> CrateLoader for Loader<'a> {
                                                info.ident, &info.crate_id,
                                                None, info.should_link,
                                                krate.span);
-        let macros = decoder::get_exported_macros(data);
-        let registrar = decoder::get_macro_registrar_fn(data).map(|id| {
+        let macros = decoder::get_exported_macros(&*data);
+        let registrar = decoder::get_macro_registrar_fn(&*data).map(|id| {
             decoder::get_symbol(data.data.as_slice(), id)
         });
         MacroCrate {
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index f02f9c61582..4ebf4a52e41 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -33,8 +33,8 @@ pub struct StaticMethodInfo {
 }
 
 pub fn get_symbol(cstore: &cstore::CStore, def: ast::DefId) -> ~str {
-    let cdata = cstore.get_crate_data(def.krate).data();
-    return decoder::get_symbol(cdata, def.node);
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::get_symbol(cdata.data(), def.node)
 }
 
 /// Iterates over all the language items in the given crate.
@@ -43,7 +43,7 @@ pub fn each_lang_item(cstore: &cstore::CStore,
                       f: |ast::NodeId, uint| -> bool)
                       -> bool {
     let crate_data = cstore.get_crate_data(cnum);
-    decoder::each_lang_item(crate_data, f)
+    decoder::each_lang_item(&*crate_data, f)
 }
 
 /// Iterates over each child of the given item.
@@ -57,7 +57,7 @@ pub fn each_child_of_item(cstore: &cstore::CStore,
         cstore.get_crate_data(cnum)
     };
     decoder::each_child_of_item(cstore.intr.clone(),
-                                crate_data,
+                                &*crate_data,
                                 def_id.node,
                                 get_crate_data,
                                 callback)
@@ -74,7 +74,7 @@ pub fn each_top_level_item_of_crate(cstore: &cstore::CStore,
         cstore.get_crate_data(cnum)
     };
     decoder::each_top_level_item_of_crate(cstore.intr.clone(),
-                                          crate_data,
+                                          &*crate_data,
                                           get_crate_data,
                                           callback)
 }
@@ -82,7 +82,7 @@ pub fn each_top_level_item_of_crate(cstore: &cstore::CStore,
 pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    let path = decoder::get_item_path(cdata, def.node);
+    let path = decoder::get_item_path(&*cdata, def.node);
 
     // FIXME #1920: This path is not always correct if the crate is not linked
     // into the root namespace.
@@ -103,26 +103,26 @@ pub fn maybe_get_item_ast(tcx: &ty::ctxt, def: ast::DefId,
                        -> found_ast {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::maybe_get_item_ast(cdata, tcx, def.node, decode_inlined_item)
+    decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
 }
 
 pub fn get_enum_variants(tcx: &ty::ctxt, def: ast::DefId)
-                      -> Vec<@ty::VariantInfo> {
+                      -> Vec<Rc<ty::VariantInfo>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    return decoder::get_enum_variants(cstore.intr.clone(), cdata, def.node, tcx)
+    decoder::get_enum_variants(cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
 /// Returns information about the given implementation.
-pub fn get_impl(tcx: &ty::ctxt, impl_def_id: ast::DefId)
-                -> ty::Impl {
-    let cdata = tcx.sess.cstore.get_crate_data(impl_def_id.krate);
-    decoder::get_impl(tcx.sess.cstore.intr.clone(), cdata, impl_def_id.node, tcx)
+pub fn get_impl_methods(cstore: &cstore::CStore, impl_def_id: ast::DefId)
+                        -> Vec<ast::DefId> {
+    let cdata = cstore.get_crate_data(impl_def_id.krate);
+    decoder::get_impl_methods(&*cdata, impl_def_id.node)
 }
 
 pub fn get_method(tcx: &ty::ctxt, def: ast::DefId) -> ty::Method {
     let cdata = tcx.sess.cstore.get_crate_data(def.krate);
-    decoder::get_method(tcx.sess.cstore.intr.clone(), cdata, def.node, tcx)
+    decoder::get_method(tcx.sess.cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
 pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
@@ -130,60 +130,60 @@ pub fn get_method_name_and_explicit_self(cstore: &cstore::CStore,
                                      -> (ast::Ident, ast::ExplicitSelf_)
 {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_method_name_and_explicit_self(cstore.intr.clone(), cdata, def.node)
+    decoder::get_method_name_and_explicit_self(cstore.intr.clone(), &*cdata, def.node)
 }
 
 pub fn get_trait_method_def_ids(cstore: &cstore::CStore,
                                 def: ast::DefId) -> Vec<ast::DefId> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_method_def_ids(cdata, def.node)
+    decoder::get_trait_method_def_ids(&*cdata, def.node)
 }
 
 pub fn get_item_variances(cstore: &cstore::CStore,
                           def: ast::DefId) -> ty::ItemVariances {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_item_variances(cdata, def.node)
+    decoder::get_item_variances(&*cdata, def.node)
 }
 
 pub fn get_provided_trait_methods(tcx: &ty::ctxt,
                                   def: ast::DefId)
-                               -> Vec<@ty::Method> {
+                               -> Vec<Rc<ty::Method>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_provided_trait_methods(cstore.intr.clone(), cdata, def.node, tcx)
+    decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
-pub fn get_supertraits(tcx: &ty::ctxt, def: ast::DefId) -> Vec<@ty::TraitRef> {
+pub fn get_supertraits(tcx: &ty::ctxt, def: ast::DefId) -> Vec<Rc<ty::TraitRef>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_supertraits(cdata, def.node, tcx)
+    decoder::get_supertraits(&*cdata, def.node, tcx)
 }
 
 pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: ast::DefId)
                           -> Option<ast::Ident> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type_name_if_impl(cdata, def.node)
+    decoder::get_type_name_if_impl(&*cdata, def.node)
 }
 
 pub fn get_static_methods_if_impl(cstore: &cstore::CStore,
                                   def: ast::DefId)
                                -> Option<Vec<StaticMethodInfo> > {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_static_methods_if_impl(cstore.intr.clone(), cdata, def.node)
+    decoder::get_static_methods_if_impl(cstore.intr.clone(), &*cdata, def.node)
 }
 
 pub fn get_item_attrs(cstore: &cstore::CStore,
                       def_id: ast::DefId,
                       f: |Vec<@ast::MetaItem> |) {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_item_attrs(cdata, def_id.node, f)
+    decoder::get_item_attrs(&*cdata, def_id.node, f)
 }
 
 pub fn get_struct_fields(cstore: &cstore::CStore,
                          def: ast::DefId)
                       -> Vec<ty::field_ty> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_struct_fields(cstore.intr.clone(), cdata, def.node)
+    decoder::get_struct_fields(cstore.intr.clone(), &*cdata, def.node)
 }
 
 pub fn get_type(tcx: &ty::ctxt,
@@ -191,13 +191,13 @@ pub fn get_type(tcx: &ty::ctxt,
              -> ty::ty_param_bounds_and_ty {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type(cdata, def.node, tcx)
+    decoder::get_type(&*cdata, def.node, tcx)
 }
 
 pub fn get_trait_def(tcx: &ty::ctxt, def: ast::DefId) -> ty::TraitDef {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_def(cdata, def.node, tcx)
+    decoder::get_trait_def(&*cdata, def.node, tcx)
 }
 
 pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
@@ -213,7 +213,7 @@ pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
         decoder::maybe_find_item(def.node, class_doc),
         || format!("get_field_type: in class {:?}, field ID {:?} not found",
                  class_id, def) );
-    let ty = decoder::item_type(def, the_field, tcx, cdata);
+    let ty = decoder::item_type(def, the_field, tcx, &*cdata);
     ty::ty_param_bounds_and_ty {
         generics: ty::Generics {type_param_defs: Rc::new(Vec::new()),
                                 region_param_defs: Rc::new(Vec::new())},
@@ -224,10 +224,10 @@ pub fn get_field_type(tcx: &ty::ctxt, class_id: ast::DefId,
 // Given a def_id for an impl, return the trait it implements,
 // if there is one.
 pub fn get_impl_trait(tcx: &ty::ctxt,
-                      def: ast::DefId) -> Option<@ty::TraitRef> {
+                      def: ast::DefId) -> Option<Rc<ty::TraitRef>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_trait(cdata, def.node, tcx)
+    decoder::get_impl_trait(&*cdata, def.node, tcx)
 }
 
 // Given a def_id for an impl, return information about its vtables
@@ -235,35 +235,35 @@ pub fn get_impl_vtables(tcx: &ty::ctxt,
                         def: ast::DefId) -> typeck::impl_res {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_vtables(cdata, def.node, tcx)
+    decoder::get_impl_vtables(&*cdata, def.node, tcx)
 }
 
 pub fn get_native_libraries(cstore: &cstore::CStore,
                             crate_num: ast::CrateNum)
                                 -> Vec<(cstore::NativeLibaryKind, ~str)> {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::get_native_libraries(cdata)
+    decoder::get_native_libraries(&*cdata)
 }
 
 pub fn each_impl(cstore: &cstore::CStore,
                  crate_num: ast::CrateNum,
                  callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::each_impl(cdata, callback)
+    decoder::each_impl(&*cdata, callback)
 }
 
 pub fn each_implementation_for_type(cstore: &cstore::CStore,
                                     def_id: ast::DefId,
                                     callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::each_implementation_for_type(cdata, def_id.node, callback)
+    decoder::each_implementation_for_type(&*cdata, def_id.node, callback)
 }
 
 pub fn each_implementation_for_trait(cstore: &cstore::CStore,
                                      def_id: ast::DefId,
                                      callback: |ast::DefId|) {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::each_implementation_for_trait(cdata, def_id.node, callback)
+    decoder::each_implementation_for_trait(&*cdata, def_id.node, callback)
 }
 
 /// If the given def ID describes a method belonging to a trait (either a
@@ -274,21 +274,21 @@ pub fn get_trait_of_method(cstore: &cstore::CStore,
                            tcx: &ty::ctxt)
                            -> Option<ast::DefId> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_trait_of_method(cdata, def_id.node, tcx)
+    decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
 }
 
 pub fn get_macro_registrar_fn(cstore: &cstore::CStore,
                               crate_num: ast::CrateNum)
                               -> Option<ast::NodeId> {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::get_macro_registrar_fn(cdata)
+    decoder::get_macro_registrar_fn(&*cdata)
 }
 
 pub fn get_exported_macros(cstore: &cstore::CStore,
                            crate_num: ast::CrateNum)
                            -> Vec<~str> {
     let cdata = cstore.get_crate_data(crate_num);
-    decoder::get_exported_macros(cdata)
+    decoder::get_exported_macros(&*cdata)
 }
 
 pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
@@ -296,5 +296,5 @@ pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
     -> Option<ast::DefId>
 {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_tuple_struct_definition_if_ctor(cdata, def_id.node)
+    decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.node)
 }
diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs
index 2d46f92e88f..8e731a98dd7 100644
--- a/src/librustc/metadata/cstore.rs
+++ b/src/librustc/metadata/cstore.rs
@@ -30,7 +30,7 @@ use syntax::parse::token::IdentInterner;
 // local crate numbers (as generated during this session). Each external
 // crate may refer to types in other external crates, and each has their
 // own crate numbers.
-pub type cnum_map = @RefCell<HashMap<ast::CrateNum, ast::CrateNum>>;
+pub type cnum_map = HashMap<ast::CrateNum, ast::CrateNum>;
 
 pub enum MetadataBlob {
     MetadataVec(CVec<u8>),
@@ -68,7 +68,7 @@ pub struct CrateSource {
 }
 
 pub struct CStore {
-    metas: RefCell<HashMap<ast::CrateNum, @crate_metadata>>,
+    metas: RefCell<HashMap<ast::CrateNum, Rc<crate_metadata>>>,
     extern_mod_crate_map: RefCell<extern_mod_crate_map>,
     used_crate_sources: RefCell<Vec<CrateSource>>,
     used_libraries: RefCell<Vec<(~str, NativeLibaryKind)>>,
@@ -95,8 +95,8 @@ impl CStore {
         self.metas.borrow().len() as ast::CrateNum + 1
     }
 
-    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
-        *self.metas.borrow().get(&cnum)
+    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<crate_metadata> {
+        self.metas.borrow().get(&cnum).clone()
     }
 
     pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
@@ -104,13 +104,13 @@ impl CStore {
         decoder::get_crate_hash(cdata.data())
     }
 
-    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: @crate_metadata) {
+    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<crate_metadata>) {
         self.metas.borrow_mut().insert(cnum, data);
     }
 
-    pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) {
-        for (&k, &v) in self.metas.borrow().iter() {
-            i(k, v);
+    pub fn iter_crate_data(&self, i: |ast::CrateNum, &crate_metadata|) {
+        for (&k, v) in self.metas.borrow().iter() {
+            i(k, &**v);
         }
     }
 
@@ -155,7 +155,7 @@ impl CStore {
                  ordering: &mut Vec<ast::CrateNum>) {
             if ordering.as_slice().contains(&cnum) { return }
             let meta = cstore.get_crate_data(cnum);
-            for (_, &dep) in meta.cnum_map.borrow().iter() {
+            for (_, &dep) in meta.cnum_map.iter() {
                 visit(cstore, dep, ordering);
             }
             ordering.push(cnum);
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index b1cede8e410..37d9d3417c9 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -45,7 +45,7 @@ use syntax::ast;
 use syntax::codemap;
 use syntax::crateid::CrateId;
 
-pub type Cmd = @crate_metadata;
+pub type Cmd<'a> = &'a crate_metadata;
 
 // A function that takes a def_id relative to the crate being searched and
 // returns a def_id relative to the compilation environment, i.e. if we hit a
@@ -76,8 +76,6 @@ fn lookup_hash<'a>(d: ebml::Doc<'a>, eq_fn: |&[u8]| -> bool,
     ret
 }
 
-pub type GetCrateDataCb<'a> = |ast::CrateNum|: 'a -> Cmd;
-
 pub fn maybe_find_item<'a>(item_id: ast::NodeId,
                            items: ebml::Doc<'a>) -> Option<ebml::Doc<'a>> {
     fn eq_item(bytes: &[u8], item_id: ast::NodeId) -> bool {
@@ -388,7 +386,7 @@ pub fn get_trait_def(cdata: Cmd,
         generics: ty::Generics {type_param_defs: tp_defs,
                                 region_param_defs: rp_defs},
         bounds: bounds,
-        trait_ref: @item_trait_ref(item_doc, tcx, cdata)
+        trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
     }
 }
 
@@ -412,11 +410,11 @@ pub fn get_type(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
 
 pub fn get_impl_trait(cdata: Cmd,
                       id: ast::NodeId,
-                      tcx: &ty::ctxt) -> Option<@ty::TraitRef>
+                      tcx: &ty::ctxt) -> Option<Rc<ty::TraitRef>>
 {
     let item_doc = lookup_item(id, cdata.data());
     reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
-        @doc_trait_ref(tp, tcx, cdata)
+        Rc::new(doc_trait_ref(tp, tcx, cdata))
     })
 }
 
@@ -462,6 +460,8 @@ pub fn each_lang_item(cdata: Cmd, f: |ast::NodeId, uint| -> bool) -> bool {
     })
 }
 
+pub type GetCrateDataCb<'a> = |ast::CrateNum|: 'a -> Rc<crate_metadata>;
+
 fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
                                cdata: Cmd,
                                item_doc: ebml::Doc,
@@ -477,12 +477,17 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
 
         // This item may be in yet another crate if it was the child of a
         // reexport.
-        let other_crates_items = if child_def_id.krate == cdata.cnum {
-            reader::get_doc(reader::Doc(cdata.data()), tag_items)
+        let crate_data = if child_def_id.krate == cdata.cnum {
+            None
         } else {
-            let crate_data = get_crate_data(child_def_id.krate);
-            reader::get_doc(reader::Doc(crate_data.data()), tag_items)
+            Some(get_crate_data(child_def_id.krate))
         };
+        let crate_data = match crate_data {
+            Some(ref cdata) => &**cdata,
+            None => cdata
+        };
+
+        let other_crates_items = reader::get_doc(reader::Doc(crate_data.data()), tag_items);
 
         // Get the item.
         match maybe_find_item(child_def_id.node, other_crates_items) {
@@ -565,12 +570,17 @@ fn each_child_of_item_or_crate(intr: Rc<IdentInterner>,
         let name = name_doc.as_str_slice();
 
         // This reexport may be in yet another crate.
-        let other_crates_items = if child_def_id.krate == cdata.cnum {
-            reader::get_doc(reader::Doc(cdata.data()), tag_items)
+        let crate_data = if child_def_id.krate == cdata.cnum {
+            None
         } else {
-            let crate_data = get_crate_data(child_def_id.krate);
-            reader::get_doc(reader::Doc(crate_data.data()), tag_items)
+            Some(get_crate_data(child_def_id.krate))
         };
+        let crate_data = match crate_data {
+            Some(ref cdata) => &**cdata,
+            None => cdata
+        };
+
+        let other_crates_items = reader::get_doc(reader::Doc(crate_data.data()), tag_items);
 
         // Get the item.
         match maybe_find_item(child_def_id.node, other_crates_items) {
@@ -634,7 +644,7 @@ pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<ast_map::PathElem> {
     item_path(lookup_item(id, cdata.data()))
 }
 
-pub type DecodeInlinedItem<'a> = |cdata: @cstore::crate_metadata,
+pub type DecodeInlinedItem<'a> = |cdata: Cmd,
                                   tcx: &ty::ctxt,
                                   path: Vec<ast_map::PathElem>,
                                   par_doc: ebml::Doc|: 'a
@@ -665,27 +675,27 @@ pub fn maybe_get_item_ast(cdata: Cmd, tcx: &ty::ctxt, id: ast::NodeId,
 }
 
 pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
-                     tcx: &ty::ctxt) -> Vec<@ty::VariantInfo> {
+                     tcx: &ty::ctxt) -> Vec<Rc<ty::VariantInfo>> {
     let data = cdata.data();
     let items = reader::get_doc(reader::Doc(data), tag_items);
     let item = find_item(id, items);
-    let mut infos: Vec<@ty::VariantInfo> = Vec::new();
-    let variant_ids = enum_variant_ids(item, cdata);
     let mut disr_val = 0;
-    for did in variant_ids.iter() {
+    enum_variant_ids(item, cdata).iter().map(|did| {
         let item = find_item(did.node, items);
         let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id},
                                 item, tcx, cdata);
         let name = item_name(&*intr, item);
         let arg_tys = match ty::get(ctor_ty).sty {
-          ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
-          _ => Vec::new(), // Nullary enum variant.
+            ty::ty_bare_fn(ref f) => f.sig.inputs.clone(),
+            _ => Vec::new(), // Nullary enum variant.
         };
         match variant_disr_val(item) {
-          Some(val) => { disr_val = val; }
-          _         => { /* empty */ }
+            Some(val) => { disr_val = val; }
+            _         => { /* empty */ }
         }
-        infos.push(@ty::VariantInfo{
+        let old_disr_val = disr_val;
+        disr_val += 1;
+        Rc::new(ty::VariantInfo {
             args: arg_tys,
             arg_names: None,
             ctor_ty: ctor_ty,
@@ -693,11 +703,10 @@ pub fn get_enum_variants(intr: Rc<IdentInterner>, cdata: Cmd, id: ast::NodeId,
             // I'm not even sure if we encode visibility
             // for variants -- TEST -- tjc
             id: *did,
-            disr_val: disr_val,
-            vis: ast::Inherited});
-        disr_val += 1;
-    }
-    return infos;
+            disr_val: old_disr_val,
+            vis: ast::Inherited
+        })
+    }).collect()
 }
 
 fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
@@ -723,32 +732,17 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ {
     }
 }
 
-fn item_impl_methods(intr: Rc<IdentInterner>, cdata: Cmd, item: ebml::Doc,
-                     tcx: &ty::ctxt) -> Vec<@ty::Method> {
-    let mut rslt = Vec::new();
-    reader::tagged_docs(item, tag_item_impl_method, |doc| {
+/// Returns information about the given implementation.
+pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec<ast::DefId> {
+    let mut methods = Vec::new();
+    reader::tagged_docs(lookup_item(impl_id, cdata.data()),
+                        tag_item_impl_method, |doc| {
         let m_did = reader::with_doc_data(doc, parse_def_id);
-        rslt.push(@get_method(intr.clone(), cdata, m_did.node, tcx));
+        methods.push(translate_def_id(cdata, m_did));
         true
     });
 
-    rslt
-}
-
-/// Returns information about the given implementation.
-pub fn get_impl(intr: Rc<IdentInterner>, cdata: Cmd, impl_id: ast::NodeId,
-               tcx: &ty::ctxt)
-                -> ty::Impl {
-    let data = cdata.data();
-    let impl_item = lookup_item(impl_id, data);
-    ty::Impl {
-        did: ast::DefId {
-            krate: cdata.cnum,
-            node: impl_id,
-        },
-        ident: item_name(&*intr, impl_item),
-        methods: item_impl_methods(intr, cdata, impl_item, tcx),
-    }
+    methods
 }
 
 pub fn get_method_name_and_explicit_self(
@@ -821,8 +815,8 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
 }
 
 pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
-                                  id: ast::NodeId, tcx: &ty::ctxt) ->
-        Vec<@ty::Method> {
+                                  id: ast::NodeId, tcx: &ty::ctxt)
+                                  -> Vec<Rc<ty::Method>> {
     let data = cdata.data();
     let item = lookup_item(id, data);
     let mut result = Vec::new();
@@ -832,7 +826,7 @@ pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
         let mth = lookup_item(did.node, data);
 
         if item_method_sort(mth) == 'p' {
-            result.push(@get_method(intr.clone(), cdata, did.node, tcx));
+            result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx)));
         }
         true
     });
@@ -842,7 +836,7 @@ pub fn get_provided_trait_methods(intr: Rc<IdentInterner>, cdata: Cmd,
 
 /// Returns the supertraits of the given trait.
 pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
-                    -> Vec<@ty::TraitRef> {
+                    -> Vec<Rc<ty::TraitRef>> {
     let mut results = Vec::new();
     let item_doc = lookup_item(id, cdata.data());
     reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| {
@@ -851,7 +845,7 @@ pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
         // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place.
         let trait_ref = doc_trait_ref(trait_doc, tcx, cdata);
         if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() {
-            results.push(@trait_ref);
+            results.push(Rc::new(trait_ref));
         }
         true
     });
@@ -1155,7 +1149,7 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId {
         return ast::DefId { krate: cdata.cnum, node: did.node };
     }
 
-    match cdata.cnum_map.borrow().find(&did.krate) {
+    match cdata.cnum_map.find(&did.krate) {
         Some(&n) => {
             ast::DefId {
                 krate: n,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index f4c3f564068..848fd8d362e 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -27,7 +27,7 @@ use util::nodemap::{NodeMap, NodeSet};
 
 use serialize::Encodable;
 use std::cast;
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
 use std::hash;
 use std::hash::Hash;
 use std::io::MemWriter;
@@ -52,9 +52,6 @@ use syntax::visit;
 use syntax;
 use writer = serialize::ebml::writer;
 
-// used by astencode:
-pub type abbrev_map = @RefCell<HashMap<ty::t, tyencode::ty_abbrev>>;
-
 /// A borrowed version of ast::InlinedItem.
 pub enum InlinedItemRef<'a> {
     IIItemRef(&'a ast::Item),
@@ -71,7 +68,7 @@ pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
 pub struct EncodeParams<'a> {
     pub diag: &'a SpanHandler,
     pub tcx: &'a ty::ctxt,
-    pub reexports2: middle::resolve::ExportMap2,
+    pub reexports2: &'a middle::resolve::ExportMap2,
     pub item_symbols: &'a RefCell<NodeMap<~str>>,
     pub non_inlineable_statics: &'a RefCell<NodeSet>,
     pub link_meta: &'a LinkMeta,
@@ -79,33 +76,16 @@ pub struct EncodeParams<'a> {
     pub encode_inlined_item: EncodeInlinedItem<'a>,
 }
 
-pub struct Stats {
-    inline_bytes: Cell<u64>,
-    attr_bytes: Cell<u64>,
-    dep_bytes: Cell<u64>,
-    lang_item_bytes: Cell<u64>,
-    native_lib_bytes: Cell<u64>,
-    macro_registrar_fn_bytes: Cell<u64>,
-    macro_defs_bytes: Cell<u64>,
-    impl_bytes: Cell<u64>,
-    misc_bytes: Cell<u64>,
-    item_bytes: Cell<u64>,
-    index_bytes: Cell<u64>,
-    zero_bytes: Cell<u64>,
-    total_bytes: Cell<u64>,
-}
-
 pub struct EncodeContext<'a> {
     pub diag: &'a SpanHandler,
     pub tcx: &'a ty::ctxt,
-    pub stats: @Stats,
-    pub reexports2: middle::resolve::ExportMap2,
+    pub reexports2: &'a middle::resolve::ExportMap2,
     pub item_symbols: &'a RefCell<NodeMap<~str>>,
     pub non_inlineable_statics: &'a RefCell<NodeSet>,
     pub link_meta: &'a LinkMeta,
     pub cstore: &'a cstore::CStore,
     pub encode_inlined_item: EncodeInlinedItem<'a>,
-    pub type_abbrevs: abbrev_map,
+    pub type_abbrevs: tyencode::abbrev_map,
 }
 
 fn encode_name(ebml_w: &mut Encoder, name: Name) {
@@ -134,7 +114,7 @@ fn encode_trait_ref(ebml_w: &mut Encoder,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
 
     ebml_w.start_tag(tag);
@@ -146,8 +126,8 @@ fn encode_impl_vtables(ebml_w: &mut Encoder,
                        ecx: &EncodeContext,
                        vtables: &typeck::impl_res) {
     ebml_w.start_tag(tag_item_impl_vtables);
-    astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
-    astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
+    astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
+    astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
     ebml_w.end_tag();
 }
 
@@ -170,7 +150,7 @@ fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
     for param in params.iter() {
         ebml_w.start_tag(tag);
@@ -227,7 +207,7 @@ pub fn write_type(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
     tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
 }
@@ -249,7 +229,7 @@ fn encode_method_fty(ecx: &EncodeContext,
         diag: ecx.diag,
         ds: def_to_str,
         tcx: ecx.tcx,
-        abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
+        abbrevs: &ecx.type_abbrevs
     };
     tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
 
@@ -290,7 +270,7 @@ fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
 }
 
 fn encode_struct_fields(ebml_w: &mut Encoder,
-                        fields: &Vec<ty::field_ty>,
+                        fields: &[ty::field_ty],
                         origin: DefId) {
     for f in fields.iter() {
         if f.name == special_idents::unnamed_field.name {
@@ -313,7 +293,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             ebml_w: &mut Encoder,
                             id: NodeId,
                             variants: &[P<Variant>],
-                            index: @RefCell<Vec<entry<i64>> >,
+                            index: &mut Vec<entry<i64>>,
                             generics: &ast::Generics) {
     debug!("encode_enum_variant_info(id={:?})", id);
 
@@ -323,7 +303,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                                ast::DefId { krate: LOCAL_CRATE, node: id });
     for variant in variants.iter() {
         let def_id = local_def(variant.node.id);
-        index.borrow_mut().push(entry {
+        index.push(entry {
             val: variant.node.id as i64,
             pos: ebml_w.writer.tell().unwrap(),
         });
@@ -347,11 +327,10 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
                 let idx = encode_info_for_struct(ecx,
                                                  ebml_w,
-                                                 &fields,
+                                                 fields.as_slice(),
                                                  index);
-                encode_struct_fields(ebml_w, &fields, def_id);
-                let bkts = create_index(idx);
-                encode_index(ebml_w, bkts, write_i64);
+                encode_struct_fields(ebml_w, fields.as_slice(), def_id);
+                encode_index(ebml_w, idx, write_i64);
             }
         }
         if vi.get(i).disr_val != disr_val {
@@ -402,10 +381,12 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
                                          ebml_w: &mut Encoder,
                                          exp: &middle::resolve::Export2)
                                          -> bool {
+    let impl_methods = ecx.tcx.impl_methods.borrow();
     match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
         Some(implementations) => {
-            for &base_impl in implementations.borrow().iter() {
-                for &m in base_impl.methods.iter() {
+            for base_impl_did in implementations.borrow().iter() {
+                for &method_did in impl_methods.get(base_impl_did).iter() {
+                    let m = ty::method(ecx.tcx, method_did);
                     if m.explicit_self == ast::SelfStatic {
                         encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
                     }
@@ -424,7 +405,7 @@ fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
                                           -> bool {
     match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
         Some(methods) => {
-            for &m in methods.iter() {
+            for m in methods.iter() {
                 if m.explicit_self == ast::SelfStatic {
                     encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
                 }
@@ -666,8 +647,8 @@ fn encode_provided_source(ebml_w: &mut Encoder,
 /* Returns an index of items in this class */
 fn encode_info_for_struct(ecx: &EncodeContext,
                           ebml_w: &mut Encoder,
-                          fields: &Vec<ty::field_ty>,
-                          global_index: @RefCell<Vec<entry<i64>> >)
+                          fields: &[ty::field_ty],
+                          global_index: &mut Vec<entry<i64>>)
                           -> Vec<entry<i64>> {
     /* Each class has its own index, since different classes
        may have fields with the same name */
@@ -680,7 +661,7 @@ fn encode_info_for_struct(ecx: &EncodeContext,
         let id = field.id.node;
 
         index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
-        global_index.borrow_mut().push(entry {
+        global_index.push(entry {
             val: id as i64,
             pos: ebml_w.writer.tell().unwrap(),
         });
@@ -700,9 +681,9 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
                                ebml_w: &mut Encoder,
                                name: ast::Ident,
                                ctor_id: NodeId,
-                               index: @RefCell<Vec<entry<i64>> >,
+                               index: &mut Vec<entry<i64>>,
                                struct_id: NodeId) {
-    index.borrow_mut().push(entry {
+    index.push(entry {
         val: ctor_id as i64,
         pos: ebml_w.writer.tell().unwrap(),
     });
@@ -825,10 +806,10 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
                                    def_id: DefId) {
     match ecx.tcx.inherent_impls.borrow().find(&def_id) {
         None => {}
-        Some(&implementations) => {
-            for implementation in implementations.borrow().iter() {
+        Some(implementations) => {
+            for &impl_def_id in implementations.borrow().iter() {
                 ebml_w.start_tag(tag_items_data_item_inherent_impl);
-                encode_def_id(ebml_w, implementation.did);
+                encode_def_id(ebml_w, impl_def_id);
                 ebml_w.end_tag();
             }
         }
@@ -841,10 +822,10 @@ fn encode_extension_implementations(ecx: &EncodeContext,
                                     trait_def_id: DefId) {
     match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
         None => {}
-        Some(&implementations) => {
-            for implementation in implementations.borrow().iter() {
+        Some(implementations) => {
+            for &impl_def_id in implementations.borrow().iter() {
                 ebml_w.start_tag(tag_items_data_item_extension_impl);
-                encode_def_id(ebml_w, implementation.did);
+                encode_def_id(ebml_w, impl_def_id);
                 ebml_w.end_tag();
             }
         }
@@ -854,14 +835,14 @@ fn encode_extension_implementations(ecx: &EncodeContext,
 fn encode_info_for_item(ecx: &EncodeContext,
                         ebml_w: &mut Encoder,
                         item: &Item,
-                        index: @RefCell<Vec<entry<i64>> >,
+                        index: &mut Vec<entry<i64>>,
                         path: PathElems,
                         vis: ast::Visibility) {
     let tcx = ecx.tcx;
 
     fn add_to_index(item: &Item, ebml_w: &Encoder,
-                     index: @RefCell<Vec<entry<i64>> >) {
-        index.borrow_mut().push(entry {
+                    index: &mut Vec<entry<i64>>) {
+        index.push(entry {
             val: item.id as i64,
             pos: ebml_w.writer.tell().unwrap(),
         });
@@ -988,7 +969,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
            class itself */
         let idx = encode_info_for_struct(ecx,
                                          ebml_w,
-                                         &fields,
+                                         fields.as_slice(),
                                          index);
 
         /* Index the class*/
@@ -1009,7 +990,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         /* Encode def_ids for each field and method
          for methods, write all the stuff get_trait_method
         needs to know*/
-        encode_struct_fields(ebml_w, &fields, def_id);
+        encode_struct_fields(ebml_w, fields.as_slice(), def_id);
 
         (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
 
@@ -1017,8 +998,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_inherent_implementations(ecx, ebml_w, def_id);
 
         /* Each class has its own index -- encode it */
-        let bkts = create_index(idx);
-        encode_index(ebml_w, bkts, write_i64);
+        encode_index(ebml_w, idx, write_i64);
         ebml_w.end_tag();
 
         // If this is a tuple-like struct, encode the type of the constructor.
@@ -1033,8 +1013,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
       ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
-        let impls = tcx.impls.borrow();
-        let imp = impls.get(&def_id);
+        let impl_methods = tcx.impl_methods.borrow();
+        let methods = impl_methods.get(&def_id);
 
         add_to_index(item, ebml_w, index);
         ebml_w.start_tag(tag_items_data_item);
@@ -1051,16 +1031,16 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             _ => {}
         }
-        for method in imp.methods.iter() {
+        for &method_def_id in methods.iter() {
             ebml_w.start_tag(tag_item_impl_method);
-            let s = def_to_str(method.def_id);
+            let s = def_to_str(method_def_id);
             ebml_w.writer.write(s.as_bytes());
             ebml_w.end_tag();
         }
         for ast_trait_ref in opt_trait.iter() {
             let trait_ref = ty::node_id_to_trait_ref(
                 tcx, ast_trait_ref.ref_id);
-            encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
+            encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
         }
@@ -1072,18 +1052,18 @@ fn encode_info_for_item(ecx: &EncodeContext,
         // appear first in the impl structure, in the same order they do
         // in the ast. This is a little sketchy.
         let num_implemented_methods = ast_methods.len();
-        for (i, m) in imp.methods.iter().enumerate() {
+        for (i, &method_def_id) in methods.iter().enumerate() {
             let ast_method = if i < num_implemented_methods {
                 Some(*ast_methods.get(i))
             } else { None };
 
-            index.borrow_mut().push(entry {
-                val: m.def_id.node as i64,
+            index.push(entry {
+                val: method_def_id.node as i64,
                 pos: ebml_w.writer.tell().unwrap(),
             });
             encode_info_for_method(ecx,
                                    ebml_w,
-                                   *m,
+                                   &*ty::method(tcx, method_def_id),
                                    path.clone(),
                                    false,
                                    item.id,
@@ -1101,7 +1081,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                   trait_def.generics.type_param_defs(),
                                   tag_items_data_item_ty_param_bounds);
         encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
-        encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
+        encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
         encode_name(ebml_w, item.ident.name);
         encode_attributes(ebml_w, item.attrs.as_slice());
         encode_visibility(ebml_w, vis);
@@ -1120,7 +1100,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
         for ast_trait_ref in super_traits.iter() {
             let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
-            encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
+            encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
         }
 
         // Encode the implementations of this trait.
@@ -1135,14 +1115,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
 
             let method_ty = ty::method(tcx, method_def_id);
 
-            index.borrow_mut().push(entry {
+            index.push(entry {
                 val: method_def_id.node as i64,
                 pos: ebml_w.writer.tell().unwrap(),
             });
 
             ebml_w.start_tag(tag_items_data_item);
 
-            encode_method_ty_fields(ecx, ebml_w, method_ty);
+            encode_method_ty_fields(ecx, ebml_w, &*method_ty);
 
             encode_parent_item(ebml_w, def_id);
 
@@ -1202,10 +1182,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
 fn encode_info_for_foreign_item(ecx: &EncodeContext,
                                 ebml_w: &mut Encoder,
                                 nitem: &ForeignItem,
-                                index: @RefCell<Vec<entry<i64>> >,
+                                index: &mut Vec<entry<i64>>,
                                 path: PathElems,
                                 abi: abi::Abi) {
-    index.borrow_mut().push(entry {
+    index.push(entry {
         val: nitem.id as i64,
         pos: ebml_w.writer.tell().unwrap(),
     });
@@ -1244,7 +1224,7 @@ fn my_visit_expr(_e: &Expr) { }
 fn my_visit_item(i: &Item,
                  ebml_w: &mut Encoder,
                  ecx_ptr: *int,
-                 index: @RefCell<Vec<entry<i64>> >) {
+                 index: &mut Vec<entry<i64>>) {
     let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
     // See above
     let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
@@ -1256,7 +1236,7 @@ fn my_visit_item(i: &Item,
 fn my_visit_foreign_item(ni: &ForeignItem,
                          ebml_w: &mut Encoder,
                          ecx_ptr:*int,
-                         index: @RefCell<Vec<entry<i64>> >) {
+                         index: &mut Vec<entry<i64>>) {
     // See above
     let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
     debug!("writing foreign item {}::{}",
@@ -1277,7 +1257,7 @@ fn my_visit_foreign_item(ni: &ForeignItem,
 struct EncodeVisitor<'a,'b> {
     ebml_w_for_visit_item: &'a mut Encoder<'b>,
     ecx_ptr:*int,
-    index: @RefCell<Vec<entry<i64>> >,
+    index: &'a mut Vec<entry<i64>>,
 }
 
 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
@@ -1305,9 +1285,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
                          ebml_w: &mut Encoder,
                          krate: &Crate)
                          -> Vec<entry<i64>> {
-    let index = @RefCell::new(Vec::new());
+    let mut index = Vec::new();
     ebml_w.start_tag(tag_items_data);
-    index.borrow_mut().push(entry {
+    index.push(entry {
         val: CRATE_NODE_ID as i64,
         pos: ebml_w.writer.tell().unwrap(),
     });
@@ -1321,53 +1301,34 @@ fn encode_info_for_items(ecx: &EncodeContext,
 
     // See comment in `encode_side_tables_for_ii` in astencode
     let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
-    {
-        let mut visitor = EncodeVisitor {
-            index: index,
-            ecx_ptr: ecx_ptr,
-            ebml_w_for_visit_item: &mut *ebml_w,
-        };
-
-        visit::walk_crate(&mut visitor, krate, ());
-    }
+    visit::walk_crate(&mut EncodeVisitor {
+        index: &mut index,
+        ecx_ptr: ecx_ptr,
+        ebml_w_for_visit_item: &mut *ebml_w,
+    }, krate, ());
 
     ebml_w.end_tag();
-    return /*bad*/index.borrow().clone();
+    index
 }
 
 
 // Path and definition ID indexing
 
-fn create_index<T:Clone + Hash + 'static>(
-                index: Vec<entry<T>> )
-                -> Vec<@Vec<entry<T>> > {
-    let mut buckets: Vec<@RefCell<Vec<entry<T>> >> = Vec::new();
-    for _ in range(0u, 256u) {
-        buckets.push(@RefCell::new(Vec::new()));
-    }
-    for elt in index.iter() {
+fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
+                         write_fn: |&mut MemWriter, &T|) {
+    let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
+    for elt in index.move_iter() {
         let h = hash::hash(&elt.val) as uint;
-        buckets.get_mut(h % 256).borrow_mut().push((*elt).clone());
-    }
-
-    let mut buckets_frozen = Vec::new();
-    for bucket in buckets.iter() {
-        buckets_frozen.push(@/*bad*/bucket.borrow().clone());
+        buckets.get_mut(h % 256).push(elt);
     }
-    return buckets_frozen;
-}
 
-fn encode_index<T:'static>(
-                ebml_w: &mut Encoder,
-                buckets: Vec<@Vec<entry<T>> > ,
-                write_fn: |&mut MemWriter, &T|) {
     ebml_w.start_tag(tag_index);
     let mut bucket_locs = Vec::new();
     ebml_w.start_tag(tag_index_buckets);
     for bucket in buckets.iter() {
         bucket_locs.push(ebml_w.writer.tell().unwrap());
         ebml_w.start_tag(tag_index_buckets_bucket);
-        for elt in (**bucket).iter() {
+        for elt in bucket.iter() {
             ebml_w.start_tag(tag_index_buckets_bucket_elt);
             assert!(elt.pos < 0xffff_ffff);
             {
@@ -1614,7 +1575,7 @@ impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
     fn visit_item(&mut self, item: &Item, _: ()) {
         match item.node {
             ItemImpl(_, Some(ref trait_ref), _, _) => {
-                let def_map = self.ecx.tcx.def_map;
+                let def_map = &self.ecx.tcx.def_map;
                 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
                 let def_id = ast_util::def_id_of_def(trait_def);
 
@@ -1723,20 +1684,33 @@ pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
 }
 
 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
-    let stats = Stats {
-        inline_bytes: Cell::new(0),
-        attr_bytes: Cell::new(0),
-        dep_bytes: Cell::new(0),
-        lang_item_bytes: Cell::new(0),
-        native_lib_bytes: Cell::new(0),
-        macro_registrar_fn_bytes: Cell::new(0),
-        macro_defs_bytes: Cell::new(0),
-        impl_bytes: Cell::new(0),
-        misc_bytes: Cell::new(0),
-        item_bytes: Cell::new(0),
-        index_bytes: Cell::new(0),
-        zero_bytes: Cell::new(0),
-        total_bytes: Cell::new(0),
+    struct Stats {
+        attr_bytes: u64,
+        dep_bytes: u64,
+        lang_item_bytes: u64,
+        native_lib_bytes: u64,
+        macro_registrar_fn_bytes: u64,
+        macro_defs_bytes: u64,
+        impl_bytes: u64,
+        misc_bytes: u64,
+        item_bytes: u64,
+        index_bytes: u64,
+        zero_bytes: u64,
+        total_bytes: u64,
+    }
+    let mut stats = Stats {
+        attr_bytes: 0,
+        dep_bytes: 0,
+        lang_item_bytes: 0,
+        native_lib_bytes: 0,
+        macro_registrar_fn_bytes: 0,
+        macro_defs_bytes: 0,
+        impl_bytes: 0,
+        misc_bytes: 0,
+        item_bytes: 0,
+        index_bytes: 0,
+        zero_bytes: 0,
+        total_bytes: 0,
     };
     let EncodeParams {
         item_symbols,
@@ -1749,19 +1723,16 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
         non_inlineable_statics,
         ..
     } = parms;
-    let type_abbrevs = @RefCell::new(HashMap::new());
-    let stats = @stats;
     let ecx = EncodeContext {
         diag: diag,
         tcx: tcx,
-        stats: stats,
         reexports2: reexports2,
         item_symbols: item_symbols,
         non_inlineable_statics: non_inlineable_statics,
         link_meta: link_meta,
         cstore: cstore,
         encode_inlined_item: encode_inlined_item,
-        type_abbrevs: type_abbrevs,
+        type_abbrevs: RefCell::new(HashMap::new()),
      };
 
     let mut ebml_w = writer::Encoder(wr);
@@ -1772,88 +1743,86 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
     let mut i = ebml_w.writer.tell().unwrap();
     let crate_attrs = synthesize_crate_attrs(&ecx, krate);
     encode_attributes(&mut ebml_w, crate_attrs.as_slice());
-    ecx.stats.attr_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
 
     i = ebml_w.writer.tell().unwrap();
     encode_crate_deps(&mut ebml_w, ecx.cstore);
-    ecx.stats.dep_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the language items.
     i = ebml_w.writer.tell().unwrap();
     encode_lang_items(&ecx, &mut ebml_w);
-    ecx.stats.lang_item_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the native libraries used
     i = ebml_w.writer.tell().unwrap();
     encode_native_libraries(&ecx, &mut ebml_w);
-    ecx.stats.native_lib_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the macro registrar function
     i = ebml_w.writer.tell().unwrap();
     encode_macro_registrar_fn(&ecx, &mut ebml_w);
-    ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode macro definitions
     i = ebml_w.writer.tell().unwrap();
     encode_macro_defs(&ecx, krate, &mut ebml_w);
-    ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode the def IDs of impls, for coherence checking.
     i = ebml_w.writer.tell().unwrap();
     encode_impls(&ecx, krate, &mut ebml_w);
-    ecx.stats.impl_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode miscellaneous info.
     i = ebml_w.writer.tell().unwrap();
     encode_misc_info(&ecx, krate, &mut ebml_w);
-    ecx.stats.misc_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
 
     // Encode and index the items.
     ebml_w.start_tag(tag_items);
     i = ebml_w.writer.tell().unwrap();
     let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
-    ecx.stats.item_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
 
     i = ebml_w.writer.tell().unwrap();
-    let items_buckets = create_index(items_index);
-    encode_index(&mut ebml_w, items_buckets, write_i64);
-    ecx.stats.index_bytes.set(ebml_w.writer.tell().unwrap() - i);
+    encode_index(&mut ebml_w, items_index, write_i64);
+    stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
     ebml_w.end_tag();
 
-    ecx.stats.total_bytes.set(ebml_w.writer.tell().unwrap());
+    stats.total_bytes = ebml_w.writer.tell().unwrap();
 
     if tcx.sess.meta_stats() {
         for e in ebml_w.writer.get_ref().iter() {
             if *e == 0 {
-                ecx.stats.zero_bytes.set(ecx.stats.zero_bytes.get() + 1);
+                stats.zero_bytes += 1;
             }
         }
 
         println!("metadata stats:");
-        println!("         inline bytes: {}", ecx.stats.inline_bytes.get());
-        println!("      attribute bytes: {}", ecx.stats.attr_bytes.get());
-        println!("            dep bytes: {}", ecx.stats.dep_bytes.get());
-        println!("      lang item bytes: {}", ecx.stats.lang_item_bytes.get());
-        println!("         native bytes: {}", ecx.stats.native_lib_bytes.get());
-        println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get());
-        println!("      macro def bytes: {}", ecx.stats.macro_defs_bytes.get());
-        println!("           impl bytes: {}", ecx.stats.impl_bytes.get());
-        println!("           misc bytes: {}", ecx.stats.misc_bytes.get());
-        println!("           item bytes: {}", ecx.stats.item_bytes.get());
-        println!("          index bytes: {}", ecx.stats.index_bytes.get());
-        println!("           zero bytes: {}", ecx.stats.zero_bytes.get());
-        println!("          total bytes: {}", ecx.stats.total_bytes.get());
+        println!("      attribute bytes: {}", stats.attr_bytes);
+        println!("            dep bytes: {}", stats.dep_bytes);
+        println!("      lang item bytes: {}", stats.lang_item_bytes);
+        println!("         native bytes: {}", stats.native_lib_bytes);
+        println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
+        println!("      macro def bytes: {}", stats.macro_defs_bytes);
+        println!("           impl bytes: {}", stats.impl_bytes);
+        println!("           misc bytes: {}", stats.misc_bytes);
+        println!("           item bytes: {}", stats.item_bytes);
+        println!("          index bytes: {}", stats.index_bytes);
+        println!("           zero bytes: {}", stats.zero_bytes);
+        println!("          total bytes: {}", stats.total_bytes);
     }
 }
 
 // Get the encoded string for a type
 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> ~str {
-    let cx = &tyencode::ctxt {
+    let mut wr = MemWriter::new();
+    tyencode::enc_ty(&mut wr, &tyencode::ctxt {
         diag: tcx.sess.diagnostic(),
         ds: def_to_str,
         tcx: tcx,
-        abbrevs: tyencode::ac_no_abbrevs};
-    let mut wr = MemWriter::new();
-    tyencode::enc_ty(&mut wr, cx, t);
+        abbrevs: &RefCell::new(HashMap::new())
+    }, t);
     str::from_utf8_owned(wr.get_ref().to_owned()).unwrap()
 }
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index 5a342e39d70..bd95ba95c70 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -222,7 +222,7 @@ impl<'a> Context<'a> {
         //
         // A Library candidate is created if the metadata for the set of
         // libraries corresponds to the crate id and hash criteria that this
-        // serach is being performed for.
+        // search is being performed for.
         let mut libraries = Vec::new();
         for (_hash, (rlibs, dylibs)) in candidates.move_iter() {
             let mut metadata = None;
@@ -278,7 +278,7 @@ impl<'a> Context<'a> {
     // rlib/dylib).
     //
     // The return value is `None` if `file` doesn't look like a rust-generated
-    // library, or if a specific version was requested and it doens't match the
+    // library, or if a specific version was requested and it doesn't match the
     // apparent file's version.
     //
     // If everything checks out, then `Some(hash)` is returned where `hash` is
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index cfa2d647ec9..3ba8dd3b30f 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -18,6 +18,7 @@
 
 use middle::ty;
 
+use std::rc::Rc;
 use std::str;
 use std::strbuf::StrBuf;
 use std::uint;
@@ -563,7 +564,7 @@ fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef
     ty::TypeParameterDef {
         ident: parse_ident(st, ':'),
         def_id: parse_def(st, NominalType, |x,y| conv(x,y)),
-        bounds: @parse_bounds(st, |x,y| conv(x,y)),
+        bounds: Rc::new(parse_bounds(st, |x,y| conv(x,y))),
         default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)))
     }
 }
@@ -591,7 +592,7 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds {
                 param_bounds.builtin_bounds.add(ty::BoundShare);
             }
             'I' => {
-                param_bounds.trait_bounds.push(@parse_trait_ref(st, |x,y| conv(x,y)));
+                param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y))));
             }
             '.' => {
                 return param_bounds;
diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs
index 1d7d43f895e..13d24e7a1d0 100644
--- a/src/librustc/metadata/tyencode.rs
+++ b/src/librustc/metadata/tyencode.rs
@@ -17,7 +17,6 @@ use std::cell::RefCell;
 use collections::HashMap;
 use std::io;
 use std::io::MemWriter;
-use std::str;
 use std::fmt;
 
 use middle::ty::param_ty;
@@ -39,7 +38,7 @@ pub struct ctxt<'a> {
     pub ds: fn(DefId) -> ~str,
     // The type context.
     pub tcx: &'a ty::ctxt,
-    pub abbrevs: abbrev_ctxt
+    pub abbrevs: &'a abbrev_map
 }
 
 // Compact string representation for ty.t values. API ty_str & parse_from_str.
@@ -51,61 +50,35 @@ pub struct ty_abbrev {
     s: ~str
 }
 
-pub enum abbrev_ctxt {
-    ac_no_abbrevs,
-    ac_use_abbrevs(@RefCell<HashMap<ty::t, ty_abbrev>>),
-}
+pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
 
 fn mywrite(w: &mut MemWriter, fmt: &fmt::Arguments) {
     fmt::write(&mut *w as &mut io::Writer, fmt);
 }
 
 pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
-    match cx.abbrevs {
-      ac_no_abbrevs => {
-          let result_str_opt = cx.tcx.short_names_cache.borrow()
-                                            .find(&t)
-                                            .map(|result| {
-                                                (*result).clone()
-                                            });
-          let result_str = match result_str_opt {
-            Some(s) => s,
-            None => {
-                let wr = &mut MemWriter::new();
-                enc_sty(wr, cx, &ty::get(t).sty);
-                let s = str::from_utf8(wr.get_ref()).unwrap();
-                cx.tcx.short_names_cache.borrow_mut().insert(t, s.to_str());
-                s.to_str()
-            }
-          };
-          w.write(result_str.as_bytes());
-      }
-      ac_use_abbrevs(abbrevs) => {
-          match abbrevs.borrow_mut().find(&t) {
-              Some(a) => { w.write(a.s.as_bytes()); return; }
-              None => {}
-          }
-          let pos = w.tell().unwrap();
-          enc_sty(w, cx, &ty::get(t).sty);
-          let end = w.tell().unwrap();
-          let len = end - pos;
-          fn estimate_sz(u: u64) -> u64 {
-              let mut n = u;
-              let mut len = 0;
-              while n != 0 { len += 1; n = n >> 4; }
-              return len;
-          }
-          let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
-          if abbrev_len < len {
-              // I.e. it's actually an abbreviation.
-              let s = format!("\\#{:x}:{:x}\\#", pos, len);
-              let a = ty_abbrev { pos: pos as uint,
-                                  len: len as uint,
-                                  s: s };
-              abbrevs.borrow_mut().insert(t, a);
-          }
-          return;
-      }
+    match cx.abbrevs.borrow_mut().find(&t) {
+        Some(a) => { w.write(a.s.as_bytes()); return; }
+        None => {}
+    }
+    let pos = w.tell().unwrap();
+    enc_sty(w, cx, &ty::get(t).sty);
+    let end = w.tell().unwrap();
+    let len = end - pos;
+    fn estimate_sz(u: u64) -> u64 {
+        let mut n = u;
+        let mut len = 0;
+        while n != 0 { len += 1; n = n >> 4; }
+        return len;
+    }
+    let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
+    if abbrev_len < len {
+        // I.e. it's actually an abbreviation.
+        cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
+            pos: pos as uint,
+            len: len as uint,
+            s: format!("\\#{:x}:{:x}\\#", pos, len)
+        });
     }
 }
 
@@ -393,9 +366,9 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
         }
     }
 
-    for &tp in bs.trait_bounds.iter() {
+    for tp in bs.trait_bounds.iter() {
         mywrite!(w, "I");
-        enc_trait_ref(w, cx, tp);
+        enc_trait_ref(w, cx, &**tp);
     }
 
     mywrite!(w, ".");
@@ -403,6 +376,6 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
 
 pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
     mywrite!(w, "{}:{}|", token::get_ident(v.ident), (cx.ds)(v.def_id));
-    enc_bounds(w, cx, v.bounds);
+    enc_bounds(w, cx, &*v.bounds);
     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
 }
diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs
index 49a2b6326c8..08133a8b69e 100644
--- a/src/librustc/middle/astencode.rs
+++ b/src/librustc/middle/astencode.rs
@@ -55,13 +55,11 @@ use writer = serialize::ebml::writer;
 // Auxiliary maps of things to be encoded
 pub struct Maps {
     pub root_map: middle::borrowck::root_map,
-    pub method_map: middle::typeck::MethodMap,
-    pub vtable_map: middle::typeck::vtable_map,
     pub capture_map: RefCell<middle::moves::CaptureMap>,
 }
 
 struct DecodeContext<'a> {
-    cdata: @cstore::crate_metadata,
+    cdata: &'a cstore::crate_metadata,
     tcx: &'a ty::ctxt,
     maps: &'a Maps
 }
@@ -112,7 +110,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
            ebml_w.writer.tell());
 }
 
-pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
+pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
                            tcx: &ty::ctxt,
                            maps: &Maps,
                            path: Vec<ast_map::PathElem>,
@@ -273,7 +271,7 @@ impl<S:serialize::Encoder<E>, E> def_id_encoder_helpers for S {
 trait def_id_decoder_helpers {
     fn read_def_id(&mut self, xcx: &ExtendedDecodeContext) -> ast::DefId;
     fn read_def_id_noxcx(&mut self,
-                         cdata: @cstore::crate_metadata) -> ast::DefId;
+                         cdata: &cstore::crate_metadata) -> ast::DefId;
 }
 
 impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
@@ -283,7 +281,7 @@ impl<D:serialize::Decoder<E>, E> def_id_decoder_helpers for D {
     }
 
     fn read_def_id_noxcx(&mut self,
-                         cdata: @cstore::crate_metadata) -> ast::DefId {
+                         cdata: &cstore::crate_metadata) -> ast::DefId {
         let did: ast::DefId = Decodable::decode(self).ok().unwrap();
         decoder::translate_def_id(cdata, did)
     }
@@ -528,7 +526,7 @@ impl tr for ty::TraitStore {
 // ______________________________________________________________________
 // Encoding and decoding of freevar information
 
-fn encode_freevar_entry(ebml_w: &mut Encoder, fv: @freevar_entry) {
+fn encode_freevar_entry(ebml_w: &mut Encoder, fv: &freevar_entry) {
     (*fv).encode(ebml_w).unwrap();
 }
 
@@ -660,7 +658,7 @@ impl tr for MethodOrigin {
 fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
                               ebml_w: &mut Encoder,
                               autoderef: u32,
-                              dr: typeck::vtable_res) {
+                              dr: &typeck::vtable_res) {
     ebml_w.emit_struct("VtableWithKey", 2, |ebml_w| {
         ebml_w.emit_struct_field("autoderef", 0u, |ebml_w| {
             autoderef.encode(ebml_w)
@@ -673,19 +671,19 @@ fn encode_vtable_res_with_key(ecx: &e::EncodeContext,
 
 pub fn encode_vtable_res(ecx: &e::EncodeContext,
                      ebml_w: &mut Encoder,
-                     dr: typeck::vtable_res) {
+                     dr: &typeck::vtable_res) {
     // can't autogenerate this code because automatic code of
     // ty::t doesn't work, and there is no way (atm) to have
     // hand-written encoding routines combine with auto-generated
     // ones.  perhaps we should fix this.
     ebml_w.emit_from_vec(dr.as_slice(), |ebml_w, param_tables| {
-        Ok(encode_vtable_param_res(ecx, ebml_w, *param_tables))
+        Ok(encode_vtable_param_res(ecx, ebml_w, param_tables))
     }).unwrap()
 }
 
 pub fn encode_vtable_param_res(ecx: &e::EncodeContext,
                      ebml_w: &mut Encoder,
-                     param_tables: typeck::vtable_param_res) {
+                     param_tables: &typeck::vtable_param_res) {
     ebml_w.emit_from_vec(param_tables.as_slice(), |ebml_w, vtable_origin| {
         Ok(encode_vtable_origin(ecx, ebml_w, vtable_origin))
     }).unwrap()
@@ -697,7 +695,7 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
                         vtable_origin: &typeck::vtable_origin) {
     ebml_w.emit_enum("vtable_origin", |ebml_w| {
         match *vtable_origin {
-          typeck::vtable_static(def_id, ref tys, vtable_res) => {
+          typeck::vtable_static(def_id, ref tys, ref vtable_res) => {
             ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| {
                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
                     Ok(ebml_w.emit_def_id(def_id))
@@ -727,23 +725,23 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
 pub trait vtable_decoder_helpers {
     fn read_vtable_res_with_key(&mut self,
                                 tcx: &ty::ctxt,
-                                cdata: @cstore::crate_metadata)
+                                cdata: &cstore::crate_metadata)
                                 -> (u32, typeck::vtable_res);
     fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_res;
     fn read_vtable_param_res(&mut self,
-                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_param_res;
     fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                          tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                           -> typeck::vtable_origin;
 }
 
 impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     fn read_vtable_res_with_key(&mut self,
                                 tcx: &ty::ctxt,
-                                cdata: @cstore::crate_metadata)
+                                cdata: &cstore::crate_metadata)
                                 -> (u32, typeck::vtable_res) {
         self.read_struct("VtableWithKey", 2, |this| {
             let autoderef = this.read_struct_field("autoderef", 0, |this| {
@@ -756,27 +754,21 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
     }
 
     fn read_vtable_res(&mut self,
-                       tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                       tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_res {
-        @self.read_to_vec(|this|
-                          Ok(this.read_vtable_param_res(tcx, cdata)))
-             .unwrap()
-             .move_iter()
-             .collect()
+        self.read_to_vec(|this| Ok(this.read_vtable_param_res(tcx, cdata)))
+             .unwrap().move_iter().collect()
     }
 
     fn read_vtable_param_res(&mut self,
-                             tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                             tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
                       -> typeck::vtable_param_res {
-        @self.read_to_vec(|this|
-                          Ok(this.read_vtable_origin(tcx, cdata)))
-             .unwrap()
-             .move_iter()
-             .collect()
+        self.read_to_vec(|this| Ok(this.read_vtable_origin(tcx, cdata)))
+             .unwrap().move_iter().collect()
     }
 
     fn read_vtable_origin(&mut self,
-                          tcx: &ty::ctxt, cdata: @cstore::crate_metadata)
+                          tcx: &ty::ctxt, cdata: &cstore::crate_metadata)
         -> typeck::vtable_origin {
         self.read_enum("vtable_origin", |this| {
             this.read_enum_variant(["vtable_static",
@@ -828,7 +820,7 @@ impl<'a> get_ty_str_ctxt for e::EncodeContext<'a> {
             diag: self.tcx.sess.diagnostic(),
             ds: e::def_to_str,
             tcx: self.tcx,
-            abbrevs: tyencode::ac_use_abbrevs(self.type_abbrevs)
+            abbrevs: &self.type_abbrevs
         }
     }
 }
@@ -1026,7 +1018,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
                 ebml_w.emit_from_vec(fv.as_slice(), |ebml_w, fv_entry| {
-                    Ok(encode_freevar_entry(ebml_w, *fv_entry))
+                    Ok(encode_freevar_entry(ebml_w, fv_entry))
                 });
             })
         })
@@ -1052,7 +1044,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
     }
 
     let method_call = MethodCall::expr(id);
-    for &method in maps.method_map.borrow().find(&method_call).iter() {
+    for &method in tcx.method_map.borrow().find(&method_call).iter() {
         ebml_w.tag(c::tag_table_method_map, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1061,21 +1053,21 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
+    for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
-                encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, *dr);
+                encode_vtable_res_with_key(ecx, ebml_w, method_call.autoderef, dr);
             })
         })
     }
 
-    for adj in tcx.adjustments.borrow().find(&id).iter() {
-        match ***adj {
+    for &adj in tcx.adjustments.borrow().find(&id).iter() {
+        match *adj {
             ty::AutoDerefRef(adj) => {
                 for autoderef in range(0, adj.autoderefs) {
                     let method_call = MethodCall::autoderef(id, autoderef as u32);
-                    for &method in maps.method_map.borrow().find(&method_call).iter() {
+                    for &method in tcx.method_map.borrow().find(&method_call).iter() {
                         ebml_w.tag(c::tag_table_method_map, |ebml_w| {
                             ebml_w.id(id);
                             ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1084,12 +1076,12 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
                         })
                     }
 
-                    for &dr in maps.vtable_map.borrow().find(&method_call).iter() {
+                    for &dr in tcx.vtable_map.borrow().find(&method_call).iter() {
                         ebml_w.tag(c::tag_table_vtable_map, |ebml_w| {
                             ebml_w.id(id);
                             ebml_w.tag(c::tag_table_val, |ebml_w| {
                                 encode_vtable_res_with_key(ecx, ebml_w,
-                                                           method_call.autoderef, *dr);
+                                                           method_call.autoderef, dr);
                             })
                         })
                     }
@@ -1101,7 +1093,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         ebml_w.tag(c::tag_table_adjustments, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
-                ebml_w.emit_auto_adjustment(ecx, **adj);
+                ebml_w.emit_auto_adjustment(ecx, adj);
             })
         })
     }
@@ -1148,15 +1140,15 @@ trait ebml_decoder_decoder_helpers {
     // Versions of the type reading functions that don't need the full
     // ExtendedDecodeContext.
     fn read_ty_noxcx(&mut self,
-                     tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t;
+                     tcx: &ty::ctxt, cdata: &cstore::crate_metadata) -> ty::t;
     fn read_tys_noxcx(&mut self,
                       tcx: &ty::ctxt,
-                      cdata: @cstore::crate_metadata) -> Vec<ty::t>;
+                      cdata: &cstore::crate_metadata) -> Vec<ty::t>;
 }
 
 impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
     fn read_ty_noxcx(&mut self,
-                     tcx: &ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
+                     tcx: &ty::ctxt, cdata: &cstore::crate_metadata) -> ty::t {
         self.read_opaque(|_, doc| {
             Ok(tydecode::parse_ty_data(
                 doc.data,
@@ -1169,7 +1161,7 @@ impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
 
     fn read_tys_noxcx(&mut self,
                       tcx: &ty::ctxt,
-                      cdata: @cstore::crate_metadata) -> Vec<ty::t> {
+                      cdata: &cstore::crate_metadata) -> Vec<ty::t> {
         self.read_to_vec(|this| Ok(this.read_ty_noxcx(tcx, cdata)) )
             .unwrap()
             .move_iter()
@@ -1378,8 +1370,8 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                         dcx.tcx.node_type_substs.borrow_mut().insert(id, tys);
                     }
                     c::tag_table_freevars => {
-                        let fv_info = @val_dsr.read_to_vec(|val_dsr| {
-                            Ok(@val_dsr.read_freevar_entry(xcx))
+                        let fv_info = val_dsr.read_to_vec(|val_dsr| {
+                            Ok(val_dsr.read_freevar_entry(xcx))
                         }).unwrap().move_iter().collect();
                         dcx.tcx.freevars.borrow_mut().insert(id, fv_info);
                     }
@@ -1398,7 +1390,7 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                             expr_id: id,
                             autoderef: autoderef
                         };
-                        dcx.maps.method_map.borrow_mut().insert(method_call, method);
+                        dcx.tcx.method_map.borrow_mut().insert(method_call, method);
                     }
                     c::tag_table_vtable_map => {
                         let (autoderef, vtable_res) =
@@ -1408,10 +1400,10 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                             expr_id: id,
                             autoderef: autoderef
                         };
-                        dcx.maps.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
+                        dcx.tcx.vtable_map.borrow_mut().insert(vtable_key, vtable_res);
                     }
                     c::tag_table_adjustments => {
-                        let adj: @ty::AutoAdjustment = @val_dsr.read_auto_adjustment(xcx);
+                        let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(xcx);
                         dcx.tcx.adjustments.borrow_mut().insert(id, adj);
                     }
                     c::tag_table_capture_map => {
diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs
index 5e0425141ac..e09507f5d5f 100644
--- a/src/librustc/middle/borrowck/check_loans.rs
+++ b/src/librustc/middle/borrowck/check_loans.rs
@@ -30,6 +30,8 @@ use syntax::visit::Visitor;
 use syntax::visit;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
+
 struct CheckLoanCtxt<'a> {
     bccx: &'a BorrowckCtxt<'a>,
     dfcx_loans: &'a LoanDataFlow<'a>,
@@ -82,7 +84,7 @@ pub fn check_loans(bccx: &BorrowckCtxt,
 #[deriving(Eq)]
 enum MoveError {
     MoveOk,
-    MoveWhileBorrowed(/*loan*/@LoanPath, /*loan*/Span)
+    MoveWhileBorrowed(/*loan*/Rc<LoanPath>, /*loan*/Span)
 }
 
 impl<'a> CheckLoanCtxt<'a> {
@@ -121,7 +123,7 @@ impl<'a> CheckLoanCtxt<'a> {
 
     pub fn each_in_scope_restriction(&self,
                                      scope_id: ast::NodeId,
-                                     loan_path: @LoanPath,
+                                     loan_path: &LoanPath,
                                      op: |&Loan, &Restriction| -> bool)
                                      -> bool {
         //! Iterates through all the in-scope restrictions for the
@@ -133,7 +135,7 @@ impl<'a> CheckLoanCtxt<'a> {
 
             let mut ret = true;
             for restr in loan.restrictions.iter() {
-                if restr.loan_path == loan_path {
+                if *restr.loan_path == *loan_path {
                     if !op(loan, restr) {
                         ret = false;
                         break;
@@ -243,7 +245,7 @@ impl<'a> CheckLoanCtxt<'a> {
                 "it".to_owned()
             } else {
                 format!("`{}`",
-                        self.bccx.loan_path_to_str(old_loan.loan_path))
+                        self.bccx.loan_path_to_str(&*old_loan.loan_path))
             };
 
             match (new_loan.kind, old_loan.kind) {
@@ -252,7 +254,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("cannot borrow `{}` as mutable \
                                 more than once at a time",
-                                self.bccx.loan_path_to_str(new_loan.loan_path)));
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path)));
                 }
 
                 (ty::UniqueImmBorrow, _) => {
@@ -260,7 +262,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("closure requires unique access to `{}` \
                                 but {} is already borrowed",
-                                self.bccx.loan_path_to_str(new_loan.loan_path),
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path),
                                 old_pronoun));
                 }
 
@@ -269,7 +271,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("cannot borrow `{}` as {} because \
                                 previous closure requires unique access",
-                                self.bccx.loan_path_to_str(new_loan.loan_path),
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path),
                                 new_loan.kind.to_user_str()));
                 }
 
@@ -278,7 +280,7 @@ impl<'a> CheckLoanCtxt<'a> {
                         new_loan.span,
                         format!("cannot borrow `{}` as {} because \
                                 {} is also borrowed as {}",
-                                self.bccx.loan_path_to_str(new_loan.loan_path),
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path),
                                 new_loan.kind.to_user_str(),
                                 old_pronoun,
                                 old_loan.kind.to_user_str()));
@@ -290,7 +292,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     self.bccx.span_note(
                         span,
                         format!("borrow occurs due to use of `{}` in closure",
-                                self.bccx.loan_path_to_str(new_loan.loan_path)));
+                                self.bccx.loan_path_to_str(&*new_loan.loan_path)));
                 }
                 _ => { }
             }
@@ -300,21 +302,21 @@ impl<'a> CheckLoanCtxt<'a> {
                     format!("the mutable borrow prevents subsequent \
                             moves, borrows, or modification of `{0}` \
                             until the borrow ends",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
 
                 ty::ImmBorrow => {
                     format!("the immutable borrow prevents subsequent \
                             moves or mutable borrows of `{0}` \
                             until the borrow ends",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
 
                 ty::UniqueImmBorrow => {
                     format!("the unique capture prevents subsequent \
                             moves or borrows of `{0}` \
                             until the borrow ends",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
             };
 
@@ -322,12 +324,12 @@ impl<'a> CheckLoanCtxt<'a> {
                 ClosureCapture(_) => {
                     format!("previous borrow of `{}` occurs here due to \
                             use in closure",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
 
                 AddrOf | AutoRef | RefBinding => {
                     format!("previous borrow of `{}` occurs here",
-                            self.bccx.loan_path_to_str(old_loan.loan_path))
+                            self.bccx.loan_path_to_str(&*old_loan.loan_path))
                 }
             };
 
@@ -356,7 +358,7 @@ impl<'a> CheckLoanCtxt<'a> {
                                   id: ast::NodeId,
                                   span: Span,
                                   use_kind: MovedValueUseKind,
-                                  lp: @LoanPath) {
+                                  lp: &Rc<LoanPath>) {
         /*!
          * Reports an error if `expr` (which should be a path)
          * is using a moved/uninitialized value
@@ -368,7 +370,7 @@ impl<'a> CheckLoanCtxt<'a> {
             self.bccx.report_use_of_moved_value(
                 span,
                 use_kind,
-                lp,
+                &**lp,
                 move,
                 moved_lp);
             false
@@ -378,7 +380,7 @@ impl<'a> CheckLoanCtxt<'a> {
     pub fn check_assignment(&self, expr: &ast::Expr) {
         // We don't use cat_expr() here because we don't want to treat
         // auto-ref'd parameters in overloaded operators as rvalues.
-        let cmt = match self.bccx.tcx.adjustments.borrow().find_copy(&expr.id) {
+        let cmt = match self.bccx.tcx.adjustments.borrow().find(&expr.id) {
             None => self.bccx.cat_expr_unadjusted(expr),
             Some(adj) => self.bccx.cat_expr_autoderefd(expr, adj)
         };
@@ -388,10 +390,9 @@ impl<'a> CheckLoanCtxt<'a> {
         // Mutable values can be assigned, as long as they obey loans
         // and aliasing restrictions:
         if cmt.mutbl.is_mutable() {
-            if check_for_aliasable_mutable_writes(self, expr, cmt) {
+            if check_for_aliasable_mutable_writes(self, expr, cmt.clone()) {
                 if check_for_assignment_to_restricted_or_frozen_location(
-                    self, expr, cmt)
-                {
+                    self, expr, cmt.clone()) {
                     // Safe, but record for lint pass later:
                     mark_variable_as_used_mut(self, cmt);
                 }
@@ -401,13 +402,13 @@ impl<'a> CheckLoanCtxt<'a> {
 
         // For immutable local variables, assignments are legal
         // if they cannot already have been assigned
-        if self.is_local_variable(cmt) {
+        if self.is_local_variable(cmt.clone()) {
             assert!(cmt.mutbl.is_immutable()); // no "const" locals
-            let lp = opt_loan_path(cmt).unwrap();
-            self.move_data.each_assignment_of(expr.id, lp, |assign| {
+            let lp = opt_loan_path(&cmt).unwrap();
+            self.move_data.each_assignment_of(expr.id, &lp, |assign| {
                 self.bccx.report_reassigned_immutable_variable(
                     expr.span,
-                    lp,
+                    &*lp,
                     assign);
                 false
             });
@@ -415,21 +416,21 @@ impl<'a> CheckLoanCtxt<'a> {
         }
 
         // Otherwise, just a plain error.
-        match opt_loan_path(cmt) {
+        match opt_loan_path(&cmt) {
             Some(lp) => {
                 self.bccx.span_err(
                     expr.span,
                     format!("cannot assign to {} {} `{}`",
                             cmt.mutbl.to_user_str(),
-                            self.bccx.cmt_to_str(cmt),
-                            self.bccx.loan_path_to_str(lp)));
+                            self.bccx.cmt_to_str(&*cmt),
+                            self.bccx.loan_path_to_str(&*lp)));
             }
             None => {
                 self.bccx.span_err(
                     expr.span,
                     format!("cannot assign to {} {}",
                             cmt.mutbl.to_user_str(),
-                            self.bccx.cmt_to_str(cmt)));
+                            self.bccx.cmt_to_str(&*cmt)));
             }
         }
         return;
@@ -446,7 +447,7 @@ impl<'a> CheckLoanCtxt<'a> {
             loop {
                 debug!("mark_writes_through_upvars_as_used_mut(cmt={})",
                        cmt.repr(this.tcx()));
-                match cmt.cat {
+                match cmt.cat.clone() {
                     mc::cat_local(id) | mc::cat_arg(id) => {
                         this.tcx().used_mut_nodes.borrow_mut().insert(id);
                         return;
@@ -494,10 +495,10 @@ impl<'a> CheckLoanCtxt<'a> {
             debug!("check_for_aliasable_mutable_writes(cmt={}, guarantor={})",
                    cmt.repr(this.tcx()), guarantor.repr(this.tcx()));
             match guarantor.cat {
-                mc::cat_deref(b, _, mc::BorrowedPtr(ty::MutBorrow, _)) => {
+                mc::cat_deref(ref b, _, mc::BorrowedPtr(ty::MutBorrow, _)) => {
                     // Statically prohibit writes to `&mut` when aliasable
 
-                    check_for_aliasability_violation(this, expr, b);
+                    check_for_aliasability_violation(this, expr, b.clone());
                 }
 
                 _ => {}
@@ -535,7 +536,7 @@ impl<'a> CheckLoanCtxt<'a> {
             //! Check for assignments that violate the terms of an
             //! outstanding loan.
 
-            let loan_path = match opt_loan_path(cmt) {
+            let loan_path = match opt_loan_path(&cmt) {
                 Some(lp) => lp,
                 None => { return true; /* no loan path, can't be any loans */ }
             };
@@ -571,10 +572,10 @@ impl<'a> CheckLoanCtxt<'a> {
             // owned pointer are borrowed, and hence while `v[*]` is not
             // restricted from being written, `v` is.
             let cont = this.each_in_scope_restriction(expr.id,
-                                                      loan_path,
+                                                      &*loan_path,
                                                       |loan, restr| {
                 if restr.set.intersects(RESTR_MUTATE) {
-                    this.report_illegal_mutation(expr, loan_path, loan);
+                    this.report_illegal_mutation(expr, &*loan_path, loan);
                     false
                 } else {
                     true
@@ -623,17 +624,17 @@ impl<'a> CheckLoanCtxt<'a> {
             //
             // Here the restriction that `v` not be mutated would be misapplied
             // to block the subpath `v[1]`.
-            let full_loan_path = loan_path;
+            let full_loan_path = loan_path.clone();
             let mut loan_path = loan_path;
             loop {
-                match *loan_path {
+                loan_path = match *loan_path {
                     // Peel back one layer if, for `loan_path` to be
                     // mutable, `lp_base` must be mutable. This occurs
                     // with inherited mutability and with `&mut`
                     // pointers.
-                    LpExtend(lp_base, mc::McInherited, _) |
-                    LpExtend(lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
-                        loan_path = lp_base;
+                    LpExtend(ref lp_base, mc::McInherited, _) |
+                    LpExtend(ref lp_base, _, LpDeref(mc::BorrowedPtr(ty::MutBorrow, _))) => {
+                        lp_base.clone()
                     }
 
                     // Otherwise stop iterating
@@ -642,12 +643,12 @@ impl<'a> CheckLoanCtxt<'a> {
                     LpVar(_) => {
                         return true;
                     }
-                }
+                };
 
                 // Check for a non-const loan of `loan_path`
                 let cont = this.each_in_scope_loan(expr.id, |loan| {
                     if loan.loan_path == loan_path {
-                        this.report_illegal_mutation(expr, full_loan_path, loan);
+                        this.report_illegal_mutation(expr, &*full_loan_path, loan);
                         false
                     } else {
                         true
@@ -700,7 +701,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     self.bccx.span_note(
                         loan_span,
                         format!("borrow of `{}` occurs here",
-                                self.bccx.loan_path_to_str(loan_path)));
+                                self.bccx.loan_path_to_str(&*loan_path)));
                 }
             }
             true
@@ -712,13 +713,12 @@ impl<'a> CheckLoanCtxt<'a> {
                                 span: Span) {
         for cap_var in self.bccx.capture_map.get(&closure_id).iter() {
             let var_id = ast_util::def_id_of_def(cap_var.def).node;
-            let var_path = @LpVar(var_id);
             self.check_if_path_is_moved(closure_id, span,
-                                        MovedInCapture, var_path);
+                                        MovedInCapture, &Rc::new(LpVar(var_id)));
             match cap_var.mode {
                 moves::CapRef | moves::CapCopy => {}
                 moves::CapMove => {
-                    check_by_move_capture(self, closure_id, cap_var, var_path);
+                    check_by_move_capture(self, closure_id, cap_var, &LpVar(var_id));
                 }
             }
         }
@@ -727,7 +727,7 @@ impl<'a> CheckLoanCtxt<'a> {
         fn check_by_move_capture(this: &CheckLoanCtxt,
                                  closure_id: ast::NodeId,
                                  cap_var: &moves::CaptureVar,
-                                 move_path: @LoanPath) {
+                                 move_path: &LoanPath) {
             let move_err = this.analyze_move_out_from(closure_id, move_path);
             match move_err {
                 MoveOk => {}
@@ -740,7 +740,7 @@ impl<'a> CheckLoanCtxt<'a> {
                     this.bccx.span_note(
                         loan_span,
                         format!("borrow of `{}` occurs here",
-                                this.bccx.loan_path_to_str(loan_path)));
+                                this.bccx.loan_path_to_str(&*loan_path)));
                 }
             }
         }
@@ -748,7 +748,7 @@ impl<'a> CheckLoanCtxt<'a> {
 
     pub fn analyze_move_out_from(&self,
                                  expr_id: ast::NodeId,
-                                 mut move_path: @LoanPath)
+                                 move_path: &LoanPath)
                                  -> MoveError {
         debug!("analyze_move_out_from(expr_id={:?}, move_path={})",
                self.tcx().map.node_to_str(expr_id),
@@ -756,22 +756,23 @@ impl<'a> CheckLoanCtxt<'a> {
 
         // We must check every element of a move path. See
         // `borrowck-move-subcomponent.rs` for a test case.
-        loop {
-            // check for a conflicting loan:
-            let mut ret = MoveOk;
-            self.each_in_scope_restriction(expr_id, move_path, |loan, _| {
-                // Any restriction prevents moves.
-                ret = MoveWhileBorrowed(loan.loan_path, loan.span);
-                false
-            });
 
-            if ret != MoveOk {
-                return ret
-            }
+        // check for a conflicting loan:
+        let mut ret = MoveOk;
+        self.each_in_scope_restriction(expr_id, move_path, |loan, _| {
+            // Any restriction prevents moves.
+            ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span);
+            false
+        });
+
+        if ret != MoveOk {
+            return ret
+        }
 
-            match *move_path {
-                LpVar(_) => return MoveOk,
-                LpExtend(subpath, _, _) => move_path = subpath,
+        match *move_path {
+            LpVar(_) => MoveOk,
+            LpExtend(ref subpath, _, _) => {
+                self.analyze_move_out_from(expr_id, &**subpath)
             }
         }
     }
@@ -806,14 +807,13 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
     this.check_for_conflicting_loans(expr.id);
     this.check_move_out_from_expr(expr);
 
-    let method_map = this.bccx.method_map.borrow();
+    let method_map = this.bccx.tcx.method_map.borrow();
     match expr.node {
       ast::ExprPath(..) => {
           if !this.move_data.is_assignee(expr.id) {
               let cmt = this.bccx.cat_expr_unadjusted(expr);
               debug!("path cmt={}", cmt.repr(this.tcx()));
-              let r = opt_loan_path(cmt);
-              for &lp in r.iter() {
+              for lp in opt_loan_path(&cmt).iter() {
                   this.check_if_path_is_moved(expr.id, expr.span, MovedInUse, lp);
               }
           }
diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
index f250b105d0b..f4eee0526dd 100644
--- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs
@@ -23,6 +23,8 @@ use syntax::ast;
 use syntax::codemap::Span;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
+
 struct GatherMoveInfo {
     id: ast::NodeId,
     kind: MoveKind,
@@ -35,7 +37,7 @@ pub fn gather_decl(bccx: &BorrowckCtxt,
                    decl_id: ast::NodeId,
                    _decl_span: Span,
                    var_id: ast::NodeId) {
-    let loan_path = @LpVar(var_id);
+    let loan_path = Rc::new(LpVar(var_id));
     move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
 }
 
@@ -105,7 +107,7 @@ fn gather_move(bccx: &BorrowckCtxt,
            move_info.id, move_info.cmt.repr(bccx.tcx));
 
     let potentially_illegal_move =
-                check_and_get_illegal_move_origin(bccx, move_info.cmt);
+                check_and_get_illegal_move_origin(bccx, &move_info.cmt);
     match potentially_illegal_move {
         Some(illegal_move_origin) => {
             let error = MoveError::with_move_info(illegal_move_origin,
@@ -116,7 +118,7 @@ fn gather_move(bccx: &BorrowckCtxt,
         None => ()
     }
 
-    match opt_loan_path(move_info.cmt) {
+    match opt_loan_path(&move_info.cmt) {
         Some(loan_path) => {
             move_data.add_move(bccx.tcx, loan_path,
                                move_info.id, move_info.kind);
@@ -131,7 +133,7 @@ pub fn gather_assignment(bccx: &BorrowckCtxt,
                          move_data: &MoveData,
                          assignment_id: ast::NodeId,
                          assignment_span: Span,
-                         assignee_loan_path: @LoanPath,
+                         assignee_loan_path: Rc<LoanPath>,
                          assignee_id: ast::NodeId) {
     move_data.add_assignment(bccx.tcx,
                              assignee_loan_path,
@@ -145,7 +147,7 @@ pub fn gather_move_and_assignment(bccx: &BorrowckCtxt,
                                   move_data: &MoveData,
                                   assignment_id: ast::NodeId,
                                   assignment_span: Span,
-                                  assignee_loan_path: @LoanPath,
+                                  assignee_loan_path: Rc<LoanPath>,
                                   assignee_id: ast::NodeId) {
     move_data.add_assignment(bccx.tcx,
                              assignee_loan_path,
@@ -156,14 +158,14 @@ pub fn gather_move_and_assignment(bccx: &BorrowckCtxt,
 }
 
 fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
-                                     cmt: mc::cmt) -> Option<mc::cmt> {
+                                     cmt: &mc::cmt) -> Option<mc::cmt> {
     match cmt.cat {
         mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
         mc::cat_deref(_, _, mc::GcPtr) |
         mc::cat_deref(_, _, mc::UnsafePtr(..)) |
         mc::cat_upvar(..) | mc::cat_static_item |
         mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => {
-            Some(cmt)
+            Some(cmt.clone())
         }
 
         // Can move out of captured upvars only if the destination closure
@@ -179,12 +181,12 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
             None
         }
 
-        mc::cat_downcast(b) |
-        mc::cat_interior(b, _) => {
+        mc::cat_downcast(ref b) |
+        mc::cat_interior(ref b, _) => {
             match ty::get(b.ty).sty {
                 ty::ty_struct(did, _) | ty::ty_enum(did, _) => {
                     if ty::has_dtor(bccx.tcx, did) {
-                        Some(cmt)
+                        Some(cmt.clone())
                     } else {
                         check_and_get_illegal_move_origin(bccx, b)
                     }
@@ -195,8 +197,8 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt,
             }
         }
 
-        mc::cat_deref(b, _, mc::OwnedPtr) |
-        mc::cat_discr(b, _) => {
+        mc::cat_deref(ref b, _, mc::OwnedPtr) |
+        mc::cat_discr(ref b, _) => {
             check_and_get_illegal_move_origin(bccx, b)
         }
     }
diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
index a04afd6d5f3..a27fe5cec22 100644
--- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs
@@ -39,9 +39,9 @@ pub fn guarantee_lifetime(bccx: &BorrowckCtxt,
                                          cause: cause,
                                          loan_region: loan_region,
                                          loan_kind: loan_kind,
-                                         cmt_original: cmt,
+                                         cmt_original: cmt.clone(),
                                          root_scope_id: root_scope_id};
-    ctxt.check(cmt, None)
+    ctxt.check(&cmt, None)
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -69,7 +69,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         self.bccx.tcx
     }
 
-    fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
+    fn check(&self, cmt: &mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
         //! Main routine. Walks down `cmt` until we find the "guarantor".
         debug!("guarantee_lifetime.check(cmt={}, loan_region={})",
                cmt.repr(self.bccx.tcx),
@@ -83,15 +83,14 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             mc::cat_upvar(..) |
             mc::cat_deref(_, _, mc::BorrowedPtr(..)) |  // L-Deref-Borrowed
             mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
-                let scope = self.scope(cmt);
-                self.check_scope(scope)
+                self.check_scope(self.scope(cmt))
             }
 
             mc::cat_static_item => {
                 Ok(())
             }
 
-            mc::cat_deref(base, derefs, mc::GcPtr) => {
+            mc::cat_deref(ref base, derefs, mc::GcPtr) => {
                 let base_scope = self.scope(base);
 
                 // L-Deref-Managed-Imm-User-Root
@@ -111,13 +110,13 @@ impl<'a> GuaranteeLifetimeContext<'a> {
                 }
             }
 
-            mc::cat_downcast(base) |
-            mc::cat_deref(base, _, mc::OwnedPtr) |     // L-Deref-Send
-            mc::cat_interior(base, _) => {             // L-Field
+            mc::cat_downcast(ref base) |
+            mc::cat_deref(ref base, _, mc::OwnedPtr) |     // L-Deref-Send
+            mc::cat_interior(ref base, _) => {             // L-Field
                 self.check(base, discr_scope)
             }
 
-            mc::cat_discr(base, new_discr_scope) => {
+            mc::cat_discr(ref base, new_discr_scope) => {
                 // Subtle: in a match, we must ensure that each binding
                 // variable remains valid for the duration of the arm in
                 // which it appears, presuming that this arm is taken.
@@ -176,7 +175,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
     }
 
     fn is_rvalue_or_immutable(&self,
-                              cmt: mc::cmt) -> bool {
+                              cmt: &mc::cmt) -> bool {
         //! We can omit the root on an `@T` value if the location
         //! that holds the box is either (1) an rvalue, in which case
         //! it is in a non-user-accessible temporary, or (2) an immutable
@@ -189,8 +188,8 @@ impl<'a> GuaranteeLifetimeContext<'a> {
     }
 
     fn check_root(&self,
-                  cmt_deref: mc::cmt,
-                  cmt_base: mc::cmt,
+                  cmt_deref: &mc::cmt,
+                  cmt_base: &mc::cmt,
                   derefs: uint,
                   discr_scope: Option<ast::NodeId>) -> R {
         debug!("check_root(cmt_deref={}, cmt_base={}, derefs={:?}, \
@@ -253,7 +252,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         }
     }
 
-    fn is_moved(&self, cmt: mc::cmt) -> bool {
+    fn is_moved(&self, cmt: &mc::cmt) -> bool {
         //! True if `cmt` is something that is potentially moved
         //! out of the current stack frame.
 
@@ -269,9 +268,9 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             mc::cat_upvar(..) => {
                 false
             }
-            r @ mc::cat_downcast(..) |
-            r @ mc::cat_interior(..) |
-            r @ mc::cat_discr(..) => {
+            ref r @ mc::cat_downcast(..) |
+            ref r @ mc::cat_interior(..) |
+            ref r @ mc::cat_discr(..) => {
                 self.tcx().sess.span_bug(
                     cmt.span,
                     format!("illegal guarantor category: {:?}", r));
@@ -279,7 +278,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
         }
     }
 
-    fn scope(&self, cmt: mc::cmt) -> ty::Region {
+    fn scope(&self, cmt: &mc::cmt) -> ty::Region {
         //! Returns the maximal region scope for the which the
         //! lvalue `cmt` is guaranteed to be valid without any
         //! rooting etc, and presuming `cmt` is not mutated.
@@ -307,18 +306,18 @@ impl<'a> GuaranteeLifetimeContext<'a> {
             mc::cat_deref(_, _, mc::BorrowedPtr(_, r)) => {
                 r
             }
-            mc::cat_downcast(cmt) |
-            mc::cat_deref(cmt, _, mc::OwnedPtr) |
-            mc::cat_deref(cmt, _, mc::GcPtr) |
-            mc::cat_interior(cmt, _) |
-            mc::cat_discr(cmt, _) => {
+            mc::cat_downcast(ref cmt) |
+            mc::cat_deref(ref cmt, _, mc::OwnedPtr) |
+            mc::cat_deref(ref cmt, _, mc::GcPtr) |
+            mc::cat_interior(ref cmt, _) |
+            mc::cat_discr(ref cmt, _) => {
                 self.scope(cmt)
             }
         }
     }
 
     fn report_error(&self, code: bckerr_code) {
-        self.bccx.report(BckError { cmt: self.cmt_original,
+        self.bccx.report(BckError { cmt: self.cmt_original.clone(),
                                     span: self.span,
                                     cause: self.cause,
                                     code: code });
diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs
index dd9f2eb970b..7f748dffd70 100644
--- a/src/librustc/middle/borrowck/gather_loans/mod.rs
+++ b/src/librustc/middle/borrowck/gather_loans/mod.rs
@@ -36,6 +36,8 @@ use syntax::visit;
 use syntax::visit::{Visitor, FnKind};
 use syntax::ast::{Expr, FnDecl, Block, NodeId, Stmt, Pat, Local};
 
+use std::rc::Rc;
+
 mod lifetime;
 mod restrictions;
 mod gather_moves;
@@ -146,7 +148,7 @@ fn gather_loans_in_local(this: &mut GatherLoanCtxt,
         None => {
             // Variable declarations without initializers are considered "moves":
             let tcx = this.bccx.tcx;
-            pat_util::pat_bindings(tcx.def_map, local.pat, |_, id, span, _| {
+            pat_util::pat_bindings(&tcx.def_map, local.pat, |_, id, span, _| {
                 gather_moves::gather_decl(this.bccx,
                                           &this.move_data,
                                           id,
@@ -177,7 +179,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
 
     // If this expression is borrowed, have to ensure it remains valid:
     for &adjustments in tcx.adjustments.borrow().find(&ex.id).iter() {
-        this.guarantee_adjustments(ex, *adjustments);
+        this.guarantee_adjustments(ex, adjustments);
     }
 
     // If this expression is a move, gather it:
@@ -188,7 +190,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
     }
 
     // Special checks for various kinds of expressions:
-    let method_map = this.bccx.method_map.borrow();
+    let method_map = this.bccx.tcx.method_map.borrow();
     match ex.node {
       ast::ExprAddrOf(mutbl, base) => {
         let base_cmt = this.bccx.cat_expr(base);
@@ -228,7 +230,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
         let cmt = this.bccx.cat_expr(ex_v);
         for arm in arms.iter() {
             for pat in arm.pats.iter() {
-                this.gather_pat(cmt, *pat, Some((arm.body.id, ex.id)));
+                this.gather_pat(cmt.clone(), *pat, Some((arm.body.id, ex.id)));
             }
         }
         visit::walk_expr(this, ex, ());
@@ -296,9 +298,9 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
     }
 }
 
-fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |@LoanPath|) {
+fn with_assignee_loan_path(bccx: &BorrowckCtxt, expr: &ast::Expr, op: |Rc<LoanPath>|) {
     let cmt = bccx.cat_expr(expr);
-    match opt_loan_path(cmt) {
+    match opt_loan_path(&cmt) {
         Some(lp) => op(lp),
         None => {
             // This can occur with e.g. `*foo() = 5`.  In such
@@ -375,14 +377,13 @@ impl<'a> GatherLoanCtxt<'a> {
     pub fn guarantee_autoderefs(&mut self,
                                 expr: &ast::Expr,
                                 autoderefs: uint) {
-        let method_map = self.bccx.method_map.borrow();
+        let method_map = self.bccx.tcx.method_map.borrow();
         for i in range(0, autoderefs) {
             match method_map.find(&MethodCall::autoderef(expr.id, i as u32)) {
                 Some(method) => {
                     // Treat overloaded autoderefs as if an AutoRef adjustment
                     // was applied on the base type, as that is always the case.
-                    let mut mc = self.bccx.mc();
-                    let cmt = match mc.cat_expr_autoderefd(expr, i) {
+                    let cmt = match self.bccx.mc().cat_expr_autoderefd(expr, i) {
                         Ok(v) => v,
                         Err(()) => self.tcx().sess.span_bug(expr.span, "Err from mc")
                     };
@@ -431,7 +432,7 @@ impl<'a> GatherLoanCtxt<'a> {
                     autoref: Some(ref autoref),
                     autoderefs}) => {
                 self.guarantee_autoderefs(expr, autoderefs);
-                let mut mc = self.bccx.mc();
+                let mc = self.bccx.mc();
                 let cmt = match mc.cat_expr_autoderefd(expr, autoderefs) {
                     Ok(v) => v,
                     Err(()) => self.tcx().sess.span_bug(expr.span, "Err from mc")
@@ -551,20 +552,20 @@ impl<'a> GatherLoanCtxt<'a> {
         // Check that the lifetime of the borrow does not exceed
         // the lifetime of the data being borrowed.
         if lifetime::guarantee_lifetime(self.bccx, self.item_ub, root_ub,
-                                        borrow_span, cause, cmt, loan_region,
+                                        borrow_span, cause, cmt.clone(), loan_region,
                                         req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of non-mutable data.
         if check_mutability(self.bccx, borrow_span, cause,
-                            cmt, req_kind).is_err() {
+                            cmt.clone(), req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
         // Check that we don't allow mutable borrows of aliasable data.
         if check_aliasability(self.bccx, borrow_span, cause,
-                              cmt, req_kind).is_err() {
+                              cmt.clone(), req_kind).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
@@ -572,7 +573,7 @@ impl<'a> GatherLoanCtxt<'a> {
         // loan is safe.
         let restr = restrictions::compute_restrictions(
             self.bccx, borrow_span, cause,
-            cmt, loan_region, self.restriction_set(req_kind));
+            cmt.clone(), loan_region, self.restriction_set(req_kind));
 
         // Create the loan record (if needed).
         let loan = match restr {
@@ -612,11 +613,11 @@ impl<'a> GatherLoanCtxt<'a> {
                 let gen_scope = self.compute_gen_scope(borrow_id, loan_scope);
                 debug!("gen_scope = {:?}", gen_scope);
 
-                let kill_scope = self.compute_kill_scope(loan_scope, loan_path);
+                let kill_scope = self.compute_kill_scope(loan_scope, &*loan_path);
                 debug!("kill_scope = {:?}", kill_scope);
 
                 if req_kind == ty::MutBorrow {
-                    self.mark_loan_path_as_mutated(loan_path);
+                    self.mark_loan_path_as_mutated(&*loan_path);
                 }
 
                 Loan {
@@ -718,7 +719,7 @@ impl<'a> GatherLoanCtxt<'a> {
         }
     }
 
-    pub fn mark_loan_path_as_mutated(&self, loan_path: @LoanPath) {
+    pub fn mark_loan_path_as_mutated(&self, loan_path: &LoanPath) {
         //! For mutable loans of content whose mutability derives
         //! from a local variable, mark the mutability decl as necessary.
 
@@ -726,8 +727,8 @@ impl<'a> GatherLoanCtxt<'a> {
             LpVar(local_id) => {
                 self.tcx().used_mut_nodes.borrow_mut().insert(local_id);
             }
-            LpExtend(base, mc::McInherited, _) => {
-                self.mark_loan_path_as_mutated(base);
+            LpExtend(ref base, mc::McInherited, _) => {
+                self.mark_loan_path_as_mutated(&**base);
             }
             LpExtend(_, mc::McDeclared, _) |
             LpExtend(_, mc::McImmutable, _) => {
@@ -752,7 +753,7 @@ impl<'a> GatherLoanCtxt<'a> {
         }
     }
 
-    pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: @LoanPath)
+    pub fn compute_kill_scope(&self, loan_scope: ast::NodeId, lp: &LoanPath)
                               -> ast::NodeId {
         //! Determine when the loan restrictions go out of scope.
         //! This is either when the lifetime expires or when the
@@ -793,7 +794,7 @@ impl<'a> GatherLoanCtxt<'a> {
          * `gather_pat()`.
          */
 
-        let mut mc = self.bccx.mc();
+        let mc = self.bccx.mc();
         for arg in decl.inputs.iter() {
             let arg_ty = ty::node_id_to_type(self.tcx(), arg.pat.id);
 
@@ -822,12 +823,12 @@ impl<'a> GatherLoanCtxt<'a> {
               ast::PatIdent(bm, _, _) if self.pat_is_binding(pat) => {
                 // Each match binding is effectively an assignment.
                 let tcx = self.bccx.tcx;
-                pat_util::pat_bindings(tcx.def_map, pat, |_, id, span, _| {
+                pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
                     gather_moves::gather_assignment(self.bccx,
                                                     &self.move_data,
                                                     id,
                                                     span,
-                                                    @LpVar(id),
+                                                    Rc::new(LpVar(id)),
                                                     id);
                 });
 
@@ -920,7 +921,7 @@ impl<'a> GatherLoanCtxt<'a> {
     }
 
     pub fn pat_is_binding(&self, pat: &ast::Pat) -> bool {
-        pat_util::pat_is_binding(self.bccx.tcx.def_map, pat)
+        pat_util::pat_is_binding(&self.bccx.tcx.def_map, pat)
     }
 
     pub fn report_potential_errors(&self) {
diff --git a/src/librustc/middle/borrowck/gather_loans/move_error.rs b/src/librustc/middle/borrowck/gather_loans/move_error.rs
index c9a8df0f535..24d873e0ff7 100644
--- a/src/librustc/middle/borrowck/gather_loans/move_error.rs
+++ b/src/librustc/middle/borrowck/gather_loans/move_error.rs
@@ -79,7 +79,7 @@ pub struct GroupedMoveErrors {
 fn report_move_errors(bccx: &BorrowckCtxt, errors: &Vec<MoveError>) {
     let grouped_errors = group_errors_with_same_origin(errors);
     for error in grouped_errors.iter() {
-        report_cannot_move_out_of(bccx, error.move_from);
+        report_cannot_move_out_of(bccx, error.move_from.clone());
         let mut is_first_note = true;
         for move_to in error.move_to_places.iter() {
             note_move_destination(bccx, move_to.span,
@@ -112,7 +112,7 @@ fn group_errors_with_same_origin(errors: &Vec<MoveError>)
             }
         }
         grouped_errors.push(GroupedMoveErrors {
-            move_from: error.move_from,
+            move_from: error.move_from.clone(),
             move_to_places: move_to
         })
     }
@@ -128,11 +128,11 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) {
             bccx.span_err(
                 move_from.span,
                 format!("cannot move out of {}",
-                        bccx.cmt_to_str(move_from)));
+                        bccx.cmt_to_str(&*move_from)));
         }
 
-        mc::cat_downcast(b) |
-        mc::cat_interior(b, _) => {
+        mc::cat_downcast(ref b) |
+        mc::cat_interior(ref b, _) => {
             match ty::get(b.ty).sty {
                 ty::ty_struct(did, _)
                 | ty::ty_enum(did, _) if ty::has_dtor(bccx.tcx, did) => {
diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
index 39ea9e17b26..de4ce84fb0a 100644
--- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs
@@ -18,9 +18,11 @@ use middle::ty;
 use syntax::codemap::Span;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
+
 pub enum RestrictionResult {
     Safe,
-    SafeIf(@LoanPath, Vec<Restriction> )
+    SafeIf(Rc<LoanPath>, Vec<Restriction>)
 }
 
 pub fn compute_restrictions(bccx: &BorrowckCtxt,
@@ -33,7 +35,7 @@ pub fn compute_restrictions(bccx: &BorrowckCtxt,
         bccx: bccx,
         span: span,
         cause: cause,
-        cmt_original: cmt,
+        cmt_original: cmt.clone(),
         loan_region: loan_region,
     };
 
@@ -59,7 +61,7 @@ impl<'a> RestrictionsContext<'a> {
                cmt.repr(self.bccx.tcx),
                restrictions.repr(self.bccx.tcx));
 
-        match cmt.cat {
+        match cmt.cat.clone() {
             mc::cat_rvalue(..) => {
                 // Effectively, rvalues are stored into a
                 // non-aliasable temporary on the stack. Since they
@@ -73,9 +75,11 @@ impl<'a> RestrictionsContext<'a> {
             mc::cat_arg(local_id) |
             mc::cat_upvar(ty::UpvarId {var_id: local_id, ..}, _) => {
                 // R-Variable
-                let lp = @LpVar(local_id);
-                SafeIf(lp, vec!(Restriction {loan_path: lp,
-                                          set: restrictions}))
+                let lp = Rc::new(LpVar(local_id));
+                SafeIf(lp.clone(), vec!(Restriction {
+                    loan_path: lp,
+                    set: restrictions
+                }))
             }
 
             mc::cat_downcast(cmt_base) => {
@@ -170,9 +174,13 @@ impl<'a> RestrictionsContext<'a> {
               restrictions: RestrictionSet) -> RestrictionResult {
         match result {
             Safe => Safe,
-            SafeIf(base_lp, base_vec) => {
-                let lp = @LpExtend(base_lp, mc, elem);
-                SafeIf(lp, base_vec.append_one(Restriction { loan_path: lp, set: restrictions }))
+            SafeIf(base_lp, mut base_vec) => {
+                let lp = Rc::new(LpExtend(base_lp, mc, elem));
+                base_vec.push(Restriction {
+                    loan_path: lp.clone(),
+                    set: restrictions
+                });
+                SafeIf(lp, base_vec)
             }
         }
     }
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index 21e68e2724f..06491d36b02 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -18,14 +18,14 @@ use middle::typeck;
 use middle::moves;
 use middle::dataflow::DataFlowContext;
 use middle::dataflow::DataFlowOperator;
-use util::nodemap::NodeSet;
+use util::nodemap::{NodeMap, NodeSet};
 use util::ppaux::{note_and_explain_region, Repr, UserString};
 
-use std::cell::{Cell, RefCell};
-use collections::HashMap;
+use std::cell::RefCell;
 use std::ops::{BitOr, BitAnd};
-use std::result::Result;
+use std::rc::Rc;
 use std::strbuf::StrBuf;
+use collections::HashMap;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util;
@@ -76,7 +76,6 @@ impl<'a> Visitor<()> for BorrowckCtxt<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    moves_map: &NodeSet,
                    moved_variables_set: &NodeSet,
                    capture_map: &moves::CaptureMap,
@@ -84,41 +83,15 @@ pub fn check_crate(tcx: &ty::ctxt,
                    -> root_map {
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
-        method_map: method_map,
         moves_map: moves_map,
         moved_variables_set: moved_variables_set,
         capture_map: capture_map,
-        root_map: root_map(),
-        stats: @BorrowStats {
-            loaned_paths_same: Cell::new(0),
-            loaned_paths_imm: Cell::new(0),
-            stable_paths: Cell::new(0),
-            guaranteed_paths: Cell::new(0),
-        }
+        root_map: RefCell::new(HashMap::new())
     };
-    let bccx = &mut bccx;
-
-    visit::walk_crate(bccx, krate, ());
 
-    if tcx.sess.borrowck_stats() {
-        println!("--- borrowck stats ---");
-        println!("paths requiring guarantees: {}",
-                 bccx.stats.guaranteed_paths.get());
-        println!("paths requiring loans     : {}",
-                 make_stat(bccx, bccx.stats.loaned_paths_same.get()));
-        println!("paths requiring imm loans : {}",
-                 make_stat(bccx, bccx.stats.loaned_paths_imm.get()));
-        println!("stable paths              : {}",
-                 make_stat(bccx, bccx.stats.stable_paths.get()));
-    }
-
-    return bccx.root_map;
+    visit::walk_crate(&mut bccx, krate, ());
 
-    fn make_stat(bccx: &mut BorrowckCtxt, stat: uint) -> ~str {
-        let stat_f = stat as f64;
-        let total = bccx.stats.guaranteed_paths.get() as f64;
-        format!("{} ({:.0f}%)", stat  , stat_f * 100.0 / total)
-    }
+    return bccx.root_map.unwrap();
 }
 
 fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
@@ -149,7 +122,6 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
         gather_loans::gather_loans_in_fn(this, decl, body);
     let mut loan_dfcx =
         DataFlowContext::new(this.tcx,
-                             this.method_map,
                              LoanDataFlowOperator,
                              id_range,
                              all_loans.len());
@@ -161,7 +133,6 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
     let flowed_moves = move_data::FlowedMoveData::new(move_data,
                                                       this.tcx,
-                                                      this.method_map,
                                                       id_range,
                                                       body);
 
@@ -176,21 +147,10 @@ fn borrowck_fn(this: &mut BorrowckCtxt,
 
 pub struct BorrowckCtxt<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
     moves_map: &'a NodeSet,
     moved_variables_set: &'a NodeSet,
     capture_map: &'a moves::CaptureMap,
-    root_map: root_map,
-
-    // Statistics:
-    stats: @BorrowStats
-}
-
-pub struct BorrowStats {
-    loaned_paths_same: Cell<uint>,
-    loaned_paths_imm: Cell<uint>,
-    stable_paths: Cell<uint>,
-    guaranteed_paths: Cell<uint>,
+    root_map: RefCell<root_map>,
 }
 
 // The keys to the root map combine the `id` of the deref expression
@@ -226,10 +186,10 @@ pub enum PartialTotal {
 /// Record of a loan that was issued.
 pub struct Loan {
     index: uint,
-    loan_path: @LoanPath,
+    loan_path: Rc<LoanPath>,
     cmt: mc::cmt,
     kind: ty::BorrowKind,
-    restrictions: Vec<Restriction> ,
+    restrictions: Vec<Restriction>,
     gen_scope: ast::NodeId,
     kill_scope: ast::NodeId,
     span: Span,
@@ -247,7 +207,7 @@ pub enum LoanCause {
 #[deriving(Eq, TotalEq, Hash)]
 pub enum LoanPath {
     LpVar(ast::NodeId),               // `x` in doc.rs
-    LpExtend(@LoanPath, mc::MutabilityCategory, LoanPathElem)
+    LpExtend(Rc<LoanPath>, mc::MutabilityCategory, LoanPathElem)
 }
 
 #[deriving(Eq, TotalEq, Hash)]
@@ -260,12 +220,12 @@ impl LoanPath {
     pub fn node_id(&self) -> ast::NodeId {
         match *self {
             LpVar(local_id) => local_id,
-            LpExtend(base, _, _) => base.node_id()
+            LpExtend(ref base, _, _) => base.node_id()
         }
     }
 }
 
-pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
+pub fn opt_loan_path(cmt: &mc::cmt) -> Option<Rc<LoanPath>> {
     //! Computes the `LoanPath` (if any) for a `cmt`.
     //! Note that this logic is somewhat duplicated in
     //! the method `compute()` found in `gather_loans::restrictions`,
@@ -283,23 +243,23 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
         mc::cat_arg(id) |
         mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) |
         mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => {
-            Some(@LpVar(id))
+            Some(Rc::new(LpVar(id)))
         }
 
-        mc::cat_deref(cmt_base, _, pk) => {
+        mc::cat_deref(ref cmt_base, _, pk) => {
             opt_loan_path(cmt_base).map(|lp| {
-                @LpExtend(lp, cmt.mutbl, LpDeref(pk))
+                Rc::new(LpExtend(lp, cmt.mutbl, LpDeref(pk)))
             })
         }
 
-        mc::cat_interior(cmt_base, ik) => {
+        mc::cat_interior(ref cmt_base, ik) => {
             opt_loan_path(cmt_base).map(|lp| {
-                @LpExtend(lp, cmt.mutbl, LpInterior(ik))
+                Rc::new(LpExtend(lp, cmt.mutbl, LpInterior(ik)))
             })
         }
 
-        mc::cat_downcast(cmt_base) |
-        mc::cat_discr(cmt_base, _) => {
+        mc::cat_downcast(ref cmt_base) |
+        mc::cat_discr(ref cmt_base, _) => {
             opt_loan_path(cmt_base)
         }
     }
@@ -319,7 +279,7 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
 // because the restriction against moves is implied.
 
 pub struct Restriction {
-    loan_path: @LoanPath,
+    loan_path: Rc<LoanPath>,
     set: RestrictionSet
 }
 
@@ -380,11 +340,7 @@ pub struct RootInfo {
     pub scope: ast::NodeId,
 }
 
-pub type root_map = @RefCell<HashMap<root_map_key, RootInfo>>;
-
-pub fn root_map() -> root_map {
-    return @RefCell::new(HashMap::new());
-}
+pub type root_map = HashMap<root_map_key, RootInfo>;
 
 ///////////////////////////////////////////////////////////////////////////
 // Errors
@@ -437,12 +393,9 @@ impl<'a> BorrowckCtxt<'a> {
         self.moves_map.contains(&id)
     }
 
-    pub fn mc(&self) -> mc::MemCategorizationContext<TcxTyper<'a>> {
+    pub fn mc(&self) -> mc::MemCategorizationContext<&'a ty::ctxt> {
         mc::MemCategorizationContext {
-            typer: TcxTyper {
-                tcx: self.tcx,
-                method_map: self.method_map
-            }
+            typer: self.tcx,
         }
     }
 
@@ -516,14 +469,16 @@ impl<'a> BorrowckCtxt<'a> {
     }
 
     pub fn cat_discr(&self, cmt: mc::cmt, match_id: ast::NodeId) -> mc::cmt {
-        @mc::cmt_ {cat:mc::cat_discr(cmt, match_id),
-                   mutbl:cmt.mutbl.inherit(),
-                   ..*cmt}
+        Rc::new(mc::cmt_ {
+            cat: mc::cat_discr(cmt.clone(), match_id),
+            mutbl: cmt.mutbl.inherit(),
+            ..*cmt
+        })
     }
 
     pub fn cat_pattern(&self,
                        cmt: mc::cmt,
-                       pat: @ast::Pat,
+                       pat: &ast::Pat,
                        op: |mc::cmt, &ast::Pat|) {
         let r = self.mc().cat_pattern(cmt, pat, |_,x,y| op(x,y));
         assert!(r.is_ok());
@@ -532,7 +487,7 @@ impl<'a> BorrowckCtxt<'a> {
     pub fn report(&self, err: BckError) {
         self.span_err(
             err.span,
-            self.bckerr_to_str(err));
+            self.bckerr_to_str(&err));
         self.note_and_explain_bckerr(err);
     }
 
@@ -541,7 +496,7 @@ impl<'a> BorrowckCtxt<'a> {
                                      use_kind: MovedValueUseKind,
                                      lp: &LoanPath,
                                      move: &move_data::Move,
-                                     moved_lp: @LoanPath) {
+                                     moved_lp: &LoanPath) {
         let verb = match use_kind {
             MovedInUse => "use",
             MovedInCapture => "capture",
@@ -572,8 +527,7 @@ impl<'a> BorrowckCtxt<'a> {
             move_data::MoveExpr => {
                 let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
                     Some(ast_map::NodeExpr(expr)) => {
-                        (ty::expr_ty_adjusted(self.tcx, expr,
-                                              &*self.method_map.borrow()), expr.span)
+                        (ty::expr_ty_adjusted(self.tcx, expr), expr.span)
                     }
                     r => self.tcx.sess.bug(format!("MoveExpr({:?}) maps to {:?}, not Expr",
                                                    move.id, r))
@@ -599,8 +553,7 @@ impl<'a> BorrowckCtxt<'a> {
             move_data::Captured => {
                 let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
                     Some(ast_map::NodeExpr(expr)) => {
-                        (ty::expr_ty_adjusted(self.tcx, expr,
-                                              &*self.method_map.borrow()), expr.span)
+                        (ty::expr_ty_adjusted(self.tcx, expr), expr.span)
                     }
                     r => self.tcx.sess.bug(format!("Captured({:?}) maps to {:?}, not Expr",
                                                    move.id, r))
@@ -656,17 +609,17 @@ impl<'a> BorrowckCtxt<'a> {
         self.tcx.sess.span_end_note(s, m);
     }
 
-    pub fn bckerr_to_str(&self, err: BckError) -> ~str {
+    pub fn bckerr_to_str(&self, err: &BckError) -> ~str {
         match err.code {
             err_mutbl => {
-                let descr = match opt_loan_path(err.cmt) {
+                let descr = match opt_loan_path(&err.cmt) {
                     None => format!("{} {}",
                                     err.cmt.mutbl.to_user_str(),
-                                    self.cmt_to_str(err.cmt)),
+                                    self.cmt_to_str(&*err.cmt)),
                     Some(lp) => format!("{} {} `{}`",
                                         err.cmt.mutbl.to_user_str(),
-                                        self.cmt_to_str(err.cmt),
-                                        self.loan_path_to_str(lp)),
+                                        self.cmt_to_str(&*err.cmt),
+                                        self.loan_path_to_str(&*lp)),
                 };
 
                 match err.cause {
@@ -682,16 +635,16 @@ impl<'a> BorrowckCtxt<'a> {
                 format!("cannot root managed value long enough")
             }
             err_out_of_scope(..) => {
-                let msg = match opt_loan_path(err.cmt) {
+                let msg = match opt_loan_path(&err.cmt) {
                     None => format!("borrowed value"),
-                    Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
+                    Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
                 };
                 format!("{} does not live long enough", msg)
             }
             err_borrowed_pointer_too_short(..) => {
-                let descr = match opt_loan_path(err.cmt) {
-                    Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
-                    None => self.cmt_to_str(err.cmt),
+                let descr = match opt_loan_path(&err.cmt) {
+                    Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
+                    None => self.cmt_to_str(&*err.cmt),
                 };
 
                 format!("lifetime of {} is too short to guarantee \
@@ -783,9 +736,9 @@ impl<'a> BorrowckCtxt<'a> {
             }
 
             err_borrowed_pointer_too_short(loan_scope, ptr_scope, _) => {
-                let descr = match opt_loan_path(err.cmt) {
-                    Some(lp) => format!("`{}`", self.loan_path_to_str(lp)),
-                    None => self.cmt_to_str(err.cmt),
+                let descr = match opt_loan_path(&err.cmt) {
+                    Some(lp) => format!("`{}`", self.loan_path_to_str(&*lp)),
+                    None => self.cmt_to_str(&*err.cmt),
                 };
                 note_and_explain_region(
                     self.tcx,
@@ -809,8 +762,8 @@ impl<'a> BorrowckCtxt<'a> {
                 out.push_str(ty::local_var_name_str(self.tcx, id).get());
             }
 
-            LpExtend(lp_base, _, LpInterior(mc::InteriorField(fname))) => {
-                self.append_autoderefd_loan_path_to_str(lp_base, out);
+            LpExtend(ref lp_base, _, LpInterior(mc::InteriorField(fname))) => {
+                self.append_autoderefd_loan_path_to_str(&**lp_base, out);
                 match fname {
                     mc::NamedField(fname) => {
                         out.push_char('.');
@@ -823,14 +776,14 @@ impl<'a> BorrowckCtxt<'a> {
                 }
             }
 
-            LpExtend(lp_base, _, LpInterior(mc::InteriorElement(_))) => {
-                self.append_autoderefd_loan_path_to_str(lp_base, out);
+            LpExtend(ref lp_base, _, LpInterior(mc::InteriorElement(_))) => {
+                self.append_autoderefd_loan_path_to_str(&**lp_base, out);
                 out.push_str("[..]");
             }
 
-            LpExtend(lp_base, _, LpDeref(_)) => {
+            LpExtend(ref lp_base, _, LpDeref(_)) => {
                 out.push_char('*');
-                self.append_loan_path_to_str(lp_base, out);
+                self.append_loan_path_to_str(&**lp_base, out);
             }
         }
     }
@@ -839,11 +792,11 @@ impl<'a> BorrowckCtxt<'a> {
                                               loan_path: &LoanPath,
                                               out: &mut StrBuf) {
         match *loan_path {
-            LpExtend(lp_base, _, LpDeref(_)) => {
+            LpExtend(ref lp_base, _, LpDeref(_)) => {
                 // For a path like `(*x).f` or `(*x)[3]`, autoderef
                 // rules would normally allow users to omit the `*x`.
                 // So just serialize such paths to `x.f` or x[3]` respectively.
-                self.append_autoderefd_loan_path_to_str(lp_base, out)
+                self.append_autoderefd_loan_path_to_str(&**lp_base, out)
             }
 
             LpVar(..) | LpExtend(_, _, LpInterior(..)) => {
@@ -858,7 +811,7 @@ impl<'a> BorrowckCtxt<'a> {
         result.into_owned()
     }
 
-    pub fn cmt_to_str(&self, cmt: mc::cmt) -> ~str {
+    pub fn cmt_to_str(&self, cmt: &mc::cmt_) -> ~str {
         self.mc().cmt_to_str(cmt)
     }
 }
@@ -902,11 +855,11 @@ impl Repr for LoanPath {
                 format!("$({})", tcx.map.node_to_str(id))
             }
 
-            &LpExtend(lp, _, LpDeref(_)) => {
+            &LpExtend(ref lp, _, LpDeref(_)) => {
                 format!("{}.*", lp.repr(tcx))
             }
 
-            &LpExtend(lp, _, LpInterior(ref interior)) => {
+            &LpExtend(ref lp, _, LpInterior(ref interior)) => {
                 format!("{}.{}", lp.repr(tcx), interior.repr(tcx))
             }
         }
@@ -915,37 +868,32 @@ impl Repr for LoanPath {
 
 ///////////////////////////////////////////////////////////////////////////
 
-pub struct TcxTyper<'a> {
-    tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
-}
-
-impl<'a> mc::Typer for TcxTyper<'a> {
+impl<'a> mc::Typer for &'a ty::ctxt {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
-        self.tcx
+        *self
     }
 
-    fn node_ty(&mut self, id: ast::NodeId) -> mc::McResult<ty::t> {
-        Ok(ty::node_id_to_type(self.tcx, id))
+    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
+        Ok(ty::node_id_to_type(*self, id))
     }
 
     fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t> {
         self.method_map.borrow().find(&method_call).map(|method| method.ty)
     }
 
-    fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
-        self.tcx.adjustments.borrow().find_copy(&id)
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+        &self.adjustments
     }
 
-    fn is_method_call(&mut self, id: ast::NodeId) -> bool {
+    fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
     }
 
-    fn temporary_scope(&mut self, id: ast::NodeId) -> Option<ast::NodeId> {
-        self.tcx.region_maps.temporary_scope(id)
+    fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
+        self.region_maps.temporary_scope(id)
     }
 
-    fn upvar_borrow(&mut self, id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.tcx.upvar_borrow_map.borrow().get_copy(&id)
+    fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
+        self.upvar_borrow_map.borrow().get_copy(&id)
     }
 }
diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs
index 0e18946a3a1..efdc103d14d 100644
--- a/src/librustc/middle/borrowck/move_data.rs
+++ b/src/librustc/middle/borrowck/move_data.rs
@@ -16,13 +16,13 @@ comments in the section "Moves and initialization" and in `doc.rs`.
 */
 
 use std::cell::RefCell;
+use std::rc::Rc;
 use std::uint;
 use collections::{HashMap, HashSet};
 use middle::borrowck::*;
 use middle::dataflow::DataFlowContext;
 use middle::dataflow::DataFlowOperator;
 use middle::ty;
-use middle::typeck;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
@@ -33,7 +33,7 @@ pub struct MoveData {
     pub paths: RefCell<Vec<MovePath>>,
 
     /// Cache of loan path to move path index, for easy lookup.
-    pub path_map: RefCell<HashMap<@LoanPath, MovePathIndex>>,
+    pub path_map: RefCell<HashMap<Rc<LoanPath>, MovePathIndex>>,
 
     /// Each move or uninitialized variable gets an entry here.
     pub moves: RefCell<Vec<Move>>,
@@ -97,7 +97,7 @@ static InvalidMoveIndex: MoveIndex =
 
 pub struct MovePath {
     /// Loan path corresponding to this move path
-    pub loan_path: @LoanPath,
+    pub loan_path: Rc<LoanPath>,
 
     /// Parent pointer, `InvalidMovePathIndex` if root
     pub parent: MovePathIndex,
@@ -182,8 +182,8 @@ impl MoveData {
         }
     }
 
-    fn path_loan_path(&self, index: MovePathIndex) -> @LoanPath {
-        self.paths.borrow().get(index.get()).loan_path
+    fn path_loan_path(&self, index: MovePathIndex) -> Rc<LoanPath> {
+        self.paths.borrow().get(index.get()).loan_path.clone()
     }
 
     fn path_parent(&self, index: MovePathIndex) -> MovePathIndex {
@@ -226,7 +226,7 @@ impl MoveData {
 
     pub fn move_path(&self,
                      tcx: &ty::ctxt,
-                     lp: @LoanPath) -> MovePathIndex {
+                     lp: Rc<LoanPath>) -> MovePathIndex {
         /*!
          * Returns the existing move path index for `lp`, if any,
          * and otherwise adds a new index for `lp` and any of its
@@ -245,7 +245,7 @@ impl MoveData {
                 let index = MovePathIndex(self.paths.borrow().len());
 
                 self.paths.borrow_mut().push(MovePath {
-                    loan_path: lp,
+                    loan_path: lp.clone(),
                     parent: InvalidMovePathIndex,
                     first_move: InvalidMoveIndex,
                     first_child: InvalidMovePathIndex,
@@ -255,8 +255,8 @@ impl MoveData {
                 index
             }
 
-            LpExtend(base, _, _) => {
-                let parent_index = self.move_path(tcx, base);
+            LpExtend(ref base, _, _) => {
+                let parent_index = self.move_path(tcx, base.clone());
 
                 let index = MovePathIndex(self.paths.borrow().len());
 
@@ -264,7 +264,7 @@ impl MoveData {
                 self.set_path_first_child(parent_index, index);
 
                 self.paths.borrow_mut().push(MovePath {
-                    loan_path: lp,
+                    loan_path: lp.clone(),
                     parent: parent_index,
                     first_move: InvalidMoveIndex,
                     first_child: InvalidMovePathIndex,
@@ -284,29 +284,26 @@ impl MoveData {
         return index;
     }
 
-    fn existing_move_path(&self,
-                          lp: @LoanPath)
+    fn existing_move_path(&self, lp: &Rc<LoanPath>)
                           -> Option<MovePathIndex> {
-        self.path_map.borrow().find_copy(&lp)
+        self.path_map.borrow().find_copy(lp)
     }
 
-    fn existing_base_paths(&self,
-                           lp: @LoanPath)
+    fn existing_base_paths(&self, lp: &Rc<LoanPath>)
                            -> Vec<MovePathIndex> {
         let mut result = vec!();
         self.add_existing_base_paths(lp, &mut result);
         result
     }
 
-    fn add_existing_base_paths(&self,
-                               lp: @LoanPath,
+    fn add_existing_base_paths(&self, lp: &Rc<LoanPath>,
                                result: &mut Vec<MovePathIndex>) {
         /*!
          * Adds any existing move path indices for `lp` and any base
          * paths of `lp` to `result`, but does not add new move paths
          */
 
-        match self.path_map.borrow().find_copy(&lp) {
+        match self.path_map.borrow().find_copy(lp) {
             Some(index) => {
                 self.each_base_path(index, |p| {
                     result.push(p);
@@ -314,9 +311,9 @@ impl MoveData {
                 });
             }
             None => {
-                match *lp {
+                match **lp {
                     LpVar(..) => { }
-                    LpExtend(b, _, _) => {
+                    LpExtend(ref b, _, _) => {
                         self.add_existing_base_paths(b, result);
                     }
                 }
@@ -327,7 +324,7 @@ impl MoveData {
 
     pub fn add_move(&self,
                     tcx: &ty::ctxt,
-                    lp: @LoanPath,
+                    lp: Rc<LoanPath>,
                     id: ast::NodeId,
                     kind: MoveKind) {
         /*!
@@ -356,7 +353,7 @@ impl MoveData {
 
     pub fn add_assignment(&self,
                           tcx: &ty::ctxt,
-                          lp: @LoanPath,
+                          lp: Rc<LoanPath>,
                           assign_id: ast::NodeId,
                           span: Span,
                           assignee_id: ast::NodeId,
@@ -369,7 +366,7 @@ impl MoveData {
         debug!("add_assignment(lp={}, assign_id={:?}, assignee_id={:?}",
                lp.repr(tcx), assign_id, assignee_id);
 
-        let path_index = self.move_path(tcx, lp);
+        let path_index = self.move_path(tcx, lp.clone());
 
         if !is_also_move {
             self.assignee_ids.borrow_mut().insert(assignee_id);
@@ -511,19 +508,16 @@ impl MoveData {
 impl<'a> FlowedMoveData<'a> {
     pub fn new(move_data: MoveData,
                tcx: &'a ty::ctxt,
-               method_map: typeck::MethodMap,
                id_range: ast_util::IdRange,
                body: &ast::Block)
                -> FlowedMoveData<'a> {
         let mut dfcx_moves =
             DataFlowContext::new(tcx,
-                                 method_map,
                                  MoveDataFlowOperator,
                                  id_range,
                                  move_data.moves.borrow().len());
         let mut dfcx_assign =
             DataFlowContext::new(tcx,
-                                 method_map,
                                  AssignDataFlowOperator,
                                  id_range,
                                  move_data.var_assignments.borrow().len());
@@ -539,7 +533,7 @@ impl<'a> FlowedMoveData<'a> {
 
     pub fn each_path_moved_by(&self,
                               id: ast::NodeId,
-                              f: |&Move, @LoanPath| -> bool)
+                              f: |&Move, &LoanPath| -> bool)
                               -> bool {
         /*!
          * Iterates through each path moved by `id`
@@ -549,14 +543,14 @@ impl<'a> FlowedMoveData<'a> {
             let move = self.move_data.moves.borrow();
             let move = move.get(index);
             let moved_path = move.path;
-            f(move, self.move_data.path_loan_path(moved_path))
+            f(move, &*self.move_data.path_loan_path(moved_path))
         })
     }
 
     pub fn each_move_of(&self,
                         id: ast::NodeId,
-                        loan_path: @LoanPath,
-                        f: |&Move, @LoanPath| -> bool)
+                        loan_path: &Rc<LoanPath>,
+                        f: |&Move, &LoanPath| -> bool)
                         -> bool {
         /*!
          * Iterates through each move of `loan_path` (or some base path
@@ -591,7 +585,7 @@ impl<'a> FlowedMoveData<'a> {
             if base_indices.iter().any(|x| x == &moved_path) {
                 // Scenario 1 or 2: `loan_path` or some base path of
                 // `loan_path` was moved.
-                if !f(move, self.move_data.path_loan_path(moved_path)) {
+                if !f(move, &*self.move_data.path_loan_path(moved_path)) {
                     ret = false;
                 }
             } else {
@@ -600,7 +594,7 @@ impl<'a> FlowedMoveData<'a> {
                         if p == loan_path_index {
                             // Scenario 3: some extension of `loan_path`
                             // was moved
-                            f(move, self.move_data.path_loan_path(moved_path))
+                            f(move, &*self.move_data.path_loan_path(moved_path))
                         } else {
                             true
                         }
@@ -621,7 +615,7 @@ impl<'a> FlowedMoveData<'a> {
 
     pub fn each_assignment_of(&self,
                               id: ast::NodeId,
-                              loan_path: @LoanPath,
+                              loan_path: &Rc<LoanPath>,
                               f: |&Assignment| -> bool)
                               -> bool {
         /*!
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 67f3b8fe906..eb52aa18de8 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -21,8 +21,6 @@ use syntax::visit::Visitor;
 use syntax::visit;
 
 pub struct CheckCrateVisitor<'a> {
-    def_map: resolve::DefMap,
-    method_map: typeck::MethodMap,
     tcx: &'a ty::ctxt,
 }
 
@@ -38,16 +36,8 @@ impl<'a> Visitor<bool> for CheckCrateVisitor<'a> {
     }
 }
 
-pub fn check_crate(krate: &Crate,
-                   def_map: resolve::DefMap,
-                   method_map: typeck::MethodMap,
-                   tcx: &ty::ctxt) {
-    let mut v = CheckCrateVisitor {
-        def_map: def_map,
-        method_map: method_map,
-        tcx: tcx,
-    };
-    visit::walk_crate(&mut v, krate, false);
+pub fn check_crate(krate: &Crate, tcx: &ty::ctxt) {
+    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx }, krate, false);
     tcx.sess.abort_if_errors();
 }
 
@@ -55,7 +45,7 @@ fn check_item(v: &mut CheckCrateVisitor, it: &Item, _is_const: bool) {
     match it.node {
         ItemStatic(_, _, ex) => {
             v.visit_expr(ex, true);
-            check_item_recursion(&v.tcx.sess, &v.tcx.map, v.def_map, it);
+            check_item_recursion(&v.tcx.sess, &v.tcx.map, &v.tcx.def_map, it);
         }
         ItemEnum(ref enum_definition, _) => {
             for var in (*enum_definition).variants.iter() {
@@ -103,7 +93,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
           ExprLit(lit) if ast_util::lit_is_str(lit) => {}
           ExprBinary(..) | ExprUnary(..) => {
             let method_call = typeck::MethodCall::expr(e.id);
-            if v.method_map.borrow().contains_key(&method_call) {
+            if v.tcx.method_map.borrow().contains_key(&method_call) {
                 v.tcx.sess.span_err(e.span, "user-defined operators are not \
                                              allowed in constant expressions");
             }
@@ -127,7 +117,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
                                     "paths in constants may only refer to \
                                      items without type parameters");
             }
-            match v.def_map.borrow().find(&e.id) {
+            match v.tcx.def_map.borrow().find(&e.id) {
               Some(&DefStatic(..)) |
               Some(&DefFn(_, _)) |
               Some(&DefVariant(_, _, _)) |
@@ -145,7 +135,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) {
             }
           }
           ExprCall(callee, _) => {
-            match v.def_map.borrow().find(&callee.id) {
+            match v.tcx.def_map.borrow().find(&callee.id) {
                 Some(&DefStruct(..)) => {}    // OK.
                 Some(&DefVariant(..)) => {}    // OK.
                 _ => {
@@ -188,14 +178,14 @@ struct CheckItemRecursionVisitor<'a> {
     root_it: &'a Item,
     sess: &'a Session,
     ast_map: &'a ast_map::Map,
-    def_map: resolve::DefMap,
+    def_map: &'a resolve::DefMap,
     idstack: Vec<NodeId> }
 
 // Make sure a const item doesn't recursively refer to itself
 // FIXME: Should use the dependency graph when it's available (#1356)
 pub fn check_item_recursion<'a>(sess: &'a Session,
                                 ast_map: &'a ast_map::Map,
-                                def_map: resolve::DefMap,
+                                def_map: &'a resolve::DefMap,
                                 it: &'a Item) {
 
     let mut visitor = CheckItemRecursionVisitor {
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index db1badb7d59..2ef009e36e4 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -15,7 +15,6 @@ use middle::const_eval::{eval_const_expr, const_val, const_bool, const_float};
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
-use middle::typeck::MethodMap;
 use util::nodemap::NodeSet;
 use util::ppaux::ty_to_str;
 
@@ -30,7 +29,6 @@ use syntax::visit::{Visitor, FnKind};
 
 struct MatchCheckCtxt<'a> {
     tcx: &'a ty::ctxt,
-    method_map: MethodMap,
     moves_map: &'a NodeSet
 }
 
@@ -47,12 +45,10 @@ impl<'a> Visitor<()> for MatchCheckCtxt<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: MethodMap,
                    moves_map: &NodeSet,
                    krate: &Crate) {
     let mut cx = MatchCheckCtxt {
         tcx: tcx,
-        method_map: method_map,
         moves_map: moves_map
     };
 
@@ -938,7 +934,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                                        has_guard: bool,
                                        pats: &[@Pat]) {
     let tcx = cx.tcx;
-    let def_map = tcx.def_map;
+    let def_map = &tcx.def_map;
     let mut by_ref_span = None;
     let mut any_by_move = false;
     for pat in pats.iter() {
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index d39f0721b42..cd3ab100e55 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -15,7 +15,7 @@ use middle::astencode;
 
 use middle::ty;
 use middle::typeck::astconv;
-use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
+use util::nodemap::{DefIdMap, NodeMap};
 
 use syntax::ast::*;
 use syntax::parse::token::InternedString;
@@ -127,9 +127,7 @@ pub fn lookup_variant_by_id(tcx: &ty::ctxt,
             None => {}
         }
         let maps = astencode::Maps {
-            root_map: @RefCell::new(HashMap::new()),
-            method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(FnvHashMap::new()),
+            root_map: HashMap::new(),
             capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, enum_def,
@@ -168,9 +166,7 @@ pub fn lookup_const_by_id(tcx: &ty::ctxt, def_id: ast::DefId)
             None => {}
         }
         let maps = astencode::Maps {
-            root_map: @RefCell::new(HashMap::new()),
-            method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(FnvHashMap::new()),
+            root_map: HashMap::new(),
             capture_map: RefCell::new(NodeMap::new())
         };
         let e = match csearch::maybe_get_item_ast(tcx, def_id,
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index 2b79917f9d5..742daa82ecd 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -32,7 +32,6 @@ use util::nodemap::NodeMap;
 #[deriving(Clone)]
 pub struct DataFlowContext<'a, O> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
 
     /// the data flow operator
     oper: O,
@@ -123,7 +122,6 @@ impl<'a, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, O> {
 
 impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
     pub fn new(tcx: &'a ty::ctxt,
-               method_map: typeck::MethodMap,
                oper: O,
                id_range: IdRange,
                bits_per_id: uint) -> DataFlowContext<'a, O> {
@@ -138,7 +136,6 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> {
 
         DataFlowContext {
             tcx: tcx,
-            method_map: method_map,
             words_per_id: words_per_id,
             nodeid_to_bitset: NodeMap::new(),
             bits_per_id: bits_per_id,
@@ -784,7 +781,7 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> {
 
     fn is_method_call(&self, expr: &ast::Expr) -> bool {
         let method_call = typeck::MethodCall::expr(expr.id);
-        self.dfcx.method_map.borrow().contains_key(&method_call)
+        self.dfcx.tcx.method_map.borrow().contains_key(&method_call)
     }
 
     fn reset(&mut self, bits: &mut [uint]) {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index d0bf70ea1c2..74355357fe7 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -50,18 +50,15 @@ fn should_explore(tcx: &ty::ctxt, def_id: ast::DefId) -> bool {
 
 struct MarkSymbolVisitor<'a> {
     worklist: Vec<ast::NodeId>,
-    method_map: typeck::MethodMap,
     tcx: &'a ty::ctxt,
     live_symbols: ~HashSet<ast::NodeId>,
 }
 
 impl<'a> MarkSymbolVisitor<'a> {
     fn new(tcx: &'a ty::ctxt,
-           method_map: typeck::MethodMap,
            worklist: Vec<ast::NodeId>) -> MarkSymbolVisitor<'a> {
         MarkSymbolVisitor {
             worklist: worklist,
-            method_map: method_map,
             tcx: tcx,
             live_symbols: ~HashSet::new(),
         }
@@ -93,7 +90,7 @@ impl<'a> MarkSymbolVisitor<'a> {
     fn lookup_and_handle_method(&mut self, id: ast::NodeId,
                                 span: codemap::Span) {
         let method_call = typeck::MethodCall::expr(id);
-        match self.method_map.borrow().find(&method_call) {
+        match self.tcx.method_map.borrow().find(&method_call) {
             Some(method) => {
                 match method.origin {
                     typeck::MethodStatic(def_id) => {
@@ -275,7 +272,7 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
         None => ()
     }
 
-    // Seed implemeneted trait methods
+    // Seed implemented trait methods
     let mut life_seeder = LifeSeeder {
         worklist: worklist
     };
@@ -285,14 +282,13 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
 }
 
 fn find_live(tcx: &ty::ctxt,
-             method_map: typeck::MethodMap,
              exported_items: &privacy::ExportedItems,
              reachable_symbols: &NodeSet,
              krate: &ast::Crate)
              -> ~HashSet<ast::NodeId> {
     let worklist = create_and_seed_worklist(tcx, exported_items,
                                             reachable_symbols, krate);
-    let mut symbol_visitor = MarkSymbolVisitor::new(tcx, method_map, worklist);
+    let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
     symbol_visitor.mark_live_symbols();
     symbol_visitor.live_symbols
 }
@@ -340,13 +336,13 @@ impl<'a> DeadVisitor<'a> {
         // This is done to handle the case where, for example, the static
         // method of a private type is used, but the type itself is never
         // called directly.
-        let def_id = local_def(id);
-        match self.tcx.inherent_impls.borrow().find(&def_id) {
+        let impl_methods = self.tcx.impl_methods.borrow();
+        match self.tcx.inherent_impls.borrow().find(&local_def(id)) {
             None => (),
-            Some(ref impl_list) => {
-                for impl_ in impl_list.borrow().iter() {
-                    for method in impl_.methods.iter() {
-                        if self.live_symbols.contains(&method.def_id.node) {
+            Some(impl_list) => {
+                for impl_did in impl_list.borrow().iter() {
+                    for method_did in impl_methods.get(impl_did).iter() {
+                        if self.live_symbols.contains(&method_did.node) {
                             return true;
                         }
                     }
@@ -406,11 +402,10 @@ impl<'a> Visitor<()> for DeadVisitor<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    reachable_symbols: &NodeSet,
                    krate: &ast::Crate) {
-    let live_symbols = find_live(tcx, method_map, exported_items,
+    let live_symbols = find_live(tcx, exported_items,
                                  reachable_symbols, krate);
     let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
     visit::walk_crate(&mut visitor, krate, ());
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 827d07484b7..ef7c5924844 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -12,7 +12,7 @@
 /// `unsafe`.
 
 use middle::ty;
-use middle::typeck::{MethodCall, MethodMap};
+use middle::typeck::MethodCall;
 use util::ppaux;
 
 use syntax::ast;
@@ -38,8 +38,6 @@ fn type_is_unsafe_function(ty: ty::t) -> bool {
 struct EffectCheckVisitor<'a> {
     tcx: &'a ty::ctxt,
 
-    /// The method map.
-    method_map: MethodMap,
     /// Whether we're in an unsafe context.
     unsafe_context: UnsafeContext,
 }
@@ -138,7 +136,7 @@ impl<'a> Visitor<()> for EffectCheckVisitor<'a> {
         match expr.node {
             ast::ExprMethodCall(_, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
-                let base_type = self.method_map.borrow().get(&method_call).ty;
+                let base_type = self.tcx.method_map.borrow().get(&method_call).ty;
                 debug!("effect: method call case, base type is {}",
                        ppaux::ty_to_str(self.tcx, base_type));
                 if type_is_unsafe_function(base_type) {
@@ -190,10 +188,9 @@ impl<'a> Visitor<()> for EffectCheckVisitor<'a> {
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt, method_map: MethodMap, krate: &ast::Crate) {
+pub fn check_crate(tcx: &ty::ctxt, krate: &ast::Crate) {
     let mut visitor = EffectCheckVisitor {
         tcx: tcx,
-        method_map: method_map,
         unsafe_context: SafeContext,
     };
 
diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs
index d6adb19419b..83f6d5abfa4 100644
--- a/src/librustc/middle/freevars.rs
+++ b/src/librustc/middle/freevars.rs
@@ -29,16 +29,15 @@ pub struct freevar_entry {
     pub def: ast::Def, //< The variable being accessed free.
     pub span: Span     //< First span where it is accessed (there can be multiple)
 }
-pub type freevar_info = @Vec<@freevar_entry> ;
-pub type freevar_map = NodeMap<freevar_info>;
+pub type freevar_map = NodeMap<Vec<freevar_entry>>;
 
-struct CollectFreevarsVisitor {
+struct CollectFreevarsVisitor<'a> {
     seen: NodeSet,
-    refs: Vec<@freevar_entry> ,
-    def_map: resolve::DefMap,
+    refs: Vec<freevar_entry>,
+    def_map: &'a resolve::DefMap,
 }
 
-impl Visitor<int> for CollectFreevarsVisitor {
+impl<'a> Visitor<int> for CollectFreevarsVisitor<'a> {
 
     fn visit_item(&mut self, _: &ast::Item, _: int) {
         // ignore_item
@@ -65,7 +64,7 @@ impl Visitor<int> for CollectFreevarsVisitor {
                         if i == depth { // Made it to end of loop
                             let dnum = ast_util::def_id_of_def(def).node;
                             if !self.seen.contains(&dnum) {
-                                self.refs.push(@freevar_entry {
+                                self.refs.push(freevar_entry {
                                     def: def,
                                     span: expr.span,
                                 });
@@ -87,30 +86,23 @@ impl Visitor<int> for CollectFreevarsVisitor {
 // Since we want to be able to collect upvars in some arbitrary piece
 // of the AST, we take a walker function that we invoke with a visitor
 // in order to start the search.
-fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block) -> freevar_info {
-    let seen = NodeSet::new();
-    let refs = Vec::new();
-
+fn collect_freevars(def_map: &resolve::DefMap, blk: &ast::Block) -> Vec<freevar_entry> {
     let mut v = CollectFreevarsVisitor {
-        seen: seen,
-        refs: refs,
+        seen: NodeSet::new(),
+        refs: Vec::new(),
         def_map: def_map,
     };
 
     v.visit_block(blk, 1);
-    let CollectFreevarsVisitor {
-        refs,
-        ..
-    } = v;
-    return @refs;
+    v.refs
 }
 
-struct AnnotateFreevarsVisitor {
-    def_map: resolve::DefMap,
+struct AnnotateFreevarsVisitor<'a> {
+    def_map: &'a resolve::DefMap,
     freevars: freevar_map,
 }
 
-impl Visitor<()> for AnnotateFreevarsVisitor {
+impl<'a> Visitor<()> for AnnotateFreevarsVisitor<'a> {
     fn visit_fn(&mut self, fk: &visit::FnKind, fd: &ast::FnDecl,
                 blk: &ast::Block, s: Span, nid: ast::NodeId, _: ()) {
         let vars = collect_freevars(self.def_map, blk);
@@ -124,7 +116,7 @@ impl Visitor<()> for AnnotateFreevarsVisitor {
 // efficient as it fully recomputes the free variables at every
 // node of interest rather than building up the free variables in
 // one pass. This could be improved upon if it turns out to matter.
-pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) ->
+pub fn annotate_freevars(def_map: &resolve::DefMap, krate: &ast::Crate) ->
    freevar_map {
     let mut visitor = AnnotateFreevarsVisitor {
         def_map: def_map,
@@ -132,16 +124,12 @@ pub fn annotate_freevars(def_map: resolve::DefMap, krate: &ast::Crate) ->
     };
     visit::walk_crate(&mut visitor, krate, ());
 
-    let AnnotateFreevarsVisitor {
-        freevars,
-        ..
-    } = visitor;
-    freevars
+    visitor.freevars
 }
 
-pub fn get_freevars(tcx: &ty::ctxt, fid: ast::NodeId) -> freevar_info {
+pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| -> T) -> T {
     match tcx.freevars.borrow().find(&fid) {
-        None => fail!("get_freevars: {} has no freevars", fid),
-        Some(&d) => return d
+        None => fail!("with_freevars: {} has no freevars", fid),
+        Some(d) => f(d.as_slice())
     }
 }
diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs
index a152e06eb06..e6c885e56f1 100644
--- a/src/librustc/middle/kind.rs
+++ b/src/librustc/middle/kind.rs
@@ -47,7 +47,6 @@ use syntax::visit::Visitor;
 #[deriving(Clone)]
 pub struct Context<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
 }
 
 impl<'a> Visitor<()> for Context<'a> {
@@ -70,11 +69,9 @@ impl<'a> Visitor<()> for Context<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    krate: &Crate) {
     let mut ctx = Context {
         tcx: tcx,
-        method_map: method_map,
     };
     visit::walk_crate(&mut ctx, krate, ());
     tcx.sess.abort_if_errors();
@@ -115,9 +112,9 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t
                               .find(&trait_ref.ref_id)
                               .expect("trait ref not in def map!");
     let trait_def_id = ast_util::def_id_of_def(ast_trait_def);
-    let trait_def = *cx.tcx.trait_defs.borrow()
-                           .find(&trait_def_id)
-                           .expect("trait def not in trait-defs map!");
+    let trait_def = cx.tcx.trait_defs.borrow()
+                          .find_copy(&trait_def_id)
+                          .expect("trait def not in trait-defs map!");
 
     // If this trait has builtin-kind supertraits, meet them.
     let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id);
@@ -166,7 +163,7 @@ fn check_item(cx: &mut Context, item: &Item) {
 // closure.
 fn with_appropriate_checker(cx: &Context,
                             id: NodeId,
-                            b: |checker: |&Context, @freevar_entry||) {
+                            b: |checker: |&Context, &freevar_entry||) {
     fn check_for_uniq(cx: &Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) {
         // all captured data must be owned, regardless of whether it is
         // moved in or copied in.
@@ -187,7 +184,7 @@ fn with_appropriate_checker(cx: &Context,
                              bounds, Some(var_t));
     }
 
-    fn check_for_bare(cx: &Context, fv: @freevar_entry) {
+    fn check_for_bare(cx: &Context, fv: &freevar_entry) {
         cx.tcx.sess.span_err(
             fv.span,
             "can't capture dynamic environment in a fn item; \
@@ -226,10 +223,11 @@ fn check_fn(
 
     // Check kinds on free variables:
     with_appropriate_checker(cx, fn_id, |chk| {
-        let r = freevars::get_freevars(cx.tcx, fn_id);
-        for fv in r.iter() {
-            chk(cx, *fv);
-        }
+        freevars::with_freevars(cx.tcx, fn_id, |r| {
+            for fv in r.iter() {
+                chk(cx, fv);
+            }
+        })
     });
 
     visit::walk_fn(cx, fk, decl, body, sp, fn_id, ());
@@ -240,7 +238,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
 
     // Handle any kind bounds on type parameters
     {
-        let method_map = cx.method_map.borrow();
+        let method_map = cx.tcx.method_map.borrow();
         let method = method_map.find(&typeck::MethodCall::expr(e.id));
         let node_type_substs = cx.tcx.node_type_substs.borrow();
         let r = match method {
@@ -309,11 +307,10 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
     // Search for auto-adjustments to find trait coercions.
     match cx.tcx.adjustments.borrow().find(&e.id) {
         Some(adjustment) => {
-            match **adjustment {
+            match *adjustment {
                 ty::AutoObject(..) => {
                     let source_ty = ty::expr_ty(cx.tcx, e);
-                    let target_ty = ty::expr_ty_adjusted(cx.tcx, e,
-                                                         &*cx.method_map.borrow());
+                    let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
                     check_trait_cast(cx, source_ty, target_ty, e.span);
                 }
                 ty::AutoAddEnv(..) |
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 7fca0e56aa2..42ef8b9d51b 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -195,12 +195,12 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
 }
 
 pub fn collect_language_items(krate: &ast::Crate,
-                              session: &Session) -> @LanguageItems {
+                              session: &Session) -> LanguageItems {
     let mut collector = LanguageItemCollector::new(session);
     collector.collect(krate);
     let LanguageItemCollector { items, .. } = collector;
     session.abort_if_errors();
-    @items
+    items
 }
 
 // End of the macro
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index 6ce815d9bc4..d1cc7d7bc40 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -53,6 +53,7 @@ use std::i16;
 use std::i32;
 use std::i64;
 use std::i8;
+use std::rc::Rc;
 use std::to_str::ToStr;
 use std::u16;
 use std::u32;
@@ -423,23 +424,16 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
   '-' to '_' in command-line flags
  */
 pub fn get_lint_dict() -> LintDict {
-    let mut map = HashMap::new();
-    for &(k, v) in lint_table.iter() {
-        map.insert(k, v);
-    }
-    return map;
+    lint_table.iter().map(|&(k, v)| (k, v)).collect()
 }
 
 struct Context<'a> {
     // All known lint modes (string versions)
-    dict: @LintDict,
+    dict: LintDict,
     // Current levels of each lint warning
     cur: SmallIntMap<(level, LintSource)>,
     // context we're checking in (used to access fields like sess)
     tcx: &'a ty::ctxt,
-    // maps from an expression id that corresponds to a method call to the
-    // details of the method to be invoked
-    method_map: typeck::MethodMap,
     // Items exported by the crate; used by the missing_doc lint.
     exported_items: &'a privacy::ExportedItems,
     // The id of the current `ast::StructDef` being walked.
@@ -685,7 +679,7 @@ impl<'a> AstConv for Context<'a>{
         ty::lookup_item_type(self.tcx, id)
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
         ty::lookup_trait_def(self.tcx, id)
     }
 
@@ -1340,7 +1334,7 @@ fn check_unsafe_block(cx: &Context, e: &ast::Expr) {
 fn check_unused_mut_pat(cx: &Context, p: &ast::Pat) {
     match p.node {
         ast::PatIdent(ast::BindByValue(ast::MutMutable),
-                      ref path, _) if pat_util::pat_is_binding(cx.tcx.def_map, p)=> {
+                      ref path, _) if pat_util::pat_is_binding(&cx.tcx.def_map, p) => {
             // `let mut _a = 1;` doesn't need a warning.
             let initial_underscore = if path.segments.len() == 1 {
                 token::get_ident(path.segments
@@ -1390,7 +1384,7 @@ fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
         cx.span_lint(UnnecessaryAllocation, e.span, msg);
     };
 
-    match cx.tcx.adjustments.borrow().find_copy(&e.id) {
+    match cx.tcx.adjustments.borrow().find(&e.id) {
         Some(adjustment) => {
             match *adjustment {
                 ty::AutoDerefRef(ty::AutoDerefRef { autoref, .. }) => {
@@ -1472,7 +1466,7 @@ fn check_missing_doc_method(cx: &Context, m: &ast::Method) {
         node: m.id
     };
 
-    match cx.tcx.methods.borrow().find(&did).map(|method| *method) {
+    match cx.tcx.methods.borrow().find_copy(&did) {
         None => cx.tcx.sess.span_bug(m.span, "missing method descriptor?!"),
         Some(md) => {
             match md.container {
@@ -1537,7 +1531,7 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
         }
         ast::ExprMethodCall(..) => {
             let method_call = typeck::MethodCall::expr(e.id);
-            match cx.method_map.borrow().find(&method_call) {
+            match cx.tcx.method_map.borrow().find(&method_call) {
                 Some(method) => {
                     match method.origin {
                         typeck::MethodStatic(def_id) => {
@@ -1775,14 +1769,12 @@ impl<'a> IdVisitingOperation for Context<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    exported_items: &privacy::ExportedItems,
                    krate: &ast::Crate) {
     let mut cx = Context {
-        dict: @get_lint_dict(),
+        dict: get_lint_dict(),
         cur: SmallIntMap::new(),
         tcx: tcx,
-        method_map: method_map,
         exported_items: exported_items,
         cur_struct_def_id: -1,
         is_doc_hidden: false,
@@ -1793,7 +1785,9 @@ pub fn check_crate(tcx: &ty::ctxt,
     // Install default lint levels, followed by the command line levels, and
     // then actually visit the whole crate.
     for (_, spec) in cx.dict.iter() {
-        cx.set_level(spec.lint, spec.default, Default);
+        if spec.default != allow {
+            cx.cur.insert(spec.lint as uint, (spec.default, Default));
+        }
     }
     for &(lint, level) in tcx.sess.opts.lint_opts.iter() {
         cx.set_level(lint, level, CommandLine);
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index a13b6001495..4be9992367d 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -106,7 +106,6 @@
 use middle::lint::{UnusedVariable, DeadAssignment};
 use middle::pat_util;
 use middle::ty;
-use middle::typeck;
 use middle::moves;
 use util::nodemap::NodeMap;
 
@@ -171,10 +170,9 @@ impl<'a> Visitor<()> for IrMaps<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: typeck::MethodMap,
                    capture_map: &moves::CaptureMap,
                    krate: &Crate) {
-    visit::walk_crate(&mut IrMaps(tcx, method_map, capture_map), krate, ());
+    visit::walk_crate(&mut IrMaps(tcx, capture_map), krate, ());
     tcx.sess.abort_if_errors();
 }
 
@@ -247,7 +245,6 @@ enum VarKind {
 
 struct IrMaps<'a> {
     tcx: &'a ty::ctxt,
-    method_map: typeck::MethodMap,
     capture_map: &'a moves::CaptureMap,
 
     num_live_nodes: uint,
@@ -260,12 +257,10 @@ struct IrMaps<'a> {
 }
 
 fn IrMaps<'a>(tcx: &'a ty::ctxt,
-              method_map: typeck::MethodMap,
               capture_map: &'a moves::CaptureMap)
               -> IrMaps<'a> {
     IrMaps {
         tcx: tcx,
-        method_map: method_map,
         capture_map: capture_map,
         num_live_nodes: 0,
         num_vars: 0,
@@ -366,14 +361,14 @@ fn visit_fn(ir: &mut IrMaps,
     let _i = ::util::common::indenter();
 
     // swap in a new set of IR maps for this function body:
-    let mut fn_maps = IrMaps(ir.tcx, ir.method_map, ir.capture_map);
+    let mut fn_maps = IrMaps(ir.tcx, ir.capture_map);
 
     unsafe {
         debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(&fn_maps));
     }
 
     for arg in decl.inputs.iter() {
-        pat_util::pat_bindings(ir.tcx.def_map,
+        pat_util::pat_bindings(&ir.tcx.def_map,
                                arg.pat,
                                |_bm, arg_id, _x, path| {
             debug!("adding argument {}", arg_id);
@@ -407,7 +402,7 @@ fn visit_fn(ir: &mut IrMaps,
 }
 
 fn visit_local(ir: &mut IrMaps, local: &Local) {
-    pat_util::pat_bindings(ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
+    pat_util::pat_bindings(&ir.tcx.def_map, local.pat, |bm, p_id, sp, path| {
         debug!("adding local variable {}", p_id);
         let name = ast_util::path_to_ident(path);
         ir.add_live_node_for_node(p_id, VarDefNode(sp));
@@ -431,7 +426,7 @@ fn visit_local(ir: &mut IrMaps, local: &Local) {
 
 fn visit_arm(ir: &mut IrMaps, arm: &Arm) {
     for pat in arm.pats.iter() {
-        pat_util::pat_bindings(ir.tcx.def_map, *pat, |bm, p_id, sp, path| {
+        pat_util::pat_bindings(&ir.tcx.def_map, *pat, |bm, p_id, sp, path| {
             debug!("adding local variable {} from match with bm {:?}",
                    p_id, bm);
             let name = ast_util::path_to_ident(path);
@@ -480,7 +475,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
                     // var must be dead afterwards
                     moves::CapMove => true,
 
-                    // var can stil be used
+                    // var can still be used
                     moves::CapCopy | moves::CapRef => false
                 };
                 call_caps.push(CaptureInfo {ln: cv_ln,
@@ -601,7 +596,7 @@ impl<'a> Liveness<'a> {
     fn pat_bindings(&mut self,
                     pat: &Pat,
                     f: |&mut Liveness<'a>, LiveNode, Variable, Span, NodeId|) {
-        pat_util::pat_bindings(self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
+        pat_util::pat_bindings(&self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
             let ln = self.live_node(p_id, sp);
             let var = self.variable(p_id, sp);
             f(self, ln, var, sp, p_id);
@@ -613,7 +608,7 @@ impl<'a> Liveness<'a> {
                          f: |&mut Liveness<'a>, LiveNode, Variable, Span, NodeId|) {
         // only consider the first pattern; any later patterns must have
         // the same bindings, and we also consider the first pattern to be
-        // the "authoratative" set of ids
+        // the "authoritative" set of ids
         if !pats.is_empty() {
             self.pat_bindings(pats[0], f)
         }
@@ -1529,7 +1524,7 @@ impl<'a> Liveness<'a> {
 
     fn warn_about_unused_args(&self, decl: &FnDecl, entry_ln: LiveNode) {
         for arg in decl.inputs.iter() {
-            pat_util::pat_bindings(self.ir.tcx.def_map,
+            pat_util::pat_bindings(&self.ir.tcx.def_map,
                                    arg.pat,
                                    |_bm, p_id, sp, path| {
                 let var = self.variable(p_id, sp);
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 84e9151c11c..35124aa9916 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -64,6 +64,7 @@
 
 use middle::ty;
 use middle::typeck;
+use util::nodemap::NodeMap;
 use util::ppaux::{ty_to_str, Repr};
 
 use syntax::ast::{MutImmutable, MutMutable};
@@ -72,7 +73,10 @@ use syntax::codemap::Span;
 use syntax::print::pprust;
 use syntax::parse::token;
 
-#[deriving(Eq)]
+use std::cell::RefCell;
+use std::rc::Rc;
+
+#[deriving(Clone, Eq)]
 pub enum categorization {
     cat_rvalue(ty::Region),            // temporary val, argument is its scope
     cat_static_item,
@@ -88,14 +92,14 @@ pub enum categorization {
     // (*1) downcast is only required if the enum has more than one variant
 }
 
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct CopiedUpvar {
     pub upvar_id: ast::NodeId,
     pub onceness: ast::Onceness,
 }
 
 // different kinds of pointers:
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum PointerKind {
     OwnedPtr,
     GcPtr,
@@ -105,26 +109,26 @@ pub enum PointerKind {
 
 // We use the term "interior" to mean "something reachable from the
 // base without a pointer dereference", e.g. a field
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum InteriorKind {
     InteriorField(FieldName),
     InteriorElement(ElementKind),
 }
 
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum FieldName {
     NamedField(ast::Name),
     PositionalField(uint)
 }
 
-#[deriving(Eq, TotalEq, Hash)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
 pub enum ElementKind {
     VecElement,
     StrElement,
     OtherElement,
 }
 
-#[deriving(Eq, TotalEq, Hash, Show)]
+#[deriving(Clone, Eq, TotalEq, Hash, Show)]
 pub enum MutabilityCategory {
     McImmutable, // Immutable.
     McDeclared,  // Directly declared as mutable.
@@ -145,7 +149,7 @@ pub enum MutabilityCategory {
 // dereference, but its type is the type *before* the dereference
 // (`@T`). So use `cmt.type` to find the type of the value in a consistent
 // fashion. For more details, see the method `cat_pattern`
-#[deriving(Eq)]
+#[deriving(Clone, Eq)]
 pub struct cmt_ {
     pub id: ast::NodeId,          // id of expr/pat producing this value
     pub span: Span,                // span of same expr/pat
@@ -154,7 +158,7 @@ pub struct cmt_ {
     pub ty: ty::t                  // type of the expr (*see WARNING above*)
 }
 
-pub type cmt = @cmt_;
+pub type cmt = Rc<cmt_>;
 
 // We pun on *T to mean both actual deref of a ptr as well
 // as accessing of components:
@@ -263,12 +267,12 @@ pub type McResult<T> = Result<T, ()>;
  */
 pub trait Typer {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt;
-    fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t>;
+    fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t>;
     fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<ty::t>;
-    fn adjustment(&mut self, node_id: ast::NodeId) -> Option<@ty::AutoAdjustment>;
-    fn is_method_call(&mut self, id: ast::NodeId) -> bool;
-    fn temporary_scope(&mut self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
-    fn upvar_borrow(&mut self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>>;
+    fn is_method_call(&self, id: ast::NodeId) -> bool;
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
+    fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow;
 }
 
 impl MutabilityCategory {
@@ -350,31 +354,27 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         self.typer.tcx()
     }
 
-    fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
-        self.typer.adjustment(id)
-    }
-
-    fn expr_ty(&mut self, expr: &ast::Expr) -> McResult<ty::t> {
+    fn expr_ty(&self, expr: &ast::Expr) -> McResult<ty::t> {
         self.typer.node_ty(expr.id)
     }
 
-    fn expr_ty_adjusted(&mut self, expr: &ast::Expr) -> McResult<ty::t> {
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<ty::t> {
         let unadjusted_ty = if_ok!(self.expr_ty(expr));
-        let adjustment = self.adjustment(expr.id);
-        Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, adjustment,
+        Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
+                         self.typer.adjustments().borrow().find(&expr.id),
                          |method_call| self.typer.node_method_ty(method_call)))
     }
 
-    fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t> {
+    fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
         self.typer.node_ty(id)
     }
 
-    fn pat_ty(&mut self, pat: @ast::Pat) -> McResult<ty::t> {
+    fn pat_ty(&self, pat: &ast::Pat) -> McResult<ty::t> {
         self.typer.node_ty(pat.id)
     }
 
-    pub fn cat_expr(&mut self, expr: &ast::Expr) -> McResult<cmt> {
-        match self.adjustment(expr.id) {
+    pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt> {
+        match self.typer.adjustments().borrow().find(&expr.id) {
             None => {
                 // No adjustments.
                 self.cat_expr_unadjusted(expr)
@@ -386,8 +386,9 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                         // Implicity casts a concrete object to trait object
                         // so just patch up the type
                         let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
-                        let expr_cmt = if_ok!(self.cat_expr_unadjusted(expr));
-                        Ok(@cmt_ {ty: expr_ty, ..*expr_cmt})
+                        let mut expr_cmt = (*if_ok!(self.cat_expr_unadjusted(expr))).clone();
+                        expr_cmt.ty = expr_ty;
+                        Ok(Rc::new(expr_cmt))
                     }
 
                     ty::AutoAddEnv(..) => {
@@ -417,7 +418,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_expr_autoderefd(&mut self, expr: &ast::Expr, autoderefs: uint)
+    pub fn cat_expr_autoderefd(&self, expr: &ast::Expr, autoderefs: uint)
                                -> McResult<cmt> {
         let mut cmt = if_ok!(self.cat_expr_unadjusted(expr));
         for deref in range(1u, autoderefs + 1) {
@@ -426,7 +427,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         return Ok(cmt);
     }
 
-    pub fn cat_expr_unadjusted(&mut self, expr: &ast::Expr) -> McResult<cmt> {
+    pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt> {
         debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
 
         let expr_ty = if_ok!(self.expr_ty(expr));
@@ -475,7 +476,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_def(&mut self,
+    pub fn cat_def(&self,
                    id: ast::NodeId,
                    span: Span,
                    expr_ty: ty::t,
@@ -493,23 +494,23 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           ast::DefUse(_) | ast::DefTrait(_) | ast::DefTy(_) | ast::DefPrimTy(_) |
           ast::DefTyParam(..) | ast::DefTyParamBinder(..) | ast::DefRegion(_) |
           ast::DefLabel(_) | ast::DefSelfTy(..) | ast::DefMethod(..) => {
-              Ok(@cmt_ {
+              Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
                   mutbl: McImmutable,
                   ty:expr_ty
-              })
+              }))
           }
 
           ast::DefStatic(_, true) => {
-              Ok(@cmt_ {
+              Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
                   mutbl: McDeclared,
                   ty:expr_ty
-              })
+              }))
           }
 
           ast::DefArg(vid, binding_mode) => {
@@ -521,13 +522,13 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 ast::BindByValue(ast::MutMutable) => McDeclared,
                 _ => McImmutable
             };
-            Ok(@cmt_ {
+            Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_arg(vid),
                 mutbl: m,
                 ty:expr_ty
-            })
+            }))
           }
 
           ast::DefUpvar(var_id, _, fn_node_id, _) => {
@@ -551,7 +552,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                           self.cat_upvar(id, span, var_id, fn_node_id)
                       } else {
                           // FIXME #2152 allow mutation of moved upvars
-                          Ok(@cmt_ {
+                          Ok(Rc::new(cmt_ {
                               id:id,
                               span:span,
                               cat:cat_copied_upvar(CopiedUpvar {
@@ -559,7 +560,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                                   onceness: closure_ty.onceness}),
                               mutbl:McImmutable,
                               ty:expr_ty
-                          })
+                          }))
                       }
                   }
                   _ => {
@@ -579,18 +580,18 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 _ => McImmutable
             };
 
-            Ok(@cmt_ {
+            Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_local(vid),
                 mutbl: m,
                 ty: expr_ty
-            })
+            }))
           }
         }
     }
 
-    fn cat_upvar(&mut self,
+    fn cat_upvar(&self,
                  id: ast::NodeId,
                  span: Span,
                  var_id: ast::NodeId,
@@ -619,28 +620,28 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         // give err type. Nobody should be inspecting this type anyhow.
         let upvar_ty = ty::mk_err();
 
-        let base_cmt = @cmt_ {
+        let base_cmt = Rc::new(cmt_ {
             id:id,
             span:span,
             cat:cat_upvar(upvar_id, upvar_borrow),
             mutbl:McImmutable,
             ty:upvar_ty,
-        };
+        });
 
         let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region);
 
-        let deref_cmt = @cmt_ {
+        let deref_cmt = Rc::new(cmt_ {
             id:id,
             span:span,
             cat:cat_deref(base_cmt, 0, ptr),
             mutbl:MutabilityCategory::from_borrow_kind(upvar_borrow.kind),
             ty:var_ty,
-        };
+        });
 
         Ok(deref_cmt)
     }
 
-    pub fn cat_rvalue_node(&mut self,
+    pub fn cat_rvalue_node(&self,
                            id: ast::NodeId,
                            span: Span,
                            expr_ty: ty::t)
@@ -655,40 +656,40 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_rvalue(&mut self,
+    pub fn cat_rvalue(&self,
                       cmt_id: ast::NodeId,
                       span: Span,
                       temp_scope: ty::Region,
                       expr_ty: ty::t) -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id:cmt_id,
             span:span,
             cat:cat_rvalue(temp_scope),
             mutbl:McDeclared,
             ty:expr_ty
-        }
+        })
     }
 
-    pub fn cat_field<N:ast_node>(&mut self,
+    pub fn cat_field<N:ast_node>(&self,
                                  node: &N,
                                  base_cmt: cmt,
                                  f_name: ast::Ident,
                                  f_ty: ty::t)
                                  -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
             mutbl: base_cmt.mutbl.inherit(),
+            cat: cat_interior(base_cmt, InteriorField(NamedField(f_name.name))),
             ty: f_ty
-        }
+        })
     }
 
-    pub fn cat_deref_obj<N:ast_node>(&mut self, node: &N, base_cmt: cmt) -> cmt {
+    pub fn cat_deref_obj<N:ast_node>(&self, node: &N, base_cmt: cmt) -> cmt {
         self.cat_deref_common(node, base_cmt, 0, ty::mk_nil())
     }
 
-    fn cat_deref<N:ast_node>(&mut self,
+    fn cat_deref<N:ast_node>(&self,
                              node: &N,
                              base_cmt: cmt,
                              deref_cnt: uint)
@@ -720,7 +721,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    fn cat_deref_common<N:ast_node>(&mut self,
+    fn cat_deref_common<N:ast_node>(&self,
                                     node: &N,
                                     base_cmt: cmt,
                                     deref_cnt: uint,
@@ -737,16 +738,16 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 (base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
             }
         };
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
             cat: cat,
             mutbl: m,
             ty: deref_ty
-        }
+        })
     }
 
-    pub fn cat_index<N:ast_node>(&mut self,
+    pub fn cat_index<N:ast_node>(&self,
                                  elt: &N,
                                  base_cmt: cmt,
                                  derefs: uint)
@@ -799,13 +800,13 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
             let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr);
 
             // the deref is explicit in the resulting cmt
-            let deref_cmt = @cmt_ {
+            let deref_cmt = Rc::new(cmt_ {
                 id:elt.id(),
                 span:elt.span(),
-                cat:cat_deref(base_cmt, derefs, ptr),
+                cat:cat_deref(base_cmt.clone(), derefs, ptr),
                 mutbl:m,
                 ty:element_ty
-            };
+            });
 
             interior(elt, deref_cmt, base_cmt.ty, m.inherit(), element_ty)
           }
@@ -813,7 +814,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           deref_interior(_) => {
             // fixed-length vectors have no deref
             let m = base_cmt.mutbl.inherit();
-            interior(elt, base_cmt, base_cmt.ty, m, element_ty)
+            interior(elt, base_cmt.clone(), base_cmt.ty, m, element_ty)
           }
         };
 
@@ -823,19 +824,19 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                                  mutbl: MutabilityCategory,
                                  element_ty: ty::t) -> cmt
         {
-            @cmt_ {
+            Rc::new(cmt_ {
                 id:elt.id(),
                 span:elt.span(),
                 cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
                 mutbl:mutbl,
                 ty:element_ty
-            }
+            })
         }
     }
 
-    pub fn cat_slice_pattern(&mut self,
+    pub fn cat_slice_pattern(&self,
                              vec_cmt: cmt,
-                             slice_pat: @ast::Pat)
+                             slice_pat: &ast::Pat)
                              -> McResult<(cmt, ast::Mutability, ty::Region)> {
         /*!
          * Given a pattern P like: `[_, ..Q, _]`, where `vec_cmt` is
@@ -855,7 +856,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         return Ok((cmt_slice, slice_mutbl, slice_r));
 
         fn vec_slice_info(tcx: &ty::ctxt,
-                          pat: @ast::Pat,
+                          pat: &ast::Pat,
                           slice_ty: ty::t)
                           -> (ast::Mutability, ty::Region) {
             /*!
@@ -880,41 +881,41 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         }
     }
 
-    pub fn cat_imm_interior<N:ast_node>(&mut self,
+    pub fn cat_imm_interior<N:ast_node>(&self,
                                         node: &N,
                                         base_cmt: cmt,
                                         interior_ty: ty::t,
                                         interior: InteriorKind)
                                         -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat_interior(base_cmt, interior),
             mutbl: base_cmt.mutbl.inherit(),
+            cat: cat_interior(base_cmt, interior),
             ty: interior_ty
-        }
+        })
     }
 
-    pub fn cat_downcast<N:ast_node>(&mut self,
+    pub fn cat_downcast<N:ast_node>(&self,
                                     node: &N,
                                     base_cmt: cmt,
                                     downcast_ty: ty::t)
                                     -> cmt {
-        @cmt_ {
+        Rc::new(cmt_ {
             id: node.id(),
             span: node.span(),
-            cat: cat_downcast(base_cmt),
             mutbl: base_cmt.mutbl.inherit(),
+            cat: cat_downcast(base_cmt),
             ty: downcast_ty
-        }
+        })
     }
 
-    pub fn cat_pattern(&mut self,
+    pub fn cat_pattern(&self,
                        cmt: cmt,
-                       pat: @ast::Pat,
-                       op: |&mut MemCategorizationContext<TYPER>,
+                       pat: &ast::Pat,
+                       op: |&MemCategorizationContext<TYPER>,
                             cmt,
-                            @ast::Pat|)
+                            &ast::Pat|)
                        -> McResult<()> {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
@@ -965,7 +966,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                pat.id, pprust::pat_to_str(pat),
                cmt.repr(self.tcx()));
 
-        op(self, cmt, pat);
+        op(self, cmt.clone(), pat);
 
         match pat.node {
           ast::PatWild | ast::PatWildMulti => {
@@ -984,7 +985,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                         if ty::enum_is_univariant(self.tcx(), enum_did) {
                             cmt // univariant, no downcast needed
                         } else {
-                            self.cat_downcast(pat, cmt, cmt.ty)
+                            self.cat_downcast(pat, cmt.clone(), cmt.ty)
                         }
                     };
 
@@ -993,7 +994,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
 
                         let subcmt =
                             self.cat_imm_interior(
-                                pat, downcast_cmt, subpat_ty,
+                                pat, downcast_cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
 
                         if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
@@ -1005,14 +1006,14 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                         let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
                         let cmt_field =
                             self.cat_imm_interior(
-                                pat, cmt, subpat_ty,
+                                pat, cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
                         if_ok!(self.cat_pattern(cmt_field, subpat, |x,y,z| op(x,y,z)));
                     }
                 }
                 Some(&ast::DefStatic(..)) => {
                     for &subpat in subpats.iter() {
-                        if_ok!(self.cat_pattern(cmt, subpat, |x,y,z| op(x,y,z)));
+                        if_ok!(self.cat_pattern(cmt.clone(), subpat, |x,y,z| op(x,y,z)));
                     }
                 }
                 _ => {
@@ -1035,7 +1036,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
             // {f1: p1, ..., fN: pN}
             for fp in field_pats.iter() {
                 let field_ty = if_ok!(self.pat_ty(fp.pat)); // see (*2)
-                let cmt_field = self.cat_field(pat, cmt, fp.ident, field_ty);
+                let cmt_field = self.cat_field(pat, cmt.clone(), fp.ident, field_ty);
                 if_ok!(self.cat_pattern(cmt_field, fp.pat, |x,y,z| op(x,y,z)));
             }
           }
@@ -1046,7 +1047,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                 let subpat_ty = if_ok!(self.pat_ty(subpat)); // see (*2)
                 let subcmt =
                     self.cat_imm_interior(
-                        pat, cmt, subpat_ty,
+                        pat, cmt.clone(), subpat_ty,
                         InteriorField(PositionalField(i)));
                 if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z)));
             }
@@ -1061,7 +1062,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           ast::PatVec(ref before, slice, ref after) => {
               let elt_cmt = self.cat_index(pat, cmt, 0);
               for &before_pat in before.iter() {
-                  if_ok!(self.cat_pattern(elt_cmt, before_pat, |x,y,z| op(x,y,z)));
+                  if_ok!(self.cat_pattern(elt_cmt.clone(), before_pat, |x,y,z| op(x,y,z)));
               }
               for &slice_pat in slice.iter() {
                   let slice_ty = if_ok!(self.pat_ty(slice_pat));
@@ -1069,7 +1070,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
                   if_ok!(self.cat_pattern(slice_cmt, slice_pat, |x,y,z| op(x,y,z)));
               }
               for &after_pat in after.iter() {
-                  if_ok!(self.cat_pattern(elt_cmt, after_pat, |x,y,z| op(x,y,z)));
+                  if_ok!(self.cat_pattern(elt_cmt.clone(), after_pat, |x,y,z| op(x,y,z)));
               }
           }
 
@@ -1081,7 +1082,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
         Ok(())
     }
 
-    pub fn cmt_to_str(&self, cmt: cmt) -> ~str {
+    pub fn cmt_to_str(&self, cmt: &cmt_) -> ~str {
         match cmt.cat {
           cat_static_item => {
               "static item".to_owned()
@@ -1098,7 +1099,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           cat_arg(..) => {
               "argument".to_owned()
           }
-          cat_deref(base, _, pk) => {
+          cat_deref(ref base, _, pk) => {
               match base.cat {
                   cat_upvar(..) => {
                       format!("captured outer variable")
@@ -1126,11 +1127,11 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
           cat_upvar(..) => {
               "captured outer variable".to_owned()
           }
-          cat_discr(cmt, _) => {
-            self.cmt_to_str(cmt)
+          cat_discr(ref cmt, _) => {
+            self.cmt_to_str(&**cmt)
           }
-          cat_downcast(cmt) => {
-            self.cmt_to_str(cmt)
+          cat_downcast(ref cmt) => {
+            self.cmt_to_str(&**cmt)
           }
         }
     }
@@ -1150,7 +1151,7 @@ pub enum AliasableReason {
 }
 
 impl cmt_ {
-    pub fn guarantor(self) -> cmt {
+    pub fn guarantor(&self) -> cmt {
         //! Returns `self` after stripping away any owned pointer derefs or
         //! interior content. The return value is basically the `cmt` which
         //! determines how long the value in `self` remains live.
@@ -1165,12 +1166,12 @@ impl cmt_ {
             cat_deref(_, _, GcPtr(..)) |
             cat_deref(_, _, BorrowedPtr(..)) |
             cat_upvar(..) => {
-                @self
+                Rc::new((*self).clone())
             }
-            cat_downcast(b) |
-            cat_discr(b, _) |
-            cat_interior(b, _) |
-            cat_deref(b, _, OwnedPtr) => {
+            cat_downcast(ref b) |
+            cat_discr(ref b, _) |
+            cat_interior(ref b, _) |
+            cat_deref(ref b, _, OwnedPtr) => {
                 b.guarantor()
             }
         }
@@ -1187,12 +1188,12 @@ impl cmt_ {
         // aliased and eventually recused.
 
         match self.cat {
-            cat_deref(b, _, BorrowedPtr(ty::MutBorrow, _)) |
-            cat_deref(b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
-            cat_downcast(b) |
-            cat_deref(b, _, OwnedPtr) |
-            cat_interior(b, _) |
-            cat_discr(b, _) => {
+            cat_deref(ref b, _, BorrowedPtr(ty::MutBorrow, _)) |
+            cat_deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
+            cat_downcast(ref b) |
+            cat_deref(ref b, _, OwnedPtr) |
+            cat_interior(ref b, _) |
+            cat_discr(ref b, _) => {
                 // Aliasability depends on base cmt
                 b.freely_aliasable(ctxt)
             }
@@ -1256,21 +1257,21 @@ impl Repr for categorization {
             cat_arg(..) => {
                 format!("{:?}", *self)
             }
-            cat_deref(cmt, derefs, ptr) => {
+            cat_deref(ref cmt, derefs, ptr) => {
                 format!("{}-{}{}->",
                         cmt.cat.repr(tcx),
                         ptr_sigil(ptr),
                         derefs)
             }
-            cat_interior(cmt, interior) => {
+            cat_interior(ref cmt, interior) => {
                 format!("{}.{}",
                      cmt.cat.repr(tcx),
                      interior.repr(tcx))
             }
-            cat_downcast(cmt) => {
+            cat_downcast(ref cmt) => {
                 format!("{}->(enum)", cmt.cat.repr(tcx))
             }
-            cat_discr(cmt, _) => {
+            cat_discr(ref cmt, _) => {
                 cmt.cat.repr(tcx)
             }
         }
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 2029df38b10..53d3dec6713 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -130,7 +130,7 @@ and so on.
 use middle::pat_util::{pat_bindings};
 use middle::freevars;
 use middle::ty;
-use middle::typeck::{MethodCall, MethodMap};
+use middle::typeck::MethodCall;
 use util::ppaux;
 use util::ppaux::Repr;
 use util::common::indenter;
@@ -177,7 +177,6 @@ pub struct MoveMaps {
 #[deriving(Clone)]
 struct VisitContext<'a> {
     tcx: &'a ty::ctxt,
-    method_map: MethodMap,
     move_maps: MoveMaps
 }
 
@@ -202,13 +201,9 @@ impl<'a> visit::Visitor<()> for VisitContext<'a> {
     fn visit_ty(&mut self, _t: &Ty, _: ()) {}
 }
 
-pub fn compute_moves(tcx: &ty::ctxt,
-                     method_map: MethodMap,
-                     krate: &Crate) -> MoveMaps
-{
+pub fn compute_moves(tcx: &ty::ctxt, krate: &Crate) -> MoveMaps {
     let mut visit_cx = VisitContext {
         tcx: tcx,
-        method_map: method_map,
         move_maps: MoveMaps {
             moves_map: NodeSet::new(),
             moved_variables_set: NodeSet::new(),
@@ -274,8 +269,7 @@ impl<'a> VisitContext<'a> {
         debug!("consume_expr(expr={})",
                expr.repr(self.tcx));
 
-        let expr_ty = ty::expr_ty_adjusted(self.tcx, expr,
-                                           &*self.method_map.borrow());
+        let expr_ty = ty::expr_ty_adjusted(self.tcx, expr);
         if ty::type_moves_by_default(self.tcx, expr_ty) {
             self.move_maps.moves_map.insert(expr.id);
             self.use_expr(expr, Move);
@@ -318,7 +312,7 @@ impl<'a> VisitContext<'a> {
         // reading the underlying expression, not moving it.
         let comp_mode = match self.tcx.adjustments.borrow().find(&expr.id) {
             Some(adjustment) => {
-                match **adjustment {
+                match *adjustment {
                     ty::AutoDerefRef(ty::AutoDerefRef {
                         autoref: Some(_),
                         ..
@@ -550,7 +544,7 @@ impl<'a> VisitContext<'a> {
                     self.use_pat(a.pat);
                 }
                 let cap_vars = self.compute_captures(expr.id);
-                self.move_maps.capture_map.insert(expr.id, cap_vars);
+                self.move_maps.capture_map.insert(expr.id, Rc::new(cap_vars));
                 self.consume_block(body);
             }
 
@@ -577,7 +571,7 @@ impl<'a> VisitContext<'a> {
                                    arg_exprs: &[@Expr])
                                    -> bool {
         let method_call = MethodCall::expr(expr.id);
-        if !self.method_map.borrow().contains_key(&method_call) {
+        if !self.tcx.method_map.borrow().contains_key(&method_call) {
             return false;
         }
 
@@ -611,7 +605,7 @@ impl<'a> VisitContext<'a> {
          * into itself or not based on its type and annotation.
          */
 
-        pat_bindings(self.tcx.def_map, pat, |bm, id, _span, path| {
+        pat_bindings(&self.tcx.def_map, pat, |bm, id, _span, path| {
             let binding_moves = match bm {
                 BindByRef(_) => false,
                 BindByValue(_) => {
@@ -645,34 +639,35 @@ impl<'a> VisitContext<'a> {
         self.consume_expr(arg_expr)
     }
 
-    pub fn compute_captures(&mut self, fn_expr_id: NodeId) -> Rc<Vec<CaptureVar> > {
+    fn compute_captures(&mut self, fn_expr_id: NodeId) -> Vec<CaptureVar> {
         debug!("compute_capture_vars(fn_expr_id={:?})", fn_expr_id);
         let _indenter = indenter();
 
         let fn_ty = ty::node_id_to_type(self.tcx, fn_expr_id);
-        let freevars = freevars::get_freevars(self.tcx, fn_expr_id);
-        Rc::new(match ty::ty_closure_store(fn_ty) {
-            ty::RegionTraitStore(..) => {
-                // || captures everything by ref
-                freevars.iter()
-                        .map(|fvar| CaptureVar {def: fvar.def, span: fvar.span, mode: CapRef})
-                        .collect()
-            }
-            ty::UniqTraitStore => {
-                // proc captures by copy or by move depending on type
-                freevars.iter()
-                        .map(|fvar| {
-                    let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
-                    let fvar_ty = ty::node_id_to_type(self.tcx, fvar_def_id);
-                    debug!("fvar_def_id={:?} fvar_ty={}",
-                        fvar_def_id, ppaux::ty_to_str(self.tcx, fvar_ty));
-                    let mode = if ty::type_moves_by_default(self.tcx, fvar_ty) {
-                        CapMove
-                    } else {
-                        CapCopy
-                    };
-                    CaptureVar {def: fvar.def, span: fvar.span, mode:mode}
-                }).collect()
+        freevars::with_freevars(self.tcx, fn_expr_id, |freevars| {
+            match ty::ty_closure_store(fn_ty) {
+                ty::RegionTraitStore(..) => {
+                    // || captures everything by ref
+                    freevars.iter()
+                            .map(|fvar| CaptureVar {def: fvar.def, span: fvar.span, mode: CapRef})
+                            .collect()
+                }
+                ty::UniqTraitStore => {
+                    // proc captures by copy or by move depending on type
+                    freevars.iter()
+                            .map(|fvar| {
+                        let fvar_def_id = ast_util::def_id_of_def(fvar.def).node;
+                        let fvar_ty = ty::node_id_to_type(self.tcx, fvar_def_id);
+                        debug!("fvar_def_id={:?} fvar_ty={}",
+                            fvar_def_id, ppaux::ty_to_str(self.tcx, fvar_ty));
+                        let mode = if ty::type_moves_by_default(self.tcx, fvar_ty) {
+                            CapMove
+                        } else {
+                            CapCopy
+                        };
+                        CaptureVar {def: fvar.def, span: fvar.span, mode:mode}
+                    }).collect()
+                }
             }
         })
     }
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 2d50d2e0f77..842d3bae6a7 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -20,7 +20,7 @@ pub type PatIdMap = HashMap<Ident, NodeId>;
 
 // This is used because same-named variables in alternative patterns need to
 // use the NodeId of their namesake in the first pattern.
-pub fn pat_id_map(dm: resolve::DefMap, pat: &Pat) -> PatIdMap {
+pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap {
     let mut map = HashMap::new();
     pat_bindings(dm, pat, |_bm, p_id, _s, n| {
       map.insert(path_to_ident(n), p_id);
@@ -28,7 +28,7 @@ pub fn pat_id_map(dm: resolve::DefMap, pat: &Pat) -> PatIdMap {
     map
 }
 
-pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_variant_or_struct(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatEnum(_, _) | PatIdent(_, _, None) | PatStruct(..) => {
             match dm.borrow().find(&pat.id) {
@@ -40,7 +40,7 @@ pub fn pat_is_variant_or_struct(dm: resolve::DefMap, pat: &Pat) -> bool {
     }
 }
 
-pub fn pat_is_const(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_const(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(_, _, None) | PatEnum(..) => {
             match dm.borrow().find(&pat.id) {
@@ -52,7 +52,7 @@ pub fn pat_is_const(dm: resolve::DefMap, pat: &Pat) -> bool {
     }
 }
 
-pub fn pat_is_binding(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_binding(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(..) => {
             !pat_is_variant_or_struct(dm, pat) &&
@@ -62,7 +62,7 @@ pub fn pat_is_binding(dm: resolve::DefMap, pat: &Pat) -> bool {
     }
 }
 
-pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_is_binding_or_wild(dm: &resolve::DefMap, pat: &Pat) -> bool {
     match pat.node {
         PatIdent(..) => pat_is_binding(dm, pat),
         PatWild | PatWildMulti => true,
@@ -72,7 +72,7 @@ pub fn pat_is_binding_or_wild(dm: resolve::DefMap, pat: &Pat) -> bool {
 
 /// Call `it` on every "binding" in a pattern, e.g., on `a` in
 /// `match foo() { Some(a) => (), None => () }`
-pub fn pat_bindings(dm: resolve::DefMap,
+pub fn pat_bindings(dm: &resolve::DefMap,
                     pat: &Pat,
                     it: |BindingMode, NodeId, Span, &Path|) {
     walk_pat(pat, |p| {
@@ -88,7 +88,7 @@ pub fn pat_bindings(dm: resolve::DefMap,
 
 /// Checks if the pattern contains any patterns that bind something to
 /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
-pub fn pat_contains_bindings(dm: resolve::DefMap, pat: &Pat) -> bool {
+pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool {
     let mut contains_bindings = false;
     walk_pat(pat, |p| {
         if pat_is_binding(dm, p) {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index 20b17cce12e..427a7f406b0 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -63,7 +63,7 @@ impl Visitor<()> for ParentVisitor {
         let prev = self.curparent;
         match item.node {
             ast::ItemMod(..) => { self.curparent = item.id; }
-            // Enum variants are parented to the enum definition itself beacuse
+            // Enum variants are parented to the enum definition itself because
             // they inherit privacy
             ast::ItemEnum(ref def, _) => {
                 for variant in def.variants.iter() {
@@ -254,7 +254,7 @@ impl<'a> Visitor<()> for EmbargoVisitor<'a> {
                     _ => true,
                 };
                 let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
-                let public_trait = tr.map_or(false, |tr| {
+                let public_trait = tr.clone().map_or(false, |tr| {
                     !is_local(tr.def_id) ||
                      self.exported_items.contains(&tr.def_id.node)
                 });
@@ -337,7 +337,6 @@ struct PrivacyVisitor<'a> {
     curitem: ast::NodeId,
     in_fn: bool,
     in_foreign: bool,
-    method_map: &'a MethodMap,
     parents: NodeMap<ast::NodeId>,
     external_exports: resolve::ExternalExports,
     last_private_map: resolve::LastPrivateMap,
@@ -775,8 +774,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
     fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
         match expr.node {
             ast::ExprField(base, ident, _) => {
-                match ty::get(ty::expr_ty_adjusted(self.tcx, base,
-                                                   &*self.method_map.borrow())).sty {
+                match ty::get(ty::expr_ty_adjusted(self.tcx, base)).sty {
                     ty::ty_struct(id, _) => {
                         self.check_field(expr.span, id, NamedField(ident));
                     }
@@ -785,7 +783,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
             }
             ast::ExprMethodCall(ident, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
-                match self.method_map.borrow().find(&method_call) {
+                match self.tcx.method_map.borrow().find(&method_call) {
                     None => {
                         self.tcx.sess.span_bug(expr.span,
                                                 "method call not in \
@@ -1034,7 +1032,7 @@ impl<'a> Visitor<()> for SanePrivacyVisitor<'a> {
 }
 
 impl<'a> SanePrivacyVisitor<'a> {
-    /// Validates all of the visibility qualifers placed on the item given. This
+    /// Validates all of the visibility qualifiers placed on the item given. This
     /// ensures that there are no extraneous qualifiers that don't actually do
     /// anything. In theory these qualifiers wouldn't parse, but that may happen
     /// later on down the road...
@@ -1262,7 +1260,7 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
                     self_is_public_path = visitor.outer_type_is_public_path;
                 }
 
-                // miscellanous info about the impl
+                // miscellaneous info about the impl
 
                 // `true` iff this is `impl Private for ...`.
                 let not_private_trait =
@@ -1404,7 +1402,6 @@ impl<'a> Visitor<()> for VisiblePrivateTypesVisitor<'a> {
 }
 
 pub fn check_crate(tcx: &ty::ctxt,
-                   method_map: &MethodMap,
                    exp_map2: &resolve::ExportMap2,
                    external_exports: resolve::ExternalExports,
                    last_private_map: resolve::LastPrivateMap,
@@ -1423,7 +1420,6 @@ pub fn check_crate(tcx: &ty::ctxt,
         in_foreign: false,
         tcx: tcx,
         parents: visitor.parents,
-        method_map: method_map,
         external_exports: external_exports,
         last_private_map: last_private_map,
     };
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 839f1d6039c..6e2edb4e8b2 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -84,9 +84,6 @@ fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
 struct ReachableContext<'a> {
     // The type context.
     tcx: &'a ty::ctxt,
-    // The method map, which links node IDs of method call expressions to the
-    // methods they've been resolved to.
-    method_map: typeck::MethodMap,
     // The set of items which must be exported in the linkage sense.
     reachable_symbols: NodeSet,
     // A worklist of item IDs. Each item ID in this worklist will be inlined
@@ -133,7 +130,7 @@ impl<'a> Visitor<()> for ReachableContext<'a> {
             }
             ast::ExprMethodCall(..) => {
                 let method_call = typeck::MethodCall::expr(expr.id);
-                match self.method_map.borrow().get(&method_call).origin {
+                match self.tcx.method_map.borrow().get(&method_call).origin {
                     typeck::MethodStatic(def_id) => {
                         if is_local(def_id) {
                             if self.def_id_represents_local_inlined_item(def_id) {
@@ -159,10 +156,9 @@ impl<'a> Visitor<()> for ReachableContext<'a> {
 
 impl<'a> ReachableContext<'a> {
     // Creates a new reachability computation context.
-    fn new(tcx: &'a ty::ctxt, method_map: typeck::MethodMap) -> ReachableContext<'a> {
+    fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
         ReachableContext {
             tcx: tcx,
-            method_map: method_map,
             reachable_symbols: NodeSet::new(),
             worklist: Vec::new(),
         }
@@ -339,10 +335,9 @@ impl<'a> ReachableContext<'a> {
 }
 
 pub fn find_reachable(tcx: &ty::ctxt,
-                      method_map: typeck::MethodMap,
                       exported_items: &privacy::ExportedItems)
                       -> NodeSet {
-    let mut reachable_context = ReachableContext::new(tcx, method_map);
+    let mut reachable_context = ReachableContext::new(tcx);
 
     // Step 1: Seed the worklist with all nodes which were found to be public as
     //         a result of the privacy pass along with all local lang items. If
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 8a5e0d3df17..33db3b44d95 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -182,7 +182,7 @@ impl RegionMaps {
 
         // else, locate the innermost terminating scope
         // if there's one. Static items, for instance, won't
-        // have an enclusing scope, hence no scope will be
+        // have an enclosing scope, hence no scope will be
         // returned.
         let mut id = match self.opt_encl_scope(expr_id) {
             Some(i) => i,
@@ -533,7 +533,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor,
             // the invoked function is actually running* and call.id
             // represents *the time to prepare the arguments and make the
             // call*.  See the section "Borrows in Calls" borrowck/doc.rs
-            // for an extended explanantion of why this distinction is
+            // for an extended explanation of why this distinction is
             // important.
             //
             // record_superlifetime(new_cx, expr.callee_id);
@@ -604,7 +604,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
     //    (covers cases `expr` borrows an rvalue that is then assigned
     //     to memory (at least partially) owned by the binding)
     //
-    // Here are some examples hopefully giving an intution where each
+    // Here are some examples hopefully giving an intuition where each
     // rule comes into play and why:
     //
     // Rule A. `let (ref x, ref y) = (foo().x, 44)`. The rvalue `(22, 44)`
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 9112434b12c..d645b628aff 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -16,7 +16,7 @@ use metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use middle::lang_items::LanguageItems;
 use middle::lint::{UnnecessaryQualification, UnusedImports};
 use middle::pat_util::pat_bindings;
-use util::nodemap::{NodeMap, DefIdSet};
+use util::nodemap::{NodeMap, DefIdSet, FnvHashSet};
 
 use syntax::ast::*;
 use syntax::ast;
@@ -34,11 +34,12 @@ use syntax::visit::Visitor;
 use collections::{HashMap, HashSet};
 use std::cell::{Cell, RefCell};
 use std::mem::replace;
+use std::rc::{Rc, Weak};
 use std::strbuf::StrBuf;
 use std::uint;
 
 // Definition mapping
-pub type DefMap = @RefCell<NodeMap<Def>>;
+pub type DefMap = RefCell<NodeMap<Def>>;
 
 struct binding_info {
     span: Span,
@@ -53,7 +54,7 @@ pub type TraitMap = NodeMap<Vec<DefId> >;
 
 // This is the replacement export map. It maps a module to all of the exports
 // within.
-pub type ExportMap2 = @RefCell<NodeMap<Vec<Export2> >>;
+pub type ExportMap2 = RefCell<NodeMap<Vec<Export2> >>;
 
 pub struct Export2 {
     pub name: ~str,        // The name of the target.
@@ -72,7 +73,7 @@ pub enum LastPrivate {
     // `use` directives (imports) can refer to two separate definitions in the
     // type and value namespaces. We record here the last private node for each
     // and whether the import is in fact used for each.
-    // If the Option<PrivateDep> fields are None, it means there is no defintion
+    // If the Option<PrivateDep> fields are None, it means there is no definition
     // in that namespace.
     LastImport{pub value_priv: Option<PrivateDep>,
                pub value_used: ImportUse,
@@ -125,6 +126,7 @@ enum NamespaceError {
 /// A NamespaceResult represents the result of resolving an import in
 /// a particular namespace. The result is either definitely-resolved,
 /// definitely- unresolved, or unknown.
+#[deriving(Clone)]
 enum NamespaceResult {
     /// Means that resolve hasn't gathered enough information yet to determine
     /// whether the name is bound in this namespace. (That is, it hasn't
@@ -135,7 +137,7 @@ enum NamespaceResult {
     UnboundResult,
     /// Means that resolve has determined that the name is bound in the Module
     /// argument, and specified by the NameBindings argument.
-    BoundResult(@Module, @NameBindings)
+    BoundResult(Rc<Module>, Rc<NameBindings>)
 }
 
 impl NamespaceResult {
@@ -189,14 +191,14 @@ enum ImportDirectiveSubclass {
 /// The context that we thread through while building the reduced graph.
 #[deriving(Clone)]
 enum ReducedGraphParent {
-    ModuleReducedGraphParent(@Module)
+    ModuleReducedGraphParent(Rc<Module>)
 }
 
 impl ReducedGraphParent {
-    fn module(&self) -> @Module {
+    fn module(&self) -> Rc<Module> {
         match *self {
-            ModuleReducedGraphParent(m) => {
-                m
+            ModuleReducedGraphParent(ref m) => {
+                m.clone()
             }
         }
     }
@@ -279,7 +281,7 @@ enum SearchThroughModulesFlag {
 
 enum ModulePrefixResult {
     NoPrefixFound,
-    PrefixFound(@Module, uint)
+    PrefixFound(Rc<Module>, uint)
 }
 
 #[deriving(Eq)]
@@ -326,8 +328,8 @@ impl Rib {
 
 /// One import directive.
 struct ImportDirective {
-    module_path: Vec<Ident> ,
-    subclass: @ImportDirectiveSubclass,
+    module_path: Vec<Ident>,
+    subclass: ImportDirectiveSubclass,
     span: Span,
     id: NodeId,
     is_public: bool, // see note in ImportResolution about how to use this
@@ -335,7 +337,7 @@ struct ImportDirective {
 
 impl ImportDirective {
     fn new(module_path: Vec<Ident> ,
-           subclass: @ImportDirectiveSubclass,
+           subclass: ImportDirectiveSubclass,
            span: Span,
            id: NodeId,
            is_public: bool)
@@ -353,12 +355,12 @@ impl ImportDirective {
 /// The item that an import resolves to.
 #[deriving(Clone)]
 struct Target {
-    target_module: @Module,
-    bindings: @NameBindings,
+    target_module: Rc<Module>,
+    bindings: Rc<NameBindings>,
 }
 
 impl Target {
-    fn new(target_module: @Module, bindings: @NameBindings) -> Target {
+    fn new(target_module: Rc<Module>, bindings: Rc<NameBindings>) -> Target {
         Target {
             target_module: target_module,
             bindings: bindings
@@ -372,63 +374,60 @@ struct ImportResolution {
     /// should *not* be used whenever resolution is being performed, this is
     /// only looked at for glob imports statements currently. Privacy testing
     /// occurs during a later phase of compilation.
-    is_public: Cell<bool>,
+    is_public: bool,
 
     // The number of outstanding references to this name. When this reaches
     // zero, outside modules can count on the targets being correct. Before
     // then, all bets are off; future imports could override this name.
-    outstanding_references: Cell<uint>,
+    outstanding_references: uint,
 
     /// The value that this `use` directive names, if there is one.
-    value_target: RefCell<Option<Target>>,
+    value_target: Option<Target>,
     /// The source node of the `use` directive leading to the value target
     /// being non-none
-    value_id: Cell<NodeId>,
+    value_id: NodeId,
 
     /// The type that this `use` directive names, if there is one.
-    type_target: RefCell<Option<Target>>,
+    type_target: Option<Target>,
     /// The source node of the `use` directive leading to the type target
     /// being non-none
-    type_id: Cell<NodeId>,
-}
-
-fn get<T: Clone>(cell: &RefCell<T>) -> T {
-    cell.borrow().clone()
+    type_id: NodeId,
 }
 
 impl ImportResolution {
     fn new(id: NodeId, is_public: bool) -> ImportResolution {
         ImportResolution {
-            type_id: Cell::new(id),
-            value_id: Cell::new(id),
-            outstanding_references: Cell::new(0),
-            value_target: RefCell::new(None),
-            type_target: RefCell::new(None),
-            is_public: Cell::new(is_public),
+            type_id: id,
+            value_id: id,
+            outstanding_references: 0,
+            value_target: None,
+            type_target: None,
+            is_public: is_public,
         }
     }
 
     fn target_for_namespace(&self, namespace: Namespace)
                                 -> Option<Target> {
         match namespace {
-            TypeNS      => return self.type_target.borrow().clone(),
-            ValueNS     => return self.value_target.borrow().clone(),
+            TypeNS  => self.type_target.clone(),
+            ValueNS => self.value_target.clone(),
         }
     }
 
     fn id(&self, namespace: Namespace) -> NodeId {
         match namespace {
-            TypeNS  => self.type_id.get(),
-            ValueNS => self.value_id.get(),
+            TypeNS  => self.type_id,
+            ValueNS => self.value_id,
         }
     }
 }
 
 /// The link from a module up to its nearest parent node.
+#[deriving(Clone)]
 enum ParentLink {
     NoParentLink,
-    ModuleParentLink(@Module, Ident),
-    BlockParentLink(@Module, NodeId)
+    ModuleParentLink(Weak<Module>, Ident),
+    BlockParentLink(Weak<Module>, NodeId)
 }
 
 /// The type of module this is.
@@ -448,12 +447,12 @@ struct Module {
     kind: Cell<ModuleKind>,
     is_public: bool,
 
-    children: RefCell<HashMap<Name, @NameBindings>>,
-    imports: RefCell<Vec<@ImportDirective> >,
+    children: RefCell<HashMap<Name, Rc<NameBindings>>>,
+    imports: RefCell<Vec<ImportDirective>>,
 
     // The external module children of this node that were declared with
     // `extern crate`.
-    external_module_children: RefCell<HashMap<Name, @Module>>,
+    external_module_children: RefCell<HashMap<Name, Rc<Module>>>,
 
     // The anonymous children of this node. Anonymous children are pseudo-
     // modules that are implicitly created around items contained within
@@ -469,10 +468,10 @@ struct Module {
     //
     // There will be an anonymous module created around `g` with the ID of the
     // entry block for `f`.
-    anonymous_children: RefCell<NodeMap<@Module>>,
+    anonymous_children: RefCell<NodeMap<Rc<Module>>>,
 
     // The status of resolving each import in this module.
-    import_resolutions: RefCell<HashMap<Name, @ImportResolution>>,
+    import_resolutions: RefCell<HashMap<Name, ImportResolution>>,
 
     // The number of unresolved globs that this module exports.
     glob_count: Cell<uint>,
@@ -518,7 +517,7 @@ impl Module {
 #[deriving(Clone)]
 struct TypeNsDef {
     is_public: bool, // see note in ImportResolution about how to use this
-    module_def: Option<@Module>,
+    module_def: Option<Rc<Module>>,
     type_def: Option<Def>,
     type_span: Option<Span>
 }
@@ -555,8 +554,8 @@ impl NameBindings {
                      is_public: bool,
                      sp: Span) {
         // Merges the module with the existing type def or creates a new one.
-        let module_ = @Module::new(parent_link, def_id, kind, external,
-                                       is_public);
+        let module_ = Rc::new(Module::new(parent_link, def_id, kind, external,
+                                          is_public));
         let type_def = self.type_def.borrow().clone();
         match type_def {
             None => {
@@ -589,11 +588,11 @@ impl NameBindings {
         let type_def = self.type_def.borrow().clone();
         match type_def {
             None => {
-                let module = @Module::new(parent_link, def_id, kind,
-                                              external, is_public);
+                let module = Module::new(parent_link, def_id, kind,
+                                         external, is_public);
                 *self.type_def.borrow_mut() = Some(TypeNsDef {
                     is_public: is_public,
-                    module_def: Some(module),
+                    module_def: Some(Rc::new(module)),
                     type_def: None,
                     type_span: None,
                 });
@@ -601,14 +600,14 @@ impl NameBindings {
             Some(type_def) => {
                 match type_def.module_def {
                     None => {
-                        let module = @Module::new(parent_link,
-                                                      def_id,
-                                                      kind,
-                                                      external,
-                                                      is_public);
+                        let module = Module::new(parent_link,
+                                                 def_id,
+                                                 kind,
+                                                 external,
+                                                 is_public);
                         *self.type_def.borrow_mut() = Some(TypeNsDef {
                             is_public: is_public,
-                            module_def: Some(module),
+                            module_def: Some(Rc::new(module)),
                             type_def: type_def.type_def,
                             type_span: None,
                         });
@@ -653,9 +652,9 @@ impl NameBindings {
     }
 
     /// Returns the module node if applicable.
-    fn get_module_if_available(&self) -> Option<@Module> {
+    fn get_module_if_available(&self) -> Option<Rc<Module>> {
         match *self.type_def.borrow() {
-            Some(ref type_def) => (*type_def).module_def,
+            Some(ref type_def) => type_def.module_def.clone(),
             None => None
         }
     }
@@ -664,7 +663,7 @@ impl NameBindings {
      * Returns the module node. Fails if this node does not have a module
      * definition.
      */
-    fn get_module(&self) -> @Module {
+    fn get_module(&self) -> Rc<Module> {
         match self.get_module_if_available() {
             None => {
                 fail!("get_module called on a node with no module \
@@ -684,10 +683,10 @@ impl NameBindings {
     fn defined_in_public_namespace(&self, namespace: Namespace) -> bool {
         match namespace {
             TypeNS => match *self.type_def.borrow() {
-                Some(def) => def.is_public, None => false
+                Some(ref def) => def.is_public, None => false
             },
             ValueNS => match *self.value_def.borrow() {
-                Some(def) => def.is_public, None => false
+                Some(ref def) => def.is_public, None => false
             }
         }
     }
@@ -697,12 +696,12 @@ impl NameBindings {
             TypeNS => {
                 match *self.type_def.borrow() {
                     None => None,
-                    Some(type_def) => {
+                    Some(ref type_def) => {
                         match type_def.type_def {
                             Some(type_def) => Some(type_def),
                             None => {
                                 match type_def.module_def {
-                                    Some(module) => {
+                                    Some(ref module) => {
                                         match module.def_id.get() {
                                             Some(did) => Some(DefMod(did)),
                                             None => None,
@@ -730,13 +729,13 @@ impl NameBindings {
                 TypeNS  => {
                     match *self.type_def.borrow() {
                         None => None,
-                        Some(type_def) => type_def.type_span
+                        Some(ref type_def) => type_def.type_span
                     }
                 }
                 ValueNS => {
                     match *self.value_def.borrow() {
                         None => None,
-                        Some(value_def) => value_def.value_span
+                        Some(ref value_def) => value_def.value_span
                     }
                 }
             }
@@ -799,9 +798,9 @@ fn namespace_error_to_str(ns: NamespaceError) -> &'static str {
 }
 
 fn Resolver<'a>(session: &'a Session,
-                lang_items: @LanguageItems,
+                lang_items: &'a LanguageItems,
                 crate_span: Span) -> Resolver<'a> {
-    let graph_root = @NameBindings();
+    let graph_root = NameBindings();
 
     graph_root.define_module(NoParentLink,
                              Some(DefId { krate: 0, node: 0 }),
@@ -821,27 +820,27 @@ fn Resolver<'a>(session: &'a Session,
 
         graph_root: graph_root,
 
-        method_map: @RefCell::new(HashMap::new()),
+        method_set: RefCell::new(FnvHashSet::new()),
         structs: HashSet::new(),
 
         unresolved_imports: 0,
 
         current_module: current_module,
-        value_ribs: @RefCell::new(Vec::new()),
-        type_ribs: @RefCell::new(Vec::new()),
-        label_ribs: @RefCell::new(Vec::new()),
+        value_ribs: RefCell::new(Vec::new()),
+        type_ribs: RefCell::new(Vec::new()),
+        label_ribs: RefCell::new(Vec::new()),
 
         current_trait_refs: None,
 
         self_ident: special_idents::self_,
         type_self_ident: special_idents::type_self,
 
-        primitive_type_table: @PrimitiveTypeTable(),
+        primitive_type_table: PrimitiveTypeTable(),
 
         namespaces: vec!(TypeNS, ValueNS),
 
-        def_map: @RefCell::new(NodeMap::new()),
-        export_map2: @RefCell::new(NodeMap::new()),
+        def_map: RefCell::new(NodeMap::new()),
+        export_map2: RefCell::new(NodeMap::new()),
         trait_map: NodeMap::new(),
         used_imports: HashSet::new(),
         external_exports: DefIdSet::new(),
@@ -856,28 +855,28 @@ fn Resolver<'a>(session: &'a Session,
 /// The main resolver class.
 struct Resolver<'a> {
     session: &'a Session,
-    lang_items: @LanguageItems,
+    lang_items: &'a LanguageItems,
 
-    graph_root: @NameBindings,
+    graph_root: NameBindings,
 
-    method_map: @RefCell<HashMap<Name, HashSet<DefId>>>,
+    method_set: RefCell<FnvHashSet<(Name, DefId)>>,
     structs: HashSet<DefId>,
 
     // The number of imports that are currently unresolved.
     unresolved_imports: uint,
 
     // The module that represents the current item scope.
-    current_module: @Module,
+    current_module: Rc<Module>,
 
     // The current set of local scopes, for values.
     // FIXME #4948: Reuse ribs to avoid allocation.
-    value_ribs: @RefCell<Vec<@Rib> >,
+    value_ribs: RefCell<Vec<Rib>>,
 
     // The current set of local scopes, for types.
-    type_ribs: @RefCell<Vec<@Rib> >,
+    type_ribs: RefCell<Vec<Rib>>,
 
     // The current set of local scopes, for labels.
-    label_ribs: @RefCell<Vec<@Rib> >,
+    label_ribs: RefCell<Vec<Rib>>,
 
     // The trait that the current context can refer to.
     current_trait_refs: Option<Vec<DefId> >,
@@ -888,7 +887,7 @@ struct Resolver<'a> {
     type_self_ident: Ident,
 
     // The idents for the primitive types.
-    primitive_type_table: @PrimitiveTypeTable,
+    primitive_type_table: PrimitiveTypeTable,
 
     // The four namespaces.
     namespaces: Vec<Namespace> ,
@@ -921,10 +920,10 @@ impl<'a, 'b> Visitor<ReducedGraphParent> for BuildReducedGraphVisitor<'a, 'b> {
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem,
                           context: ReducedGraphParent) {
         self.resolver.build_reduced_graph_for_foreign_item(foreign_item,
-                                                           context,
-                                                           |r, c| {
+                                                           context.clone(),
+                                                           |r| {
             let mut v = BuildReducedGraphVisitor{ resolver: r };
-            visit::walk_foreign_item(&mut v, foreign_item, c);
+            visit::walk_foreign_item(&mut v, foreign_item, context.clone());
         })
     }
 
@@ -982,17 +981,6 @@ impl<'a> Resolver<'a> {
         visit::walk_crate(&mut visitor, krate, initial_parent);
     }
 
-    /// Returns the current module tracked by the reduced graph parent.
-    fn get_module_from_parent(&mut self,
-                                  reduced_graph_parent: ReducedGraphParent)
-                                  -> @Module {
-        match reduced_graph_parent {
-            ModuleReducedGraphParent(module_) => {
-                return module_;
-            }
-        }
-    }
-
     /**
      * Adds a new child item to the module definition of the parent node and
      * returns its corresponding name bindings as well as the current parent.
@@ -1003,32 +991,26 @@ impl<'a> Resolver<'a> {
      * If this node does not have a module definition and we are not inside
      * a block, fails.
      */
-    fn add_child(&mut self,
-                     name: Ident,
-                     reduced_graph_parent: ReducedGraphParent,
-                     duplicate_checking_mode: DuplicateCheckingMode,
-                     // For printing errors
-                     sp: Span)
-                     -> (@NameBindings, ReducedGraphParent) {
+    fn add_child(&self,
+                 name: Ident,
+                 reduced_graph_parent: ReducedGraphParent,
+                 duplicate_checking_mode: DuplicateCheckingMode,
+                 // For printing errors
+                 sp: Span)
+                 -> Rc<NameBindings> {
         // If this is the immediate descendant of a module, then we add the
         // child name directly. Otherwise, we create or reuse an anonymous
         // module and add the child to that.
 
-        let module_;
-        match reduced_graph_parent {
-            ModuleReducedGraphParent(parent_module) => {
-                module_ = parent_module;
-            }
-        }
+        let module_ = reduced_graph_parent.module();
 
         // Add or reuse the child.
-        let new_parent = ModuleReducedGraphParent(module_);
-        let child_opt = module_.children.borrow().find_copy(&name.name);
-        match child_opt {
+        let child = module_.children.borrow().find_copy(&name.name);
+        match child {
             None => {
-                let child = @NameBindings();
-                module_.children.borrow_mut().insert(name.name, child);
-                return (child, new_parent);
+                let child = Rc::new(NameBindings());
+                module_.children.borrow_mut().insert(name.name, child.clone());
+                child
             }
             Some(child) => {
                 // Enforce the duplicate checking mode:
@@ -1105,7 +1087,7 @@ impl<'a> Resolver<'a> {
                         }
                     }
                 }
-                return (child, new_parent);
+                child
             }
         }
     }
@@ -1145,7 +1127,7 @@ impl<'a> Resolver<'a> {
                            -> ParentLink {
         match parent {
             ModuleReducedGraphParent(module_) => {
-                return ModuleParentLink(module_, name);
+                return ModuleParentLink(module_.downgrade(), name);
             }
         }
     }
@@ -1162,10 +1144,10 @@ impl<'a> Resolver<'a> {
 
         match item.node {
             ItemMod(..) => {
-                let (name_bindings, new_parent) =
-                    self.add_child(ident, parent, ForbidDuplicateModules, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateModules, sp);
 
-                let parent_link = self.get_parent_link(new_parent, ident);
+                let parent_link = self.get_parent_link(parent, ident);
                 let def_id = DefId { krate: 0, node: item.id };
                 name_bindings.define_module(parent_link,
                                             Some(def_id),
@@ -1181,8 +1163,8 @@ impl<'a> Resolver<'a> {
 
             // These items live in the value namespace.
             ItemStatic(_, m, _) => {
-                let (name_bindings, _) =
-                    self.add_child(ident, parent, ForbidDuplicateValues, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateValues, sp);
                 let mutbl = m == ast::MutMutable;
 
                 name_bindings.define_value
@@ -1190,18 +1172,18 @@ impl<'a> Resolver<'a> {
                 parent
             }
             ItemFn(_, fn_style, _, _, _) => {
-              let (name_bindings, new_parent) =
-                self.add_child(ident, parent, ForbidDuplicateValues, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateValues, sp);
 
                 let def = DefFn(local_def(item.id), fn_style);
                 name_bindings.define_value(def, sp, is_public);
-                new_parent
+                parent
             }
 
             // These items live in the type namespace.
             ItemTy(..) => {
-                let (name_bindings, _) =
-                    self.add_child(ident, parent, ForbidDuplicateTypes, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
 
                 name_bindings.define_type
                     (DefTy(local_def(item.id)), sp, is_public);
@@ -1209,8 +1191,8 @@ impl<'a> Resolver<'a> {
             }
 
             ItemEnum(ref enum_definition, _) => {
-                let (name_bindings, new_parent) =
-                    self.add_child(ident, parent, ForbidDuplicateTypes, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
 
                 name_bindings.define_type
                     (DefTy(local_def(item.id)), sp, is_public);
@@ -1219,7 +1201,7 @@ impl<'a> Resolver<'a> {
                     self.build_reduced_graph_for_variant(
                         variant,
                         local_def(item.id),
-                        new_parent,
+                        parent.clone(),
                         is_public);
                 }
                 parent
@@ -1233,7 +1215,7 @@ impl<'a> Resolver<'a> {
                     None            => (ForbidDuplicateTypes, None)
                 };
 
-                let (name_bindings, new_parent) = self.add_child(ident, parent, forbid, sp);
+                let name_bindings = self.add_child(ident, parent.clone(), forbid, sp);
 
                 // Define a name in the type namespace.
                 name_bindings.define_type(DefTy(local_def(item.id)), sp, is_public);
@@ -1249,7 +1231,7 @@ impl<'a> Resolver<'a> {
                 // Record the def ID of this struct.
                 self.structs.insert(local_def(item.id));
 
-                new_parent
+                parent
             }
 
             ItemImpl(_, None, ty, ref methods) => {
@@ -1270,7 +1252,7 @@ impl<'a> Resolver<'a> {
                                                .find_copy(&name.name);
                         let new_parent = match parent_opt {
                             // It already exists
-                            Some(child) if child.get_module_if_available()
+                            Some(ref child) if child.get_module_if_available()
                                                 .is_some() &&
                                            child.get_module().kind.get() ==
                                                 ImplModuleKind => {
@@ -1278,14 +1260,14 @@ impl<'a> Resolver<'a> {
                             }
                             // Create the module
                             _ => {
-                                let (name_bindings, new_parent) =
+                                let name_bindings =
                                     self.add_child(name,
-                                                   parent,
+                                                   parent.clone(),
                                                    ForbidDuplicateModules,
                                                    sp);
 
                                 let parent_link =
-                                    self.get_parent_link(new_parent, ident);
+                                    self.get_parent_link(parent.clone(), ident);
                                 let def_id = local_def(item.id);
                                 let ns = TypeNS;
                                 let is_public =
@@ -1308,9 +1290,9 @@ impl<'a> Resolver<'a> {
                         for method in methods.iter() {
                             // Add the method to the module.
                             let ident = method.ident;
-                            let (method_name_bindings, _) =
+                            let method_name_bindings =
                                 self.add_child(ident,
-                                               new_parent,
+                                               new_parent.clone(),
                                                ForbidDuplicateValues,
                                                method.span);
                             let def = match method.explicit_self.node {
@@ -1344,11 +1326,11 @@ impl<'a> Resolver<'a> {
             ItemImpl(_, Some(_), _, _) => parent,
 
             ItemTrait(_, _, ref methods) => {
-                let (name_bindings, new_parent) =
-                    self.add_child(ident, parent, ForbidDuplicateTypes, sp);
+                let name_bindings =
+                    self.add_child(ident, parent.clone(), ForbidDuplicateTypes, sp);
 
                 // Add all the methods within to a new module.
-                let parent_link = self.get_parent_link(parent, ident);
+                let parent_link = self.get_parent_link(parent.clone(), ident);
                 name_bindings.define_module(parent_link,
                                             Some(local_def(item.id)),
                                             TraitModuleKind,
@@ -1358,8 +1340,9 @@ impl<'a> Resolver<'a> {
                 let module_parent = ModuleReducedGraphParent(name_bindings.
                                                              get_module());
 
+                let def_id = local_def(item.id);
+
                 // Add the names of all the methods to the trait info.
-                let mut method_names = HashMap::new();
                 for method in methods.iter() {
                     let ty_m = trait_method_to_ty_method(method);
 
@@ -1380,36 +1363,21 @@ impl<'a> Resolver<'a> {
                         }
                     };
 
-                    let (method_name_bindings, _) =
+                    let method_name_bindings =
                         self.add_child(ident,
-                                       module_parent,
+                                       module_parent.clone(),
                                        ForbidDuplicateValues,
                                        ty_m.span);
                     method_name_bindings.define_value(def, ty_m.span, true);
 
                     // Add it to the trait info if not static.
-                    match ty_m.explicit_self.node {
-                        SelfStatic => {}
-                        _ => {
-                            method_names.insert(ident.name, ());
-                        }
-                    }
-                }
-
-                let def_id = local_def(item.id);
-                for (name, _) in method_names.iter() {
-                    let mut method_map = self.method_map.borrow_mut();
-                    if !method_map.contains_key(name) {
-                        method_map.insert(*name, HashSet::new());
-                    }
-                    match method_map.find_mut(name) {
-                        Some(s) => { s.insert(def_id); },
-                        _ => fail!("can't happen"),
+                    if ty_m.explicit_self.node != SelfStatic {
+                        self.method_set.borrow_mut().insert((ident.name, def_id));
                     }
                 }
 
                 name_bindings.define_type(DefTrait(def_id), sp, is_public);
-                new_parent
+                parent
             }
             ItemMac(..) => parent
         }
@@ -1426,15 +1394,15 @@ impl<'a> Resolver<'a> {
 
         match variant.node.kind {
             TupleVariantKind(_) => {
-                let (child, _) = self.add_child(ident, parent, ForbidDuplicateValues,
-                                                variant.span);
+                let child = self.add_child(ident, parent, ForbidDuplicateValues, variant.span);
                 child.define_value(DefVariant(item_id,
                                               local_def(variant.node.id), false),
                                    variant.span, is_public);
             }
             StructVariantKind(_) => {
-                let (child, _) = self.add_child(ident, parent, ForbidDuplicateTypesAndValues,
-                                                variant.span);
+                let child = self.add_child(ident, parent,
+                                           ForbidDuplicateTypesAndValues,
+                                           variant.span);
                 child.define_type(DefVariant(item_id,
                                              local_def(variant.node.id), true),
                                   variant.span, is_public);
@@ -1478,15 +1446,15 @@ impl<'a> Resolver<'a> {
                     }
 
                     // Build up the import directives.
-                    let module_ = self.get_module_from_parent(parent);
+                    let module_ = parent.module();
                     let is_public = view_item.vis == ast::Public;
                     match view_path.node {
                         ViewPathSimple(binding, ref full_path, id) => {
                             let source_ident =
                                 full_path.segments.last().unwrap().identifier;
-                            let subclass = @SingleImport(binding,
-                                                         source_ident);
-                            self.build_import_directive(module_,
+                            let subclass = SingleImport(binding,
+                                                        source_ident);
+                            self.build_import_directive(&*module_,
                                                         module_path,
                                                         subclass,
                                                         view_path.span,
@@ -1496,20 +1464,19 @@ impl<'a> Resolver<'a> {
                         ViewPathList(_, ref source_idents, _) => {
                             for source_ident in source_idents.iter() {
                                 let name = source_ident.node.name;
-                                let subclass = @SingleImport(name, name);
                                 self.build_import_directive(
-                                    module_,
+                                    &*module_,
                                     module_path.clone(),
-                                    subclass,
+                                    SingleImport(name, name),
                                     source_ident.span,
                                     source_ident.node.id,
                                     is_public);
                             }
                         }
                         ViewPathGlob(_, id) => {
-                            self.build_import_directive(module_,
+                            self.build_import_directive(&*module_,
                                                         module_path,
-                                                        @GlobImport,
+                                                        GlobImport,
                                                         view_path.span,
                                                         id,
                                                         is_public);
@@ -1525,16 +1492,16 @@ impl<'a> Resolver<'a> {
                         let def_id = DefId { krate: crate_id, node: 0 };
                         self.external_exports.insert(def_id);
                         let parent_link = ModuleParentLink
-                            (self.get_module_from_parent(parent), name);
-                        let external_module = @Module::new(parent_link,
-                                                          Some(def_id),
-                                                          NormalModuleKind,
-                                                          false,
-                                                          true);
+                            (parent.module().downgrade(), name);
+                        let external_module = Rc::new(Module::new(parent_link,
+                                                                  Some(def_id),
+                                                                  NormalModuleKind,
+                                                                  false,
+                                                                  true));
 
                         parent.module().external_module_children
                               .borrow_mut().insert(name.name,
-                                                   external_module);
+                                                   external_module.clone());
 
                         self.build_reduced_graph_for_external_crate(
                             external_module);
@@ -1549,11 +1516,10 @@ impl<'a> Resolver<'a> {
     fn build_reduced_graph_for_foreign_item(&mut self,
                                             foreign_item: &ForeignItem,
                                             parent: ReducedGraphParent,
-                                            f: |&mut Resolver,
-                                                ReducedGraphParent|) {
+                                            f: |&mut Resolver|) {
         let name = foreign_item.ident;
         let is_public = foreign_item.vis == ast::Public;
-        let (name_bindings, new_parent) =
+        let name_bindings =
             self.add_child(name, parent, ForbidDuplicateValues,
                            foreign_item.span);
 
@@ -1567,13 +1533,13 @@ impl<'a> Resolver<'a> {
                                       foreign_item.id,
                                       0,
                                       NormalRibKind),
-                    |this| f(this, new_parent));
+                    f);
             }
             ForeignItemStatic(_, m) => {
                 let def = DefStatic(local_def(foreign_item.id), m);
                 name_bindings.define_value(def, foreign_item.span, is_public);
 
-                f(self, new_parent)
+                f(self)
             }
         }
     }
@@ -1590,15 +1556,15 @@ impl<'a> Resolver<'a> {
                     anonymous module for block {}",
                    block_id);
 
-            let parent_module = self.get_module_from_parent(parent);
-            let new_module = @Module::new(
-                BlockParentLink(parent_module, block_id),
+            let parent_module = parent.module();
+            let new_module = Rc::new(Module::new(
+                BlockParentLink(parent_module.downgrade(), block_id),
                 None,
                 AnonymousModuleKind,
                 false,
-                false);
+                false));
             parent_module.anonymous_children.borrow_mut()
-                         .insert(block_id, new_module);
+                         .insert(block_id, new_module.clone());
             ModuleReducedGraphParent(new_module)
         } else {
             parent
@@ -1608,7 +1574,7 @@ impl<'a> Resolver<'a> {
     fn handle_external_def(&mut self,
                            def: Def,
                            vis: Visibility,
-                           child_name_bindings: @NameBindings,
+                           child_name_bindings: &NameBindings,
                            final_ident: &str,
                            ident: Ident,
                            new_parent: ReducedGraphParent) {
@@ -1617,7 +1583,7 @@ impl<'a> Resolver<'a> {
                vis);
         let is_public = vis == ast::Public;
         let is_exported = is_public && match new_parent {
-            ModuleReducedGraphParent(module) => {
+            ModuleReducedGraphParent(ref module) => {
                 match module.def_id.get() {
                     None => true,
                     Some(did) => self.external_exports.contains(&did)
@@ -1641,7 +1607,7 @@ impl<'a> Resolver<'a> {
                 debug!("(building reduced graph for \
                         external crate) building module \
                         {}", final_ident);
-                let parent_link = self.get_parent_link(new_parent, ident);
+                let parent_link = self.get_parent_link(new_parent.clone(), ident);
 
                 child_name_bindings.define_module(parent_link,
                                                   Some(def_id),
@@ -1685,7 +1651,6 @@ impl<'a> Resolver<'a> {
 
               let method_def_ids =
                 csearch::get_trait_method_def_ids(&self.session.cstore, def_id);
-              let mut interned_method_names = HashSet::new();
               for &method_def_id in method_def_ids.iter() {
                   let (method_name, explicit_self) =
                       csearch::get_method_name_and_explicit_self(&self.session.cstore,
@@ -1698,22 +1663,12 @@ impl<'a> Resolver<'a> {
 
                   // Add it to the trait info if not static.
                   if explicit_self != SelfStatic {
-                      interned_method_names.insert(method_name.name);
+                      self.method_set.borrow_mut().insert((method_name.name, def_id));
                   }
                   if is_exported {
                       self.external_exports.insert(method_def_id);
                   }
               }
-              for name in interned_method_names.iter() {
-                  let mut method_map = self.method_map.borrow_mut();
-                  if !method_map.contains_key(name) {
-                      method_map.insert(*name, HashSet::new());
-                  }
-                  match method_map.find_mut(name) {
-                      Some(s) => { s.insert(def_id); },
-                      _ => fail!("can't happen"),
-                  }
-              }
 
               child_name_bindings.define_type(def, DUMMY_SP, is_public);
 
@@ -1758,7 +1713,7 @@ impl<'a> Resolver<'a> {
 
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_def(&mut self,
-                                                  root: @Module,
+                                                  root: Rc<Module>,
                                                   def_like: DefLike,
                                                   ident: Ident,
                                                   visibility: Visibility) {
@@ -1775,25 +1730,25 @@ impl<'a> Resolver<'a> {
                                                      child_ident,
                                                      vis| {
                             self.build_reduced_graph_for_external_crate_def(
-                                root,
+                                root.clone(),
                                 def_like,
                                 child_ident,
                                 vis)
                         });
                     }
                     _ => {
-                        let (child_name_bindings, new_parent) =
+                        let child_name_bindings =
                             self.add_child(ident,
-                                           ModuleReducedGraphParent(root),
+                                           ModuleReducedGraphParent(root.clone()),
                                            OverwriteDuplicates,
                                            DUMMY_SP);
 
                         self.handle_external_def(def,
                                                  visibility,
-                                                 child_name_bindings,
+                                                 &*child_name_bindings,
                                                  token::get_ident(ident).get(),
                                                  ident,
-                                                 new_parent);
+                                                 ModuleReducedGraphParent(root));
                     }
                 }
             }
@@ -1812,10 +1767,10 @@ impl<'a> Resolver<'a> {
                                         static methods for type name {}",
                                         token::get_ident(final_ident));
 
-                                let (child_name_bindings, new_parent) =
+                                let child_name_bindings =
                                     self.add_child(
                                         final_ident,
-                                        ModuleReducedGraphParent(root),
+                                        ModuleReducedGraphParent(root.clone()),
                                         OverwriteDuplicates,
                                         DUMMY_SP);
 
@@ -1838,7 +1793,7 @@ impl<'a> Resolver<'a> {
                                     }
                                     Some(_) | None => {
                                         let parent_link =
-                                            self.get_parent_link(new_parent,
+                                            self.get_parent_link(ModuleReducedGraphParent(root),
                                                                  final_ident);
                                         child_name_bindings.define_module(
                                             parent_link,
@@ -1864,9 +1819,9 @@ impl<'a> Resolver<'a> {
                                              static method '{}'",
                                            token::get_ident(ident));
 
-                                    let (method_name_bindings, _) =
+                                    let method_name_bindings =
                                         self.add_child(ident,
-                                                       new_parent,
+                                                       new_parent.clone(),
                                                        OverwriteDuplicates,
                                                        DUMMY_SP);
                                     let def = DefFn(
@@ -1893,9 +1848,9 @@ impl<'a> Resolver<'a> {
     }
 
     /// Builds the reduced graph rooted at the given external module.
-    fn populate_external_module(&mut self, module: @Module) {
+    fn populate_external_module(&mut self, module: Rc<Module>) {
         debug!("(populating external module) attempting to populate {}",
-               self.module_to_str(module));
+               self.module_to_str(&*module));
 
         let def_id = match module.def_id.get() {
             None => {
@@ -1910,7 +1865,7 @@ impl<'a> Resolver<'a> {
                                     |def_like, child_ident, visibility| {
             debug!("(populating external module) ... found ident: {}",
                    token::get_ident(child_ident));
-            self.build_reduced_graph_for_external_crate_def(module,
+            self.build_reduced_graph_for_external_crate_def(module.clone(),
                                                             def_like,
                                                             child_ident,
                                                             visibility)
@@ -1920,24 +1875,23 @@ impl<'a> Resolver<'a> {
 
     /// Ensures that the reduced graph rooted at the given external module
     /// is built, building it if it is not.
-    fn populate_module_if_necessary(&mut self, module: @Module) {
+    fn populate_module_if_necessary(&mut self, module: &Rc<Module>) {
         if !module.populated.get() {
-            self.populate_external_module(module)
+            self.populate_external_module(module.clone())
         }
         assert!(module.populated.get())
     }
 
     /// Builds the reduced graph rooted at the 'use' directive for an external
     /// crate.
-    fn build_reduced_graph_for_external_crate(&mut self,
-                                              root: @Module) {
+    fn build_reduced_graph_for_external_crate(&mut self, root: Rc<Module>) {
         csearch::each_top_level_item_of_crate(&self.session.cstore,
                                               root.def_id
                                                   .get()
                                                   .unwrap()
                                                   .krate,
                                               |def_like, ident, visibility| {
-            self.build_reduced_graph_for_external_crate_def(root,
+            self.build_reduced_graph_for_external_crate_def(root.clone(),
                                                             def_like,
                                                             ident,
                                                             visibility)
@@ -1946,47 +1900,48 @@ impl<'a> Resolver<'a> {
 
     /// Creates and adds an import directive to the given module.
     fn build_import_directive(&mut self,
-                              module_: @Module,
+                              module_: &Module,
                               module_path: Vec<Ident> ,
-                              subclass: @ImportDirectiveSubclass,
+                              subclass: ImportDirectiveSubclass,
                               span: Span,
                               id: NodeId,
                               is_public: bool) {
-        let directive = @ImportDirective::new(module_path,
-                                              subclass, span, id,
-                                              is_public);
-        module_.imports.borrow_mut().push(directive);
+        module_.imports.borrow_mut().push(ImportDirective::new(module_path,
+                                                               subclass,
+                                                               span, id,
+                                                               is_public));
+        self.unresolved_imports += 1;
         // Bump the reference count on the name. Or, if this is a glob, set
         // the appropriate flag.
 
-        match *subclass {
+        match subclass {
             SingleImport(target, _) => {
                 debug!("(building import directive) building import \
                         directive: {}::{}",
-                       self.idents_to_str(directive.module_path.as_slice()),
+                       self.idents_to_str(module_.imports.borrow().last().unwrap()
+                                                 .module_path.as_slice()),
                        token::get_ident(target));
 
                 let mut import_resolutions = module_.import_resolutions
                                                     .borrow_mut();
-                match import_resolutions.find(&target.name) {
-                    Some(&resolution) => {
+                match import_resolutions.find_mut(&target.name) {
+                    Some(resolution) => {
                         debug!("(building import directive) bumping \
                                 reference");
-                        resolution.outstanding_references.set(
-                            resolution.outstanding_references.get() + 1);
+                        resolution.outstanding_references += 1;
 
                         // the source of this name is different now
-                        resolution.type_id.set(id);
-                        resolution.value_id.set(id);
-                        resolution.is_public.set(is_public);
-                    }
-                    None => {
-                        debug!("(building import directive) creating new");
-                        let resolution = @ImportResolution::new(id, is_public);
-                        resolution.outstanding_references.set(1);
-                        import_resolutions.insert(target.name, resolution);
+                        resolution.type_id = id;
+                        resolution.value_id = id;
+                        resolution.is_public = is_public;
+                        return;
                     }
+                    None => {}
                 }
+                debug!("(building import directive) creating new");
+                let mut resolution = ImportResolution::new(id, is_public);
+                resolution.outstanding_references = 1;
+                import_resolutions.insert(target.name, resolution);
             }
             GlobImport => {
                 // Set the glob flag. This tells us that we don't know the
@@ -1995,8 +1950,6 @@ impl<'a> Resolver<'a> {
                 module_.glob_count.set(module_.glob_count.get() + 1);
             }
         }
-
-        self.unresolved_imports += 1;
     }
 
     // Import resolution
@@ -2017,7 +1970,7 @@ impl<'a> Resolver<'a> {
                    i, self.unresolved_imports);
 
             let module_root = self.graph_root.get_module();
-            self.resolve_imports_for_module_subtree(module_root);
+            self.resolve_imports_for_module_subtree(module_root.clone());
 
             if self.unresolved_imports == 0 {
                 debug!("(resolving imports) success");
@@ -2036,14 +1989,13 @@ impl<'a> Resolver<'a> {
 
     /// Attempts to resolve imports for the given module and all of its
     /// submodules.
-    fn resolve_imports_for_module_subtree(&mut self,
-                                              module_: @Module) {
+    fn resolve_imports_for_module_subtree(&mut self, module_: Rc<Module>) {
         debug!("(resolving imports for module subtree) resolving {}",
-               self.module_to_str(module_));
-        self.resolve_imports_for_module(module_);
+               self.module_to_str(&*module_));
+        self.resolve_imports_for_module(module_.clone());
 
-        self.populate_module_if_necessary(module_);
-        for (_, &child_node) in module_.children.borrow().iter() {
+        self.populate_module_if_necessary(&module_);
+        for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
                     // Nothing to do.
@@ -2054,17 +2006,17 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for (_, &child_module) in module_.anonymous_children.borrow().iter() {
-            self.resolve_imports_for_module_subtree(child_module);
+        for (_, child_module) in module_.anonymous_children.borrow().iter() {
+            self.resolve_imports_for_module_subtree(child_module.clone());
         }
     }
 
     /// Attempts to resolve imports for the given module only.
-    fn resolve_imports_for_module(&mut self, module: @Module) {
+    fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
         if module.all_imports_resolved() {
             debug!("(resolving imports for module) all imports resolved for \
                    {}",
-                   self.module_to_str(module));
+                   self.module_to_str(&*module));
             return;
         }
 
@@ -2072,15 +2024,15 @@ impl<'a> Resolver<'a> {
         let import_count = imports.len();
         while module.resolved_import_count.get() < import_count {
             let import_index = module.resolved_import_count.get();
-            let import_directive = *imports.get(import_index);
-            match self.resolve_import_for_module(module, import_directive) {
+            let import_directive = imports.get(import_index);
+            match self.resolve_import_for_module(module.clone(), import_directive) {
                 Failed => {
                     // We presumably emitted an error. Continue.
                     let msg = format!("failed to resolve import `{}`",
                                    self.import_path_to_str(
                                        import_directive.module_path
                                                        .as_slice(),
-                                       *import_directive.subclass));
+                                       import_directive.subclass));
                     self.resolve_error(import_directive.span, msg);
                 }
                 Indeterminate => {
@@ -2149,8 +2101,8 @@ impl<'a> Resolver<'a> {
     /// currently-unresolved imports, or success if we know the name exists.
     /// If successful, the resolved bindings are written into the module.
     fn resolve_import_for_module(&mut self,
-                                 module_: @Module,
-                                 import_directive: @ImportDirective)
+                                 module_: Rc<Module>,
+                                 import_directive: &ImportDirective)
                                  -> ResolveResult<()> {
         let mut resolution_result = Failed;
         let module_path = &import_directive.module_path;
@@ -2158,14 +2110,14 @@ impl<'a> Resolver<'a> {
         debug!("(resolving import for module) resolving import `{}::...` in \
                 `{}`",
                self.idents_to_str(module_path.as_slice()),
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // First, resolve the module path for the directive, if necessary.
         let container = if module_path.len() == 0 {
             // Use the crate root.
             Some((self.graph_root.get_module(), LastMod(AllPublic)))
         } else {
-            match self.resolve_module_path(module_,
+            match self.resolve_module_path(module_.clone(),
                                            module_path.as_slice(),
                                            DontUseLexicalScope,
                                            import_directive.span,
@@ -2186,10 +2138,10 @@ impl<'a> Resolver<'a> {
                 // We found the module that the target is contained
                 // within. Attempt to resolve the import within it.
 
-                match *import_directive.subclass {
+                match import_directive.subclass {
                     SingleImport(target, source) => {
                         resolution_result =
-                            self.resolve_single_import(module_,
+                            self.resolve_single_import(&*module_,
                                                        containing_module,
                                                        target,
                                                        source,
@@ -2198,7 +2150,7 @@ impl<'a> Resolver<'a> {
                     }
                     GlobImport => {
                         resolution_result =
-                            self.resolve_glob_import(module_,
+                            self.resolve_glob_import(&*module_,
                                                      containing_module,
                                                      import_directive.id,
                                                      import_directive.is_public,
@@ -2225,7 +2177,7 @@ impl<'a> Resolver<'a> {
         // resolve_imports_for_module.)
 
         if !resolution_result.indeterminate() {
-            match *import_directive.subclass {
+            match import_directive.subclass {
                 GlobImport => {
                     assert!(module_.glob_count.get() >= 1);
                     module_.glob_count.set(module_.glob_count.get() - 1);
@@ -2239,7 +2191,7 @@ impl<'a> Resolver<'a> {
         return resolution_result;
     }
 
-    fn create_name_bindings_from_module(module: @Module) -> NameBindings {
+    fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
         NameBindings {
             type_def: RefCell::new(Some(TypeNsDef {
                 is_public: false,
@@ -2252,8 +2204,8 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_single_import(&mut self,
-                             module_: @Module,
-                             containing_module: @Module,
+                             module_: &Module,
+                             containing_module: Rc<Module>,
                              target: Ident,
                              source: Ident,
                              directive: &ImportDirective,
@@ -2262,7 +2214,7 @@ impl<'a> Resolver<'a> {
         debug!("(resolving single import) resolving `{}` = `{}::{}` from \
                 `{}` id {}, last private {:?}",
                token::get_ident(target),
-               self.module_to_str(containing_module),
+               self.module_to_str(&*containing_module),
                token::get_ident(source),
                self.module_to_str(module_),
                directive.id,
@@ -2281,22 +2233,22 @@ impl<'a> Resolver<'a> {
         let mut type_result = UnknownResult;
 
         // Search for direct children of the containing module.
-        self.populate_module_if_necessary(containing_module);
+        self.populate_module_if_necessary(&containing_module);
 
         match containing_module.children.borrow().find(&source.name) {
             None => {
                 // Continue.
             }
-            Some(child_name_bindings) => {
+            Some(ref child_name_bindings) => {
                 if child_name_bindings.defined_in_namespace(ValueNS) {
                     debug!("(resolving single import) found value binding");
-                    value_result = BoundResult(containing_module,
-                                               *child_name_bindings);
+                    value_result = BoundResult(containing_module.clone(),
+                                               (*child_name_bindings).clone());
                 }
                 if child_name_bindings.defined_in_namespace(TypeNS) {
                     debug!("(resolving single import) found type binding");
-                    type_result = BoundResult(containing_module,
-                                              *child_name_bindings);
+                    type_result = BoundResult(containing_module.clone(),
+                                              (*child_name_bindings).clone());
                 }
             }
         }
@@ -2305,7 +2257,7 @@ impl<'a> Resolver<'a> {
         // search imports as well.
         let mut value_used_reexport = false;
         let mut type_used_reexport = false;
-        match (value_result, type_result) {
+        match (value_result.clone(), type_result.clone()) {
             (BoundResult(..), BoundResult(..)) => {} // Continue.
             _ => {
                 // If there is an unresolved glob at this point in the
@@ -2318,12 +2270,8 @@ impl<'a> Resolver<'a> {
                     return Indeterminate;
                 }
 
-                // Now search the exported imports within the containing
-                // module.
-
-                let import_resolutions = containing_module.import_resolutions
-                                                          .borrow();
-                match import_resolutions.find(&source.name) {
+                // Now search the exported imports within the containing module.
+                match containing_module.import_resolutions.borrow().find(&source.name) {
                     None => {
                         debug!("(resolving single import) no import");
                         // The containing module definitely doesn't have an
@@ -2339,32 +2287,30 @@ impl<'a> Resolver<'a> {
                         }
                     }
                     Some(import_resolution)
-                            if import_resolution.outstanding_references.get()
-                                == 0 => {
+                            if import_resolution.outstanding_references == 0 => {
 
                         fn get_binding(this: &mut Resolver,
-                                       import_resolution: @ImportResolution,
+                                       import_resolution: &ImportResolution,
                                        namespace: Namespace)
                                     -> NamespaceResult {
 
                             // Import resolutions must be declared with "pub"
                             // in order to be exported.
-                            if !import_resolution.is_public.get() {
+                            if !import_resolution.is_public {
                                 return UnboundResult;
                             }
 
-                            match (*import_resolution).
+                            match import_resolution.
                                     target_for_namespace(namespace) {
                                 None => {
                                     return UnboundResult;
                                 }
-                                Some(target) => {
+                                Some(Target {target_module, bindings}) => {
                                     debug!("(resolving single import) found \
                                             import in ns {:?}", namespace);
                                     let id = import_resolution.id(namespace);
                                     this.used_imports.insert((id, namespace));
-                                    return BoundResult(target.target_module,
-                                                       target.bindings);
+                                    return BoundResult(target_module, bindings);
                                 }
                             }
                         }
@@ -2372,14 +2318,14 @@ impl<'a> Resolver<'a> {
                         // The name is an import which has been fully
                         // resolved. We can, therefore, just follow it.
                         if value_result.is_unknown() {
-                            value_result = get_binding(self, *import_resolution,
+                            value_result = get_binding(self, import_resolution,
                                                        ValueNS);
-                            value_used_reexport = import_resolution.is_public.get();
+                            value_used_reexport = import_resolution.is_public;
                         }
                         if type_result.is_unknown() {
-                            type_result = get_binding(self, *import_resolution,
+                            type_result = get_binding(self, import_resolution,
                                                       TypeNS);
-                            type_used_reexport = import_resolution.is_public.get();
+                            type_used_reexport = import_resolution.is_public;
                         }
 
                     }
@@ -2407,9 +2353,9 @@ impl<'a> Resolver<'a> {
                         debug!("(resolving single import) found external \
                                 module");
                         let name_bindings =
-                            @Resolver::create_name_bindings_from_module(
-                                module);
-                        type_result = BoundResult(containing_module,
+                            Rc::new(Resolver::create_name_bindings_from_module(
+                                module));
+                        type_result = BoundResult(containing_module.clone(),
                                                   name_bindings);
                         type_used_public = true;
                     }
@@ -2418,18 +2364,15 @@ impl<'a> Resolver<'a> {
         }
 
         // We've successfully resolved the import. Write the results in.
-        let import_resolution = {
-            let import_resolutions = module_.import_resolutions.borrow();
-            assert!(import_resolutions.contains_key(&target.name));
-            import_resolutions.get_copy(&target.name)
-        };
+        let mut import_resolutions = module_.import_resolutions.borrow_mut();
+        let import_resolution = import_resolutions.get_mut(&target.name);
 
         match value_result {
-            BoundResult(target_module, name_bindings) => {
+            BoundResult(ref target_module, ref name_bindings) => {
                 debug!("(resolving single import) found value target");
-                *import_resolution.value_target.borrow_mut() =
-                    Some(Target::new(target_module, name_bindings));
-                import_resolution.value_id.set(directive.id);
+                import_resolution.value_target = Some(Target::new(target_module.clone(),
+                                                                  name_bindings.clone()));
+                import_resolution.value_id = directive.id;
                 value_used_public = name_bindings.defined_in_public_namespace(ValueNS);
             }
             UnboundResult => { /* Continue. */ }
@@ -2438,12 +2381,12 @@ impl<'a> Resolver<'a> {
             }
         }
         match type_result {
-            BoundResult(target_module, name_bindings) => {
+            BoundResult(ref target_module, ref name_bindings) => {
                 debug!("(resolving single import) found type target: {:?}",
                        { name_bindings.type_def.borrow().clone().unwrap().type_def });
-                *import_resolution.type_target.borrow_mut() =
-                    Some(Target::new(target_module, name_bindings));
-                import_resolution.type_id.set(directive.id);
+                import_resolution.type_target =
+                    Some(Target::new(target_module.clone(), name_bindings.clone()));
+                import_resolution.type_id = directive.id;
                 type_used_public = name_bindings.defined_in_public_namespace(TypeNS);
             }
             UnboundResult => { /* Continue. */ }
@@ -2456,22 +2399,21 @@ impl<'a> Resolver<'a> {
             let msg = format!("unresolved import: there is no \
                                `{}` in `{}`",
                               token::get_ident(source),
-                              self.module_to_str(containing_module));
+                              self.module_to_str(&*containing_module));
             self.resolve_error(directive.span, msg);
             return Failed;
         }
         let value_used_public = value_used_reexport || value_used_public;
         let type_used_public = type_used_reexport || type_used_public;
 
-        assert!(import_resolution.outstanding_references.get() >= 1);
-        import_resolution.outstanding_references.set(
-            import_resolution.outstanding_references.get() - 1);
+        assert!(import_resolution.outstanding_references >= 1);
+        import_resolution.outstanding_references -= 1;
 
         // record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
-        let value_private = match *import_resolution.value_target.borrow() {
-            Some(target) => {
+        let value_private = match import_resolution.value_target {
+            Some(ref target) => {
                 let def = target.bindings.def_for_namespace(ValueNS).unwrap();
                 self.def_map.borrow_mut().insert(directive.id, def);
                 let did = def_id_of_def(def);
@@ -2481,8 +2423,8 @@ impl<'a> Resolver<'a> {
             // _exists is false.
             None => None,
         };
-        let type_private = match *import_resolution.type_target.borrow() {
-            Some(target) => {
+        let type_private = match import_resolution.type_target {
+            Some(ref target) => {
                 let def = target.bindings.def_for_namespace(TypeNS).unwrap();
                 self.def_map.borrow_mut().insert(directive.id, def);
                 let did = def_id_of_def(def);
@@ -2504,8 +2446,8 @@ impl<'a> Resolver<'a> {
     // succeeds or bails out (as importing * from an empty module or a module
     // that exports nothing is valid).
     fn resolve_glob_import(&mut self,
-                           module_: @Module,
-                           containing_module: @Module,
+                           module_: &Module,
+                           containing_module: Rc<Module>,
                            id: NodeId,
                            is_public: bool,
                            lp: LastPrivate)
@@ -2531,70 +2473,71 @@ impl<'a> Resolver<'a> {
         for (ident, target_import_resolution) in import_resolutions.iter() {
             debug!("(resolving glob import) writing module resolution \
                     {:?} into `{}`",
-                   target_import_resolution.type_target.borrow().is_none(),
+                   target_import_resolution.type_target.is_none(),
                    self.module_to_str(module_));
 
-            if !target_import_resolution.is_public.get() {
+            if !target_import_resolution.is_public {
                 debug!("(resolving glob import) nevermind, just kidding");
                 continue
             }
 
             // Here we merge two import resolutions.
             let mut import_resolutions = module_.import_resolutions.borrow_mut();
-            match import_resolutions.find(ident) {
-                None => {
-                    // Simple: just copy the old import resolution.
-                    let new_import_resolution =
-                        @ImportResolution::new(id, is_public);
-                    *new_import_resolution.value_target.borrow_mut() =
-                        get(&target_import_resolution.value_target);
-                    *new_import_resolution.type_target.borrow_mut() =
-                        get(&target_import_resolution.type_target);
-
-                    import_resolutions.insert
-                        (*ident, new_import_resolution);
-                }
-                Some(&dest_import_resolution) => {
+            match import_resolutions.find_mut(ident) {
+                Some(dest_import_resolution) => {
                     // Merge the two import resolutions at a finer-grained
                     // level.
 
-                    match *target_import_resolution.value_target.borrow() {
+                    match target_import_resolution.value_target {
                         None => {
                             // Continue.
                         }
-                        Some(value_target) => {
-                            *dest_import_resolution.value_target.borrow_mut() = Some(value_target);
+                        Some(ref value_target) => {
+                            dest_import_resolution.value_target =
+                                Some(value_target.clone());
                         }
                     }
-                    match *target_import_resolution.type_target.borrow() {
+                    match target_import_resolution.type_target {
                         None => {
                             // Continue.
                         }
-                        Some(type_target) => {
-                            *dest_import_resolution.type_target.borrow_mut() = Some(type_target);
+                        Some(ref type_target) => {
+                            dest_import_resolution.type_target =
+                                Some(type_target.clone());
                         }
                     }
-                    dest_import_resolution.is_public.set(is_public);
+                    dest_import_resolution.is_public = is_public;
+                    continue;
                 }
+                None => {}
             }
+
+            // Simple: just copy the old import resolution.
+            let mut new_import_resolution = ImportResolution::new(id, is_public);
+            new_import_resolution.value_target =
+                target_import_resolution.value_target.clone();
+            new_import_resolution.type_target =
+                target_import_resolution.type_target.clone();
+
+            import_resolutions.insert(*ident, new_import_resolution);
         }
 
         // Add all children from the containing module.
-        self.populate_module_if_necessary(containing_module);
+        self.populate_module_if_necessary(&containing_module);
 
         for (&name, name_bindings) in containing_module.children
                                                        .borrow().iter() {
-            self.merge_import_resolution(module_, containing_module,
+            self.merge_import_resolution(module_, containing_module.clone(),
                                          id, is_public,
-                                         name, *name_bindings);
+                                         name, name_bindings.clone());
         }
 
         // Add external module children from the containing module.
         for (&name, module) in containing_module.external_module_children
                                                 .borrow().iter() {
             let name_bindings =
-                @Resolver::create_name_bindings_from_module(*module);
-            self.merge_import_resolution(module_, containing_module,
+                Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
+            self.merge_import_resolution(module_, containing_module.clone(),
                                          id, is_public,
                                          name, name_bindings);
         }
@@ -2613,58 +2556,49 @@ impl<'a> Resolver<'a> {
     }
 
     fn merge_import_resolution(&mut self,
-                               module_: @Module,
-                               containing_module: @Module,
+                               module_: &Module,
+                               containing_module: Rc<Module>,
                                id: NodeId,
                                is_public: bool,
                                name: Name,
-                               name_bindings: @NameBindings) {
-        let dest_import_resolution;
+                               name_bindings: Rc<NameBindings>) {
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        match import_resolutions.find(&name) {
-            None => {
-                // Create a new import resolution from this child.
-                dest_import_resolution =
-                    @ImportResolution::new(id, is_public);
-                import_resolutions.insert(name,
-                                                dest_import_resolution);
-            }
-            Some(&existing_import_resolution) => {
-                dest_import_resolution = existing_import_resolution;
-            }
-        }
+        let dest_import_resolution = import_resolutions.find_or_insert_with(name, |_| {
+            // Create a new import resolution from this child.
+            ImportResolution::new(id, is_public)
+        });
 
         debug!("(resolving glob import) writing resolution `{}` in `{}` \
                to `{}`",
                token::get_name(name).get().to_str(),
-               self.module_to_str(containing_module),
+               self.module_to_str(&*containing_module),
                self.module_to_str(module_));
 
         // Merge the child item into the import resolution.
         if name_bindings.defined_in_public_namespace(ValueNS) {
             debug!("(resolving glob import) ... for value target");
-            *dest_import_resolution.value_target.borrow_mut() =
-                Some(Target::new(containing_module, name_bindings));
-            dest_import_resolution.value_id.set(id);
+            dest_import_resolution.value_target =
+                Some(Target::new(containing_module.clone(), name_bindings.clone()));
+            dest_import_resolution.value_id = id;
         }
         if name_bindings.defined_in_public_namespace(TypeNS) {
             debug!("(resolving glob import) ... for type target");
-            *dest_import_resolution.type_target.borrow_mut() =
-                Some(Target::new(containing_module, name_bindings));
-            dest_import_resolution.type_id.set(id);
+            dest_import_resolution.type_target =
+                Some(Target::new(containing_module, name_bindings.clone()));
+            dest_import_resolution.type_id = id;
         }
-        dest_import_resolution.is_public.set(is_public);
+        dest_import_resolution.is_public = is_public;
     }
 
     /// Resolves the given module path from the given root `module_`.
     fn resolve_module_path_from_root(&mut self,
-                                     module_: @Module,
+                                     module_: Rc<Module>,
                                      module_path: &[Ident],
                                      index: uint,
                                      span: Span,
                                      name_search_type: NameSearchType,
                                      lp: LastPrivate)
-                                -> ResolveResult<(@Module, LastPrivate)> {
+                                -> ResolveResult<(Rc<Module>, LastPrivate)> {
         let mut search_module = module_;
         let mut index = index;
         let module_path_len = module_path.len();
@@ -2675,14 +2609,14 @@ impl<'a> Resolver<'a> {
         // modules as we go.
         while index < module_path_len {
             let name = module_path[index];
-            match self.resolve_name_in_module(search_module,
+            match self.resolve_name_in_module(search_module.clone(),
                                               name,
                                               TypeNS,
                                               name_search_type,
                                               false) {
                 Failed => {
                     let segment_name = token::get_ident(name);
-                    let module_name = self.module_to_str(search_module);
+                    let module_name = self.module_to_str(&*search_module);
                     if "???" == module_name {
                         let span = Span {
                             lo: span.lo,
@@ -2710,7 +2644,7 @@ impl<'a> Resolver<'a> {
                     // Check to see whether there are type bindings, and, if
                     // so, whether there is a module within.
                     match *target.bindings.type_def.borrow() {
-                        Some(type_def) => {
+                        Some(ref type_def) => {
                             match type_def.module_def {
                                 None => {
                                     // Not a module.
@@ -2718,7 +2652,7 @@ impl<'a> Resolver<'a> {
                                                                  token::get_ident(name)));
                                     return Failed;
                                 }
-                                Some(module_def) => {
+                                Some(ref module_def) => {
                                     // If we're doing the search for an
                                     // import, do not allow traits and impls
                                     // to be selected.
@@ -2733,7 +2667,7 @@ impl<'a> Resolver<'a> {
                                             return Failed;
                                         }
                                         (_, _) => {
-                                            search_module = module_def;
+                                            search_module = module_def.clone();
 
                                             // Keep track of the closest
                                             // private module used when
@@ -2777,22 +2711,22 @@ impl<'a> Resolver<'a> {
     /// On success, returns the resolved module, and the closest *private*
     /// module found to the destination when resolving this path.
     fn resolve_module_path(&mut self,
-                           module_: @Module,
+                           module_: Rc<Module>,
                            module_path: &[Ident],
                            use_lexical_scope: UseLexicalScopeFlag,
                            span: Span,
                            name_search_type: NameSearchType)
-                               -> ResolveResult<(@Module, LastPrivate)> {
+                               -> ResolveResult<(Rc<Module>, LastPrivate)> {
         let module_path_len = module_path.len();
         assert!(module_path_len > 0);
 
         debug!("(resolving module path for import) processing `{}` rooted at \
                `{}`",
                self.idents_to_str(module_path),
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // Resolve the module prefix, if any.
-        let module_prefix_result = self.resolve_module_prefix(module_,
+        let module_prefix_result = self.resolve_module_prefix(module_.clone(),
                                                               module_path);
 
         let search_module;
@@ -2857,8 +2791,8 @@ impl<'a> Resolver<'a> {
                     }
                 }
             }
-            Success(PrefixFound(containing_module, index)) => {
-                search_module = containing_module;
+            Success(PrefixFound(ref containing_module, index)) => {
+                search_module = containing_module.clone();
                 start_index = index;
                 last_private = LastMod(DependsOn(containing_module.def_id
                                                                   .get()
@@ -2877,7 +2811,7 @@ impl<'a> Resolver<'a> {
     /// Invariant: This must only be called during main resolution, not during
     /// import resolution.
     fn resolve_item_in_lexical_scope(&mut self,
-                                     module_: @Module,
+                                     module_: Rc<Module>,
                                      name: Ident,
                                      namespace: Namespace,
                                      search_through_modules:
@@ -2887,17 +2821,17 @@ impl<'a> Resolver<'a> {
                 namespace {:?} in `{}`",
                token::get_ident(name),
                namespace,
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // The current module node is handled specially. First, check for
         // its immediate children.
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
 
         match module_.children.borrow().find(&name.name) {
             Some(name_bindings)
                     if name_bindings.defined_in_namespace(namespace) => {
                 debug!("top name bindings succeeded");
-                return Success((Target::new(module_, *name_bindings),
+                return Success((Target::new(module_.clone(), name_bindings.clone()),
                                false));
             }
             Some(_) | None => { /* Not found; continue. */ }
@@ -2935,7 +2869,7 @@ impl<'a> Resolver<'a> {
                 None => {}
                 Some(module) => {
                     let name_bindings =
-                        @Resolver::create_name_bindings_from_module(module);
+                        Rc::new(Resolver::create_name_bindings_from_module(module));
                     debug!("lower name bindings succeeded");
                     return Success((Target::new(module_, name_bindings), false));
                 }
@@ -2946,7 +2880,7 @@ impl<'a> Resolver<'a> {
         let mut search_module = module_;
         loop {
             // Go to the next parent.
-            match search_module.parent_link {
+            match search_module.parent_link.clone() {
                 NoParentLink => {
                     // No more parents. This module was unresolved.
                     debug!("(resolving item in lexical scope) unresolved \
@@ -2969,22 +2903,22 @@ impl<'a> Resolver<'a> {
                                 TraitModuleKind |
                                 ImplModuleKind |
                                 AnonymousModuleKind => {
-                                    search_module = parent_module_node;
+                                    search_module = parent_module_node.upgrade().unwrap();
                                 }
                             }
                         }
                         SearchThroughModules => {
-                            search_module = parent_module_node;
+                            search_module = parent_module_node.upgrade().unwrap();
                         }
                     }
                 }
-                BlockParentLink(parent_module_node, _) => {
-                    search_module = parent_module_node;
+                BlockParentLink(ref parent_module_node, _) => {
+                    search_module = parent_module_node.upgrade().unwrap();
                 }
             }
 
             // Resolve the name in the parent module.
-            match self.resolve_name_in_module(search_module,
+            match self.resolve_name_in_module(search_module.clone(),
                                               name,
                                               namespace,
                                               PathSearch,
@@ -3012,9 +2946,9 @@ impl<'a> Resolver<'a> {
 
     /// Resolves a module name in the current lexical scope.
     fn resolve_module_in_lexical_scope(&mut self,
-                                       module_: @Module,
+                                       module_: Rc<Module>,
                                        name: Ident)
-                                -> ResolveResult<@Module> {
+                                -> ResolveResult<Rc<Module>> {
         // If this module is an anonymous module, resolve the item in the
         // lexical scope. Otherwise, resolve the item from the crate root.
         let resolve_result = self.resolve_item_in_lexical_scope(
@@ -3023,7 +2957,7 @@ impl<'a> Resolver<'a> {
             Success((target, _)) => {
                 let bindings = &*target.bindings;
                 match *bindings.type_def.borrow() {
-                    Some(type_def) => {
+                    Some(ref type_def) => {
                         match type_def.module_def {
                             None => {
                                 error!("!!! (resolving module in lexical \
@@ -3031,8 +2965,8 @@ impl<'a> Resolver<'a> {
                                         module!");
                                 return Failed;
                             }
-                            Some(module_def) => {
-                                return Success(module_def);
+                            Some(ref module_def) => {
+                                return Success(module_def.clone());
                             }
                         }
                     }
@@ -3057,14 +2991,15 @@ impl<'a> Resolver<'a> {
     }
 
     /// Returns the nearest normal module parent of the given module.
-    fn get_nearest_normal_module_parent(&mut self, module_: @Module)
-                                            -> Option<@Module> {
+    fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>)
+                                            -> Option<Rc<Module>> {
         let mut module_ = module_;
         loop {
-            match module_.parent_link {
+            match module_.parent_link.clone() {
                 NoParentLink => return None,
                 ModuleParentLink(new_module, _) |
                 BlockParentLink(new_module, _) => {
+                    let new_module = new_module.upgrade().unwrap();
                     match new_module.kind.get() {
                         NormalModuleKind => return Some(new_module),
                         ExternModuleKind |
@@ -3079,15 +3014,15 @@ impl<'a> Resolver<'a> {
 
     /// Returns the nearest normal module parent of the given module, or the
     /// module itself if it is a normal module.
-    fn get_nearest_normal_module_parent_or_self(&mut self, module_: @Module)
-                                                -> @Module {
+    fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>)
+                                                -> Rc<Module> {
         match module_.kind.get() {
             NormalModuleKind => return module_,
             ExternModuleKind |
             TraitModuleKind |
             ImplModuleKind |
             AnonymousModuleKind => {
-                match self.get_nearest_normal_module_parent(module_) {
+                match self.get_nearest_normal_module_parent(module_.clone()) {
                     None => module_,
                     Some(new_module) => new_module
                 }
@@ -3099,7 +3034,7 @@ impl<'a> Resolver<'a> {
     /// (b) some chain of `super::`.
     /// grammar: (SELF MOD_SEP ) ? (SUPER MOD_SEP) *
     fn resolve_module_prefix(&mut self,
-                             module_: @Module,
+                             module_: Rc<Module>,
                              module_path: &[Ident])
                                  -> ResolveResult<ModulePrefixResult> {
         // Start at the current module if we see `self` or `super`, or at the
@@ -3126,7 +3061,7 @@ impl<'a> Resolver<'a> {
                 break
             }
             debug!("(resolving module prefix) resolving `super` at {}",
-                   self.module_to_str(containing_module));
+                   self.module_to_str(&*containing_module));
             match self.get_nearest_normal_module_parent(containing_module) {
                 None => return Failed,
                 Some(new_module) => {
@@ -3137,7 +3072,7 @@ impl<'a> Resolver<'a> {
         }
 
         debug!("(resolving module prefix) finished resolving prefix at {}",
-               self.module_to_str(containing_module));
+               self.module_to_str(&*containing_module));
 
         return Success(PrefixFound(containing_module, i));
     }
@@ -3149,7 +3084,7 @@ impl<'a> Resolver<'a> {
     /// The boolean returned on success is an indicator of whether this lookup
     /// passed through a public re-export proxy.
     fn resolve_name_in_module(&mut self,
-                              module_: @Module,
+                              module_: Rc<Module>,
                               name: Ident,
                               namespace: Namespace,
                               name_search_type: NameSearchType,
@@ -3157,16 +3092,16 @@ impl<'a> Resolver<'a> {
                               -> ResolveResult<(Target, bool)> {
         debug!("(resolving name in module) resolving `{}` in `{}`",
                token::get_ident(name),
-               self.module_to_str(module_));
+               self.module_to_str(&*module_));
 
         // First, check the direct children of the module.
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
 
         match module_.children.borrow().find(&name.name) {
             Some(name_bindings)
                     if name_bindings.defined_in_namespace(namespace) => {
                 debug!("(resolving name in module) found node as child");
-                return Success((Target::new(module_, *name_bindings),
+                return Success((Target::new(module_.clone(), name_bindings.clone()),
                                false));
             }
             Some(_) | None => {
@@ -3185,10 +3120,10 @@ impl<'a> Resolver<'a> {
         // Check the list of resolved imports.
         match module_.import_resolutions.borrow().find(&name.name) {
             Some(import_resolution) if allow_private_imports ||
-                                       import_resolution.is_public.get() => {
+                                       import_resolution.is_public => {
 
-                if import_resolution.is_public.get() &&
-                        import_resolution.outstanding_references.get() != 0 {
+                if import_resolution.is_public &&
+                        import_resolution.outstanding_references != 0 {
                     debug!("(resolving name in module) import \
                            unresolved; bailing out");
                     return Indeterminate;
@@ -3216,7 +3151,7 @@ impl<'a> Resolver<'a> {
                 None => {}
                 Some(module) => {
                     let name_bindings =
-                        @Resolver::create_name_bindings_from_module(module);
+                        Rc::new(Resolver::create_name_bindings_from_module(module));
                     return Success((Target::new(module_, name_bindings), false));
                 }
             }
@@ -3228,7 +3163,7 @@ impl<'a> Resolver<'a> {
         return Failed;
     }
 
-    fn report_unresolved_imports(&mut self, module_: @Module) {
+    fn report_unresolved_imports(&mut self, module_: Rc<Module>) {
         let index = module_.resolved_import_count.get();
         let imports = module_.imports.borrow();
         let import_count = imports.len();
@@ -3248,9 +3183,9 @@ impl<'a> Resolver<'a> {
         }
 
         // Descend into children and anonymous children.
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
 
-        for (_, &child_node) in module_.children.borrow().iter() {
+        for (_, child_node) in module_.children.borrow().iter() {
             match child_node.get_module_if_available() {
                 None => {
                     // Continue.
@@ -3261,8 +3196,8 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for (_, &module_) in module_.anonymous_children.borrow().iter() {
-            self.report_unresolved_imports(module_);
+        for (_, module_) in module_.anonymous_children.borrow().iter() {
+            self.report_unresolved_imports(module_.clone());
         }
     }
 
@@ -3281,7 +3216,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn record_exports_for_module_subtree(&mut self,
-                                             module_: @Module) {
+                                             module_: Rc<Module>) {
         // If this isn't a local krate, then bail out. We don't need to record
         // exports for nonlocal crates.
 
@@ -3290,27 +3225,27 @@ impl<'a> Resolver<'a> {
                 // OK. Continue.
                 debug!("(recording exports for module subtree) recording \
                         exports for local module `{}`",
-                       self.module_to_str(module_));
+                       self.module_to_str(&*module_));
             }
             None => {
                 // Record exports for the root module.
                 debug!("(recording exports for module subtree) recording \
                         exports for root module `{}`",
-                       self.module_to_str(module_));
+                       self.module_to_str(&*module_));
             }
             Some(_) => {
                 // Bail out.
                 debug!("(recording exports for module subtree) not recording \
                         exports for `{}`",
-                       self.module_to_str(module_));
+                       self.module_to_str(&*module_));
                 return;
             }
         }
 
-        self.record_exports_for_module(module_);
-        self.populate_module_if_necessary(module_);
+        self.record_exports_for_module(&*module_);
+        self.populate_module_if_necessary(&module_);
 
-        for (_, &child_name_bindings) in module_.children.borrow().iter() {
+        for (_, child_name_bindings) in module_.children.borrow().iter() {
             match child_name_bindings.get_module_if_available() {
                 None => {
                     // Nothing to do.
@@ -3321,12 +3256,12 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for (_, &child_module) in module_.anonymous_children.borrow().iter() {
-            self.record_exports_for_module_subtree(child_module);
+        for (_, child_module) in module_.anonymous_children.borrow().iter() {
+            self.record_exports_for_module_subtree(child_module.clone());
         }
     }
 
-    fn record_exports_for_module(&mut self, module_: @Module) {
+    fn record_exports_for_module(&mut self, module_: &Module) {
         let mut exports2 = Vec::new();
 
         self.add_exports_for_module(&mut exports2, module_);
@@ -3343,7 +3278,7 @@ impl<'a> Resolver<'a> {
     fn add_exports_of_namebindings(&mut self,
                                    exports2: &mut Vec<Export2> ,
                                    name: Name,
-                                   namebindings: @NameBindings,
+                                   namebindings: &NameBindings,
                                    ns: Namespace) {
         match namebindings.def_for_namespace(ns) {
             Some(d) => {
@@ -3363,9 +3298,9 @@ impl<'a> Resolver<'a> {
 
     fn add_exports_for_module(&mut self,
                               exports2: &mut Vec<Export2> ,
-                              module_: @Module) {
+                              module_: &Module) {
         for (name, importresolution) in module_.import_resolutions.borrow().iter() {
-            if !importresolution.is_public.get() {
+            if !importresolution.is_public {
                 continue
             }
             let xs = [TypeNS, ValueNS];
@@ -3376,7 +3311,7 @@ impl<'a> Resolver<'a> {
                                token::get_name(*name));
                         self.add_exports_of_namebindings(exports2,
                                                          *name,
-                                                         target.bindings,
+                                                         &*target.bindings,
                                                          ns)
                     }
                     _ => ()
@@ -3404,7 +3339,7 @@ impl<'a> Resolver<'a> {
     // implementations thus found, for compatibility with old resolve pass.
 
     fn with_scope(&mut self, name: Option<Ident>, f: |&mut Resolver|) {
-        let orig_module = self.current_module;
+        let orig_module = self.current_module.clone();
 
         // Move down in the graph.
         match name {
@@ -3412,13 +3347,13 @@ impl<'a> Resolver<'a> {
                 // Nothing to do.
             }
             Some(name) => {
-                self.populate_module_if_necessary(orig_module);
+                self.populate_module_if_necessary(&orig_module);
 
                 match orig_module.children.borrow().find(&name.name) {
                     None => {
                         debug!("!!! (with scope) didn't find `{}` in `{}`",
                                token::get_ident(name),
-                               self.module_to_str(orig_module));
+                               self.module_to_str(&*orig_module));
                     }
                     Some(name_bindings) => {
                         match (*name_bindings).get_module_if_available() {
@@ -3426,7 +3361,7 @@ impl<'a> Resolver<'a> {
                                 debug!("!!! (with scope) didn't find module \
                                         for `{}` in `{}`",
                                        token::get_ident(name),
-                                       self.module_to_str(orig_module));
+                                       self.module_to_str(&*orig_module));
                             }
                             Some(module_) => {
                                 self.current_module = module_;
@@ -3444,12 +3379,12 @@ impl<'a> Resolver<'a> {
 
     /// Wraps the given definition in the appropriate number of `def_upvar`
     /// wrappers.
-    fn upvarify(&mut self,
-                    ribs: &mut Vec<@Rib> ,
-                    rib_index: uint,
-                    def_like: DefLike,
-                    span: Span)
-                    -> Option<DefLike> {
+    fn upvarify(&self,
+                ribs: &[Rib],
+                rib_index: uint,
+                def_like: DefLike,
+                span: Span)
+                -> Option<DefLike> {
         let mut def;
         let is_ty_param;
 
@@ -3470,7 +3405,7 @@ impl<'a> Resolver<'a> {
 
         let mut rib_index = rib_index + 1;
         while rib_index < ribs.len() {
-            match ribs.get(rib_index).kind {
+            match ribs[rib_index].kind {
                 NormalRibKind => {
                     // Nothing to do. Continue.
                 }
@@ -3560,18 +3495,18 @@ impl<'a> Resolver<'a> {
         return Some(DlDef(def));
     }
 
-    fn search_ribs(&mut self,
-                       ribs: &mut Vec<@Rib> ,
-                       name: Name,
-                       span: Span)
-                       -> Option<DefLike> {
+    fn search_ribs(&self,
+                   ribs: &[Rib],
+                   name: Name,
+                   span: Span)
+                   -> Option<DefLike> {
         // FIXME #4950: This should not use a while loop.
         // FIXME #4950: Try caching?
 
         let mut i = ribs.len();
         while i != 0 {
             i -= 1;
-            let binding_opt = ribs.get(i).bindings.borrow().find_copy(&name);
+            let binding_opt = ribs[i].bindings.borrow().find_copy(&name);
             match binding_opt {
                 Some(def_like) => {
                     return self.upvarify(ribs, i, def_like, span);
@@ -3610,7 +3545,7 @@ impl<'a> Resolver<'a> {
                     }
                 }
 
-                // n.b. the discr expr gets visted twice.
+                // n.b. the discr expr gets visited twice.
                 // but maybe it's okay since the first time will signal an
                 // error if there is one? -- tjc
                 self.with_type_parameter_rib(HasTypeParameters(generics,
@@ -3645,12 +3580,12 @@ impl<'a> Resolver<'a> {
 
             ItemTrait(ref generics, ref traits, ref methods) => {
                 // Create a new rib for the self type.
-                let self_type_rib = @Rib::new(NormalRibKind);
-                self.type_ribs.borrow_mut().push(self_type_rib);
+                let self_type_rib = Rib::new(NormalRibKind);
                 // plain insert (no renaming)
                 let name = self.type_self_ident.name;
                 self_type_rib.bindings.borrow_mut()
                              .insert(name, DlDef(DefSelfTy(item.id)));
+                self.type_ribs.borrow_mut().push(self_type_rib);
 
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics,
@@ -3772,8 +3707,7 @@ impl<'a> Resolver<'a> {
             HasTypeParameters(generics, node_id, initial_index,
                               rib_kind) => {
 
-                let function_type_rib = @Rib::new(rib_kind);
-                self.type_ribs.borrow_mut().push(function_type_rib);
+                let function_type_rib = Rib::new(rib_kind);
 
                 for (index, type_parameter) in generics.ty_params.iter().enumerate() {
                     let ident = type_parameter.ident;
@@ -3790,6 +3724,7 @@ impl<'a> Resolver<'a> {
                     function_type_rib.bindings.borrow_mut()
                                      .insert(ident.name, def_like);
                 }
+                self.type_ribs.borrow_mut().push(function_type_rib);
             }
 
             NoTypeParameters => {
@@ -3806,14 +3741,14 @@ impl<'a> Resolver<'a> {
     }
 
     fn with_label_rib(&mut self, f: |&mut Resolver|) {
-        self.label_ribs.borrow_mut().push(@Rib::new(NormalRibKind));
+        self.label_ribs.borrow_mut().push(Rib::new(NormalRibKind));
         f(self);
         self.label_ribs.borrow_mut().pop();
     }
 
     fn with_constant_rib(&mut self, f: |&mut Resolver|) {
-        self.value_ribs.borrow_mut().push(@Rib::new(ConstantItemRibKind));
-        self.type_ribs.borrow_mut().push(@Rib::new(ConstantItemRibKind));
+        self.value_ribs.borrow_mut().push(Rib::new(ConstantItemRibKind));
+        self.type_ribs.borrow_mut().push(Rib::new(ConstantItemRibKind));
         f(self);
         self.type_ribs.borrow_mut().pop();
         self.value_ribs.borrow_mut().pop();
@@ -3825,11 +3760,11 @@ impl<'a> Resolver<'a> {
                         type_parameters: TypeParameters,
                         block: P<Block>) {
         // Create a value rib for the function.
-        let function_value_rib = @Rib::new(rib_kind);
+        let function_value_rib = Rib::new(rib_kind);
         self.value_ribs.borrow_mut().push(function_value_rib);
 
         // Create a label rib for the function.
-        let function_label_rib = @Rib::new(rib_kind);
+        let function_label_rib = Rib::new(rib_kind);
         self.label_ribs.borrow_mut().push(function_label_rib);
 
         // If this function has type parameters, add them now.
@@ -3980,7 +3915,7 @@ impl<'a> Resolver<'a> {
     // to be NormalRibKind?
     fn resolve_method(&mut self,
                       rib_kind: RibKind,
-                      method: @Method,
+                      method: &Method,
                       outer_type_parameter_count: uint) {
         let method_generics = &method.generics;
         let type_parameters =
@@ -4093,9 +4028,9 @@ impl<'a> Resolver<'a> {
     // this is done hygienically. This could arise for a macro
     // that expands into an or-pattern where one 'x' was from the
     // user and one 'x' came from the macro.
-    fn binding_mode_map(&mut self, pat: @Pat) -> BindingMap {
+    fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
         let mut result = HashMap::new();
-        pat_bindings(self.def_map, pat, |binding_mode, _id, sp, path| {
+        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| {
             let name = mtwt::resolve(path_to_ident(path));
             result.insert(name,
                           binding_info {span: sp,
@@ -4151,7 +4086,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_arm(&mut self, arm: &Arm) {
-        self.value_ribs.borrow_mut().push(@Rib::new(NormalRibKind));
+        self.value_ribs.borrow_mut().push(Rib::new(NormalRibKind));
 
         let mut bindings_list = HashMap::new();
         for pattern in arm.pats.iter() {
@@ -4172,19 +4107,16 @@ impl<'a> Resolver<'a> {
 
     fn resolve_block(&mut self, block: &Block) {
         debug!("(resolving block) entering block");
-        self.value_ribs.borrow_mut().push(@Rib::new(NormalRibKind));
+        self.value_ribs.borrow_mut().push(Rib::new(NormalRibKind));
 
         // Move down in the graph, if there's an anonymous module rooted here.
-        let orig_module = self.current_module;
-        let anonymous_children = self.current_module
-                                     .anonymous_children
-                                     .borrow();
-        match anonymous_children.find(&block.id) {
+        let orig_module = self.current_module.clone();
+        match orig_module.anonymous_children.borrow().find(&block.id) {
             None => { /* Nothing to do. */ }
-            Some(&anonymous_module) => {
+            Some(anonymous_module) => {
                 debug!("(resolving block) found anonymous module, moving \
                         down");
-                self.current_module = anonymous_module;
+                self.current_module = anonymous_module.clone();
             }
         }
 
@@ -4302,7 +4234,7 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_pattern(&mut self,
-                       pattern: @Pat,
+                       pattern: &Pat,
                        mode: PatternBindingMode,
                        // Maps idents to the node ID for the (outermost)
                        // pattern that binds them
@@ -4553,9 +4485,9 @@ impl<'a> Resolver<'a> {
     }
 
     fn resolve_bare_identifier_pattern(&mut self, name: Ident)
-                                           ->
-                                           BareIdentifierPatternResolution {
-        match self.resolve_item_in_lexical_scope(self.current_module,
+                                       -> BareIdentifierPatternResolution {
+        let module = self.current_module.clone();
+        match self.resolve_item_in_lexical_scope(module,
                                                  name,
                                                  ValueNS,
                                                  SearchThroughModules) {
@@ -4668,12 +4600,12 @@ impl<'a> Resolver<'a> {
 
     // FIXME #4952: Merge me with resolve_name_in_module?
     fn resolve_definition_of_name_in_module(&mut self,
-                                            containing_module: @Module,
+                                            containing_module: Rc<Module>,
                                             name: Ident,
                                             namespace: Namespace)
                                                 -> NameDefinition {
         // First, search children.
-        self.populate_module_if_necessary(containing_module);
+        self.populate_module_if_necessary(&containing_module);
 
         match containing_module.children.borrow().find(&name.name) {
             Some(child_name_bindings) => {
@@ -4695,7 +4627,7 @@ impl<'a> Resolver<'a> {
 
         // Next, search import resolutions.
         match containing_module.import_resolutions.borrow().find(&name.name) {
-            Some(import_resolution) if import_resolution.is_public.get() => {
+            Some(import_resolution) if import_resolution.is_public => {
                 match (*import_resolution).target_for_namespace(namespace) {
                     Some(target) => {
                         match target.bindings.def_for_namespace(namespace) {
@@ -4750,7 +4682,8 @@ impl<'a> Resolver<'a> {
 
         let containing_module;
         let last_private;
-        match self.resolve_module_path(self.current_module,
+        let module = self.current_module.clone();
+        match self.resolve_module_path(module,
                                        module_path_idents.as_slice(),
                                        UseLexicalScope,
                                        path.span,
@@ -4773,7 +4706,7 @@ impl<'a> Resolver<'a> {
         }
 
         let ident = path.segments.last().unwrap().identifier;
-        let def = match self.resolve_definition_of_name_in_module(containing_module,
+        let def = match self.resolve_definition_of_name_in_module(containing_module.clone(),
                                                         ident,
                                                         namespace) {
             NoNameDefinition => {
@@ -4786,22 +4719,17 @@ impl<'a> Resolver<'a> {
         };
         match containing_module.kind.get() {
             TraitModuleKind | ImplModuleKind => {
-                match self.method_map.borrow().find(&ident.name) {
-                    Some(s) => {
-                        match containing_module.def_id.get() {
-                            Some(def_id) if s.contains(&def_id) => {
-                                debug!("containing module was a trait or impl \
-                                        and name was a method -> not resolved");
-                                return None;
-                            },
-                            _ => (),
-                        }
+                match containing_module.def_id.get() {
+                    Some(def_id) if self.method_set.borrow().contains(&(ident.name, def_id)) => {
+                        debug!("containing module was a trait or impl \
+                                and name was a method -> not resolved");
+                        return None;
                     },
-                    None => (),
+                    _ => (),
                 }
             },
             _ => (),
-        };
+        }
         return Some(def);
     }
 
@@ -4865,12 +4793,12 @@ impl<'a> Resolver<'a> {
         let search_result = match namespace {
             ValueNS => {
                 let renamed = mtwt::resolve(ident);
-                self.search_ribs(&mut *self.value_ribs.borrow_mut(),
+                self.search_ribs(self.value_ribs.borrow().as_slice(),
                                  renamed, span)
             }
             TypeNS => {
                 let name = ident.name;
-                self.search_ribs(&mut *self.type_ribs.borrow_mut(), name, span)
+                self.search_ribs(self.type_ribs.borrow().as_slice(), name, span)
             }
         };
 
@@ -4893,7 +4821,8 @@ impl<'a> Resolver<'a> {
                                                    namespace: Namespace)
                                                 -> Option<(Def, LastPrivate)> {
         // Check the items.
-        match self.resolve_item_in_lexical_scope(self.current_module,
+        let module = self.current_module.clone();
+        match self.resolve_item_in_lexical_scope(module,
                                                  ident,
                                                  namespace,
                                                  DontSearchThroughModules) {
@@ -4936,7 +4865,7 @@ impl<'a> Resolver<'a> {
         rs
     }
 
-    fn resolve_error(&mut self, span: Span, s: &str) {
+    fn resolve_error(&self, span: Span, s: &str) {
         if self.emit_errors {
             self.session.span_err(span, s);
         }
@@ -5115,9 +5044,9 @@ impl<'a> Resolver<'a> {
             ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
 
             ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
-                let mut label_ribs = self.label_ribs.borrow_mut();
                 let renamed = mtwt::resolve(label);
-                match self.search_ribs(&mut *label_ribs, renamed, expr.span) {
+                match self.search_ribs(self.label_ribs.borrow().as_slice(),
+                                       renamed, expr.span) {
                     None =>
                         self.resolve_error(expr.span,
                                               format!("use of undeclared label `{}`",
@@ -5147,14 +5076,14 @@ impl<'a> Resolver<'a> {
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.search_for_traits_containing_method(ident);
+                let traits = self.search_for_traits_containing_method(ident.name);
                 self.trait_map.insert(expr.id, traits);
             }
             ExprMethodCall(ident, _, _) => {
                 debug!("(recording candidate traits for expr) recording \
                         traits for {}",
                        expr.id);
-                let traits = self.search_for_traits_containing_method(ident);
+                let traits = self.search_for_traits_containing_method(ident.name);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -5163,34 +5092,44 @@ impl<'a> Resolver<'a> {
         }
     }
 
-    fn search_for_traits_containing_method(&mut self, name: Ident) -> Vec<DefId> {
+    fn search_for_traits_containing_method(&mut self, name: Name) -> Vec<DefId> {
         debug!("(searching for traits containing method) looking for '{}'",
-               token::get_ident(name));
+               token::get_name(name));
+
+        fn add_trait_info(found_traits: &mut Vec<DefId>,
+                          trait_def_id: DefId,
+                          name: Name) {
+            debug!("(adding trait info) found trait {}:{} for method '{}'",
+                trait_def_id.krate,
+                trait_def_id.node,
+                token::get_name(name));
+            found_traits.push(trait_def_id);
+        }
 
         let mut found_traits = Vec::new();
-        let mut search_module = self.current_module;
-        match self.method_map.borrow().find(&name.name) {
-            Some(candidate_traits) => loop {
-                // Look for the current trait.
-                match self.current_trait_refs {
-                    Some(ref trait_def_ids) => {
-                        for trait_def_id in trait_def_ids.iter() {
-                            if candidate_traits.contains(trait_def_id) {
-                                self.add_trait_info(&mut found_traits,
-                                                    *trait_def_id,
-                                                    name);
-                            }
+        let mut search_module = self.current_module.clone();
+        loop {
+            // Look for the current trait.
+            match self.current_trait_refs {
+                Some(ref trait_def_ids) => {
+                    let method_set = self.method_set.borrow();
+                    for &trait_def_id in trait_def_ids.iter() {
+                        if method_set.contains(&(name, trait_def_id)) {
+                            add_trait_info(&mut found_traits, trait_def_id, name);
                         }
                     }
-                    None => {
-                        // Nothing to do.
-                    }
                 }
+                None => {
+                    // Nothing to do.
+                }
+            }
 
-                // Look for trait children.
-                self.populate_module_if_necessary(search_module);
+            // Look for trait children.
+            self.populate_module_if_necessary(&search_module);
 
-                for (_, &child_names) in search_module.children.borrow().iter() {
+            {
+                let method_set = self.method_set.borrow();
+                for (_, child_names) in search_module.children.borrow().iter() {
                     let def = match child_names.def_for_namespace(TypeNS) {
                         Some(def) => def,
                         None => continue
@@ -5199,52 +5138,37 @@ impl<'a> Resolver<'a> {
                         DefTrait(trait_def_id) => trait_def_id,
                         _ => continue,
                     };
-                    if candidate_traits.contains(&trait_def_id) {
-                        self.add_trait_info(&mut found_traits, trait_def_id,
-                                            name);
+                    if method_set.contains(&(name, trait_def_id)) {
+                        add_trait_info(&mut found_traits, trait_def_id, name);
                     }
                 }
+            }
 
-                // Look for imports.
-                let import_resolutions = search_module.import_resolutions
-                                                      .borrow();
-                for (_, &import) in import_resolutions.iter() {
-                    let target = match import.target_for_namespace(TypeNS) {
-                        None => continue,
-                        Some(target) => target,
-                    };
-                    let did = match target.bindings.def_for_namespace(TypeNS) {
-                        Some(DefTrait(trait_def_id)) => trait_def_id,
-                        Some(..) | None => continue,
-                    };
-                    if candidate_traits.contains(&did) {
-                        self.add_trait_info(&mut found_traits, did, name);
-                        self.used_imports.insert((import.type_id.get(), TypeNS));
-                    }
+            // Look for imports.
+            for (_, import) in search_module.import_resolutions.borrow().iter() {
+                let target = match import.target_for_namespace(TypeNS) {
+                    None => continue,
+                    Some(target) => target,
+                };
+                let did = match target.bindings.def_for_namespace(TypeNS) {
+                    Some(DefTrait(trait_def_id)) => trait_def_id,
+                    Some(..) | None => continue,
+                };
+                if self.method_set.borrow().contains(&(name, did)) {
+                    add_trait_info(&mut found_traits, did, name);
+                    self.used_imports.insert((import.type_id, TypeNS));
                 }
+            }
 
-                match search_module.parent_link {
-                    NoParentLink | ModuleParentLink(..) => break,
-                    BlockParentLink(parent_module, _) => {
-                        search_module = parent_module;
-                    }
+            match search_module.parent_link.clone() {
+                NoParentLink | ModuleParentLink(..) => break,
+                BlockParentLink(parent_module, _) => {
+                    search_module = parent_module.upgrade().unwrap();
                 }
-            },
-            _ => ()
+            }
         }
 
-        return found_traits;
-    }
-
-    fn add_trait_info(&self,
-                          found_traits: &mut Vec<DefId> ,
-                          trait_def_id: DefId,
-                          name: Ident) {
-        debug!("(adding trait info) found trait {}:{} for method '{}'",
-               trait_def_id.krate,
-               trait_def_id.node,
-               token::get_ident(name));
-        found_traits.push(trait_def_id);
+        found_traits
     }
 
     fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
@@ -5381,40 +5305,38 @@ impl<'a> Resolver<'a> {
     //
 
     /// A somewhat inefficient routine to obtain the name of a module.
-    fn module_to_str(&mut self, module_: @Module) -> ~str {
+    fn module_to_str(&mut self, module: &Module) -> ~str {
         let mut idents = Vec::new();
-        let mut current_module = module_;
-        loop {
-            match current_module.parent_link {
-                NoParentLink => {
-                    break;
-                }
-                ModuleParentLink(module_, name) => {
+
+        fn collect_mod(idents: &mut Vec<ast::Ident>, module: &Module) {
+            match module.parent_link {
+                NoParentLink => {}
+                ModuleParentLink(ref module, name) => {
                     idents.push(name);
-                    current_module = module_;
+                    collect_mod(idents, &*module.upgrade().unwrap());
                 }
-                BlockParentLink(module_, _) => {
+                BlockParentLink(ref module, _) => {
                     idents.push(special_idents::opaque);
-                    current_module = module_;
+                    collect_mod(idents, &*module.upgrade().unwrap());
                 }
             }
         }
+        collect_mod(&mut idents, module);
 
         if idents.len() == 0 {
             return "???".to_owned();
         }
-        return self.idents_to_str(idents.move_iter()
-                                        .rev()
-                                        .collect::<Vec<ast::Ident>>()
-                                        .as_slice());
+        self.idents_to_str(idents.move_iter().rev()
+                                 .collect::<Vec<ast::Ident>>()
+                                 .as_slice())
     }
 
     #[allow(dead_code)]   // useful for debugging
-    fn dump_module(&mut self, module_: @Module) {
-        debug!("Dump of module `{}`:", self.module_to_str(module_));
+    fn dump_module(&mut self, module_: Rc<Module>) {
+        debug!("Dump of module `{}`:", self.module_to_str(&*module_));
 
         debug!("Children:");
-        self.populate_module_if_necessary(module_);
+        self.populate_module_if_necessary(&module_);
         for (&name, _) in module_.children.borrow().iter() {
             debug!("* {}", token::get_name(name));
         }
@@ -5455,7 +5377,7 @@ pub struct CrateMap {
 
 /// Entry point to crate resolution.
 pub fn resolve_crate(session: &Session,
-                     lang_items: @LanguageItems,
+                     lang_items: &LanguageItems,
                      krate: &Crate)
                   -> CrateMap {
     let mut resolver = Resolver(session, lang_items, krate.span);
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index 0fbaf745615..e964bc5d6b0 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -272,7 +272,7 @@ impl Subst for ty::Region {
                      substs: &ty::substs,
                      _: Option<Span>) -> ty::Region {
         // Note: This routine only handles regions that are bound on
-        // type declarationss and other outer declarations, not those
+        // type declarations and other outer declarations, not those
         // bound in *fn types*. Region substitution of the bound
         // regions that appear in a function signature is done using
         // the specialized routine
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 72818576cbb..55f8b3d1fd2 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -225,6 +225,7 @@ use util::ppaux::{Repr, vec_map_to_str};
 
 use collections::HashMap;
 use std::cell::Cell;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::ast::Ident;
 use syntax::ast_util::path_to_ident;
@@ -250,7 +251,7 @@ pub enum VecLenOpt {
 // range)
 enum Opt {
     lit(Lit),
-    var(ty::Disr, @adt::Repr),
+    var(ty::Disr, Rc<adt::Repr>),
     range(@ast::Expr, @ast::Expr),
     vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
@@ -351,8 +352,8 @@ fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
             let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id);
             return single_result(rslt(bcx, llval));
         }
-        var(disr_val, repr) => {
-            return adt::trans_case(bcx, repr, disr_val);
+        var(disr_val, ref repr) => {
+            return adt::trans_case(bcx, &**repr, disr_val);
         }
         range(l1, l2) => {
             let (l1, _) = consts::const_expr(ccx, l1, true);
@@ -417,15 +418,10 @@ struct BindingInfo {
 
 type BindingsMap = HashMap<Ident, BindingInfo>;
 
-struct ArmData<'a,'b> {
+struct ArmData<'a, 'b> {
     bodycx: &'b Block<'b>,
     arm: &'a ast::Arm,
-    bindings_map: @BindingsMap
-}
-
-// FIXME #11820: method resolution is unreliable with &
-impl<'a,'b> Clone for ArmData<'a, 'b> {
-    fn clone(&self) -> ArmData<'a, 'b> { *self }
+    bindings_map: BindingsMap
 }
 
 /**
@@ -434,14 +430,13 @@ impl<'a,'b> Clone for ArmData<'a, 'b> {
  * As we proceed `bound_ptrs` are filled with pointers to values to be bound,
  * these pointers are stored in llmatch variables just before executing `data` arm.
  */
-#[deriving(Clone)]
-struct Match<'a,'b> {
-    pats: Vec<@ast::Pat> ,
-    data: ArmData<'a,'b>,
+struct Match<'a, 'b> {
+    pats: Vec<@ast::Pat>,
+    data: &'a ArmData<'a, 'b>,
     bound_ptrs: Vec<(Ident, ValueRef)>
 }
 
-impl<'a,'b> Repr for Match<'a,'b> {
+impl<'a, 'b> Repr for Match<'a, 'b> {
     fn repr(&self, tcx: &ty::ctxt) -> ~str {
         if tcx.sess.verbose() {
             // for many programs, this just take too long to serialize
@@ -462,12 +457,12 @@ fn has_nested_bindings(m: &[Match], col: uint) -> bool {
     return false;
 }
 
-fn expand_nested_bindings<'r,'b>(
+fn expand_nested_bindings<'a, 'b>(
                           bcx: &'b Block<'b>,
-                          m: &[Match<'r,'b>],
+                          m: &'a [Match<'a, 'b>],
                           col: uint,
                           val: ValueRef)
-                          -> Vec<Match<'r,'b>> {
+                          -> Vec<Match<'a, 'b>> {
     debug!("expand_nested_bindings(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -482,21 +477,25 @@ fn expand_nested_bindings<'r,'b>(
                            .append((vec!(inner))
                                    .append(br.pats.slice(col + 1u, br.pats.len())).as_slice());
 
-                let mut res = Match {
+                let mut bound_ptrs = br.bound_ptrs.clone();
+                bound_ptrs.push((path_to_ident(path), val));
+                Match {
                     pats: pats,
-                    data: br.data.clone(),
-                    bound_ptrs: br.bound_ptrs.clone()
-                };
-                res.bound_ptrs.push((path_to_ident(path), val));
-                res
+                    data: &*br.data,
+                    bound_ptrs: bound_ptrs
+                }
+            }
+            _ => Match {
+                pats: br.pats.clone(),
+                data: &*br.data,
+                bound_ptrs: br.bound_ptrs.clone()
             }
-            _ => (*br).clone(),
         }
     }).collect()
 }
 
 fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
-    if !pat_is_binding_or_wild(bcx.tcx().def_map, p) {
+    if !pat_is_binding_or_wild(&bcx.tcx().def_map, p) {
         bcx.sess().span_bug(
             p.span,
             format!("expected an identifier pattern but found p: {}",
@@ -506,14 +505,14 @@ fn assert_is_binding_or_wild(bcx: &Block, p: @ast::Pat) {
 
 type enter_pat<'a> = |@ast::Pat|: 'a -> Option<Vec<@ast::Pat>>;
 
-fn enter_match<'r,'b>(
+fn enter_match<'a, 'b>(
                bcx: &'b Block<'b>,
-               dm: DefMap,
-               m: &[Match<'r,'b>],
+               dm: &DefMap,
+               m: &'a [Match<'a, 'b>],
                col: uint,
                val: ValueRef,
                e: enter_pat)
-               -> Vec<Match<'r,'b>> {
+               -> Vec<Match<'a, 'b>> {
     debug!("enter_match(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -521,47 +520,39 @@ fn enter_match<'r,'b>(
            bcx.val_to_str(val));
     let _indenter = indenter();
 
-    let mut result = Vec::new();
-    for br in m.iter() {
-        match e(*br.pats.get(col)) {
-            Some(sub) => {
-                let pats = sub.append(br.pats.slice(0u, col))
-                              .append(br.pats.slice(col + 1u, br.pats.len()));
-
-                let this = *br.pats.get(col);
-                let mut bound_ptrs = br.bound_ptrs.clone();
-                match this.node {
-                    ast::PatIdent(_, ref path, None) => {
-                        if pat_is_binding(dm, this) {
-                            bound_ptrs.push((path_to_ident(path), val));
-                        }
+    m.iter().filter_map(|br| {
+        e(*br.pats.get(col)).map(|sub| {
+            let pats = sub.append(br.pats.slice(0u, col))
+                            .append(br.pats.slice(col + 1u, br.pats.len()));
+
+            let this = *br.pats.get(col);
+            let mut bound_ptrs = br.bound_ptrs.clone();
+            match this.node {
+                ast::PatIdent(_, ref path, None) => {
+                    if pat_is_binding(dm, this) {
+                        bound_ptrs.push((path_to_ident(path), val));
                     }
-                    _ => {}
                 }
-
-                result.push(Match {
-                    pats: pats,
-                    data: br.data.clone(),
-                    bound_ptrs: bound_ptrs
-                });
+                _ => {}
             }
-            None => ()
-        }
-    }
-
-    debug!("result={}", result.repr(bcx.tcx()));
 
-    return result;
+            Match {
+                pats: pats,
+                data: br.data,
+                bound_ptrs: bound_ptrs
+            }
+        })
+    }).collect()
 }
 
-fn enter_default<'r,'b>(
+fn enter_default<'a, 'b>(
                  bcx: &'b Block<'b>,
-                 dm: DefMap,
-                 m: &[Match<'r,'b>],
+                 dm: &DefMap,
+                 m: &'a [Match<'a, 'b>],
                  col: uint,
                  val: ValueRef,
                  chk: &FailureHandler)
-                 -> Vec<Match<'r,'b>> {
+                 -> Vec<Match<'a, 'b>> {
     debug!("enter_default(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -625,14 +616,14 @@ fn enter_default<'r,'b>(
 // <nmatsakis> so all patterns must either be records (resp. tuples) or
 //             wildcards
 
-fn enter_opt<'r,'b>(
+fn enter_opt<'a, 'b>(
              bcx: &'b Block<'b>,
-             m: &[Match<'r,'b>],
+             m: &'a [Match<'a, 'b>],
              opt: &Opt,
              col: uint,
              variant_size: uint,
              val: ValueRef)
-             -> Vec<Match<'r,'b>> {
+             -> Vec<Match<'a, 'b>> {
     debug!("enter_opt(bcx={}, m={}, opt={:?}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -657,10 +648,10 @@ fn enter_opt<'r,'b>(
     // "column" of arm patterns and the algorithm will converge.
     let guarded = m.iter().any(|x| x.data.arm.guard.is_some());
     let multi_pats = m.len() > 0 && m[0].pats.len() > 1;
-    enter_match(bcx, tcx.def_map, m, col, val, |p| {
+    enter_match(bcx, &tcx.def_map, m, col, val, |p| {
         let answer = match p.node {
             ast::PatEnum(..) |
-            ast::PatIdent(_, _, None) if pat_is_const(tcx.def_map, p) => {
+            ast::PatIdent(_, _, None) if pat_is_const(&tcx.def_map, p) => {
                 let const_def = tcx.def_map.borrow().get_copy(&p.id);
                 let const_def_id = ast_util::def_id_of_def(const_def);
                 let konst = lit(ConstLit(const_def_id));
@@ -684,7 +675,7 @@ fn enter_opt<'r,'b>(
                 }
             }
             ast::PatIdent(_, _, None)
-                    if pat_is_variant_or_struct(tcx.def_map, p) => {
+                    if pat_is_variant_or_struct(&tcx.def_map, p) => {
                 if opt_eq(tcx, &variant_opt(bcx, p.id), opt) {
                     Some(Vec::new())
                 } else {
@@ -799,14 +790,14 @@ fn enter_opt<'r,'b>(
     })
 }
 
-fn enter_rec_or_struct<'r,'b>(
+fn enter_rec_or_struct<'a, 'b>(
                        bcx: &'b Block<'b>,
-                       dm: DefMap,
-                       m: &[Match<'r,'b>],
+                       dm: &DefMap,
+                       m: &'a [Match<'a, 'b>],
                        col: uint,
                        fields: &[ast::Ident],
                        val: ValueRef)
-                       -> Vec<Match<'r,'b>> {
+                       -> Vec<Match<'a, 'b>> {
     debug!("enter_rec_or_struct(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -835,14 +826,14 @@ fn enter_rec_or_struct<'r,'b>(
     })
 }
 
-fn enter_tup<'r,'b>(
+fn enter_tup<'a, 'b>(
              bcx: &'b Block<'b>,
-             dm: DefMap,
-             m: &[Match<'r,'b>],
+             dm: &DefMap,
+             m: &'a [Match<'a, 'b>],
              col: uint,
              val: ValueRef,
              n_elts: uint)
-             -> Vec<Match<'r,'b>> {
+             -> Vec<Match<'a, 'b>> {
     debug!("enter_tup(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -868,14 +859,14 @@ fn enter_tup<'r,'b>(
     })
 }
 
-fn enter_tuple_struct<'r,'b>(
+fn enter_tuple_struct<'a, 'b>(
                       bcx: &'b Block<'b>,
-                      dm: DefMap,
-                      m: &[Match<'r,'b>],
+                      dm: &DefMap,
+                      m: &'a [Match<'a, 'b>],
                       col: uint,
                       val: ValueRef,
                       n_elts: uint)
-                      -> Vec<Match<'r,'b>> {
+                      -> Vec<Match<'a, 'b>> {
     debug!("enter_tuple_struct(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -897,13 +888,13 @@ fn enter_tuple_struct<'r,'b>(
     })
 }
 
-fn enter_uniq<'r,'b>(
+fn enter_uniq<'a, 'b>(
               bcx: &'b Block<'b>,
-              dm: DefMap,
-              m: &[Match<'r,'b>],
+              dm: &DefMap,
+              m: &'a [Match<'a, 'b>],
               col: uint,
               val: ValueRef)
-              -> Vec<Match<'r,'b>> {
+              -> Vec<Match<'a, 'b>> {
     debug!("enter_uniq(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -925,14 +916,13 @@ fn enter_uniq<'r,'b>(
     })
 }
 
-fn enter_region<'r,
-                'b>(
+fn enter_region<'a, 'b>(
                 bcx: &'b Block<'b>,
-                dm: DefMap,
-                m: &[Match<'r,'b>],
+                dm: &DefMap,
+                m: &'a [Match<'a, 'b>],
                 col: uint,
                 val: ValueRef)
-                -> Vec<Match<'r,'b>> {
+                -> Vec<Match<'a, 'b>> {
     debug!("enter_region(bcx={}, m={}, col={}, val={})",
            bcx.to_str(),
            m.repr(bcx.tcx()),
@@ -963,7 +953,7 @@ fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec<Opt> {
         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
         set.push(val);
     }
-    // Vector comparisions are special in that since the actual
+    // Vector comparisons are special in that since the actual
     // conditions over-match, we need to be careful about them. This
     // means that in order to properly handle things in order, we need
     // to not always merge conditions.
@@ -1170,7 +1160,7 @@ fn pats_require_rooting(bcx: &Block, m: &[Match], col: uint) -> bool {
     m.iter().any(|br| {
         let pat_id = br.pats.get(col).id;
         let key = root_map_key {id: pat_id, derefs: 0u };
-        bcx.ccx().maps.root_map.borrow().contains_key(&key)
+        bcx.ccx().maps.root_map.contains_key(&key)
     })
 }
 
@@ -1424,12 +1414,11 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
     bcx
 }
 
-fn compile_guard<'r,
-                 'b>(
+fn compile_guard<'a, 'b>(
                  bcx: &'b Block<'b>,
                  guard_expr: &ast::Expr,
                  data: &ArmData,
-                 m: &[Match<'r,'b>],
+                 m: &'a [Match<'a, 'b>],
                  vals: &[ValueRef],
                  chk: &FailureHandler)
                  -> &'b Block<'b> {
@@ -1445,9 +1434,9 @@ fn compile_guard<'r,
     let temp_scope = bcx.fcx.push_custom_cleanup_scope();
 
     let mut bcx = bcx;
-    bcx = store_non_ref_bindings(bcx, data.bindings_map,
+    bcx = store_non_ref_bindings(bcx, &data.bindings_map,
                                  Some(cleanup::CustomScope(temp_scope)));
-    bcx = insert_lllocals(bcx, data.bindings_map,
+    bcx = insert_lllocals(bcx, &data.bindings_map,
                           cleanup::CustomScope(temp_scope));
 
     let val = unpack_datum!(bcx, expr::trans(bcx, guard_expr));
@@ -1482,10 +1471,9 @@ fn compile_guard<'r,
     }
 }
 
-fn compile_submatch<'r,
-                    'b>(
+fn compile_submatch<'a, 'b>(
                     bcx: &'b Block<'b>,
-                    m: &[Match<'r,'b>],
+                    m: &'a [Match<'a, 'b>],
                     vals: &[ValueRef],
                     chk: &FailureHandler) {
     debug!("compile_submatch(bcx={}, m={}, vals={})",
@@ -1514,7 +1502,7 @@ fn compile_submatch<'r,
             Some(guard_expr) => {
                 bcx = compile_guard(bcx,
                                     guard_expr,
-                                    &m[0].data,
+                                    m[0].data,
                                     m.slice(1, m.len()),
                                     vals,
                                     chk);
@@ -1541,17 +1529,16 @@ fn compile_submatch<'r,
     }
 }
 
-fn compile_submatch_continue<'r,
-                             'b>(
+fn compile_submatch_continue<'a, 'b>(
                              mut bcx: &'b Block<'b>,
-                             m: &[Match<'r,'b>],
+                             m: &'a [Match<'a, 'b>],
                              vals: &[ValueRef],
                              chk: &FailureHandler,
                              col: uint,
                              val: ValueRef) {
     let fcx = bcx.fcx;
     let tcx = bcx.tcx();
-    let dm = tcx.def_map;
+    let dm = &tcx.def_map;
 
     let vals_left = Vec::from_slice(vals.slice(0u, col)).append(vals.slice(col + 1u, vals.len()));
     let ccx = bcx.fcx.ccx;
@@ -1575,7 +1562,7 @@ fn compile_submatch_continue<'r,
             expr::with_field_tys(tcx, pat_ty, Some(pat_id), |discr, field_tys| {
                 let rec_vals = rec_fields.iter().map(|field_name| {
                         let ix = ty::field_idx_strict(tcx, field_name.name, field_tys);
-                        adt::trans_field_ptr(bcx, pat_repr, val, discr, ix)
+                        adt::trans_field_ptr(bcx, &*pat_repr, val, discr, ix)
                         }).collect::<Vec<_>>();
                 compile_submatch(
                         bcx,
@@ -1601,7 +1588,7 @@ fn compile_submatch_continue<'r,
           _ => ccx.sess().bug("non-tuple type in tuple pattern")
         };
         let tup_vals = Vec::from_fn(n_tup_elts, |i| {
-            adt::trans_field_ptr(bcx, tup_repr, val, 0, i)
+            adt::trans_field_ptr(bcx, &*tup_repr, val, 0, i)
         });
         compile_submatch(bcx,
                          enter_tup(bcx,
@@ -1630,7 +1617,7 @@ fn compile_submatch_continue<'r,
 
         let struct_repr = adt::represent_type(bcx.ccx(), struct_ty);
         let llstructvals = Vec::from_fn(struct_element_count, |i| {
-            adt::trans_field_ptr(bcx, struct_repr, val, 0, i)
+            adt::trans_field_ptr(bcx, &*struct_repr, val, 0, i)
         });
         compile_submatch(bcx,
                          enter_tuple_struct(bcx, dm, m, col, val,
@@ -1666,8 +1653,8 @@ fn compile_submatch_continue<'r,
     debug!("test_val={}", bcx.val_to_str(test_val));
     if opts.len() > 0u {
         match *opts.get(0) {
-            var(_, repr) => {
-                let (the_kind, val_opt) = adt::trans_switch(bcx, repr, val);
+            var(_, ref repr) => {
+                let (the_kind, val_opt) = adt::trans_switch(bcx, &**repr, val);
                 kind = the_kind;
                 for &tval in val_opt.iter() { test_val = tval; }
             }
@@ -1813,9 +1800,9 @@ fn compile_submatch_continue<'r,
         let mut size = 0u;
         let mut unpacked = Vec::new();
         match *opt {
-            var(disr_val, repr) => {
+            var(disr_val, ref repr) => {
                 let ExtractedBlock {vals: argvals, bcx: new_bcx} =
-                    extract_variant_args(opt_cx, repr, disr_val, val);
+                    extract_variant_args(opt_cx, &**repr, disr_val, val);
                 size = argvals.len();
                 unpacked = argvals;
                 opt_cx = new_bcx;
@@ -1885,7 +1872,7 @@ fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap {
     let ccx = bcx.ccx();
     let tcx = bcx.tcx();
     let mut bindings_map = HashMap::new();
-    pat_bindings(tcx.def_map, pat, |bm, p_id, span, path| {
+    pat_bindings(&tcx.def_map, pat, |bm, p_id, span, path| {
         let ident = path_to_ident(path);
         let variable_ty = node_id_type(bcx, p_id);
         let llvariable_ty = type_of::type_of(ccx, variable_ty);
@@ -1933,26 +1920,6 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
         return bcx;
     }
 
-    let mut arm_datas = Vec::new();
-    let mut matches = Vec::new();
-    for arm in arms.iter() {
-        let body = fcx.new_id_block("case_body", arm.body.id);
-        let bindings_map = create_bindings_map(bcx, *arm.pats.get(0));
-        let arm_data = ArmData {
-            bodycx: body,
-            arm: arm,
-            bindings_map: @bindings_map
-        };
-        arm_datas.push(arm_data.clone());
-        for p in arm.pats.iter() {
-            matches.push(Match {
-                pats: vec!(*p),
-                data: arm_data.clone(),
-                bound_ptrs: Vec::new(),
-            });
-        }
-    }
-
     let t = node_id_type(bcx, discr_expr.id);
     let chk = {
         if ty::type_is_empty(tcx, t) {
@@ -1970,8 +1937,23 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
             Infallible
         }
     };
-    let lldiscr = discr_datum.val;
-    compile_submatch(bcx, matches.as_slice(), [lldiscr], &chk);
+
+    let arm_datas: Vec<ArmData> = arms.iter().map(|arm| ArmData {
+        bodycx: fcx.new_id_block("case_body", arm.body.id),
+        arm: arm,
+        bindings_map: create_bindings_map(bcx, *arm.pats.get(0))
+    }).collect();
+
+    let mut matches = Vec::new();
+    for arm_data in arm_datas.iter() {
+        matches.extend(arm_data.arm.pats.iter().map(|p| Match {
+            pats: vec!(*p),
+            data: arm_data,
+            bound_ptrs: Vec::new(),
+        }));
+    }
+
+    compile_submatch(bcx, matches.as_slice(), [discr_datum.val], &chk);
 
     let mut arm_cxs = Vec::new();
     for arm_data in arm_datas.iter() {
@@ -1982,12 +1964,12 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
         // is just to reduce code space.  See extensive comment at the start
         // of the file for more details.
         if arm_data.arm.guard.is_none() {
-            bcx = store_non_ref_bindings(bcx, arm_data.bindings_map, None);
+            bcx = store_non_ref_bindings(bcx, &arm_data.bindings_map, None);
         }
 
         // insert bindings into the lllocals map and add cleanups
         let cleanup_scope = fcx.push_custom_cleanup_scope();
-        bcx = insert_lllocals(bcx, arm_data.bindings_map,
+        bcx = insert_lllocals(bcx, &arm_data.bindings_map,
                               cleanup::CustomScope(cleanup_scope));
         bcx = expr::trans_into(bcx, arm_data.arm.body, dest);
         bcx = fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
@@ -2066,7 +2048,7 @@ pub fn store_local<'a>(bcx: &'a Block<'a>,
         // create dummy memory for the variables if we have no
         // value to store into them immediately
         let tcx = bcx.tcx();
-        pat_bindings(tcx.def_map, pat, |_, p_id, _, path| {
+        pat_bindings(&tcx.def_map, pat, |_, p_id, _, path| {
                 let scope = cleanup::var_scope(tcx, p_id);
                 bcx = mk_binding_alloca(
                     bcx, p_id, path, BindLocal, scope, (),
@@ -2199,7 +2181,7 @@ fn bind_irrefutable_pat<'a>(
     let ccx = bcx.ccx();
     match pat.node {
         ast::PatIdent(pat_binding_mode, ref path, inner) => {
-            if pat_is_binding(tcx.def_map, pat) {
+            if pat_is_binding(&tcx.def_map, pat) {
                 // Allocate the stack slot where the value of this
                 // binding will live and place it into the appropriate
                 // map.
@@ -2238,7 +2220,7 @@ fn bind_irrefutable_pat<'a>(
                                                          enum_id,
                                                          var_id);
                     let args = extract_variant_args(bcx,
-                                                    repr,
+                                                    &*repr,
                                                     vinfo.disr_val,
                                                     val);
                     for sub_pat in sub_pats.iter() {
@@ -2259,7 +2241,7 @@ fn bind_irrefutable_pat<'a>(
                             // This is the tuple struct case.
                             let repr = adt::represent_node(bcx, pat.id);
                             for (i, elem) in elems.iter().enumerate() {
-                                let fldptr = adt::trans_field_ptr(bcx, repr,
+                                let fldptr = adt::trans_field_ptr(bcx, &*repr,
                                                                   val, 0, i);
                                 bcx = bind_irrefutable_pat(bcx, *elem,
                                                            fldptr, binding_mode,
@@ -2282,7 +2264,7 @@ fn bind_irrefutable_pat<'a>(
             expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| {
                 for f in fields.iter() {
                     let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys);
-                    let fldptr = adt::trans_field_ptr(bcx, pat_repr, val,
+                    let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val,
                                                       discr, ix);
                     bcx = bind_irrefutable_pat(bcx, f.pat, fldptr,
                                                binding_mode, cleanup_scope);
@@ -2292,7 +2274,7 @@ fn bind_irrefutable_pat<'a>(
         ast::PatTup(ref elems) => {
             let repr = adt::represent_node(bcx, pat.id);
             for (i, elem) in elems.iter().enumerate() {
-                let fldptr = adt::trans_field_ptr(bcx, repr, val, 0, i);
+                let fldptr = adt::trans_field_ptr(bcx, &*repr, val, 0, i);
                 bcx = bind_irrefutable_pat(bcx, *elem, fldptr,
                                            binding_mode, cleanup_scope);
             }
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index da78b650852..fbd638b6191 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -45,8 +45,8 @@
 
 use std::container::Map;
 use libc::c_ulonglong;
-use std::option::{Option, Some, None};
 use std::num::{Bitwise};
+use std::rc::Rc;
 
 use lib::llvm::{ValueRef, True, IntEQ, IntNE};
 use middle::trans::_match;
@@ -115,22 +115,22 @@ pub struct Struct {
  * these, for places in trans where the `ty::t` isn't directly
  * available.
  */
-pub fn represent_node(bcx: &Block, node: ast::NodeId) -> @Repr {
+pub fn represent_node(bcx: &Block, node: ast::NodeId) -> Rc<Repr> {
     represent_type(bcx.ccx(), node_id_type(bcx, node))
 }
 
 /// Decides how to represent a given type.
-pub fn represent_type(cx: &CrateContext, t: ty::t) -> @Repr {
+pub fn represent_type(cx: &CrateContext, t: ty::t) -> Rc<Repr> {
     debug!("Representing: {}", ty_to_str(cx.tcx(), t));
     match cx.adt_reprs.borrow().find(&t) {
-        Some(repr) => return *repr,
+        Some(repr) => return repr.clone(),
         None => {}
     }
 
-    let repr = @represent_type_uncached(cx, t);
+    let repr = Rc::new(represent_type_uncached(cx, t));
     debug!("Represented as: {:?}", repr)
-    cx.adt_reprs.borrow_mut().insert(t, repr);
-    return repr;
+    cx.adt_reprs.borrow_mut().insert(t, repr.clone());
+    repr
 }
 
 fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
@@ -267,7 +267,19 @@ impl Case {
         mk_struct(cx, self.tys.as_slice(), false).size == 0
     }
     fn find_ptr(&self) -> Option<uint> {
-        self.tys.iter().position(|&ty| mono_data_classify(ty) == MonoNonNull)
+        self.tys.iter().position(|&ty| {
+            match ty::get(ty).sty {
+                ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+                    ty::ty_vec(_, None) => false,
+                    _ => true,
+                },
+                ty::ty_uniq(..) | ty::ty_box(..) |
+                ty::ty_str(ty::VstoreUniq) |
+                ty::ty_bare_fn(..) => true,
+                // Is that everything?  Would closures or slices qualify?
+                _ => false
+            }
+        })
     }
 }
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 92a6bb73c8e..fda51e744ce 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -75,6 +75,7 @@ use libc::c_uint;
 use std::c_str::ToCStr;
 use std::cell::{Cell, RefCell};
 use std::local_data;
+use std::rc::Rc;
 use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
 use syntax::ast_util::{local_def, is_local};
 use syntax::attr::AttrMetaMethods;
@@ -398,17 +399,17 @@ pub fn malloc_raw_dyn_managed<'a>(
 
 // Type descriptor and type glue stuff
 
-pub fn get_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
+pub fn get_tydesc(ccx: &CrateContext, t: ty::t) -> Rc<tydesc_info> {
     match ccx.tydescs.borrow().find(&t) {
-        Some(&inf) => return inf,
+        Some(inf) => return inf.clone(),
         _ => { }
     }
 
     ccx.stats.n_static_tydescs.set(ccx.stats.n_static_tydescs.get() + 1u);
-    let inf = glue::declare_tydesc(ccx, t);
+    let inf = Rc::new(glue::declare_tydesc(ccx, t));
 
-    ccx.tydescs.borrow_mut().insert(t, inf);
-    return inf;
+    ccx.tydescs.borrow_mut().insert(t, inf.clone());
+    inf
 }
 
 #[allow(dead_code)] // useful
@@ -637,7 +638,7 @@ pub fn iter_structural_ty<'r,
                     cx: &'b Block<'b>,
                     repr: &adt::Repr,
                     av: ValueRef,
-                    variant: @ty::VariantInfo,
+                    variant: &ty::VariantInfo,
                     tps: &[ty::t],
                     f: val_and_ty_fn<'r,'b>)
                     -> &'b Block<'b> {
@@ -659,7 +660,7 @@ pub fn iter_structural_ty<'r,
           let repr = adt::represent_type(cx.ccx(), t);
           expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| {
               for (i, field_ty) in field_tys.iter().enumerate() {
-                  let llfld_a = adt::trans_field_ptr(cx, repr, av, discr, i);
+                  let llfld_a = adt::trans_field_ptr(cx, &*repr, av, discr, i);
                   cx = f(cx, llfld_a, field_ty.mt.ty);
               }
           })
@@ -677,7 +678,7 @@ pub fn iter_structural_ty<'r,
       ty::ty_tup(ref args) => {
           let repr = adt::represent_type(cx.ccx(), t);
           for (i, arg) in args.iter().enumerate() {
-              let llfld_a = adt::trans_field_ptr(cx, repr, av, 0, i);
+              let llfld_a = adt::trans_field_ptr(cx, &*repr, av, 0, i);
               cx = f(cx, llfld_a, *arg);
           }
       }
@@ -692,9 +693,9 @@ pub fn iter_structural_ty<'r,
           // NB: we must hit the discriminant first so that structural
           // comparison know not to proceed when the discriminants differ.
 
-          match adt::trans_switch(cx, repr, av) {
+          match adt::trans_switch(cx, &*repr, av) {
               (_match::single, None) => {
-                  cx = iter_variant(cx, repr, av, *variants.get(0),
+                  cx = iter_variant(cx, &*repr, av, &**variants.get(0),
                                     substs.tps.as_slice(), f);
               }
               (_match::switch, Some(lldiscrim_a)) => {
@@ -709,7 +710,7 @@ pub fn iter_structural_ty<'r,
                       let variant_cx =
                           fcx.new_temp_block("enum-iter-variant-".to_owned() +
                                              variant.disr_val.to_str());
-                      match adt::trans_case(cx, repr, variant.disr_val) {
+                      match adt::trans_case(cx, &*repr, variant.disr_val) {
                           _match::single_result(r) => {
                               AddCase(llswitch, r.val, variant_cx.llbb)
                           }
@@ -718,9 +719,9 @@ pub fn iter_structural_ty<'r,
                       }
                       let variant_cx =
                           iter_variant(variant_cx,
-                                       repr,
+                                       &*repr,
                                        av,
-                                       *variant,
+                                       &**variant,
                                        substs.tps.as_slice(),
                                        |x,y,z| f(x,y,z));
                       Br(variant_cx, next_cx.llbb);
@@ -1112,7 +1113,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
                        id: ast::NodeId,
                        has_env: bool,
                        output_type: ty::t,
-                       param_substs: Option<@param_substs>,
+                       param_substs: Option<&'a param_substs>,
                        sp: Option<Span>,
                        block_arena: &'a TypedArena<Block<'a>>)
                        -> FunctionContext<'a> {
@@ -1120,7 +1121,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
 
     debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
            if id == -1 { "".to_owned() } else { ccx.tcx.map.path_to_str(id) },
-           id, param_substs.repr(ccx.tcx()));
+           id, param_substs.map(|s| s.repr(ccx.tcx())));
 
     let substd_output_type = match param_substs {
         None => output_type,
@@ -1166,11 +1167,9 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
 
 /// Performs setup on a newly created function, creating the entry scope block
 /// and allocating space for the return pointer.
-pub fn init_function<'a>(
-                     fcx: &'a FunctionContext<'a>,
-                     skip_retptr: bool,
-                     output_type: ty::t,
-                     param_substs: Option<@param_substs>) {
+pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
+                         skip_retptr: bool,
+                         output_type: ty::t) {
     let entry_bcx = fcx.new_temp_block("entry-block");
 
     *fcx.entry_bcx.borrow_mut() = Some(entry_bcx);
@@ -1182,7 +1181,9 @@ pub fn init_function<'a>(
         llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
     }));
 
-    let substd_output_type = match param_substs {
+    // This shouldn't need to recompute the return type,
+    // as new_fn_ctxt did it already.
+    let substd_output_type = match fcx.param_substs {
         None => output_type,
         Some(substs) => {
             ty::subst_tps(fcx.ccx.tcx(),
@@ -1329,7 +1330,7 @@ pub fn trans_closure(ccx: &CrateContext,
                      decl: &ast::FnDecl,
                      body: &ast::Block,
                      llfndecl: ValueRef,
-                     param_substs: Option<@param_substs>,
+                     param_substs: Option<&param_substs>,
                      id: ast::NodeId,
                      _attributes: &[ast::Attribute],
                      output_type: ty::t,
@@ -1340,7 +1341,7 @@ pub fn trans_closure(ccx: &CrateContext,
     set_uwtable(llfndecl);
 
     debug!("trans_closure(..., param_substs={})",
-           param_substs.repr(ccx.tcx()));
+           param_substs.map(|s| s.repr(ccx.tcx())));
 
     let has_env = match ty::get(ty::node_id_to_type(ccx.tcx(), id)).sty {
         ty::ty_closure(_) => true,
@@ -1353,10 +1354,10 @@ pub fn trans_closure(ccx: &CrateContext,
                           id,
                           has_env,
                           output_type,
-                          param_substs,
+                          param_substs.map(|s| &*s),
                           Some(body.span),
                           &arena);
-    init_function(&fcx, false, output_type, param_substs);
+    init_function(&fcx, false, output_type);
 
     // cleanup scope for the incoming arguments
     let arg_scope = fcx.push_custom_cleanup_scope();
@@ -1429,11 +1430,11 @@ pub fn trans_fn(ccx: &CrateContext,
                 decl: &ast::FnDecl,
                 body: &ast::Block,
                 llfndecl: ValueRef,
-                param_substs: Option<@param_substs>,
+                param_substs: Option<&param_substs>,
                 id: ast::NodeId,
                 attrs: &[ast::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx.map.path_to_str(id));
-    debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx()));
+    debug!("trans_fn(param_substs={})", param_substs.map(|s| s.repr(ccx.tcx())));
     let _icx = push_ctxt("trans_fn");
     let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx(), id));
     trans_closure(ccx, decl, body, llfndecl,
@@ -1445,7 +1446,7 @@ pub fn trans_enum_variant(ccx: &CrateContext,
                           variant: &ast::Variant,
                           _args: &[ast::VariantArg],
                           disr: ty::Disr,
-                          param_substs: Option<@param_substs>,
+                          param_substs: Option<&param_substs>,
                           llfndecl: ValueRef) {
     let _icx = push_ctxt("trans_enum_variant");
 
@@ -1460,7 +1461,7 @@ pub fn trans_enum_variant(ccx: &CrateContext,
 pub fn trans_tuple_struct(ccx: &CrateContext,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
-                          param_substs: Option<@param_substs>,
+                          param_substs: Option<&param_substs>,
                           llfndecl: ValueRef) {
     let _icx = push_ctxt("trans_tuple_struct");
 
@@ -1475,24 +1476,20 @@ pub fn trans_tuple_struct(ccx: &CrateContext,
 fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
                                            ctor_id: ast::NodeId,
                                            disr: ty::Disr,
-                                           param_substs: Option<@param_substs>,
+                                           param_substs: Option<&param_substs>,
                                            llfndecl: ValueRef) {
-    let no_substs: &[ty::t] = [];
-    let ty_param_substs = match param_substs {
-        Some(ref substs) => {
-            let v: &[ty::t] = substs.tys.as_slice();
-            v
-        }
-        None => {
-            let v: &[ty::t] = no_substs;
-            v
-        }
-    };
+    let ctor_ty = {
+        let no_substs: &[ty::t] = [];
+        let ty_param_substs: &[ty::t] = match param_substs {
+            Some(substs) => substs.tys.as_slice(),
+            None => no_substs
+        };
 
-    let ctor_ty = ty::subst_tps(ccx.tcx(),
-                                ty_param_substs,
-                                None,
-                                ty::node_id_to_type(ccx.tcx(), ctor_id));
+        ty::subst_tps(ccx.tcx(),
+                      ty_param_substs,
+                      None,
+                      ty::node_id_to_type(ccx.tcx(), ctor_id))
+    };
 
     let result_ty = match ty::get(ctor_ty).sty {
         ty::ty_bare_fn(ref bft) => bft.sig.output,
@@ -1504,8 +1501,8 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfndecl, ctor_id, false, result_ty,
-                          param_substs, None, &arena);
-    init_function(&fcx, false, result_ty, param_substs);
+                          param_substs.map(|s| &*s), None, &arena);
+    init_function(&fcx, false, result_ty);
 
     let arg_tys = ty::ty_fn_args(ctor_ty);
 
@@ -1515,10 +1512,10 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     if !type_is_zero_size(fcx.ccx, result_ty) {
         let repr = adt::represent_type(ccx, result_ty);
-        adt::trans_start_init(bcx, repr, fcx.llretptr.get().unwrap(), disr);
+        adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
         for (i, arg_datum) in arg_datums.move_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
-                                                 repr,
+                                                 &*repr,
                                                  fcx.llretptr.get().unwrap(),
                                                  disr,
                                                  i);
@@ -1529,11 +1526,11 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
     finish_fn(&fcx, bcx);
 }
 
-pub fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
-                      id: ast::NodeId, vi: @Vec<@ty::VariantInfo>,
-                      i: &mut uint) {
+fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
+                  id: ast::NodeId, vi: &[Rc<ty::VariantInfo>],
+                  i: &mut uint) {
     for &variant in enum_definition.variants.iter() {
-        let disr_val = vi.get(*i).disr_val;
+        let disr_val = vi[*i].disr_val;
         *i += 1;
 
         match variant.node.kind {
@@ -1596,7 +1593,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
         if !generics.is_type_parameterized() {
             let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
             let mut i = 0;
-            trans_enum_def(ccx, enum_definition, item.id, vi, &mut i);
+            trans_enum_def(ccx, enum_definition, item.id, vi.as_slice(), &mut i);
         }
       }
       ast::ItemStatic(_, m, expr) => {
@@ -2056,17 +2053,13 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
 
 pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::EncodeInlinedItem<'r>)
     -> encoder::EncodeParams<'r> {
-
-        let diag = cx.sess().diagnostic();
-        let item_symbols = &cx.item_symbols;
-        let link_meta = &cx.link_meta;
         encoder::EncodeParams {
-            diag: diag,
+            diag: cx.sess().diagnostic(),
             tcx: cx.tcx(),
-            reexports2: cx.exp_map2,
-            item_symbols: item_symbols,
+            reexports2: &cx.exp_map2,
+            item_symbols: &cx.item_symbols,
             non_inlineable_statics: &cx.non_inlineable_statics,
-            link_meta: link_meta,
+            link_meta: &cx.link_meta,
             cstore: &cx.sess().cstore,
             encode_inlined_item: ie,
         }
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index 8bc217343f7..642ae86a979 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -176,14 +176,14 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
            def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
            vtables.repr(bcx.tcx()));
     trans_fn_ref_with_vtables(bcx, def_id, node,
-                              type_params.as_slice(),
+                              type_params,
                               vtables)
 }
 
 fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
                                            def_id: ast::DefId,
                                            ref_id: ast::NodeId,
-                                           type_params: &[ty::t],
+                                           type_params: Vec<ty::t>,
                                            vtables: Option<typeck::vtable_res>)
                                            -> Callee<'a> {
     Callee {bcx: bcx,
@@ -203,32 +203,35 @@ fn resolve_default_method_vtables(bcx: &Block,
 
     // Build up a param_substs that we are going to resolve the
     // trait_vtables under.
-    let param_substs = Some(@param_substs {
+    let param_substs = param_substs {
         tys: substs.tps.clone(),
         self_ty: substs.self_ty,
-        vtables: impl_vtables,
+        vtables: impl_vtables.clone(),
         self_vtables: None
-    });
+    };
 
-    let trait_vtables_fixed = resolve_vtables_under_param_substs(
-        bcx.tcx(), param_substs, impl_res.trait_vtables);
+    let mut param_vtables = resolve_vtables_under_param_substs(
+        bcx.tcx(), Some(&param_substs), impl_res.trait_vtables.as_slice());
 
     // Now we pull any vtables for parameters on the actual method.
     let num_method_vtables = method.generics.type_param_defs().len();
-    let method_vtables = match impl_vtables {
-        Some(vtables) => {
+    match impl_vtables {
+        Some(ref vtables) => {
             let num_impl_type_parameters =
                 vtables.len() - num_method_vtables;
-            Vec::from_slice(vtables.tailn(num_impl_type_parameters))
+            param_vtables.push_all(vtables.tailn(num_impl_type_parameters))
         },
-        None => Vec::from_elem(num_method_vtables, @Vec::new())
-    };
-
-    let method_vtables = method_vtables.as_slice();
-    let param_vtables = @((*trait_vtables_fixed).clone().append(method_vtables));
+        None => {
+            param_vtables.extend(range(0, num_method_vtables).map(
+                |_| -> typeck::vtable_param_res {
+                    Vec::new()
+                }
+            ))
+        }
+    }
 
     let self_vtables = resolve_param_vtables_under_param_substs(
-        bcx.tcx(), param_substs, impl_res.self_vtables);
+        bcx.tcx(), Some(&param_substs), impl_res.self_vtables.as_slice());
 
     (param_vtables, self_vtables)
 }
@@ -238,7 +241,7 @@ pub fn trans_fn_ref_with_vtables(
         bcx: &Block,       //
         def_id: ast::DefId,   // def id of fn
         node: ExprOrMethodCall,  // node id of use of fn; may be zero if N/A
-        type_params: &[ty::t], // values for fn's ty params
+        type_params: Vec<ty::t>, // values for fn's ty params
         vtables: Option<typeck::vtable_res>) // vtables for the call
      -> ValueRef {
     /*!
@@ -273,9 +276,11 @@ pub fn trans_fn_ref_with_vtables(
     // Polytype of the function item (may have type params)
     let fn_tpt = ty::lookup_item_type(tcx, def_id);
 
-    let substs = ty::substs { regions: ty::ErasedRegions,
-                              self_ty: None,
-                              tps: /*bad*/ Vec::from_slice(type_params) };
+    let substs = ty::substs {
+        regions: ty::ErasedRegions,
+        self_ty: None,
+        tps: type_params
+    };
 
     // Load the info for the appropriate trait if necessary.
     match ty::trait_of_method(tcx, def_id) {
@@ -313,24 +318,25 @@ pub fn trans_fn_ref_with_vtables(
 
             // Compute the first substitution
             let first_subst = make_substs_for_receiver_types(
-                tcx, impl_id, trait_ref, method);
+                tcx, impl_id, &*trait_ref, &*method);
 
             // And compose them
             let new_substs = first_subst.subst(tcx, &substs);
 
+            debug!("trans_fn_with_vtables - default method: \
+                    substs = {}, trait_subst = {}, \
+                    first_subst = {}, new_subst = {}, \
+                    vtables = {}",
+                   substs.repr(tcx), trait_ref.substs.repr(tcx),
+                   first_subst.repr(tcx), new_substs.repr(tcx),
+                   vtables.repr(tcx));
 
             let (param_vtables, self_vtables) =
                 resolve_default_method_vtables(bcx, impl_id,
-                                               method, &substs, vtables);
+                                               &*method, &substs, vtables);
 
             debug!("trans_fn_with_vtables - default method: \
-                    substs = {}, trait_subst = {}, \
-                    first_subst = {}, new_subst = {}, \
-                    vtables = {}, \
                     self_vtable = {}, param_vtables = {}",
-                   substs.repr(tcx), trait_ref.substs.repr(tcx),
-                   first_subst.repr(tcx), new_substs.repr(tcx),
-                   vtables.repr(tcx),
                    self_vtables.repr(tcx), param_vtables.repr(tcx));
 
             (true, source_id,
@@ -352,7 +358,7 @@ pub fn trans_fn_ref_with_vtables(
     // intrinsic, or is a default method.  In particular, if we see an
     // intrinsic that is inlined from a different crate, we want to reemit the
     // intrinsic instead of trying to call it in the other crate.
-    let must_monomorphise = if type_params.len() > 0 || is_default {
+    let must_monomorphise = if substs.tps.len() > 0 || is_default {
         true
     } else if def_id.krate == ast::LOCAL_CRATE {
         let map_node = session::expect(
@@ -370,7 +376,7 @@ pub fn trans_fn_ref_with_vtables(
         false
     };
 
-    // Create a monomorphic verison of generic functions
+    // Create a monomorphic version of generic functions
     if must_monomorphise {
         // Should be either intra-crate or inlined.
         assert_eq!(def_id.krate, ast::LOCAL_CRATE);
@@ -391,7 +397,7 @@ pub fn trans_fn_ref_with_vtables(
             let ref_ty = match node {
                 ExprId(id) => node_id_type(bcx, id),
                 MethodCall(method_call) => {
-                    let t = bcx.ccx().maps.method_map.borrow().get(&method_call).ty;
+                    let t = bcx.tcx().method_map.borrow().get(&method_call).ty;
                     monomorphize_type(bcx, t)
                 }
             };
@@ -474,7 +480,7 @@ pub fn trans_method_call<'a>(
     let _icx = push_ctxt("trans_method_call");
     debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx()));
     let method_call = MethodCall::expr(call_ex.id);
-    let method_ty = bcx.ccx().maps.method_map.borrow().get(&method_call).ty;
+    let method_ty = bcx.tcx().method_map.borrow().get(&method_call).ty;
     trans_call_inner(
         bcx,
         Some(common::expr_info(call_ex)),
@@ -504,7 +510,7 @@ pub fn trans_lang_call<'a>(
                                 trans_fn_ref_with_vtables_to_callee(bcx,
                                                                     did,
                                                                     0,
-                                                                    [],
+                                                                    vec!(),
                                                                     None)
                              },
                              ArgVals(args),
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index c90d457e83a..df17fb516a7 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -84,7 +84,7 @@ use syntax::ast_util;
 // because the alignment requirements of the bound data affects the
 // alignment requires of the closure_data struct as a whole.  However,
 // right now this is a non-issue in any case, because the size of the
-// rust_opaque_box header is always a mutiple of 16-bytes, which is
+// rust_opaque_box header is always a multiple of 16-bytes, which is
 // the maximum alignment requirement we ever have to worry about.
 //
 // The only reason alignment matters is that, in order to learn what data
@@ -466,7 +466,7 @@ pub fn get_wrapper_for_bare_fn(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfn, -1, true, f.sig.output, None, None, &arena);
-    init_function(&fcx, true, f.sig.output, None);
+    init_function(&fcx, true, f.sig.output);
     let bcx = fcx.entry_bcx.borrow().clone().unwrap();
 
     let args = create_datums_for_fn_args(&fcx,
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index 72e716d0c3c..edb98db416a 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -154,21 +154,6 @@ pub fn expr_info(expr: &ast::Expr) -> NodeInfo {
     NodeInfo { id: expr.id, span: expr.span }
 }
 
-pub struct Stats {
-    pub n_static_tydescs: Cell<uint>,
-    pub n_glues_created: Cell<uint>,
-    pub n_null_glues: Cell<uint>,
-    pub n_real_glues: Cell<uint>,
-    pub n_fns: Cell<uint>,
-    pub n_monos: Cell<uint>,
-    pub n_inlines: Cell<uint>,
-    pub n_closures: Cell<uint>,
-    pub n_llvm_insns: Cell<uint>,
-    pub llvm_insns: RefCell<HashMap<~str, uint>>,
-    // (ident, time-in-ms, llvm-instructions)
-    pub fn_stats: RefCell<Vec<(~str, uint, uint)> >,
-}
-
 pub struct BuilderRef_res {
     pub b: BuilderRef,
 }
@@ -274,7 +259,7 @@ pub struct FunctionContext<'a> {
 
     // If this function is being monomorphized, this contains the type
     // substitutions used.
-    pub param_substs: Option<@param_substs>,
+    pub param_substs: Option<&'a param_substs>,
 
     // The source span and nesting context where this function comes from, for
     // error reporting and symbol generation.
@@ -686,53 +671,9 @@ pub fn is_null(val: ValueRef) -> bool {
     }
 }
 
-// Used to identify cached monomorphized functions and vtables
-#[deriving(Eq, TotalEq, Hash)]
-pub enum mono_param_id {
-    mono_precise(ty::t, Option<@Vec<mono_id> >),
-    mono_any,
-    mono_repr(uint /* size */,
-              uint /* align */,
-              MonoDataClass,
-              datum::RvalueMode),
-}
-
-#[deriving(Eq, TotalEq, Hash)]
-pub enum MonoDataClass {
-    MonoBits,    // Anything not treated differently from arbitrary integer data
-    MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
-    // FIXME(#3547)---scalars and floats are
-    // treated differently in most ABIs.  But we
-    // should be doing something more detailed
-    // here.
-    MonoFloat
-}
-
-pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
-    match ty::get(t).sty {
-        ty::ty_float(_) => MonoFloat,
-        ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
-            ty::ty_vec(_, None) => MonoBits,
-            _ => MonoNonNull,
-        },
-        ty::ty_uniq(..) | ty::ty_box(..) |
-        ty::ty_str(ty::VstoreUniq) |
-        ty::ty_bare_fn(..) => MonoNonNull,
-        // Is that everything?  Would closures or slices qualify?
-        _ => MonoBits
-    }
-}
-
-#[deriving(Eq, TotalEq, Hash)]
-pub struct mono_id_ {
-    pub def: ast::DefId,
-    pub params: Vec<mono_param_id> }
-
-pub type mono_id = @mono_id_;
-
 pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
     match bcx.fcx.param_substs {
-        Some(substs) => {
+        Some(ref substs) => {
             ty::subst_tps(bcx.tcx(), substs.tys.as_slice(), substs.self_ty, t)
         }
         _ => {
@@ -754,9 +695,7 @@ pub fn expr_ty(bcx: &Block, ex: &ast::Expr) -> ty::t {
 }
 
 pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
-    let tcx = bcx.tcx();
-    let t = ty::expr_ty_adjusted(tcx, ex, &*bcx.ccx().maps.method_map.borrow());
-    monomorphize_type(bcx, t)
+    monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
 }
 
 // Key used to lookup values supplied for type parameters in an expr.
@@ -774,7 +713,7 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
     let params = match node {
         ExprId(id) => ty::node_id_to_type_params(tcx, id),
         MethodCall(method_call) => {
-            bcx.ccx().maps.method_map.borrow().get(&method_call).substs.tps.clone()
+            tcx.method_map.borrow().get(&method_call).substs.tps.clone()
         }
     };
 
@@ -788,62 +727,63 @@ pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
     }
 
     match bcx.fcx.param_substs {
-      Some(substs) => {
-        params.iter().map(|t| {
-            ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
-        }).collect()
-      }
-      _ => params
+        Some(ref substs) => {
+            params.iter().map(|t| {
+                ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
+            }).collect()
+        }
+        _ => params
     }
 }
 
 pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
                  -> Option<typeck::vtable_res> {
-    let vtable_map = bcx.ccx().maps.vtable_map.borrow();
-    let raw_vtables = vtable_map.find(&id);
-    raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
+    bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
+        resolve_vtables_in_fn_ctxt(bcx.fcx, vts.as_slice())
+    })
 }
 
 // Apply the typaram substitutions in the FunctionContext to some
 // vtables. This should eliminate any vtable_params.
-pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
-    -> typeck::vtable_res {
+pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
+                                  vts: &[typeck::vtable_param_res])
+                                  -> typeck::vtable_res {
     resolve_vtables_under_param_substs(fcx.ccx.tcx(),
                                        fcx.param_substs,
                                        vts)
 }
 
 pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
-                                          param_substs: Option<@param_substs>,
-                                          vts: typeck::vtable_res)
-    -> typeck::vtable_res {
-    @vts.iter().map(|ds|
+                                          param_substs: Option<&param_substs>,
+                                          vts: &[typeck::vtable_param_res])
+                                          -> typeck::vtable_res {
+    vts.iter().map(|ds| {
       resolve_param_vtables_under_param_substs(tcx,
                                                param_substs,
-                                               *ds))
-        .collect()
+                                               ds.as_slice())
+    }).collect()
 }
 
 pub fn resolve_param_vtables_under_param_substs(
     tcx: &ty::ctxt,
-    param_substs: Option<@param_substs>,
-    ds: typeck::vtable_param_res)
+    param_substs: Option<&param_substs>,
+    ds: &[typeck::vtable_origin])
     -> typeck::vtable_param_res {
-    @ds.iter().map(
-        |d| resolve_vtable_under_param_substs(tcx,
-                                              param_substs,
-                                              d))
-        .collect()
+    ds.iter().map(|d| {
+        resolve_vtable_under_param_substs(tcx,
+                                          param_substs,
+                                          d)
+    }).collect()
 }
 
 
 
 pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
-                                         param_substs: Option<@param_substs>,
+                                         param_substs: Option<&param_substs>,
                                          vt: &typeck::vtable_origin)
                                          -> typeck::vtable_origin {
     match *vt {
-        typeck::vtable_static(trait_id, ref tys, sub) => {
+        typeck::vtable_static(trait_id, ref tys, ref sub) => {
             let tys = match param_substs {
                 Some(substs) => {
                     tys.iter().map(|t| {
@@ -857,7 +797,7 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
             };
             typeck::vtable_static(
                 trait_id, tys,
-                resolve_vtables_under_param_substs(tcx, param_substs, sub))
+                resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
         }
         typeck::vtable_param(n_param, n_bound) => {
             match param_substs {
@@ -883,11 +823,11 @@ pub fn find_vtable(tcx: &ty::ctxt,
            n_param, n_bound, ps.repr(tcx));
 
     let param_bounds = match n_param {
-        typeck::param_self => ps.self_vtables.expect("self vtables missing"),
+        typeck::param_self => ps.self_vtables.as_ref().expect("self vtables missing"),
         typeck::param_numbered(n) => {
-            let tables = ps.vtables
+            let tables = ps.vtables.as_ref()
                 .expect("vtables missing where they are needed");
-            *tables.get(n)
+            tables.get(n)
         }
     };
     param_bounds.get(n_bound).clone()
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index 8848feb8889..759e48e633f 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -130,7 +130,7 @@ fn const_deref_ptr(cx: &CrateContext, v: ValueRef) -> ValueRef {
 fn const_deref_newtype(cx: &CrateContext, v: ValueRef, t: ty::t)
     -> ValueRef {
     let repr = adt::represent_type(cx, t);
-    adt::const_get_field(cx, repr, v, 0, 0)
+    adt::const_get_field(cx, &*repr, v, 0, 0)
 }
 
 fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool)
@@ -187,13 +187,12 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
     let mut llconst = llconst;
     let mut inlineable = inlineable;
     let ety = ty::expr_ty(cx.tcx(), e);
-    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e,
-                                            &*cx.maps.method_map.borrow());
+    let ety_adjusted = ty::expr_ty_adjusted(cx.tcx(), e);
     let opt_adj = cx.tcx.adjustments.borrow().find_copy(&e.id);
     match opt_adj {
         None => { }
         Some(adj) => {
-            match *adj {
+            match adj {
                 ty::AutoAddEnv(ty::RegionTraitStore(ty::ReStatic, _)) => {
                     let def = ty::resolve_expr(cx.tcx(), e);
                     let wrapper = closure::get_wrapper_for_bare_fn(cx,
@@ -414,19 +413,17 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
             }, true)
           }
           ast::ExprField(base, field, _) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx(), base,
-                                            &*cx.maps.method_map.borrow());
+              let bt = ty::expr_ty_adjusted(cx.tcx(), base);
               let brepr = adt::represent_type(cx, bt);
               let (bv, inlineable) = const_expr(cx, base, is_local);
               expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
                   let ix = ty::field_idx_strict(cx.tcx(), field.name, field_tys);
-                  (adt::const_get_field(cx, brepr, bv, discr, ix), inlineable)
+                  (adt::const_get_field(cx, &*brepr, bv, discr, ix), inlineable)
               })
           }
 
           ast::ExprIndex(base, index) => {
-              let bt = ty::expr_ty_adjusted(cx.tcx(), base,
-                                            &*cx.maps.method_map.borrow());
+              let bt = ty::expr_ty_adjusted(cx.tcx(), base);
               let (bv, inlineable) = const_expr(cx, base, is_local);
               let iv = match const_eval::eval_const_expr(cx.tcx(), index) {
                   const_eval::const_int(i) => i as u64,
@@ -494,7 +491,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               (expr::cast_enum, expr::cast_integral) |
               (expr::cast_enum, expr::cast_float)  => {
                 let repr = adt::represent_type(cx, basety);
-                let discr = adt::const_get_discrim(cx, repr, v);
+                let discr = adt::const_get_discrim(cx, &*repr, v);
                 let iv = C_integral(cx.int_type, discr, false);
                 let ety_cast = expr::cast_type_kind(ety);
                 match ety_cast {
@@ -527,7 +524,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
               let ety = ty::expr_ty(cx.tcx(), e);
               let repr = adt::represent_type(cx, ety);
               let (vals, inlineable) = map_list(es.as_slice());
-              (adt::trans_const(cx, repr, 0, vals.as_slice()), inlineable)
+              (adt::trans_const(cx, &*repr, 0, vals.as_slice()), inlineable)
           }
           ast::ExprStruct(_, ref fs, ref base_opt) => {
               let ety = ty::expr_ty(cx.tcx(), e);
@@ -547,7 +544,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                           None => {
                               match base_val {
                                 Some((bv, inlineable)) => {
-                                    (adt::const_get_field(cx, repr, bv, discr, ix),
+                                    (adt::const_get_field(cx, &*repr, bv, discr, ix),
                                      inlineable)
                                 }
                                 None => cx.sess().span_bug(e.span, "missing struct field")
@@ -555,7 +552,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                           }
                       }
                   }));
-                  (adt::trans_const(cx, repr, discr, cs),
+                  (adt::trans_const(cx, &*repr, discr, cs),
                    inlineable.iter().fold(true, |a, &b| a && b))
               })
           }
@@ -635,7 +632,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                     let vinfo = ty::enum_variant_with_id(cx.tcx(),
                                                          enum_did,
                                                          variant_did);
-                    (adt::trans_const(cx, repr, vinfo.disr_val, []), true)
+                    (adt::trans_const(cx, &*repr, vinfo.disr_val, []), true)
                 }
                 Some(ast::DefStruct(_)) => {
                     let ety = ty::expr_ty(cx.tcx(), e);
@@ -654,7 +651,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                       let ety = ty::expr_ty(cx.tcx(), e);
                       let repr = adt::represent_type(cx, ety);
                       let (arg_vals, inlineable) = map_list(args.as_slice());
-                      (adt::trans_const(cx, repr, 0, arg_vals.as_slice()),
+                      (adt::trans_const(cx, &*repr, 0, arg_vals.as_slice()),
                        inlineable)
                   }
                   Some(ast::DefVariant(enum_did, variant_did, _)) => {
@@ -665,7 +662,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
                                                            variant_did);
                       let (arg_vals, inlineable) = map_list(args.as_slice());
                       (adt::trans_const(cx,
-                                        repr,
+                                        &*repr,
                                         vinfo.disr_val,
                                         arg_vals.as_slice()), inlineable)
                   }
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index 4aad1cded1e..119750cd9ce 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -20,8 +20,9 @@ use middle::resolve;
 use middle::trans::adt;
 use middle::trans::base;
 use middle::trans::builder::Builder;
-use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
+use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res};
 use middle::trans::debuginfo;
+use middle::trans::monomorphize::MonoId;
 use middle::trans::type_::Type;
 use middle::ty;
 use util::sha2::Sha256;
@@ -30,10 +31,26 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap};
 use std::cell::{Cell, RefCell};
 use std::c_str::ToCStr;
 use std::ptr;
+use std::rc::Rc;
 use collections::{HashMap, HashSet};
 use syntax::ast;
 use syntax::parse::token::InternedString;
 
+pub struct Stats {
+    pub n_static_tydescs: Cell<uint>,
+    pub n_glues_created: Cell<uint>,
+    pub n_null_glues: Cell<uint>,
+    pub n_real_glues: Cell<uint>,
+    pub n_fns: Cell<uint>,
+    pub n_monos: Cell<uint>,
+    pub n_inlines: Cell<uint>,
+    pub n_closures: Cell<uint>,
+    pub n_llvm_insns: Cell<uint>,
+    pub llvm_insns: RefCell<HashMap<~str, uint>>,
+    // (ident, time-in-ms, llvm-instructions)
+    pub fn_stats: RefCell<Vec<(~str, uint, uint)> >,
+}
+
 pub struct CrateContext {
     pub llmod: ModuleRef,
     pub llcx: ContextRef,
@@ -47,7 +64,7 @@ pub struct CrateContext {
     pub item_symbols: RefCell<NodeMap<~str>>,
     pub link_meta: LinkMeta,
     pub drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
-    pub tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
+    pub tydescs: RefCell<HashMap<ty::t, Rc<tydesc_info>>>,
     /// Set when running emit_tydescs to enforce that no more tydescs are
     /// created.
     pub finished_tydescs: Cell<bool>,
@@ -61,10 +78,10 @@ pub struct CrateContext {
     /// that is generated
     pub non_inlineable_statics: RefCell<NodeSet>,
     /// Cache instances of monomorphized functions
-    pub monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
+    pub monomorphized: RefCell<HashMap<MonoId, ValueRef>>,
     pub monomorphizing: RefCell<DefIdMap<uint>>,
     /// Cache generated vtables
-    pub vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
+    pub vtables: RefCell<HashMap<(ty::t, MonoId), ValueRef>>,
     /// Cache of constant strings,
     pub const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,
 
@@ -91,13 +108,13 @@ pub struct CrateContext {
 
     pub lltypes: RefCell<HashMap<ty::t, Type>>,
     pub llsizingtypes: RefCell<HashMap<ty::t, Type>>,
-    pub adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
+    pub adt_reprs: RefCell<HashMap<ty::t, Rc<adt::Repr>>>,
     pub symbol_hasher: RefCell<Sha256>,
     pub type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
     pub all_llvm_symbols: RefCell<HashSet<~str>>,
     pub tcx: ty::ctxt,
     pub maps: astencode::Maps,
-    pub stats: @Stats,
+    pub stats: Stats,
     pub int_type: Type,
     pub opaque_vec_type: Type,
     pub builder: BuilderRef_res,
@@ -179,7 +196,7 @@ impl CrateContext {
                 all_llvm_symbols: RefCell::new(HashSet::new()),
                 tcx: tcx,
                 maps: maps,
-                stats: @Stats {
+                stats: Stats {
                     n_static_tydescs: Cell::new(0u),
                     n_glues_created: Cell::new(0u),
                     n_null_glues: Cell::new(0u),
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 1a57acf84d2..4dd929e16f7 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -57,7 +57,7 @@ For example, the following simple type for a singly-linked list...
 ```
 struct List {
     value: int,
-    tail: Option<@List>,
+    tail: Option<~List>,
 }
 ```
 
@@ -66,8 +66,8 @@ will generate the following callstack with a naive DFS algorithm:
 ```
 describe(t = List)
   describe(t = int)
-  describe(t = Option<@List>)
-    describe(t = @List)
+  describe(t = Option<~List>)
+    describe(t = ~List)
       describe(t = List) // at the beginning again...
       ...
 ```
@@ -144,6 +144,7 @@ use util::ppaux;
 
 use std::c_str::{CString, ToCStr};
 use std::cell::{Cell, RefCell};
+use std::rc::{Rc, Weak};
 use collections::HashMap;
 use collections::HashSet;
 use libc::{c_uint, c_ulonglong, c_longlong};
@@ -180,7 +181,7 @@ pub struct CrateDebugContext {
     created_files: RefCell<HashMap<~str, DIFile>>,
     created_types: RefCell<HashMap<uint, DIType>>,
     created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
-    namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
+    namespace_map: RefCell<HashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
     // This collection is used to assert that composite types (structs, enums, ...) have their
     // members only set once:
     composite_types_completed: RefCell<HashSet<DIType>>,
@@ -369,7 +370,7 @@ pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
     }
 
     let cx = bcx.ccx();
-    let def_map = cx.tcx.def_map;
+    let def_map = &cx.tcx.def_map;
 
     pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
         let var_ident = ast_util::path_to_ident(path_ref);
@@ -509,7 +510,7 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
     let fcx = bcx.fcx;
     let cx = fcx.ccx;
 
-    let def_map = cx.tcx.def_map;
+    let def_map = &cx.tcx.def_map;
     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
 
     pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
@@ -609,7 +610,7 @@ pub fn start_emitting_source_locations(fcx: &FunctionContext) {
 /// indicates why no debuginfo should be created for the function.
 pub fn create_function_debug_context(cx: &CrateContext,
                                      fn_ast_id: ast::NodeId,
-                                     param_substs: Option<@param_substs>,
+                                     param_substs: Option<&param_substs>,
                                      llfn: ValueRef) -> FunctionDebugContext {
     if cx.sess().opts.debuginfo == NoDebugInfo {
         return FunctionDebugContext { repr: DebugInfoDisabled };
@@ -775,7 +776,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
     fn get_function_signature(cx: &CrateContext,
                               fn_ast_id: ast::NodeId,
                               fn_decl: &ast::FnDecl,
-                              param_substs: Option<@param_substs>,
+                              param_substs: Option<&param_substs>,
                               error_span: Span) -> DIArray {
         if cx.sess().opts.debuginfo == LimitedDebugInfo {
             return create_DIArray(DIB(cx), []);
@@ -828,7 +829,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
 
     fn get_template_parameters(cx: &CrateContext,
                                generics: &ast::Generics,
-                               param_substs: Option<@param_substs>,
+                               param_substs: Option<&param_substs>,
                                file_metadata: DIFile,
                                name_to_append_suffix_to: &mut StrBuf)
                                -> DIArray {
@@ -1388,8 +1389,8 @@ fn prepare_tuple_metadata(cx: &CrateContext,
 }
 
 struct GeneralMemberDescriptionFactory {
-    type_rep: @adt::Repr,
-    variants: @Vec<@ty::VariantInfo> ,
+    type_rep: Rc<adt::Repr>,
+    variants: Rc<Vec<Rc<ty::VariantInfo>>>,
     discriminant_type_metadata: ValueRef,
     containing_scope: DIScope,
     file_metadata: DIFile,
@@ -1412,7 +1413,7 @@ impl GeneralMemberDescriptionFactory {
                 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
                     describe_enum_variant(cx,
                                           struct_def,
-                                          *self.variants.get(i),
+                                          &**self.variants.get(i),
                                           Some(self.discriminant_type_metadata),
                                           self.containing_scope,
                                           self.file_metadata,
@@ -1617,7 +1618,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                  member_description_factory) =
                     describe_enum_variant(cx,
                                           struct_def,
-                                          *variants.get(0),
+                                          &**variants.get(0),
                                           None,
                                           containing_scope,
                                           file_metadata,
@@ -1661,7 +1662,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                 llvm_type: enum_llvm_type,
                 file_metadata: file_metadata,
                 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
-                    type_rep: type_rep,
+                    type_rep: type_rep.clone(),
                     variants: variants,
                     discriminant_type_metadata: discriminant_type_metadata,
                     containing_scope: containing_scope,
@@ -1676,7 +1677,7 @@ fn prepare_enum_metadata(cx: &CrateContext,
                  member_description_factory) =
                     describe_enum_variant(cx,
                                           struct_def,
-                                          *variants.get(nndiscr as uint),
+                                          &**variants.get(nndiscr as uint),
                                           None,
                                           containing_scope,
                                           file_metadata,
@@ -2381,7 +2382,7 @@ fn populate_scope_map(cx: &CrateContext,
                       fn_entry_block: &ast::Block,
                       fn_metadata: DISubprogram,
                       scope_map: &mut HashMap<ast::NodeId, DIScope>) {
-    let def_map = cx.tcx.def_map;
+    let def_map = &cx.tcx.def_map;
 
     struct ScopeStackEntry {
         scope_metadata: DIScope,
@@ -2494,7 +2495,7 @@ fn populate_scope_map(cx: &CrateContext,
                     scope_stack: &mut Vec<ScopeStackEntry> ,
                     scope_map: &mut HashMap<ast::NodeId, DIScope>) {
 
-        let def_map = cx.tcx.def_map;
+        let def_map = &cx.tcx.def_map;
 
         // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
         // because we have to visit *all* nodes in order to put them into the scope map. The above
@@ -2503,7 +2504,7 @@ fn populate_scope_map(cx: &CrateContext,
             ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
 
                 // Check if this is a binding. If so we need to put it on the scope stack and maybe
-                // introduce an articial scope
+                // introduce an artificial scope
                 if pat_util::pat_is_binding(def_map, pat) {
 
                     let ident = ast_util::path_to_ident(path_ref);
@@ -2830,14 +2831,14 @@ fn populate_scope_map(cx: &CrateContext,
 struct NamespaceTreeNode {
     name: ast::Name,
     scope: DIScope,
-    parent: Option<@NamespaceTreeNode>,
+    parent: Option<Weak<NamespaceTreeNode>>,
 }
 
 impl NamespaceTreeNode {
     fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
         fn fill_nested(node: &NamespaceTreeNode, output: &mut StrBuf) {
             match node.parent {
-                Some(parent) => fill_nested(parent, output),
+                Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
                 None => {}
             }
             let string = token::get_name(node.name);
@@ -2854,7 +2855,7 @@ impl NamespaceTreeNode {
     }
 }
 
-fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
+fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
     ty::with_path(cx.tcx(), def_id, |path| {
         // prepend crate name if not already present
         let krate = if def_id.krate == ast::LOCAL_CRATE {
@@ -2866,7 +2867,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
         let mut path = krate.move_iter().chain(path).peekable();
 
         let mut current_key = Vec::new();
-        let mut parent_node: Option<@NamespaceTreeNode> = None;
+        let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
 
         // Create/Lookup namespace for each element of the path.
         loop {
@@ -2890,7 +2891,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
                 None => {
                     // create and insert
                     let parent_scope = match parent_node {
-                        Some(node) => node.scope,
+                        Some(ref node) => node.scope,
                         None => ptr::null()
                     };
                     let namespace_name = token::get_name(name);
@@ -2907,14 +2908,14 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNo
                         }
                     });
 
-                    let node = @NamespaceTreeNode {
+                    let node = Rc::new(NamespaceTreeNode {
                         name: name,
                         scope: scope,
-                        parent: parent_node,
-                    };
+                        parent: parent_node.map(|parent| parent.downgrade()),
+                    });
 
                     debug_context(cx).namespace_map.borrow_mut()
-                                     .insert(current_key.clone(), node);
+                                     .insert(current_key.clone(), node.clone());
 
                     node
                 }
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 4e850b8990a..3c1dfedcac6 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -118,7 +118,7 @@ pub fn trans_into<'a>(bcx: &'a Block<'a>,
 
     bcx.fcx.push_ast_cleanup_scope(expr.id);
 
-    let kind = ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr);
+    let kind = ty::expr_kind(bcx.tcx(), expr);
     bcx = match kind {
         ty::LvalueExpr | ty::RvalueDatumExpr => {
             trans_unadjusted(bcx, expr).store_to_dest(dest, expr.id)
@@ -175,7 +175,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
     };
     debug!("unadjusted datum for expr {}: {}",
            expr.id, datum.to_str(bcx.ccx()));
-    match *adjustment {
+    match adjustment {
         AutoAddEnv(..) => {
             datum = unpack_datum!(bcx, add_env(bcx, expr, datum));
         }
@@ -205,8 +205,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
             };
         }
         AutoObject(..) => {
-            let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr,
-                                                   &*bcx.ccx().maps.method_map.borrow());
+            let adjusted_ty = ty::expr_ty_adjusted(bcx.tcx(), expr);
             let scratch = rvalue_scratch_datum(bcx, adjusted_ty, "__adjust");
             bcx = meth::trans_trait_cast(
                 bcx, datum, expr.id, SaveIn(scratch.val));
@@ -323,7 +322,7 @@ fn trans_unadjusted<'a>(bcx: &'a Block<'a>,
 
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
-    return match ty::expr_kind(bcx.tcx(), bcx.ccx().maps.method_map, expr) {
+    return match ty::expr_kind(bcx.tcx(), expr) {
         ty::LvalueExpr | ty::RvalueDatumExpr => {
             let datum = unpack_datum!(bcx, {
                 trans_datum_unadjusted(bcx, expr)
@@ -444,7 +443,7 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>,
             let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys);
             let d = base_datum.get_element(
                 field_tys[ix].mt.ty,
-                |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, ix));
+                |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix));
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
         })
 }
@@ -680,7 +679,7 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
             let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
             let numbered_fields: Vec<(uint, @ast::Expr)> =
                 args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
-            trans_adt(bcx, repr, 0, numbered_fields.as_slice(), None, dest)
+            trans_adt(bcx, &*repr, 0, numbered_fields.as_slice(), None, dest)
         }
         ast::ExprLit(lit) => {
             match lit.node {
@@ -798,7 +797,7 @@ fn trans_def_dps_unadjusted<'a>(
                 // Nullary variant.
                 let ty = expr_ty(bcx, ref_expr);
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                adt::trans_start_init(bcx, repr, lldest,
+                adt::trans_start_init(bcx, &*repr, lldest,
                                       variant_info.disr_val);
                 return bcx;
             }
@@ -808,7 +807,7 @@ fn trans_def_dps_unadjusted<'a>(
             match ty::get(ty).sty {
                 ty::ty_struct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
-                    adt::trans_start_init(bcx, repr, lldest, 0);
+                    adt::trans_start_init(bcx, &*repr, lldest, 0);
                 }
                 _ => {}
             }
@@ -1005,7 +1004,7 @@ fn trans_rec_or_struct<'a>(
         };
 
         let repr = adt::represent_type(bcx.ccx(), ty);
-        trans_adt(bcx, repr, discr, numbered_fields.as_slice(), optbase, dest)
+        trans_adt(bcx, &*repr, discr, numbered_fields.as_slice(), optbase, dest)
     })
 }
 
@@ -1118,7 +1117,7 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
     // Otherwise, we should be in the RvalueDpsExpr path.
     assert!(
         op == ast::UnDeref ||
-        !ccx.maps.method_map.borrow().contains_key(&method_call));
+        !ccx.tcx.method_map.borrow().contains_key(&method_call));
 
     let un_ty = expr_ty(bcx, expr);
 
@@ -1240,8 +1239,8 @@ fn trans_gc<'a>(mut bcx: &'a Block<'a>,
         SaveIn(addr) => {
             let expr_ty = expr_ty(bcx, expr);
             let repr = adt::represent_type(bcx.ccx(), expr_ty);
-            adt::trans_start_init(bcx, repr, addr, 0);
-            let field_dest = adt::trans_field_ptr(bcx, repr, addr, 0, 0);
+            adt::trans_start_init(bcx, &*repr, addr, 0);
+            let field_dest = adt::trans_field_ptr(bcx, &*repr, addr, 0, 0);
             contents_datum.store_to(bcx, field_dest)
         }
     }
@@ -1403,7 +1402,7 @@ fn trans_binary<'a>(bcx: &'a Block<'a>,
     let ccx = bcx.ccx();
 
     // if overloaded, would be RvalueDpsExpr
-    assert!(!ccx.maps.method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
+    assert!(!ccx.tcx.method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
 
     match op {
         ast::BiAnd => {
@@ -1443,7 +1442,7 @@ fn trans_overloaded_op<'a, 'b>(
                        rhs: Option<(Datum<Expr>, ast::NodeId)>,
                        dest: Option<Dest>)
                        -> Result<'a> {
-    let method_ty = bcx.ccx().maps.method_map.borrow().get(&method_call).ty;
+    let method_ty = bcx.tcx().method_map.borrow().get(&method_call).ty;
     callee::trans_call_inner(bcx,
                              Some(expr_info(expr)),
                              monomorphize_type(bcx, method_ty),
@@ -1581,7 +1580,7 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
                 bcx, datum.to_lvalue_datum(bcx, "trans_imm_cast", expr.id));
             let llexpr_ptr = datum.to_llref();
             let lldiscrim_a =
-                adt::trans_get_discr(bcx, repr, llexpr_ptr, Some(Type::i64(ccx)));
+                adt::trans_get_discr(bcx, &*repr, llexpr_ptr, Some(Type::i64(ccx)));
             match k_out {
                 cast_integral => int_cast(bcx, ll_t_out,
                                           val_ty(lldiscrim_a),
@@ -1614,7 +1613,7 @@ fn trans_assign_op<'a>(
     debug!("trans_assign_op(expr={})", bcx.expr_to_str(expr));
 
     // User-defined operator methods cannot be used with `+=` etc right now
-    assert!(!bcx.ccx().maps.method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
+    assert!(!bcx.tcx().method_map.borrow().contains_key(&MethodCall::expr(expr.id)));
 
     // Evaluate LHS (destination), which should be an lvalue
     let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
@@ -1692,7 +1691,7 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
         expr_id: expr.id,
         autoderef: derefs as u32
     };
-    let method_ty = ccx.maps.method_map.borrow()
+    let method_ty = ccx.tcx.method_map.borrow()
                        .find(&method_call).map(|method| method.ty);
     let datum = match method_ty {
         Some(method_ty) => {
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 98e09b2fd31..8488261db9c 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -145,39 +145,34 @@ pub fn get_drop_glue(ccx: &CrateContext, t: ty::t) -> ValueRef {
     glue
 }
 
-pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: @tydesc_info) {
+pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: &tydesc_info) -> ValueRef {
     let _icx = push_ctxt("lazily_emit_visit_glue");
 
     let llfnty = Type::glue_fn(ccx, type_of(ccx, ti.ty).ptr_to());
 
     match ti.visit_glue.get() {
-        Some(_) => (),
+        Some(visit_glue) => visit_glue,
         None => {
             debug!("+++ lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
             let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "visit");
             ti.visit_glue.set(Some(glue_fn));
             make_generic_glue(ccx, ti.ty, glue_fn, make_visit_glue, "visit");
             debug!("--- lazily_emit_tydesc_glue VISIT {}", ppaux::ty_to_str(ccx.tcx(), ti.ty));
+            glue_fn
         }
     }
 }
 
 // See [Note-arg-mode]
 pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef,
-                       static_ti: Option<@tydesc_info>) {
+                       static_ti: Option<&tydesc_info>) {
     let _icx = push_ctxt("call_tydesc_glue_full");
     let ccx = bcx.ccx();
     // NB: Don't short-circuit even if this block is unreachable because
     // GC-based cleanup needs to the see that the roots are live.
     if bcx.unreachable.get() && !ccx.sess().no_landing_pads() { return; }
 
-    let static_glue_fn = match static_ti {
-        None => None,
-        Some(sti) => {
-            lazily_emit_visit_glue(ccx, sti);
-            sti.visit_glue.get()
-        }
-    };
+    let static_glue_fn = static_ti.map(|sti| lazily_emit_visit_glue(ccx, sti));
 
     // When static type info is available, avoid casting to a generic pointer.
     let llrawptr = if static_glue_fn.is_none() {
@@ -224,7 +219,7 @@ fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>,
                               substs: &ty::substs)
                               -> &'a Block<'a> {
     let repr = adt::represent_type(bcx.ccx(), t);
-    let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
+    let drop_flag = adt::trans_drop_flag_ptr(bcx, &*repr, v0);
     with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag)), |cx| {
         trans_struct_drop(cx, t, v0, dtor_did, class_did, substs)
     })
@@ -265,7 +260,7 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
     // this scope.
     let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
     for (i, fld) in field_tys.iter().enumerate() {
-        let llfld_a = adt::trans_field_ptr(bcx, repr, v0, 0, i);
+        let llfld_a = adt::trans_field_ptr(bcx, &*repr, v0, 0, i);
         bcx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
                                   llfld_a,
                                   fld.mt.ty);
@@ -404,7 +399,7 @@ fn incr_refcnt_of_boxed<'a>(bcx: &'a Block<'a>,
 
 
 // Generates the declaration for (but doesn't emit) a type descriptor.
-pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
+pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> tydesc_info {
     // If emit_tydescs already ran, then we shouldn't be creating any new
     // tydescs.
     assert!(!ccx.finished_tydescs.get());
@@ -430,16 +425,15 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info {
     let ty_name = token::intern_and_get_ident(ppaux::ty_to_str(ccx.tcx(), t));
     let ty_name = C_str_slice(ccx, ty_name);
 
-    let inf = @tydesc_info {
+    debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx(), t));
+    tydesc_info {
         ty: t,
         tydesc: gvar,
         size: llsize,
         align: llalign,
         name: ty_name,
         visit_glue: Cell::new(None),
-    };
-    debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx(), t));
-    return inf;
+    }
 }
 
 fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
@@ -466,7 +460,7 @@ fn make_generic_glue(ccx: &CrateContext,
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, llfn, -1, false, ty::mk_nil(), None, None, &arena);
 
-    init_function(&fcx, false, ty::mk_nil(), None);
+    init_function(&fcx, false, ty::mk_nil());
 
     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
     ccx.stats.n_glues_created.set(ccx.stats.n_glues_created.get() + 1u);
@@ -491,9 +485,7 @@ pub fn emit_tydescs(ccx: &CrateContext) {
     // As of this point, allow no more tydescs to be created.
     ccx.finished_tydescs.set(true);
     let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to();
-    for (_, &val) in ccx.tydescs.borrow().iter() {
-        let ti = val;
-
+    for (_, ti) in ccx.tydescs.borrow().iter() {
         // Each of the glue functions needs to be cast to a generic type
         // before being put into the tydesc because we only have a singleton
         // tydesc type. Then we'll recast each function to its real type when
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index 9e5213e6a99..3a0083ba5c6 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -85,7 +85,7 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Opti
 pub fn trans_intrinsic(ccx: &CrateContext,
                        decl: ValueRef,
                        item: &ast::ForeignItem,
-                       substs: @param_substs,
+                       substs: &param_substs,
                        ref_id: Option<ast::NodeId>) {
     debug!("trans_intrinsic(item.ident={})", token::get_ident(item.ident));
 
@@ -194,8 +194,8 @@ pub fn trans_intrinsic(ccx: &CrateContext,
 
     let arena = TypedArena::new();
     let fcx = new_fn_ctxt(ccx, decl, item.id, false, output_type,
-                          Some(substs), Some(item.span), &arena);
-    init_function(&fcx, true, output_type, Some(substs));
+                          Some(&*substs), Some(item.span), &arena);
+    init_function(&fcx, true, output_type);
 
     set_always_inline(fcx.llfn);
 
@@ -328,7 +328,7 @@ pub fn trans_intrinsic(ccx: &CrateContext,
         "get_tydesc" => {
             let tp_ty = *substs.tys.get(0);
             let static_ti = get_tydesc(ccx, tp_ty);
-            glue::lazily_emit_visit_glue(ccx, static_ti);
+            glue::lazily_emit_visit_glue(ccx, &*static_ti);
 
             // FIXME (#3730): ideally this shouldn't need a cast,
             // but there's a circularity between translating rust types to llvm
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index 851f8207cb6..d122edb7678 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -83,7 +83,7 @@ pub fn trans_method_callee<'a>(
                            -> Callee<'a> {
     let _icx = push_ctxt("meth::trans_method_callee");
 
-    let (origin, method_ty) = match bcx.ccx().maps.method_map
+    let (origin, method_ty) = match bcx.tcx().method_map
                                        .borrow().find(&method_call) {
         Some(method) => {
             debug!("trans_method_callee({:?}, method={})",
@@ -193,21 +193,21 @@ pub fn trans_static_method_callee(bcx: &Block,
             name={}", method_id, expr_id, token::get_name(mname));
 
     let vtable_key = MethodCall::expr(expr_id);
-    let vtbls = ccx.maps.vtable_map.borrow().get_copy(&vtable_key);
-    let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
+    let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, ccx.tcx.vtable_map.borrow()
+                                                       .get(&vtable_key).as_slice());
 
-    match vtbls.get(bound_index).get(0) {
-        &typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
+    match vtbls.move_iter().nth(bound_index).unwrap().move_iter().nth(0).unwrap() {
+        typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
             assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
 
             let mth_id = method_with_name(ccx, impl_did, mname);
             let (callee_substs, callee_origins) =
                 combine_impl_and_methods_tps(
                     bcx, mth_id, ExprId(expr_id),
-                    rcvr_substs.as_slice(), rcvr_origins);
+                    rcvr_substs, rcvr_origins);
 
             let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id),
-                                                 callee_substs.as_slice(),
+                                                 callee_substs,
                                                  Some(callee_origins));
 
             let callee_ty = node_id_type(bcx, expr_id);
@@ -221,22 +221,22 @@ pub fn trans_static_method_callee(bcx: &Block,
     }
 }
 
-pub fn method_with_name(ccx: &CrateContext,
-                        impl_id: ast::DefId,
-                        name: ast::Name) -> ast::DefId {
+fn method_with_name(ccx: &CrateContext,
+                    impl_id: ast::DefId,
+                    name: ast::Name) -> ast::DefId {
     match ccx.impl_method_cache.borrow().find_copy(&(impl_id, name)) {
         Some(m) => return m,
         None => {}
     }
 
-    let imp = ccx.tcx.impls.borrow();
-    let imp = imp.find(&impl_id)
-                 .expect("could not find impl while translating");
-    let meth = imp.methods.iter().find(|m| m.ident.name == name)
-                  .expect("could not find method while translating");
+    let methods = ccx.tcx.impl_methods.borrow();
+    let methods = methods.find(&impl_id)
+                         .expect("could not find impl while translating");
+    let meth_did = methods.iter().find(|&did| ty::method(&ccx.tcx, *did).ident.name == name)
+                                 .expect("could not find method while translating");
 
-    ccx.impl_method_cache.borrow_mut().insert((impl_id, name), meth.def_id);
-    meth.def_id
+    ccx.impl_method_cache.borrow_mut().insert((impl_id, name), *meth_did);
+    *meth_did
 }
 
 fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
@@ -247,7 +247,7 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
                                   -> Callee<'a> {
     let _icx = push_ctxt("meth::trans_monomorphized_callee");
     match vtbl {
-      typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
+      typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
           let ccx = bcx.ccx();
           let mname = ty::trait_method(ccx.tcx(), trait_id, n_method).ident;
           let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
@@ -257,13 +257,13 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
           let (callee_substs, callee_origins) =
               combine_impl_and_methods_tps(
                   bcx, mth_id,  MethodCall(method_call),
-                  rcvr_substs.as_slice(), rcvr_origins);
+                  rcvr_substs, rcvr_origins);
 
           // translate the function
           let llfn = trans_fn_ref_with_vtables(bcx,
                                                mth_id,
                                                MethodCall(method_call),
-                                               callee_substs.as_slice(),
+                                               callee_substs,
                                                Some(callee_origins));
 
           Callee { bcx: bcx, data: Fn(llfn) }
@@ -277,9 +277,9 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
 fn combine_impl_and_methods_tps(bcx: &Block,
                                 mth_did: ast::DefId,
                                 node: ExprOrMethodCall,
-                                rcvr_substs: &[ty::t],
+                                rcvr_substs: Vec<ty::t>,
                                 rcvr_origins: typeck::vtable_res)
-                                -> (Vec<ty::t> , typeck::vtable_res) {
+                                -> (Vec<ty::t>, typeck::vtable_res) {
     /*!
     *
     * Creates a concatenated set of substitutions which includes
@@ -302,10 +302,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
     let n_m_tps = method.generics.type_param_defs().len();
     let node_substs = node_id_type_params(bcx, node);
     debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
-    let ty_substs
-        = Vec::from_slice(rcvr_substs).append(node_substs.tailn(node_substs.len() - n_m_tps));
-    debug!("n_m_tps={:?}", n_m_tps);
     debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
+    let mut ty_substs = rcvr_substs;
+    {
+        let start = node_substs.len() - n_m_tps;
+        ty_substs.extend(node_substs.move_iter().skip(start));
+    }
+    debug!("n_m_tps={:?}", n_m_tps);
     debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx()));
 
 
@@ -315,14 +318,20 @@ fn combine_impl_and_methods_tps(bcx: &Block,
         ExprId(id) => MethodCall::expr(id),
         MethodCall(method_call) => method_call
     };
-    let vtables = node_vtables(bcx, vtable_key);
-    let r_m_origins = match vtables {
-        Some(vt) => vt,
-        None => @Vec::from_elem(node_substs.len(), @Vec::new())
-    };
-    let vtables
-        = @Vec::from_slice(rcvr_origins.as_slice())
-                           .append(r_m_origins.tailn(r_m_origins.len() - n_m_tps));
+    let mut vtables = rcvr_origins;
+    match node_vtables(bcx, vtable_key) {
+        Some(vt) => {
+            let start = vt.len() - n_m_tps;
+            vtables.extend(vt.move_iter().skip(start));
+        }
+        None => {
+            vtables.extend(range(0, n_m_tps).map(
+                |_| -> typeck::vtable_param_res {
+                    Vec::new()
+                }
+            ));
+        }
+    }
 
     (ty_substs, vtables)
 }
@@ -418,83 +427,50 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
     };
 }
 
-pub fn vtable_id(ccx: &CrateContext,
-                 origin: &typeck::vtable_origin)
-              -> mono_id {
-    match origin {
-        &typeck::vtable_static(impl_id, ref substs, sub_vtables) => {
-            let psubsts = param_substs {
-                tys: (*substs).clone(),
-                vtables: Some(sub_vtables),
-                self_ty: None,
-                self_vtables: None
-            };
-
-            monomorphize::make_mono_id(
-                ccx,
-                impl_id,
-                &psubsts)
-        }
-
-        // can't this be checked at the callee?
-        _ => fail!("vtable_id")
-    }
-}
-
 /// Creates a returns a dynamic vtable for the given type and vtable origin.
 /// This is used only for objects.
-pub fn get_vtable(bcx: &Block,
-                  self_ty: ty::t,
-                  origins: typeck::vtable_param_res)
-                  -> ValueRef {
+fn get_vtable(bcx: &Block,
+              self_ty: ty::t,
+              origins: typeck::vtable_param_res)
+              -> ValueRef {
     let ccx = bcx.ccx();
     let _icx = push_ctxt("meth::get_vtable");
 
     // Check the cache.
-    let hash_id = (self_ty, vtable_id(ccx, origins.get(0)));
+    let hash_id = (self_ty, monomorphize::make_vtable_id(ccx, origins.get(0)));
     match ccx.vtables.borrow().find(&hash_id) {
         Some(&val) => { return val }
         None => { }
     }
 
     // Not in the cache. Actually build it.
-    let mut methods = Vec::new();
-    for origin in origins.iter() {
-        match *origin {
-            typeck::vtable_static(id, ref substs, sub_vtables) => {
-                let vtable_methods = emit_vtable_methods(bcx,
-                                                         id,
-                                                         substs.as_slice(),
-                                                         sub_vtables);
-                for vtable_method in vtable_methods.move_iter() {
-                    methods.push(vtable_method)
-                }
+    let methods = origins.move_iter().flat_map(|origin| {
+        match origin {
+            typeck::vtable_static(id, substs, sub_vtables) => {
+                emit_vtable_methods(bcx, id, substs, sub_vtables).move_iter()
             }
             _ => ccx.sess().bug("get_vtable: expected a static origin"),
         }
-    }
+    });
 
     // Generate a destructor for the vtable.
     let drop_glue = glue::get_drop_glue(ccx, self_ty);
-    let vtable = make_vtable(ccx, drop_glue, methods.as_slice());
+    let vtable = make_vtable(ccx, drop_glue, methods);
 
     ccx.vtables.borrow_mut().insert(hash_id, vtable);
-    return vtable;
+    vtable
 }
 
 /// Helper function to declare and initialize the vtable.
-pub fn make_vtable(ccx: &CrateContext,
-                   drop_glue: ValueRef,
-                   ptrs: &[ValueRef])
-                   -> ValueRef {
-    unsafe {
-        let _icx = push_ctxt("meth::make_vtable");
+pub fn make_vtable<I: Iterator<ValueRef>>(ccx: &CrateContext,
+                                          drop_glue: ValueRef,
+                                          ptrs: I)
+                                          -> ValueRef {
+    let _icx = push_ctxt("meth::make_vtable");
 
-        let mut components = vec!(drop_glue);
-        for &ptr in ptrs.iter() {
-            components.push(ptr)
-        }
+    let components: Vec<_> = Some(drop_glue).move_iter().chain(ptrs).collect();
 
+    unsafe {
         let tbl = C_struct(ccx, components.as_slice(), false);
         let sym = token::gensym("vtable");
         let vt_gvar = format!("vtable{}", sym).with_c_str(|buf| {
@@ -509,7 +485,7 @@ pub fn make_vtable(ccx: &CrateContext,
 
 fn emit_vtable_methods(bcx: &Block,
                        impl_id: ast::DefId,
-                       substs: &[ty::t],
+                       substs: Vec<ty::t>,
                        vtables: typeck::vtable_res)
                        -> Vec<ValueRef> {
     let ccx = bcx.ccx();
@@ -539,7 +515,8 @@ fn emit_vtable_methods(bcx: &Block,
                    token::get_ident(ident));
             C_null(Type::nil(ccx).ptr_to())
         } else {
-            trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), substs, Some(vtables))
+            trans_fn_ref_with_vtables(bcx, m_id, ExprId(0),
+                                      substs.clone(), Some(vtables.clone()))
         }
     }).collect()
 }
@@ -576,8 +553,12 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
     bcx = datum.store_to(bcx, llboxdest);
 
     // Store the vtable into the second half of pair.
-    let res = *ccx.maps.vtable_map.borrow().get(&MethodCall::expr(id));
-    let origins = *resolve_vtables_in_fn_ctxt(bcx.fcx, res).get(0);
+    let origins = {
+        let vtable_map = ccx.tcx.vtable_map.borrow();
+        resolve_param_vtables_under_param_substs(ccx.tcx(),
+            bcx.fcx.param_substs,
+            vtable_map.get(&MethodCall::expr(id)).get(0).as_slice())
+    };
     let vtable = get_vtable(bcx, v_ty, origins);
     let llvtabledest = GEPi(bcx, lldest, [0u, abi::trt_field_vtable]);
     let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 20b468a0670..aa6e2dafd83 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -16,7 +16,6 @@ use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val};
 use middle::trans::base::{trans_fn, decl_internal_rust_fn};
 use middle::trans::base;
 use middle::trans::common::*;
-use middle::trans::meth;
 use middle::trans::intrinsic;
 use middle::ty;
 use middle::typeck;
@@ -26,7 +25,7 @@ use syntax::abi;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::local_def;
-use std::hash::sip;
+use std::hash::{sip, Hash};
 
 pub fn monomorphic_fn(ccx: &CrateContext,
                       fn_id: ast::DefId,
@@ -47,26 +46,51 @@ pub fn monomorphic_fn(ccx: &CrateContext,
            self_vtables.repr(ccx.tcx()),
            ref_id);
 
-    assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
+    assert!(real_substs.tps.iter().all(|t| {
+        !ty::type_needs_infer(*t) && !ty::type_has_params(*t)
+    }));
+
     let _icx = push_ctxt("monomorphic_fn");
-    let mut must_cast = false;
 
-    let psubsts = @param_substs {
+    let substs_iter = real_substs.self_ty.iter().chain(real_substs.tps.iter());
+    let param_ids: Vec<MonoParamId> = match vtables {
+        Some(ref vts) => {
+            debug!("make_mono_id vtables={} psubsts={}",
+                   vts.repr(ccx.tcx()), real_substs.tps.repr(ccx.tcx()));
+            let vts_iter = self_vtables.iter().chain(vts.iter());
+            vts_iter.zip(substs_iter).map(|(vtable, subst)| MonoParamId {
+                subst: *subst,
+                // Do we really need the vtables to be hashed? Isn't the type enough?
+                vtables: vtable.iter().map(|vt| make_vtable_id(ccx, vt)).collect()
+            }).collect()
+        }
+        None => substs_iter.map(|subst| MonoParamId {
+            subst: *subst,
+            vtables: Vec::new()
+        }).collect()
+    };
+
+    let hash_id = MonoId {
+        def: fn_id,
+        params: param_ids
+    };
+
+    match ccx.monomorphized.borrow().find(&hash_id) {
+        Some(&val) => {
+            debug!("leaving monomorphic fn {}",
+            ty::item_path_str(ccx.tcx(), fn_id));
+            return (val, false);
+        }
+        None => ()
+    }
+
+    let psubsts = param_substs {
         tys: real_substs.tps.clone(),
         vtables: vtables,
         self_ty: real_substs.self_ty.clone(),
         self_vtables: self_vtables
     };
 
-    for s in real_substs.tps.iter() { assert!(!ty::type_has_params(*s)); }
-    for s in psubsts.tys.iter() { assert!(!ty::type_has_params(*s)); }
-
-    let hash_id = make_mono_id(ccx, fn_id, &*psubsts);
-    if hash_id.params.iter().any(
-                |p| match *p { mono_precise(_, _) => false, _ => true }) {
-        must_cast = true;
-    }
-
     debug!("monomorphic_fn(\
             fn_id={}, \
             psubsts={}, \
@@ -75,15 +99,6 @@ pub fn monomorphic_fn(ccx: &CrateContext,
            psubsts.repr(ccx.tcx()),
            hash_id);
 
-    match ccx.monomorphized.borrow().find(&hash_id) {
-        Some(&val) => {
-            debug!("leaving monomorphic fn {}",
-            ty::item_path_str(ccx.tcx(), fn_id));
-            return (val, must_cast);
-        }
-        None => ()
-    }
-
     let tpt = ty::lookup_item_type(ccx.tcx(), fn_id);
     let llitem_ty = tpt.ty;
 
@@ -122,13 +137,13 @@ pub fn monomorphic_fn(ccx: &CrateContext,
 
     debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
     let mono_ty = match is_static_provided {
-        None => ty::subst_tps(ccx.tcx(), psubsts.tys.as_slice(),
-                              psubsts.self_ty, llitem_ty),
+        None => ty::subst_tps(ccx.tcx(), real_substs.tps.as_slice(),
+                              real_substs.self_ty, llitem_ty),
         Some(num_method_ty_params) => {
             // Static default methods are a little unfortunate, in
             // that the "internal" and "external" type of them differ.
             // Internally, the method body can refer to Self, but the
-            // externally visable type of the method has a type param
+            // externally visible type of the method has a type param
             // inserted in between the trait type params and the
             // method type params. The substs that we are given are
             // the proper substs *internally* to the method body, so
@@ -139,9 +154,9 @@ pub fn monomorphic_fn(ccx: &CrateContext,
             // stick a substitution for the self type in.
             // This is a bit unfortunate.
 
-            let idx = psubsts.tys.len() - num_method_ty_params;
-            let substs = psubsts.tys.slice(0, idx) +
-                &[psubsts.self_ty.unwrap()] + psubsts.tys.tailn(idx);
+            let idx = real_substs.tps.len() - num_method_ty_params;
+            let substs = real_substs.tps.slice(0, idx) +
+            &[real_substs.self_ty.unwrap()] + real_substs.tps.tailn(idx);
             debug!("static default: changed substitution to {}",
                    substs.repr(ccx.tcx()));
 
@@ -178,16 +193,22 @@ pub fn monomorphic_fn(ccx: &CrateContext,
     }
 
     let s = ccx.tcx.map.with_path(fn_id.node, |path| {
-        exported_name(path, format!("h{}", sip::hash(&(hash_id, mono_ty))),
+        let mut state = sip::SipState::new();
+        hash_id.hash(&mut state);
+        mono_ty.hash(&mut state);
+
+        exported_name(path, format!("h{}", state.result()),
                       ccx.link_meta.crateid.version_or_default())
     });
     debug!("monomorphize_fn mangled to {}", s);
 
+    // This shouldn't need to option dance.
+    let mut hash_id = Some(hash_id);
     let mk_lldecl = || {
         let lldecl = decl_internal_rust_fn(ccx, false,
                                            f.sig.inputs.as_slice(),
                                            f.sig.output, s);
-        ccx.monomorphized.borrow_mut().insert(hash_id, lldecl);
+        ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
         lldecl
     };
 
@@ -200,7 +221,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
               } => {
                   let d = mk_lldecl();
                   set_llvm_fn_attrs(i.attrs.as_slice(), d);
-                  trans_fn(ccx, decl, body, d, Some(psubsts), fn_id.node, []);
+                  trans_fn(ccx, decl, body, d, Some(&psubsts), fn_id.node, []);
                   d
               }
               _ => {
@@ -214,7 +235,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                 Some(decl) => decl,
                 None => {
                     let d = mk_lldecl();
-                    intrinsic::trans_intrinsic(ccx, d, i, psubsts, ref_id);
+                    intrinsic::trans_intrinsic(ccx, d, i, &psubsts, ref_id);
                     d
                 }
             }
@@ -222,7 +243,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeVariant(v) => {
             let parent = ccx.tcx.map.get_parent(fn_id.node);
             let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
-            let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
+            let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
             let d = mk_lldecl();
             set_inline_hint(d);
             match v.node.kind {
@@ -232,7 +253,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                                        v,
                                        args.as_slice(),
                                        this_tv.disr_val,
-                                       Some(psubsts),
+                                       Some(&psubsts),
                                        d);
                 }
                 ast::StructVariantKind(_) =>
@@ -243,7 +264,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
         ast_map::NodeMethod(mth) => {
             let d = mk_lldecl();
             set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-            trans_fn(ccx, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
+            trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
             d
         }
         ast_map::NodeTraitMethod(method) => {
@@ -251,7 +272,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                 ast::Provided(mth) => {
                     let d = mk_lldecl();
                     set_llvm_fn_attrs(mth.attrs.as_slice(), d);
-                    trans_fn(ccx, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
+                    trans_fn(ccx, mth.decl, mth.body, d, Some(&psubsts), mth.id, []);
                     d
                 }
                 _ => {
@@ -267,7 +288,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
                                      struct_def.fields.as_slice(),
                                      struct_def.ctor_id.expect("ast-mapped tuple struct \
                                                                 didn't have a ctor id"),
-                                     Some(psubsts),
+                                     Some(&psubsts),
                                      d);
             d
         }
@@ -286,32 +307,41 @@ pub fn monomorphic_fn(ccx: &CrateContext,
     ccx.monomorphizing.borrow_mut().insert(fn_id, depth);
 
     debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
-    (lldecl, must_cast)
+    (lldecl, false)
 }
 
-pub fn make_mono_id(ccx: &CrateContext,
-                    item: ast::DefId,
-                    substs: &param_substs) -> mono_id {
-    // FIXME (possibly #5801): Need a lot of type hints to get
-    // .collect() to work.
-    let substs_iter = substs.self_ty.iter().chain(substs.tys.iter());
-    let precise_param_ids: Vec<(ty::t, Option<@Vec<mono_id> >)> = match substs.vtables {
-      Some(vts) => {
-        debug!("make_mono_id vtables={} substs={}",
-               vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx()));
-        let vts_iter = substs.self_vtables.iter().chain(vts.iter());
-        vts_iter.zip(substs_iter).map(|(vtable, subst)| {
-            let v = vtable.iter().map(|vt| meth::vtable_id(ccx, vt)).collect::<Vec<_>>();
-            (*subst, if !v.is_empty() { Some(@v) } else { None })
-        }).collect()
-      }
-      None => substs_iter.map(|subst| (*subst, None::<@Vec<mono_id> >)).collect()
-    };
+// Used to identify cached monomorphized functions and vtables
+#[deriving(Eq, TotalEq, Hash)]
+pub struct MonoParamId {
+    pub subst: ty::t,
+    // Do we really need the vtables to be hashed? Isn't the type enough?
+    pub vtables: Vec<MonoId>
+}
 
+#[deriving(Eq, TotalEq, Hash)]
+pub struct MonoId {
+    pub def: ast::DefId,
+    pub params: Vec<MonoParamId>
+}
 
-    let param_ids = precise_param_ids.iter().map(|x| {
-        let (a, b) = *x;
-        mono_precise(a, b)
-    }).collect();
-    @mono_id_ {def: item, params: param_ids}
+pub fn make_vtable_id(ccx: &CrateContext,
+                      origin: &typeck::vtable_origin)
+                      -> MonoId {
+    match origin {
+        &typeck::vtable_static(impl_id, ref substs, ref sub_vtables) => {
+            MonoId {
+                def: impl_id,
+                params: sub_vtables.iter().zip(substs.iter()).map(|(vtable, subst)| {
+                    MonoParamId {
+                        subst: *subst,
+                        // Do we really need the vtables to be hashed? Isn't the type enough?
+                        vtables: vtable.iter().map(|vt| make_vtable_id(ccx, vt)).collect()
+                    }
+                }).collect()
+            }
+        }
+
+        // can't this be checked at the callee?
+        _ => fail!("make_vtable_id needs vtable_static")
+    }
 }
diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs
index 7dc4641e97f..a1752862715 100644
--- a/src/librustc/middle/trans/reflect.rs
+++ b/src/librustc/middle/trans/reflect.rs
@@ -25,6 +25,7 @@ use middle::trans::type_of::*;
 use middle::ty;
 use util::ppaux::ty_to_str;
 
+use std::rc::Rc;
 use arena::TypedArena;
 use libc::c_uint;
 use syntax::ast::DefId;
@@ -33,15 +34,15 @@ use syntax::ast_map;
 use syntax::parse::token::{InternedString, special_idents};
 use syntax::parse::token;
 
-pub struct Reflector<'a> {
+pub struct Reflector<'a, 'b> {
     visitor_val: ValueRef,
-    visitor_methods: @Vec<@ty::Method> ,
-    final_bcx: &'a Block<'a>,
+    visitor_methods: &'a [Rc<ty::Method>],
+    final_bcx: &'b Block<'b>,
     tydesc_ty: Type,
-    bcx: &'a Block<'a>
+    bcx: &'b Block<'b>
 }
 
-impl<'a> Reflector<'a> {
+impl<'a, 'b> Reflector<'a, 'b> {
     pub fn c_uint(&mut self, u: uint) -> ValueRef {
         C_uint(self.bcx.ccx(), u)
     }
@@ -75,7 +76,7 @@ impl<'a> Reflector<'a> {
     pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef {
         let bcx = self.bcx;
         let static_ti = get_tydesc(bcx.ccx(), t);
-        glue::lazily_emit_visit_glue(bcx.ccx(), static_ti);
+        glue::lazily_emit_visit_glue(bcx.ccx(), &*static_ti);
         PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to())
     }
 
@@ -92,7 +93,7 @@ impl<'a> Reflector<'a> {
                 format!("couldn't find visit method for {}", ty_name));
         let mth_ty =
             ty::mk_bare_fn(tcx,
-                           self.visitor_methods.get(mth_idx).fty.clone());
+                           self.visitor_methods[mth_idx].fty.clone());
         let v = self.visitor_val;
         debug!("passing {} args:", args.len());
         let mut bcx = self.bcx;
@@ -307,7 +308,7 @@ impl<'a> Reflector<'a> {
                 let arena = TypedArena::new();
                 let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
                                       ty::mk_u64(), None, None, &arena);
-                init_function(&fcx, false, ty::mk_u64(), None);
+                init_function(&fcx, false, ty::mk_u64());
 
                 let arg = unsafe {
                     //
@@ -319,7 +320,7 @@ impl<'a> Reflector<'a> {
                 };
                 let bcx = fcx.entry_bcx.borrow().clone().unwrap();
                 let arg = BitCast(bcx, arg, llptrty);
-                let ret = adt::trans_get_discr(bcx, repr, arg, Some(Type::i64(ccx)));
+                let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx)));
                 Store(bcx, ret, fcx.llretptr.get().unwrap());
                 match fcx.llreturn.get() {
                     Some(llreturn) => Br(bcx, llreturn),
@@ -344,7 +345,7 @@ impl<'a> Reflector<'a> {
                         for (j, a) in v.args.iter().enumerate() {
                             let bcx = this.bcx;
                             let null = C_null(llptrty);
-                            let ptr = adt::trans_field_ptr(bcx, repr, null, v.disr_val, j);
+                            let ptr = adt::trans_field_ptr(bcx, &*repr, null, v.disr_val, j);
                             let offset = p2i(ccx, ptr);
                             let field_args = [this.c_uint(j),
                                                offset,
@@ -401,9 +402,10 @@ pub fn emit_calls_to_trait_visit_ty<'a>(
     let final = fcx.new_temp_block("final");
     let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap();
     let tydesc_ty = type_of(bcx.ccx(), tydesc_ty);
+    let visitor_methods = ty::trait_methods(bcx.tcx(), visitor_trait_id);
     let mut r = Reflector {
         visitor_val: visitor_val,
-        visitor_methods: ty::trait_methods(bcx.tcx(), visitor_trait_id),
+        visitor_methods: visitor_methods.as_slice(),
         final_bcx: final,
         tydesc_ty: tydesc_ty,
         bcx: bcx
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index 48c25fb985d..0a539d5e6c6 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -142,7 +142,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
 
         ty::ty_tup(..) | ty::ty_enum(..) => {
             let repr = adt::represent_type(cx, t);
-            adt::sizing_type_of(cx, repr)
+            adt::sizing_type_of(cx, &*repr)
         }
 
         ty::ty_struct(..) => {
@@ -152,7 +152,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
                 Type::vector(&type_of(cx, et), n as u64)
             } else {
                 let repr = adt::represent_type(cx, t);
-                adt::sizing_type_of(cx, repr)
+                adt::sizing_type_of(cx, &*repr)
             }
         }
 
@@ -213,7 +213,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
         // of the enum's variants refers to the enum itself.
         let repr = adt::represent_type(cx, t);
         let name = llvm_type_name(cx, an_enum, did, substs.tps.as_slice());
-        adt::incomplete_type_of(cx, repr, name)
+        adt::incomplete_type_of(cx, &*repr, name)
       }
       ty::ty_box(typ) => {
           Type::at_box(cx, type_of(cx, typ)).ptr_to()
@@ -259,7 +259,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
       ty::ty_trait(..) => Type::opaque_trait(cx),
       ty::ty_tup(..) => {
           let repr = adt::represent_type(cx, t);
-          adt::type_of(cx, repr)
+          adt::type_of(cx, &*repr)
       }
       ty::ty_struct(did, ref substs) => {
           if ty::type_is_simd(cx.tcx(), t) {
@@ -275,7 +275,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
                                         a_struct,
                                         did,
                                         substs.tps.as_slice());
-              adt::incomplete_type_of(cx, repr, name)
+              adt::incomplete_type_of(cx, &*repr, name)
           }
       }
 
@@ -297,7 +297,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
     match ty::get(t).sty {
         ty::ty_enum(..) | ty::ty_struct(..) if !ty::type_is_simd(cx.tcx(), t) => {
             let repr = adt::represent_type(cx, t);
-            adt::finish_type_of(cx, repr, &mut llty);
+            adt::finish_type_of(cx, &*repr, &mut llty);
         }
         _ => ()
     }
diff --git a/src/librustc/middle/trans/write_guard.rs b/src/librustc/middle/trans/write_guard.rs
index 565805446f7..8f114827bfd 100644
--- a/src/librustc/middle/trans/write_guard.rs
+++ b/src/librustc/middle/trans/write_guard.rs
@@ -34,7 +34,7 @@ pub fn root_and_write_guard<'a, K:KindOps>(datum: &Datum<K>,
     //
     // (Note: root'd values are always boxes)
     let ccx = bcx.ccx();
-    match ccx.maps.root_map.borrow().find(&key) {
+    match ccx.maps.root_map.find(&key) {
         None => bcx,
         Some(&root_info) => root(datum, bcx, span, key, root_info)
     }
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 037182d8b7b..9a3bdcc1e15 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -22,7 +22,7 @@ use middle::resolve_lifetime;
 use middle::ty;
 use middle::subst::Subst;
 use middle::typeck;
-use middle::typeck::{MethodCall, MethodCallee, MethodMap};
+use middle::typeck::MethodCall;
 use middle::ty_fold;
 use middle::ty_fold::TypeFolder;
 use middle;
@@ -38,9 +38,11 @@ use std::cmp;
 use std::fmt::Show;
 use std::fmt;
 use std::hash::{Hash, sip};
+use std::iter::AdditiveIterator;
 use std::ops;
 use std::rc::Rc;
 use collections::{HashMap, HashSet};
+use syntax::abi;
 use syntax::ast::*;
 use syntax::ast_util::{is_local, lit_is_str};
 use syntax::ast_util;
@@ -51,7 +53,7 @@ use syntax::parse::token;
 use syntax::parse::token::InternedString;
 use syntax::{ast, ast_map};
 use syntax::owned_slice::OwnedSlice;
-use syntax::abi;
+use syntax::util::small_vector::SmallVector;
 use collections::enum_set::{EnumSet, CLike};
 
 pub type Disr = u64;
@@ -116,12 +118,6 @@ impl Method {
     }
 }
 
-pub struct Impl {
-    pub did: DefId,
-    pub ident: Ident,
-    pub methods: Vec<@Method>,
-}
-
 #[deriving(Clone, Eq, TotalEq, Hash)]
 pub struct mt {
     pub ty: t,
@@ -212,6 +208,7 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
+#[deriving(Clone)]
 pub enum AutoAdjustment {
     AutoAddEnv(ty::TraitStore),
     AutoDerefRef(AutoDerefRef),
@@ -221,13 +218,13 @@ pub enum AutoAdjustment {
                ty::substs /* Trait substitutions */)
 }
 
-#[deriving(Decodable, Encodable)]
+#[deriving(Clone, Decodable, Encodable)]
 pub struct AutoDerefRef {
     pub autoderefs: uint,
     pub autoref: Option<AutoRef>
 }
 
-#[deriving(Decodable, Encodable, Eq, Show)]
+#[deriving(Clone, Decodable, Encodable, Eq, Show)]
 pub enum AutoRef {
     /// Convert from T to &T
     AutoPtr(Region, ast::Mutability),
@@ -272,18 +269,18 @@ pub struct ctxt {
     pub node_type_substs: RefCell<NodeMap<Vec<t>>>,
 
     // Maps from a method to the method "descriptor"
-    pub methods: RefCell<DefIdMap<@Method>>,
+    pub methods: RefCell<DefIdMap<Rc<Method>>>,
 
     // Maps from a trait def-id to a list of the def-ids of its methods
-    pub trait_method_def_ids: RefCell<DefIdMap<@Vec<DefId> >>,
+    pub trait_method_def_ids: RefCell<DefIdMap<Rc<Vec<DefId>>>>,
 
     // A cache for the trait_methods() routine
-    pub trait_methods_cache: RefCell<DefIdMap<@Vec<@Method> >>,
+    pub trait_methods_cache: RefCell<DefIdMap<Rc<Vec<Rc<Method>>>>>,
 
-    pub impl_trait_cache: RefCell<DefIdMap<Option<@ty::TraitRef>>>,
+    pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef>>>>,
 
-    pub trait_refs: RefCell<NodeMap<@TraitRef>>,
-    pub trait_defs: RefCell<DefIdMap<@TraitDef>>,
+    pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
+    pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
 
     pub map: ast_map::Map,
     pub intrinsic_defs: RefCell<DefIdMap<t>>,
@@ -294,20 +291,20 @@ pub struct ctxt {
     pub needs_unwind_cleanup_cache: RefCell<HashMap<t, bool>>,
     pub tc_cache: RefCell<HashMap<uint, TypeContents>>,
     pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry>>,
-    pub enum_var_cache: RefCell<DefIdMap<@Vec<@VariantInfo> >>,
+    pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo>>>>>,
     pub ty_param_defs: RefCell<NodeMap<TypeParameterDef>>,
-    pub adjustments: RefCell<NodeMap<@AutoAdjustment>>,
+    pub adjustments: RefCell<NodeMap<AutoAdjustment>>,
     pub normalized_cache: RefCell<HashMap<t, t>>,
-    pub lang_items: @middle::lang_items::LanguageItems,
+    pub lang_items: middle::lang_items::LanguageItems,
     // A mapping of fake provided method def_ids to the default implementation
     pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
-    pub supertraits: RefCell<DefIdMap<@Vec<@TraitRef> >>,
+    pub supertraits: RefCell<DefIdMap<Rc<Vec<Rc<TraitRef>>>>>,
     pub superstructs: RefCell<DefIdMap<Option<ast::DefId>>>,
-    pub struct_fields: RefCell<DefIdMap<@Vec<field_ty>>>,
+    pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
 
     // Maps from def-id of a type or region parameter to its
     // (inferred) variance.
-    pub item_variance_map: RefCell<DefIdMap<@ItemVariances>>,
+    pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
 
     // A mapping from the def ID of an enum or struct type to the def ID
     // of the method that implements its destructor. If the type is not
@@ -319,18 +316,18 @@ pub struct ctxt {
     pub destructors: RefCell<DefIdSet>,
 
     // Maps a trait onto a list of impls of that trait.
-    pub trait_impls: RefCell<DefIdMap<@RefCell<Vec<@Impl> >>>,
+    pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
 
-    // Maps a def_id of a type to a list of its inherent impls.
+    // Maps a DefId of a type to a list of its inherent impls.
     // Contains implementations of methods that are inherent to a type.
     // Methods in these implementations don't need to be exported.
-    pub inherent_impls: RefCell<DefIdMap<@RefCell<Vec<@Impl> >>>,
+    pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
 
-    // Maps a def_id of an impl to an Impl structure.
+    // Maps a DefId of an impl to a list of its methods.
     // Note that this contains all of the impls that we know about,
     // including ones in other crates. It's not clear that this is the best
     // way to do it.
-    pub impls: RefCell<DefIdMap<@Impl>>,
+    pub impl_methods: RefCell<DefIdMap<Vec<ast::DefId>>>,
 
     // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
     // present in this set can be warned about.
@@ -359,6 +356,9 @@ pub struct ctxt {
     // and variants that are found.
     pub extern_const_statics: RefCell<DefIdMap<Option<@ast::Expr>>>,
     pub extern_const_variants: RefCell<DefIdMap<Option<@ast::Expr>>>,
+
+    pub method_map: typeck::MethodMap,
+    pub vtable_map: typeck::vtable_map,
 }
 
 pub enum tbox_flag {
@@ -816,7 +816,6 @@ pub enum type_err {
     terr_regions_overly_polymorphic(BoundRegion, Region),
     terr_vstores_differ(terr_vstore_kind, expected_found<Vstore>),
     terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
-    terr_in_field(@type_err, ast::Ident),
     terr_sorts(expected_found<t>),
     terr_integer_as_char,
     terr_int_mismatch(expected_found<IntVarValue>),
@@ -829,7 +828,8 @@ pub enum type_err {
 #[deriving(Eq, TotalEq, Hash)]
 pub struct ParamBounds {
     pub builtin_bounds: BuiltinBounds,
-    pub trait_bounds: Vec<@TraitRef> }
+    pub trait_bounds: Vec<Rc<TraitRef>>
+}
 
 pub type BuiltinBounds = EnumSet<BuiltinBound>;
 
@@ -983,7 +983,7 @@ impl fmt::Show for IntVarValue {
 pub struct TypeParameterDef {
     pub ident: ast::Ident,
     pub def_id: ast::DefId,
-    pub bounds: @ParamBounds,
+    pub bounds: Rc<ParamBounds>,
     pub default: Option<ty::t>
 }
 
@@ -1038,7 +1038,7 @@ pub struct ParameterEnvironment {
     pub free_substs: ty::substs,
 
     /// Bound on the Self parameter
-    pub self_param_bound: Option<@TraitRef>,
+    pub self_param_bound: Option<Rc<TraitRef>>,
 
     /// Bounds on each numbered type parameter
     pub type_param_bounds: Vec<ParamBounds> ,
@@ -1064,7 +1064,7 @@ pub struct ty_param_bounds_and_ty {
 pub struct TraitDef {
     pub generics: Generics,
     pub bounds: BuiltinBounds,
-    pub trait_ref: @ty::TraitRef,
+    pub trait_ref: Rc<ty::TraitRef>,
 }
 
 pub struct ty_param_substs_and_ty {
@@ -1082,7 +1082,7 @@ pub fn mk_ctxt(s: Session,
                map: ast_map::Map,
                freevars: freevars::freevar_map,
                region_maps: middle::region::RegionMaps,
-               lang_items: @middle::lang_items::LanguageItems)
+               lang_items: middle::lang_items::LanguageItems)
             -> ctxt {
     ctxt {
         named_region_map: named_region_map,
@@ -1122,7 +1122,7 @@ pub fn mk_ctxt(s: Session,
         destructors: RefCell::new(DefIdSet::new()),
         trait_impls: RefCell::new(DefIdMap::new()),
         inherent_impls: RefCell::new(DefIdMap::new()),
-        impls: RefCell::new(DefIdMap::new()),
+        impl_methods: RefCell::new(DefIdMap::new()),
         used_unsafe: RefCell::new(NodeSet::new()),
         used_mut_nodes: RefCell::new(NodeSet::new()),
         impl_vtables: RefCell::new(DefIdMap::new()),
@@ -1131,6 +1131,8 @@ pub fn mk_ctxt(s: Session,
         upvar_borrow_map: RefCell::new(HashMap::new()),
         extern_const_statics: RefCell::new(DefIdMap::new()),
         extern_const_variants: RefCell::new(DefIdMap::new()),
+        method_map: RefCell::new(FnvHashMap::new()),
+        vtable_map: RefCell::new(FnvHashMap::new()),
     }
 }
 
@@ -2174,7 +2176,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
                 // Self may be bounded if the associated trait has builtin kinds
                 // for supertraits. If so we can use those bounds.
                 let trait_def = lookup_trait_def(cx, def_id);
-                let traits = [trait_def.trait_ref];
+                let traits = [trait_def.trait_ref.clone()];
                 kind_bounds_to_contents(cx, trait_def.bounds, traits)
             }
 
@@ -2214,7 +2216,9 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
         } else if Some(did) == cx.lang_items.no_share_bound() {
             tc | TC::ReachesNoShare
         } else if Some(did) == cx.lang_items.unsafe_type() {
-            tc | TC::InteriorUnsafe
+            // FIXME(#13231): This shouldn't be needed after
+            // opt-in built-in bounds are implemented.
+            (tc | TC::InteriorUnsafe) - TC::Nonsharable
         } else {
             tc
         }
@@ -2269,7 +2273,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
 
     fn kind_bounds_to_contents(cx: &ctxt,
                                bounds: BuiltinBounds,
-                               traits: &[@TraitRef])
+                               traits: &[Rc<TraitRef>])
                                -> TypeContents {
         let _i = indenter();
         let mut tc = TC::All;
@@ -2288,7 +2292,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
         // those inherited from traits with builtin-kind-supertraits.
         fn each_inherited_builtin_bound(cx: &ctxt,
                                         bounds: BuiltinBounds,
-                                        traits: &[@TraitRef],
+                                        traits: &[Rc<TraitRef>],
                                         f: |BuiltinBound|) {
             for bound in bounds.iter() {
                 f(bound);
@@ -2338,7 +2342,7 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
         let r = match get(ty).sty {
             // fixed length vectors need special treatment compared to
             // normal vectors, since they don't necessarily have the
-            // possibilty to have length zero.
+            // possibility to have length zero.
             ty_vec(_, Some(0)) => false, // don't need no contents
             ty_vec(mt, Some(_)) => type_requires(cx, seen, r_ty, mt.ty),
 
@@ -2654,12 +2658,12 @@ pub fn index(t: t) -> Option<mt> {
     }
 }
 
-pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> @ty::TraitRef {
+pub fn node_id_to_trait_ref(cx: &ctxt, id: ast::NodeId) -> Rc<ty::TraitRef> {
     match cx.trait_refs.borrow().find(&id) {
-       Some(&t) => t,
-       None => cx.sess.bug(
-           format!("node_id_to_trait_ref: no trait ref for node `{}`",
-               cx.map.node_to_str(id)))
+        Some(t) => t.clone(),
+        None => cx.sess.bug(
+            format!("node_id_to_trait_ref: no trait ref for node `{}`",
+                cx.map.node_to_str(id)))
     }
 }
 
@@ -2789,10 +2793,7 @@ pub fn expr_ty_opt(cx: &ctxt, expr: &ast::Expr) -> Option<t> {
     return node_id_to_type_opt(cx, expr.id);
 }
 
-pub fn expr_ty_adjusted(cx: &ctxt,
-                        expr: &ast::Expr,
-                        method_map: &FnvHashMap<MethodCall, MethodCallee>)
-                        -> t {
+pub fn expr_ty_adjusted(cx: &ctxt, expr: &ast::Expr) -> t {
     /*!
      *
      * Returns the type of `expr`, considering any `AutoAdjustment`
@@ -2806,11 +2807,9 @@ pub fn expr_ty_adjusted(cx: &ctxt,
      * task at hand! -nmatsakis
      */
 
-    let unadjusted_ty = expr_ty(cx, expr);
-    let adjustment = cx.adjustments.borrow().find_copy(&expr.id);
-    adjust_ty(cx, expr.span, expr.id, unadjusted_ty, adjustment, |method_call| {
-        method_map.find(&method_call).map(|method| method.ty)
-    })
+    adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
+              cx.adjustments.borrow().find(&expr.id),
+              |method_call| cx.method_map.borrow().find(&method_call).map(|method| method.ty))
 }
 
 pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
@@ -2855,8 +2854,8 @@ pub fn adjust_ty(cx: &ctxt,
                  span: Span,
                  expr_id: ast::NodeId,
                  unadjusted_ty: ty::t,
-                 adjustment: Option<@AutoAdjustment>,
-                 method_type: |MethodCall| -> Option<ty::t>)
+                 adjustment: Option<&AutoAdjustment>,
+                 method_type: |typeck::MethodCall| -> Option<ty::t>)
                  -> ty::t {
     /*! See `expr_ty_adjusted` */
 
@@ -2888,7 +2887,8 @@ pub fn adjust_ty(cx: &ctxt,
 
                     if !ty::type_is_error(adjusted_ty) {
                         for i in range(0, adj.autoderefs) {
-                            match method_type(MethodCall::autoderef(expr_id, i as u32)) {
+                            let method_call = typeck::MethodCall::autoderef(expr_id, i as u32);
+                            match method_type(method_call) {
                                 Some(method_ty) => {
                                     adjusted_ty = ty_fn_ret(method_ty);
                                 }
@@ -3049,8 +3049,8 @@ pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
             // method bounds, so we must preprend the tps from the
             // trait itself.  This ought to be harmonized.
             let trait_type_param_defs =
-                lookup_trait_def(tcx, trt_id).generics.type_param_defs();
-            Rc::new(Vec::from_slice(trait_type_param_defs).append(
+                Vec::from_slice(lookup_trait_def(tcx, trt_id).generics.type_param_defs());
+            Rc::new(trait_type_param_defs.append(
                         ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs()))
         }
     }
@@ -3066,10 +3066,8 @@ pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> ast::Def {
     }
 }
 
-pub fn expr_is_lval(tcx: &ctxt,
-                    method_map: MethodMap,
-                    e: &ast::Expr) -> bool {
-    match expr_kind(tcx, method_map, e) {
+pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
+    match expr_kind(tcx, e) {
         LvalueExpr => true,
         RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
     }
@@ -3087,10 +3085,8 @@ pub enum ExprKind {
     RvalueStmtExpr
 }
 
-pub fn expr_kind(tcx: &ctxt,
-                 method_map: MethodMap,
-                 expr: &ast::Expr) -> ExprKind {
-    if method_map.borrow().contains_key(&MethodCall::expr(expr.id)) {
+pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
+    if tcx.method_map.borrow().contains_key(&typeck::MethodCall::expr(expr.id)) {
         // Overloaded operations are generally calls, and hence they are
         // generated via DPS, but there are two exceptions:
         return match expr.node {
@@ -3234,7 +3230,7 @@ pub fn expr_kind(tcx: &ctxt,
             }
         }
 
-        ast::ExprParen(e) => expr_kind(tcx, method_map, e),
+        ast::ExprParen(e) => expr_kind(tcx, e),
 
         ast::ExprMac(..) => {
             tcx.sess.span_bug(
@@ -3263,7 +3259,7 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
         fields.iter().map(|f| token::get_ident(f.ident).get().to_str()).collect::<Vec<~str>>()));
 }
 
-pub fn method_idx(id: ast::Ident, meths: &[@Method]) -> Option<uint> {
+pub fn method_idx(id: ast::Ident, meths: &[Rc<Method>]) -> Option<uint> {
     meths.iter().position(|m| m.ident == id)
 }
 
@@ -3329,6 +3325,13 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~str {
         }
     }
 
+    fn tstore_to_closure(s: &TraitStore) -> ~str {
+        match s {
+            &UniqTraitStore => "proc".to_owned(),
+            &RegionTraitStore(..) => "closure".to_owned()
+        }
+    }
+
     match *err {
         terr_mismatch => "types differ".to_owned(),
         terr_fn_style_mismatch(values) => {
@@ -3344,9 +3347,9 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~str {
                  values.expected.to_str(), values.found.to_str())
         }
         terr_sigil_mismatch(values) => {
-            format!("expected {} closure, found {} closure",
-                 values.expected.to_str(),
-                 values.found.to_str())
+            format!("expected {}, found {}",
+                    tstore_to_closure(&values.expected),
+                    tstore_to_closure(&values.found))
         }
         terr_mutability => "values differ in mutability".to_owned(),
         terr_box_mutability => "boxed values differ in mutability".to_owned(),
@@ -3408,10 +3411,6 @@ pub fn type_err_to_str(cx: &ctxt, err: &type_err) -> ~str {
                  trait_store_to_str(cx, (*values).expected),
                  trait_store_to_str(cx, (*values).found))
         }
-        terr_in_field(err, fname) => {
-            format!("in field `{}`, {}", token::get_ident(fname),
-                 type_err_to_str(cx, err))
-        }
         terr_sorts(values) => {
             format!("expected {} but found {}",
                  ty_sort_str(cx, values.expected),
@@ -3491,42 +3490,29 @@ pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
     cx.provided_method_sources.borrow().find(&id).map(|x| *x)
 }
 
-pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<@Method> {
+pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
     if is_local(id) {
-        {
-            match cx.map.find(id.node) {
-                Some(ast_map::NodeItem(item)) => {
-                    match item.node {
-                        ItemTrait(_, _, ref ms) => {
-                            let (_, p) =
-                                ast_util::split_trait_methods(ms.as_slice());
-                            p.iter()
-                             .map(|m| method(cx, ast_util::local_def(m.id)))
-                             .collect()
-                        }
-                        _ => {
-                            cx.sess.bug(format!("provided_trait_methods: \
-                                                 `{:?}` is not a trait",
-                                                id))
-                        }
+        match cx.map.find(id.node) {
+            Some(ast_map::NodeItem(item)) => {
+                match item.node {
+                    ItemTrait(_, _, ref ms) => {
+                        let (_, p) = ast_util::split_trait_methods(ms.as_slice());
+                        p.iter().map(|m| method(cx, ast_util::local_def(m.id))).collect()
                     }
-                }
-                _ => {
-                    cx.sess.bug(format!("provided_trait_methods: `{:?}` is not \
-                                         a trait",
-                                        id))
+                    _ => cx.sess.bug(format!("provided_trait_methods: `{}` is not a trait", id))
                 }
             }
+            _ => cx.sess.bug(format!("provided_trait_methods: `{}` is not a trait", id))
         }
     } else {
         csearch::get_provided_trait_methods(cx, id)
     }
 }
 
-pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
+pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<TraitRef>>> {
     // Check the cache.
     match cx.supertraits.borrow().find(&id) {
-        Some(&trait_refs) => { return trait_refs; }
+        Some(trait_refs) => { return trait_refs.clone(); }
         None => {}  // Continue.
     }
 
@@ -3536,12 +3522,12 @@ pub fn trait_supertraits(cx: &ctxt, id: ast::DefId) -> @Vec<@TraitRef> {
 
     // Get the supertraits out of the metadata and create the
     // TraitRef for each.
-    let result = @csearch::get_supertraits(cx, id);
-    cx.supertraits.borrow_mut().insert(id, result);
-    return result;
+    let result = Rc::new(csearch::get_supertraits(cx, id));
+    cx.supertraits.borrow_mut().insert(id, result.clone());
+    result
 }
 
-pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec<@TraitRef> {
+pub fn trait_ref_supertraits(cx: &ctxt, trait_ref: &ty::TraitRef) -> Vec<Rc<TraitRef>> {
     let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
     supertrait_refs.iter().map(
         |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs)).collect()
@@ -3575,44 +3561,46 @@ fn lookup_locally_or_in_crate_store<V:Clone>(
     v
 }
 
-pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> @Method {
+pub fn trait_method(cx: &ctxt, trait_did: ast::DefId, idx: uint) -> Rc<Method> {
     let method_def_id = *ty::trait_method_def_ids(cx, trait_did).get(idx);
     ty::method(cx, method_def_id)
 }
 
 
-pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> @Vec<@Method> {
+pub fn trait_methods(cx: &ctxt, trait_did: ast::DefId) -> Rc<Vec<Rc<Method>>> {
     let mut trait_methods = cx.trait_methods_cache.borrow_mut();
-    match trait_methods.find(&trait_did) {
-        Some(&methods) => methods,
+    match trait_methods.find_copy(&trait_did) {
+        Some(methods) => methods,
         None => {
             let def_ids = ty::trait_method_def_ids(cx, trait_did);
-            let methods = @def_ids.iter().map(|d| ty::method(cx, *d)).collect();
-            trait_methods.insert(trait_did, methods);
+            let methods: Rc<Vec<Rc<Method>>> = Rc::new(def_ids.iter().map(|d| {
+                ty::method(cx, *d)
+            }).collect());
+            trait_methods.insert(trait_did, methods.clone());
             methods
         }
     }
 }
 
-pub fn method(cx: &ctxt, id: ast::DefId) -> @Method {
+pub fn method(cx: &ctxt, id: ast::DefId) -> Rc<Method> {
     lookup_locally_or_in_crate_store("methods", id,
                                      &mut *cx.methods.borrow_mut(), || {
-        @csearch::get_method(cx, id)
+        Rc::new(csearch::get_method(cx, id))
     })
 }
 
-pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> @Vec<DefId> {
+pub fn trait_method_def_ids(cx: &ctxt, id: ast::DefId) -> Rc<Vec<DefId>> {
     lookup_locally_or_in_crate_store("trait_method_def_ids",
                                      id,
                                      &mut *cx.trait_method_def_ids.borrow_mut(),
                                      || {
-        @csearch::get_trait_method_def_ids(&cx.sess.cstore, id)
+        Rc::new(csearch::get_trait_method_def_ids(&cx.sess.cstore, id))
     })
 }
 
-pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<@TraitRef> {
+pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<Rc<TraitRef>> {
     match cx.impl_trait_cache.borrow().find(&id) {
-        Some(&ret) => { return ret; }
+        Some(ret) => { return ret.clone(); }
         None => {}
     }
 
@@ -3638,8 +3626,8 @@ pub fn impl_trait_ref(cx: &ctxt, id: ast::DefId) -> Option<@TraitRef> {
         csearch::get_impl_trait(cx, id)
     };
 
-    cx.impl_trait_cache.borrow_mut().insert(id, ret);
-    return ret;
+    cx.impl_trait_cache.borrow_mut().insert(id, ret.clone());
+    ret
 }
 
 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
@@ -3742,18 +3730,18 @@ impl VariantInfo {
 pub fn substd_enum_variants(cx: &ctxt,
                             id: ast::DefId,
                             substs: &substs)
-                         -> Vec<@VariantInfo> {
+                         -> Vec<Rc<VariantInfo>> {
     enum_variants(cx, id).iter().map(|variant_info| {
         let substd_args = variant_info.args.iter()
             .map(|aty| subst(cx, substs, *aty)).collect();
 
         let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
 
-        @VariantInfo {
+        Rc::new(VariantInfo {
             args: substd_args,
             ctor_ty: substd_ctor_ty,
             ..(**variant_info).clone()
-        }
+        })
     }).collect()
 }
 
@@ -3822,27 +3810,26 @@ pub fn type_is_empty(cx: &ctxt, t: t) -> bool {
      }
 }
 
-pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
+pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
     match cx.enum_var_cache.borrow().find(&id) {
-        Some(&variants) => return variants,
+        Some(variants) => return variants.clone(),
         _ => { /* fallthrough */ }
     }
 
     let result = if ast::LOCAL_CRATE != id.krate {
-        @csearch::get_enum_variants(cx, id)
+        Rc::new(csearch::get_enum_variants(cx, id))
     } else {
         /*
           Although both this code and check_enum_variants in typeck/check
           call eval_const_expr, it should never get called twice for the same
           expr, since check_enum_variants also updates the enum_var_cache
          */
-        {
-            match cx.map.get(id.node) {
-              ast_map::NodeItem(item) => {
-                  match item.node {
+        match cx.map.get(id.node) {
+            ast_map::NodeItem(item) => {
+                match item.node {
                     ast::ItemEnum(ref enum_definition, _) => {
                         let mut last_discriminant: Option<Disr> = None;
-                        @enum_definition.variants.iter().map(|&variant| {
+                        Rc::new(enum_definition.variants.iter().map(|&variant| {
 
                             let mut discriminant = match last_discriminant {
                                 Some(val) => val + 1,
@@ -3860,40 +3847,33 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
                                     Ok(_) => {
                                         cx.sess
                                           .span_err(e.span,
-                                                    "expected signed integer \
-                                                     constant");
+                                                    "expected signed integer constant");
                                     }
                                     Err(ref err) => {
                                         cx.sess
                                           .span_err(e.span,
-                                                    format!("expected \
-                                                             constant: {}",
+                                                    format!("expected constant: {}",
                                                             *err));
                                     }
                                 },
                                 None => {}
                             };
 
-                            let variant_info =
-                                @VariantInfo::from_ast_variant(cx,
-                                                               variant,
-                                                               discriminant);
                             last_discriminant = Some(discriminant);
-                            variant_info
-
-                        }).collect()
+                            Rc::new(VariantInfo::from_ast_variant(cx, variant,
+                                                                  discriminant))
+                        }).collect())
                     }
                     _ => {
                         cx.sess.bug("enum_variants: id not bound to an enum")
                     }
-                  }
-              }
-              _ => cx.sess.bug("enum_variants: id not bound to an enum")
+                }
             }
+            _ => cx.sess.bug("enum_variants: id not bound to an enum")
         }
     };
 
-    cx.enum_var_cache.borrow_mut().insert(id, result);
+    cx.enum_var_cache.borrow_mut().insert(id, result.clone());
     result
 }
 
@@ -3902,17 +3882,11 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> @Vec<@VariantInfo> {
 pub fn enum_variant_with_id(cx: &ctxt,
                             enum_id: ast::DefId,
                             variant_id: ast::DefId)
-                         -> @VariantInfo {
-    let variants = enum_variants(cx, enum_id);
-    let mut i = 0;
-    while i < variants.len() {
-        let variant = *variants.get(i);
-        if variant.id == variant_id {
-            return variant
-        }
-        i += 1;
-    }
-    cx.sess.bug("enum_variant_with_id(): no variant exists with that ID");
+                         -> Rc<VariantInfo> {
+    enum_variants(cx, enum_id).iter()
+                              .find(|variant| variant.id == variant_id)
+                              .expect("enum_variant_with_id(): no variant exists with that ID")
+                              .clone()
 }
 
 
@@ -3935,19 +3909,19 @@ pub fn lookup_impl_vtables(cx: &ctxt,
 }
 
 /// Given the did of a trait, returns its canonical trait ref.
-pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> @ty::TraitDef {
+pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc<ty::TraitDef> {
     let mut trait_defs = cx.trait_defs.borrow_mut();
-    match trait_defs.find(&did) {
-        Some(&trait_def) => {
+    match trait_defs.find_copy(&did) {
+        Some(trait_def) => {
             // The item is in this crate. The caller should have added it to the
             // type cache already
-            return trait_def;
+            trait_def
         }
         None => {
             assert!(did.krate != ast::LOCAL_CRATE);
-            let trait_def = @csearch::get_trait_def(cx, did);
-            trait_defs.insert(did, trait_def);
-            return trait_def;
+            let trait_def = Rc::new(csearch::get_trait_def(cx, did));
+            trait_defs.insert(did, trait_def.clone());
+            trait_def
         }
     }
 }
@@ -3955,7 +3929,7 @@ pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> @ty::TraitDef {
 /// Iterate over meta_items of a definition.
 // (This should really be an iterator, but that would require csearch and
 // decoder to use iterators instead of higher-order functions.)
-pub fn each_attr(tcx: &ctxt, did: DefId, f: |@MetaItem| -> bool) -> bool {
+pub fn each_attr(tcx: &ctxt, did: DefId, f: |@ast::MetaItem| -> bool) -> bool {
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
         item.attrs.iter().advance(|attr| f(attr.node.value))
@@ -4029,20 +4003,21 @@ pub fn lookup_field_type(tcx: &ctxt,
 
 // Lookup all ancestor structs of a struct indicated by did. That is the reflexive,
 // transitive closure of doing a single lookup in cx.superstructs.
-fn lookup_super_structs(cx: &ctxt,
-                            did: ast::DefId) -> Vec<DefId> {
-    let mut this_result: Vec<DefId> = vec!(did);
-    match cx.superstructs.borrow().find(&did) {
-        Some(&Some(def_id)) => {
-            let ss: Vec<DefId> = lookup_super_structs(cx, def_id);
-            this_result.extend(ss.move_iter());
-            this_result
-        },
-        Some(&None) => this_result,
-        None => {
-            cx.sess.bug(
-                format!("ID not mapped to super-struct: {}",
-                    cx.map.node_to_str(did.node)));
+fn each_super_struct(cx: &ctxt, mut did: ast::DefId, f: |ast::DefId|) {
+    let superstructs = cx.superstructs.borrow();
+
+    loop {
+        f(did);
+        match superstructs.find(&did) {
+            Some(&Some(def_id)) => {
+                did = def_id;
+            },
+            Some(&None) => break,
+            None => {
+                cx.sess.bug(
+                    format!("ID not mapped to super-struct: {}",
+                        cx.map.node_to_str(did.node)));
+            }
         }
     }
 }
@@ -4055,26 +4030,22 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
         // we have to walk the inheritance chain of the struct to get all the
         // structs (explicit and inherited) for a struct. If this is expensive
         // we could cache the whole list of fields here.
-        let structs = lookup_super_structs(cx, did);
         let struct_fields = cx.struct_fields.borrow();
-        let results: Vec<&@Vec<field_ty>> = structs.iter().map(|s| {
-            match struct_fields.find(s) {
-                Some(fields) => fields,
+        let mut results: SmallVector<&[field_ty]> = SmallVector::zero();
+        each_super_struct(cx, did, |s| {
+            match struct_fields.find(&s) {
+                Some(fields) => results.push(fields.as_slice()),
                 _ => {
                     cx.sess.bug(
                         format!("ID not mapped to struct fields: {}",
                             cx.map.node_to_str(did.node)));
                 }
             }
-        }).collect();
+        });
 
-        let len = results.iter().map(|x| x.len()).fold(0, |a, b| a + b);
+        let len = results.as_slice().iter().map(|x| x.len()).sum();
         let mut result: Vec<field_ty> = Vec::with_capacity(len);
-        for rs in results.iter() {
-            for r in rs.iter() {
-                result.push(*r);
-            }
-        }
+        result.extend(results.as_slice().iter().flat_map(|rs| rs.iter().map(|&f| f)));
         assert!(result.len() == len);
         result
     } else {
@@ -4305,31 +4276,31 @@ pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::Expr) ->
 // relation on the supertraits from each bounded trait's constraint
 // list.
 pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
-                                        bounds: &[@TraitRef],
-                                        f: |@TraitRef| -> bool)
+                                        bounds: &[Rc<TraitRef>],
+                                        f: |Rc<TraitRef>| -> bool)
                                         -> bool {
-    for &bound_trait_ref in bounds.iter() {
+    for bound_trait_ref in bounds.iter() {
         let mut supertrait_set = HashMap::new();
         let mut trait_refs = Vec::new();
         let mut i = 0;
 
         // Seed the worklist with the trait from the bound
         supertrait_set.insert(bound_trait_ref.def_id, ());
-        trait_refs.push(bound_trait_ref);
+        trait_refs.push(bound_trait_ref.clone());
 
         // Add the given trait ty to the hash map
         while i < trait_refs.len() {
             debug!("each_bound_trait_and_supertraits(i={:?}, trait_ref={})",
                    i, trait_refs.get(i).repr(tcx));
 
-            if !f(*trait_refs.get(i)) {
+            if !f(trait_refs.get(i).clone()) {
                 return false;
             }
 
             // Add supertraits to supertrait_set
             let supertrait_refs = trait_ref_supertraits(tcx,
-                                                        *trait_refs.get(i));
-            for &supertrait_ref in supertrait_refs.iter() {
+                                                        &**trait_refs.get(i));
+            for supertrait_ref in supertrait_refs.iter() {
                 debug!("each_bound_trait_and_supertraits(supertrait_ref={})",
                        supertrait_ref.repr(tcx));
 
@@ -4337,7 +4308,7 @@ pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
                 if !supertrait_set.contains_key(&d_id) {
                     // FIXME(#5527) Could have same trait multiple times
                     supertrait_set.insert(d_id, ());
-                    trait_refs.push(supertrait_ref);
+                    trait_refs.push(supertrait_ref.clone());
                 }
             }
 
@@ -4362,7 +4333,7 @@ pub fn get_opaque_ty(tcx: &ctxt) -> Result<t, ~str> {
 }
 
 pub fn visitor_object_ty(tcx: &ctxt,
-                         region: ty::Region) -> Result<(@TraitRef, t), ~str> {
+                         region: ty::Region) -> Result<(Rc<TraitRef>, t), ~str> {
     let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
         Ok(id) => id,
         Err(s) => { return Err(s); }
@@ -4372,8 +4343,8 @@ pub fn visitor_object_ty(tcx: &ctxt,
         self_ty: None,
         tps: Vec::new()
     };
-    let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
-    Ok((trait_ref,
+    let trait_ref = Rc::new(TraitRef { def_id: trait_lang_item, substs: substs });
+    Ok((trait_ref.clone(),
         mk_trait(tcx,
                  trait_ref.def_id,
                  trait_ref.substs.clone(),
@@ -4381,29 +4352,24 @@ pub fn visitor_object_ty(tcx: &ctxt,
                  EmptyBuiltinBounds())))
 }
 
-pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> @ItemVariances {
+pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
     lookup_locally_or_in_crate_store(
         "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
-        || @csearch::get_item_variances(&tcx.sess.cstore, item_id))
+        || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
 }
 
 /// Records a trait-to-implementation mapping.
-fn record_trait_implementation(tcx: &ctxt,
-                               trait_def_id: DefId,
-                               implementation: @Impl) {
-    let implementation_list;
-    let mut trait_impls = tcx.trait_impls.borrow_mut();
-    match trait_impls.find(&trait_def_id) {
-        None => {
-            implementation_list = @RefCell::new(Vec::new());
-            trait_impls.insert(trait_def_id, implementation_list);
-        }
-        Some(&existing_implementation_list) => {
-            implementation_list = existing_implementation_list
+pub fn record_trait_implementation(tcx: &ctxt,
+                                   trait_def_id: DefId,
+                                   impl_def_id: DefId) {
+    match tcx.trait_impls.borrow().find(&trait_def_id) {
+        Some(impls_for_trait) => {
+            impls_for_trait.borrow_mut().push(impl_def_id);
+            return;
         }
+        None => {}
     }
-
-    implementation_list.borrow_mut().push(implementation);
+    tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
 }
 
 /// Populates the type context with all the implementations for the given type
@@ -4418,45 +4384,38 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
     }
 
     csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
-            |implementation_def_id| {
-        let implementation = @csearch::get_impl(tcx, implementation_def_id);
+            |impl_def_id| {
+        let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
 
         // Record the trait->implementation mappings, if applicable.
-        let associated_traits = csearch::get_impl_trait(tcx,
-                                                        implementation.did);
+        let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
         for trait_ref in associated_traits.iter() {
-            record_trait_implementation(tcx,
-                                        trait_ref.def_id,
-                                        implementation);
+            record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for method in implementation.methods.iter() {
-            for source in method.provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut()
-                   .insert(method.def_id, *source);
+        for &method_def_id in methods.iter() {
+            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
+                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
             }
         }
 
+        // Store the implementation info.
+        tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
+
         // If this is an inherent implementation, record it.
         if associated_traits.is_none() {
-            let implementation_list;
-            let mut inherent_impls = tcx.inherent_impls.borrow_mut();
-            match inherent_impls.find(&type_id) {
-                None => {
-                    implementation_list = @RefCell::new(Vec::new());
-                    inherent_impls.insert(type_id, implementation_list);
-                }
-                Some(&existing_implementation_list) => {
-                    implementation_list = existing_implementation_list;
+            match tcx.inherent_impls.borrow().find(&type_id) {
+                Some(implementation_list) => {
+                    implementation_list.borrow_mut().push(impl_def_id);
+                    return;
                 }
+                None => {}
             }
-            implementation_list.borrow_mut().push(implementation);
+            tcx.inherent_impls.borrow_mut().insert(type_id,
+                                                   Rc::new(RefCell::new(vec!(impl_def_id))));
         }
-
-        // Store the implementation info.
-        tcx.impls.borrow_mut().insert(implementation_def_id, implementation);
     });
 
     tcx.populated_external_types.borrow_mut().insert(type_id);
@@ -4476,22 +4435,21 @@ pub fn populate_implementations_for_trait_if_necessary(
 
     csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
             |implementation_def_id| {
-        let implementation = @csearch::get_impl(tcx, implementation_def_id);
+        let methods = csearch::get_impl_methods(&tcx.sess.cstore, implementation_def_id);
 
         // Record the trait->implementation mapping.
-        record_trait_implementation(tcx, trait_id, implementation);
+        record_trait_implementation(tcx, trait_id, implementation_def_id);
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for method in implementation.methods.iter() {
-            for source in method.provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut()
-                   .insert(method.def_id, *source);
+        for &method_def_id in methods.iter() {
+            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
+                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
             }
         }
 
         // Store the implementation info.
-        tcx.impls.borrow_mut().insert(implementation_def_id, implementation);
+        tcx.impl_methods.borrow_mut().insert(implementation_def_id, methods);
     });
 
     tcx.populated_external_traits.borrow_mut().insert(trait_id);
@@ -4526,7 +4484,7 @@ pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
     if def_id.krate != LOCAL_CRATE {
         return csearch::get_trait_of_method(&tcx.sess.cstore, def_id, tcx);
     }
-    match tcx.methods.borrow().find(&def_id).map(|m| *m) {
+    match tcx.methods.borrow().find_copy(&def_id) {
         Some(method) => {
             match method.container {
                 TraitContainer(def_id) => Some(def_id),
@@ -4546,7 +4504,7 @@ pub fn trait_of_method(tcx: &ctxt, def_id: ast::DefId)
 pub fn trait_method_of_method(tcx: &ctxt,
                               def_id: ast::DefId) -> Option<ast::DefId> {
     let method = match tcx.methods.borrow().find(&def_id) {
-        Some(&m) => m,
+        Some(m) => m.clone(),
         None => return None,
     };
     let name = method.ident.name;
@@ -4715,7 +4673,7 @@ impl Variance {
 
 pub fn construct_parameter_environment(
     tcx: &ctxt,
-    self_bound: Option<@TraitRef>,
+    self_bound: Option<Rc<TraitRef>>,
     item_type_params: &[TypeParameterDef],
     method_type_params: &[TypeParameterDef],
     item_region_params: &[RegionParameterDef],
@@ -4730,7 +4688,7 @@ pub fn construct_parameter_environment(
     //
 
     // map Self => Self
-    let self_ty = self_bound.map(|t| ty::mk_self(tcx, t.def_id));
+    let self_ty = self_bound.as_ref().map(|t| ty::mk_self(tcx, t.def_id));
 
     // map A => A
     let num_item_type_params = item_type_params.len();
diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs
index 5de2a60114a..6ae68bdbad1 100644
--- a/src/librustc/middle/typeck/astconv.rs
+++ b/src/librustc/middle/typeck/astconv.rs
@@ -60,6 +60,7 @@ use middle::typeck::rscope::{RegionScope};
 use middle::typeck::lookup_def_tcx;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
 use syntax::abi;
 use syntax::{ast, ast_util};
 use syntax::codemap::Span;
@@ -69,7 +70,7 @@ use syntax::print::pprust::{lifetime_to_str, path_to_str};
 pub trait AstConv {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt;
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty;
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef;
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef>;
 
     // what type should we use when a type is omitted?
     fn ty_infer(&self, span: Span) -> ty::t;
@@ -261,25 +262,16 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,
 }
 
 pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
-    this: &AC,
-    rscope: &RS,
-    trait_def_id: ast::DefId,
-    self_ty: Option<ty::t>,
-    path: &ast::Path) -> @ty::TraitRef
-{
-    let trait_def =
-        this.get_trait_def(trait_def_id);
-    let substs =
-        ast_path_substs(
-            this,
-            rscope,
-            &trait_def.generics,
-            self_ty,
-            path);
-    let trait_ref =
-        @ty::TraitRef {def_id: trait_def_id,
-                       substs: substs};
-    return trait_ref;
+        this: &AC,
+        rscope: &RS,
+        trait_def_id: ast::DefId,
+        self_ty: Option<ty::t>,
+        path: &ast::Path) -> Rc<ty::TraitRef> {
+    let trait_def = this.get_trait_def(trait_def_id);
+    Rc::new(ty::TraitRef {
+        def_id: trait_def_id,
+        substs: ast_path_substs(this, rscope, &trait_def.generics, self_ty, path)
+    })
 }
 
 pub fn ast_path_to_ty<AC:AstConv,RS:RegionScope>(
diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs
index 286c8d17751..9ceb3132509 100644
--- a/src/librustc/middle/typeck/check/_match.rs
+++ b/src/librustc/middle/typeck/check/_match.rs
@@ -40,7 +40,7 @@ pub fn check_match(fcx: &FnCtxt,
     for arm in arms.iter() {
         let mut pcx = pat_ctxt {
             fcx: fcx,
-            map: pat_id_map(tcx.def_map, *arm.pats.get(0)),
+            map: pat_id_map(&tcx.def_map, *arm.pats.get(0)),
         };
 
         for p in arm.pats.iter() { check_pat(&mut pcx, *p, discrim_ty);}
@@ -467,14 +467,14 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
         fcx.write_ty(pat.id, b_ty);
       }
       ast::PatEnum(..) |
-      ast::PatIdent(..) if pat_is_const(tcx.def_map, pat) => {
+      ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
         let const_did = ast_util::def_id_of_def(tcx.def_map.borrow()
                                                    .get_copy(&pat.id));
         let const_tpt = ty::lookup_item_type(tcx, const_did);
         demand::suptype(fcx, pat.span, expected, const_tpt.ty);
         fcx.write_ty(pat.id, const_tpt.ty);
       }
-      ast::PatIdent(bm, ref name, sub) if pat_is_binding(tcx.def_map, pat) => {
+      ast::PatIdent(bm, ref name, sub) if pat_is_binding(&tcx.def_map, pat) => {
         let typ = fcx.local_ty(pat.span, pat.id);
 
         match bm {
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 178d3c8b544..3b33a17d582 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -30,7 +30,7 @@ itself (note that inherent impls can only be defined in the same
 module as the type itself).
 
 Inherent candidates are not always derived from impls.  If you have a
-trait instance, such as a value of type `@ToStr`, then the trait
+trait instance, such as a value of type `~ToStr`, then the trait
 methods (`to_str()`, in this case) are inherently associated with it.
 Another case is type parameters, in which case the methods of their
 bounds are inherent.
@@ -97,7 +97,7 @@ use util::ppaux;
 use util::ppaux::Repr;
 
 use collections::HashSet;
-use std::result;
+use std::rc::Rc;
 use syntax::ast::{DefId, SelfValue, SelfRegion};
 use syntax::ast::{SelfUniq, SelfStatic};
 use syntax::ast::{MutMutable, MutImmutable};
@@ -203,7 +203,7 @@ pub fn lookup_in_trait<'a>(
 // to a trait and its supertraits.
 fn get_method_index(tcx: &ty::ctxt,
                     trait_ref: &TraitRef,
-                    subtrait: @TraitRef,
+                    subtrait: Rc<TraitRef>,
                     n_method: uint) -> uint {
     // We need to figure the "real index" of the method in a
     // listing of all the methods of an object. We do this by
@@ -311,7 +311,7 @@ struct LookupContext<'a> {
 struct Candidate {
     rcvr_match_condition: RcvrMatchCondition,
     rcvr_substs: ty::substs,
-    method_ty: @ty::Method,
+    method_ty: Rc<ty::Method>,
     origin: MethodOrigin,
 }
 
@@ -412,7 +412,7 @@ impl<'a> LookupContext<'a> {
          * `self.inherent_candidates`.  See comment at the start of
          * the file.  To find the inherent candidates, we repeatedly
          * deref the self-ty to find the "base-type".  So, for
-         * example, if the receiver is @@C where `C` is a struct type,
+         * example, if the receiver is ~~C where `C` is a struct type,
          * we'll want to find the inherent impls for `C`.
          */
 
@@ -468,9 +468,11 @@ impl<'a> LookupContext<'a> {
         ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
 
         // Look for explicit implementations.
+        let impl_methods = self.tcx().impl_methods.borrow();
         for impl_infos in self.tcx().trait_impls.borrow().find(&trait_did).iter() {
-            for impl_info in impl_infos.borrow().iter() {
-                self.push_candidates_from_impl(*impl_info, true);
+            for impl_did in impl_infos.borrow().iter() {
+                let methods = impl_methods.get(impl_did);
+                self.push_candidates_from_impl(*impl_did, methods.as_slice(), true);
             }
         }
     }
@@ -509,12 +511,15 @@ impl<'a> LookupContext<'a> {
             self_ty: Some(ty::mk_err()),
             ..(*substs).clone()
         };
-        let trait_ref = @TraitRef { def_id: did, substs: rcvr_substs.clone() };
+        let trait_ref = Rc::new(TraitRef {
+            def_id: did,
+            substs: rcvr_substs.clone()
+        });
 
-        self.push_inherent_candidates_from_bounds_inner(&[trait_ref],
+        self.push_inherent_candidates_from_bounds_inner(&[trait_ref.clone()],
             |new_trait_ref, m, method_num, _bound_num| {
-            let vtable_index = get_method_index(tcx, new_trait_ref,
-                                                trait_ref, method_num);
+            let vtable_index = get_method_index(tcx, &*new_trait_ref,
+                                                trait_ref.clone(), method_num);
             let mut m = (*m).clone();
             // We need to fix up the transformed self type.
             *m.fty.sig.inputs.get_mut(0) =
@@ -524,7 +529,7 @@ impl<'a> LookupContext<'a> {
             Some(Candidate {
                 rcvr_match_condition: RcvrMatchesIfObject(did),
                 rcvr_substs: new_trait_ref.substs.clone(),
-                method_ty: @m,
+                method_ty: Rc::new(m),
                 origin: MethodObject(MethodObject {
                         trait_id: new_trait_ref.def_id,
                         object_trait_id: did,
@@ -561,14 +566,14 @@ impl<'a> LookupContext<'a> {
         debug!("push_inherent_candidates_from_self()");
         self.push_inherent_candidates_from_bounds(
             rcvr_ty,
-            [self.fcx.inh.param_env.self_param_bound.unwrap()],
+            [self.fcx.inh.param_env.self_param_bound.clone().unwrap()],
             restrict_to,
             param_self)
     }
 
     fn push_inherent_candidates_from_bounds(&mut self,
                                             self_ty: ty::t,
-                                            bounds: &[@TraitRef],
+                                            bounds: &[Rc<TraitRef>],
                                             restrict_to: Option<DefId>,
                                             param: param_index) {
         self.push_inherent_candidates_from_bounds_inner(bounds,
@@ -598,9 +603,9 @@ impl<'a> LookupContext<'a> {
     // Do a search through a list of bounds, using a callback to actually
     // create the candidates.
     fn push_inherent_candidates_from_bounds_inner(&mut self,
-                                                  bounds: &[@TraitRef],
-                                                  mk_cand: |tr: @TraitRef,
-                                                            m: @ty::Method,
+                                                  bounds: &[Rc<TraitRef>],
+                                                  mk_cand: |tr: Rc<TraitRef>,
+                                                            m: Rc<ty::Method>,
                                                             method_num: uint,
                                                             bound_num: uint|
                                                             -> Option<Candidate>) {
@@ -616,7 +621,7 @@ impl<'a> LookupContext<'a> {
                 m.explicit_self != ast::SelfStatic &&
                 m.ident.name == self.m_name }) {
                 Some(pos) => {
-                    let method = *trait_methods.get(pos);
+                    let method = trait_methods.get(pos).clone();
 
                     match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
                         Some(cand) => {
@@ -643,40 +648,35 @@ impl<'a> LookupContext<'a> {
         // metadata if necessary.
         ty::populate_implementations_for_type_if_necessary(self.tcx(), did);
 
+        let impl_methods = self.tcx().impl_methods.borrow();
         for impl_infos in self.tcx().inherent_impls.borrow().find(&did).iter() {
-            for impl_info in impl_infos.borrow().iter() {
-                self.push_candidates_from_impl(*impl_info, false);
+            for impl_did in impl_infos.borrow().iter() {
+                let methods = impl_methods.get(impl_did);
+                self.push_candidates_from_impl(*impl_did, methods.as_slice(), false);
             }
         }
     }
 
     fn push_candidates_from_impl(&mut self,
-                                 impl_info: &ty::Impl,
+                                 impl_did: DefId,
+                                 impl_methods: &[DefId],
                                  is_extension: bool) {
-        if !self.impl_dups.insert(impl_info.did) {
+        if !self.impl_dups.insert(impl_did) {
             return; // already visited
         }
 
-        debug!("push_candidates_from_impl: {} {} {}",
+        debug!("push_candidates_from_impl: {} {}",
                token::get_name(self.m_name),
-               impl_info.ident.repr(self.tcx()),
-               impl_info.methods.iter()
-                                .map(|m| m.ident)
-                                .collect::<Vec<ast::Ident>>()
-                                .repr(self.tcx()));
-
-        let idx = {
-            match impl_info.methods
-                           .iter()
-                           .position(|m| m.ident.name == self.m_name) {
-                Some(idx) => idx,
-                None => { return; } // No method with the right name.
-            }
+               impl_methods.iter().map(|&did| ty::method(self.tcx(), did).ident)
+                                 .collect::<Vec<ast::Ident>>()
+                                 .repr(self.tcx()));
+
+        let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did))
+                                              .find(|m| m.ident.name == self.m_name) {
+            Some(method) => method,
+            None => { return; } // No method with the right name.
         };
 
-        let method = ty::method(self.tcx(),
-                                impl_info.methods.get(idx).def_id);
-
         // determine the `self` of the impl with fresh
         // variables for each parameter:
         let span = self.self_expr.map_or(self.span, |e| e.span);
@@ -684,7 +684,7 @@ impl<'a> LookupContext<'a> {
         let ty::ty_param_substs_and_ty {
             substs: impl_substs,
             ty: impl_ty
-        } = impl_self_ty(&vcx, span, impl_info.did);
+        } = impl_self_ty(&vcx, span, impl_did);
 
         let candidates = if is_extension {
             &mut self.extension_candidates
@@ -695,8 +695,8 @@ impl<'a> LookupContext<'a> {
         candidates.push(Candidate {
             rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
             rcvr_substs: impl_substs,
+            origin: MethodStatic(method.def_id),
             method_ty: method,
-            origin: MethodStatic(method.def_id)
         });
     }
 
@@ -715,7 +715,7 @@ impl<'a> LookupContext<'a> {
         // an explicit adjustment, but rather we hardwire the single deref
         // that occurs in trans and mem_categorization.
         let adjustment = match self.self_expr {
-            Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
+            Some(expr) => Some((expr.id, ty::AutoDerefRef(auto_deref_ref))),
             None => return None
         };
 
@@ -877,7 +877,7 @@ impl<'a> LookupContext<'a> {
             }
 
             ty_trait(~ty::TyTrait { def_id: trt_did, substs: trt_substs, bounds: b, .. }) => {
-                // Coerce ~/@/&Trait instances to &Trait.
+                // Coerce ~/&Trait instances to &Trait.
 
                 self.search_for_some_kind_of_autorefd_method(
                     AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
@@ -962,7 +962,7 @@ impl<'a> LookupContext<'a> {
                         Some(self_expr_id) => {
                             self.fcx.write_adjustment(
                                 self_expr_id,
-                                @ty::AutoDerefRef(ty::AutoDerefRef {
+                                ty::AutoDerefRef(ty::AutoDerefRef {
                                     autoderefs: autoderefs,
                                     autoref: Some(kind(region, *mutbl))
                                 }));
@@ -1187,8 +1187,8 @@ impl<'a> LookupContext<'a> {
         let span = self.self_expr.map_or(self.span, |e| e.span);
         match self.fcx.mk_subty(false, infer::Misc(span),
                                 rcvr_ty, transformed_self_ty) {
-            result::Ok(_) => {}
-            result::Err(_) => {
+            Ok(_) => {}
+            Err(_) => {
                 self.bug(format!("{} was a subtype of {} but now is not?",
                               self.ty_to_str(rcvr_ty),
                               self.ty_to_str(transformed_self_ty)));
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index fb470cbdfb1..dc5b4f6d520 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -117,7 +117,7 @@ use util::nodemap::{FnvHashMap, NodeMap};
 use std::cell::{Cell, RefCell};
 use collections::HashMap;
 use std::mem::replace;
-use std::result;
+use std::rc::Rc;
 use std::vec::Vec;
 use syntax::abi;
 use syntax::ast::{Provided, Required};
@@ -155,13 +155,13 @@ pub mod method;
 /// share the inherited fields.
 pub struct Inherited<'a> {
     infcx: infer::InferCtxt<'a>,
-    locals: @RefCell<NodeMap<ty::t>>,
+    locals: RefCell<NodeMap<ty::t>>,
     param_env: ty::ParameterEnvironment,
 
     // Temporary tables:
     node_types: RefCell<NodeMap<ty::t>>,
     node_type_substs: RefCell<NodeMap<ty::substs>>,
-    adjustments: RefCell<NodeMap<@ty::AutoAdjustment>>,
+    adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
     method_map: MethodMap,
     vtable_map: vtable_map,
     upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
@@ -238,7 +238,7 @@ pub struct FnCtxt<'a> {
     //
     // What we do in such cases is to generate a region variable with
     // `region_lb` as a lower bound.  The regionck pass then adds
-    // other constriants based on how the variable is used and region
+    // other constraints based on how the variable is used and region
     // inference selects the ultimate value.  Finally, borrowck is
     // charged with guaranteeing that the value whose address was taken
     // can actually be made to live as long as it needs to live.
@@ -260,13 +260,13 @@ impl<'a> Inherited<'a> {
            -> Inherited<'a> {
         Inherited {
             infcx: infer::new_infer_ctxt(tcx),
-            locals: @RefCell::new(NodeMap::new()),
+            locals: RefCell::new(NodeMap::new()),
             param_env: param_env,
             node_types: RefCell::new(NodeMap::new()),
             node_type_substs: RefCell::new(NodeMap::new()),
             adjustments: RefCell::new(NodeMap::new()),
-            method_map: @RefCell::new(FnvHashMap::new()),
-            vtable_map: @RefCell::new(FnvHashMap::new()),
+            method_map: RefCell::new(FnvHashMap::new()),
+            vtable_map: RefCell::new(FnvHashMap::new()),
             upvar_borrow_map: RefCell::new(HashMap::new()),
         }
     }
@@ -387,7 +387,7 @@ impl<'a> Visitor<()> for GatherLocalsVisitor<'a> {
     fn visit_pat(&mut self, p: &ast::Pat, _: ()) {
             match p.node {
               ast::PatIdent(_, ref path, _)
-                  if pat_util::pat_is_binding(self.fcx.ccx.tcx.def_map, p) => {
+                  if pat_util::pat_is_binding(&self.fcx.ccx.tcx.def_map, p) => {
                 self.assign(p.id, None);
                 debug!("Pattern binding {} is assigned to {}",
                        token::get_ident(path.segments.get(0).identifier),
@@ -469,7 +469,7 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
         // Add formal parameters.
         for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
             // Create type variables for each argument.
-            pat_util::pat_bindings(tcx.def_map,
+            pat_util::pat_bindings(&tcx.def_map,
                                    input.pat,
                                    |_bm, pat_id, _sp, _path| {
                                        visit.assign(pat_id, None);
@@ -478,7 +478,7 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>,
             // Check the pattern.
             let pcx = pat_ctxt {
                 fcx: &fcx,
-                map: pat_id_map(tcx.def_map, input.pat),
+                map: pat_id_map(&tcx.def_map, input.pat),
             };
             _match::check_pat(&pcx, input.pat, *arg_ty);
         }
@@ -622,9 +622,9 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
                                              it.span,
                                              &impl_tpt.generics,
                                              ast_trait_ref,
-                                             impl_trait_ref,
+                                             &*impl_trait_ref,
                                              ms.as_slice());
-                vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, impl_trait_ref);
+                vtable::resolve_impl(ccx.tcx, it, &impl_tpt.generics, &*impl_trait_ref);
             }
             None => { }
         }
@@ -640,7 +640,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
                 }
                 Provided(m) => {
                     check_method_body(ccx, &trait_def.generics,
-                                      Some(trait_def.trait_ref), m);
+                                      Some(trait_def.trait_ref.clone()), m);
                 }
             }
         }
@@ -682,7 +682,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
 
 fn check_method_body(ccx: &CrateCtxt,
                      item_generics: &ty::Generics,
-                     self_bound: Option<@ty::TraitRef>,
+                     self_bound: Option<Rc<ty::TraitRef>>,
                      method: &ast::Method) {
     /*!
      * Type checks a method body.
@@ -744,10 +744,10 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
             Some(trait_method_ty) => {
                 compare_impl_method(ccx.tcx,
                                     impl_generics,
-                                    impl_method_ty,
+                                    &*impl_method_ty,
                                     impl_method.span,
                                     impl_method.body.id,
-                                    *trait_method_ty,
+                                    &**trait_method_ty,
                                     &impl_trait_ref.substs);
             }
             None => {
@@ -800,7 +800,7 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt,
  */
 fn compare_impl_method(tcx: &ty::ctxt,
                        impl_generics: &ty::Generics,
-                       impl_m: @ty::Method,
+                       impl_m: &ty::Method,
                        impl_m_span: Span,
                        impl_m_body_id: ast::NodeId,
                        trait_m: &ty::Method,
@@ -973,8 +973,8 @@ fn compare_impl_method(tcx: &ty::ctxt,
 
     match infer::mk_subty(&infcx, false, infer::MethodCompatCheck(impl_m_span),
                           impl_fty, trait_fty) {
-        result::Ok(()) => {}
-        result::Err(ref terr) => {
+        Ok(()) => {}
+        Err(ref terr) => {
             tcx.sess.span_err(
                 impl_m_span,
                 format!("method `{}` has an incompatible type for trait: {}",
@@ -992,7 +992,7 @@ impl<'a> AstConv for FnCtxt<'a> {
         ty::lookup_item_type(self.tcx(), id)
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
         ty::lookup_trait_def(self.tcx(), id)
     }
 
@@ -1076,7 +1076,7 @@ impl<'a> FnCtxt<'a> {
         if derefs == 0 { return; }
         self.write_adjustment(
             node_id,
-            @ty::AutoDerefRef(ty::AutoDerefRef {
+            ty::AutoDerefRef(ty::AutoDerefRef {
                 autoderefs: derefs,
                 autoref: None })
         );
@@ -1084,7 +1084,7 @@ impl<'a> FnCtxt<'a> {
 
     pub fn write_adjustment(&self,
                             node_id: ast::NodeId,
-                            adj: @ty::AutoAdjustment) {
+                            adj: ty::AutoAdjustment) {
         debug!("write_adjustment(node_id={:?}, adj={:?})", node_id, adj);
         self.inh.adjustments.borrow_mut().insert(node_id, adj);
     }
@@ -1175,8 +1175,8 @@ impl<'a> FnCtxt<'a> {
                                  infer::ExprAssignable(expr.span),
                                  sub,
                                  sup) {
-            Ok(None) => result::Ok(()),
-            Err(ref e) => result::Err((*e)),
+            Ok(None) => Ok(()),
+            Err(ref e) => Err((*e)),
             Ok(Some(adjustment)) => {
                 self.write_adjustment(expr.id, adjustment);
                 Ok(())
@@ -2100,7 +2100,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                         op: ast::BinOp,
                         rhs: @ast::Expr) -> ty::t {
         let tcx = fcx.ccx.tcx;
-        let lang = tcx.lang_items;
+        let lang = &tcx.lang_items;
         let (name, trait_did) = match op {
             ast::BiAdd => ("add", lang.add_trait()),
             ast::BiSub => ("sub", lang.sub_trait()),
@@ -2182,7 +2182,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         let expected_sty = unpack_expected(fcx,
                                            expected,
                                            |x| Some((*x).clone()));
-        let error_happened = false;
         let (expected_sig,
              expected_onceness,
              expected_bounds) = {
@@ -2192,7 +2191,24 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                         replace_late_bound_regions_in_fn_sig(
                             tcx, &cenv.sig,
                             |_| fcx.inh.infcx.fresh_bound_region(expr.id));
-                    (Some(sig), cenv.onceness, cenv.bounds)
+                    let onceness = match (&store, &cenv.store) {
+                        // As the closure type and onceness go, only three
+                        // combinations are legit:
+                        //      once closure
+                        //      many closure
+                        //      once proc
+                        // If the actual and expected closure type disagree with
+                        // each other, set expected onceness to be always Once or
+                        // Many according to the actual type. Otherwise, it will
+                        // yield either an illegal "many proc" or a less known
+                        // "once closure" in the error message.
+                        (&ty::UniqTraitStore, &ty::UniqTraitStore) |
+                        (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
+                            cenv.onceness,
+                        (&ty::UniqTraitStore, _) => ast::Once,
+                        (&ty::RegionTraitStore(..), _) => ast::Many,
+                    };
+                    (Some(sig), onceness, cenv.bounds)
                 }
                 _ => {
                     // Not an error! Means we're inferring the closure type
@@ -2218,23 +2234,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                            store,
                                            decl,
                                            expected_sig);
-
-        let fty_sig;
-        let fty = if error_happened {
-            fty_sig = FnSig {
-                binder_id: ast::CRATE_NODE_ID,
-                inputs: fn_ty.sig.inputs.iter().map(|_| ty::mk_err()).collect(),
-                output: ty::mk_err(),
-                variadic: false
-            };
-            ty::mk_err()
-        } else {
-            fty_sig = fn_ty.sig.clone();
-            ty::mk_closure(tcx, fn_ty.clone())
-        };
-
-        debug!("check_expr_fn_with_unifier fty={}",
-               fcx.infcx().ty_to_str(fty));
+        let fty_sig = fn_ty.sig.clone();
+        let fty = ty::mk_closure(tcx, fn_ty);
+        debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty));
 
         fcx.write_ty(expr.id, fty);
 
@@ -2548,7 +2550,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
                                                              ty::mt {ty: t, mutbl: mutability},
                                                              None)), // Sadly, we know the length
                                                                      // - Some(args.len()) - but
-                                                                     // must thow it away or cause
+                                                                     // must throw it away or cause
                                                                      // confusion further down the
                                                                      // pipeline. Hopefully we can
                                                                      // remedy this later.
@@ -2688,7 +2690,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         demand::suptype(fcx, expr.span, result_t, lhs_t);
 
         let tcx = fcx.tcx();
-        if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) {
+        if !ty::expr_is_lval(tcx, lhs) {
             tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
         }
 
@@ -2844,8 +2846,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         match expr_opt {
           None => match fcx.mk_eqty(false, infer::Misc(expr.span),
                                     ret_ty, ty::mk_nil()) {
-            result::Ok(_) => { /* fall through */ }
-            result::Err(_) => {
+            Ok(_) => { /* fall through */ }
+            Err(_) => {
                 tcx.sess.span_err(
                     expr.span,
                     "`return;` in function returning non-nil");
@@ -2865,7 +2867,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
         check_expr_with_lvalue_pref(fcx, lhs, PreferMutLvalue);
 
         let tcx = fcx.tcx();
-        if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) {
+        if !ty::expr_is_lval(tcx, lhs) {
             tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
         }
 
@@ -3266,7 +3268,7 @@ pub fn check_decl_local(fcx: &FnCtxt, local: &ast::Local)  {
 
     let pcx = pat_ctxt {
         fcx: fcx,
-        map: pat_id_map(tcx.def_map, local.pat),
+        map: pat_id_map(&tcx.def_map, local.pat),
     };
     _match::check_pat(&pcx, local.pat, t);
     let pat_ty = fcx.node_ty(local.pat.id);
@@ -3541,10 +3543,10 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
                 vs: &[ast::P<ast::Variant>],
                 id: ast::NodeId,
                 hint: attr::ReprAttr)
-                -> Vec<@ty::VariantInfo> {
+                -> Vec<Rc<ty::VariantInfo>> {
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
-        let mut variants: Vec<@ty::VariantInfo> = Vec::new();
+        let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
         let mut disr_vals: Vec<ty::Disr> = Vec::new();
         let mut prev_disr_val: Option<ty::Disr> = None;
 
@@ -3600,7 +3602,8 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
             }
             disr_vals.push(current_disr_val);
 
-            let variant_info = @VariantInfo::from_ast_variant(ccx.tcx, v, current_disr_val);
+            let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, v,
+                                                                     current_disr_val));
             prev_disr_val = Some(current_disr_val);
 
             variants.push(variant_info);
@@ -3622,7 +3625,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
     let variants = do_check(ccx, vs, id, hint);
 
     // cache so that ty::enum_variants won't repeat this work
-    ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), @variants);
+    ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
 
     // Check that it is possible to represent this enum.
     check_representable(ccx.tcx, sp, id, "enum");
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index f6a4d972a07..94cbd3a3a75 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -131,6 +131,7 @@ use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
 use middle::typeck::MethodCall;
 use middle::pat_util;
+use util::nodemap::NodeMap;
 use util::ppaux::{ty_to_str, region_to_str, Repr};
 
 use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar};
@@ -140,6 +141,8 @@ use syntax::codemap::Span;
 use syntax::visit;
 use syntax::visit::Visitor;
 
+use std::cell::RefCell;
+
 // If mem categorization results in an error, it's because the type
 // check failed (or will fail, when the error is uncovered and
 // reported during writeback). In this case, we just ignore this part
@@ -155,7 +158,6 @@ macro_rules! ignore_err(
 
 pub struct Rcx<'a> {
     fcx: &'a FnCtxt<'a>,
-    errors_reported: uint,
 
     // id of innermost fn or loop
     repeating_scope: ast::NodeId,
@@ -234,7 +236,7 @@ impl<'a> Rcx<'a> {
     }
 
     /// Try to resolve the type for the given node.
-    fn resolve_node_type(&mut self, id: ast::NodeId) -> ty::t {
+    fn resolve_node_type(&self, id: ast::NodeId) -> ty::t {
         let t = self.fcx.node_ty(id);
         self.resolve_type(t)
     }
@@ -252,19 +254,19 @@ impl<'a> Rcx<'a> {
             ty_unadjusted
         } else {
             let tcx = self.fcx.tcx();
-            let adjustment = self.fcx.inh.adjustments.borrow().find_copy(&expr.id);
-            ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted, adjustment,
+            ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
+                          self.fcx.inh.adjustments.borrow().find(&expr.id),
                           |method_call| self.resolve_method_type(method_call))
         }
     }
 }
 
-impl<'a, 'b> mc::Typer for &'a mut Rcx<'b> {
+impl<'a, 'b> mc::Typer for &'a Rcx<'b> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
         self.fcx.tcx()
     }
 
-    fn node_ty(&mut self, id: ast::NodeId) -> mc::McResult<ty::t> {
+    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<ty::t> {
         let t = self.resolve_node_type(id);
         if ty::type_is_error(t) {Err(())} else {Ok(t)}
     }
@@ -273,26 +275,25 @@ impl<'a, 'b> mc::Typer for &'a mut Rcx<'b> {
         self.resolve_method_type(method_call)
     }
 
-    fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
-        self.fcx.inh.adjustments.borrow().find_copy(&id)
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+        &self.fcx.inh.adjustments
     }
 
-    fn is_method_call(&mut self, id: ast::NodeId) -> bool {
+    fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
     }
 
-    fn temporary_scope(&mut self, id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, id: ast::NodeId) -> Option<ast::NodeId> {
         self.tcx().region_maps.temporary_scope(id)
     }
 
-    fn upvar_borrow(&mut self, id: ty::UpvarId) -> ty::UpvarBorrow {
+    fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
         self.fcx.inh.upvar_borrow_map.borrow().get_copy(&id)
     }
 }
 
 pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
-    let mut rcx = Rcx { fcx: fcx, errors_reported: 0,
-                         repeating_scope: e.id };
+    let mut rcx = Rcx { fcx: fcx, repeating_scope: e.id };
     let rcx = &mut rcx;
     if fcx.err_count_since_creation() == 0 {
         // regionck assumes typeck succeeded
@@ -302,8 +303,7 @@ pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
 }
 
 pub fn regionck_fn(fcx: &FnCtxt, blk: &ast::Block) {
-    let mut rcx = Rcx { fcx: fcx, errors_reported: 0,
-                         repeating_scope: blk.id };
+    let mut rcx = Rcx { fcx: fcx, repeating_scope: blk.id };
     let rcx = &mut rcx;
     if fcx.err_count_since_creation() == 0 {
         // regionck assumes typeck succeeded
@@ -361,7 +361,7 @@ fn visit_local(rcx: &mut Rcx, l: &ast::Local) {
 fn constrain_bindings_in_pat(pat: &ast::Pat, rcx: &mut Rcx) {
     let tcx = rcx.fcx.tcx();
     debug!("regionck::visit_pat(pat={})", pat.repr(tcx));
-    pat_util::pat_bindings(tcx.def_map, pat, |_, id, span, _| {
+    pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
         // If we have a variable that contains region'd data, that
         // data will be accessible from anywhere that the variable is
         // accessed. We must be wary of loops like this:
@@ -402,7 +402,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
     // Check any autoderefs or autorefs that appear.
     for &adjustment in rcx.fcx.inh.adjustments.borrow().find(&expr.id).iter() {
         debug!("adjustment={:?}", adjustment);
-        match **adjustment {
+        match *adjustment {
             ty::AutoDerefRef(ty::AutoDerefRef {autoderefs, autoref: opt_autoref}) => {
                 let expr_ty = rcx.resolve_node_type(expr.id);
                 constrain_autoderefs(rcx, expr, autoderefs, expr_ty);
@@ -611,20 +611,21 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     match ty::get(function_type).sty {
         ty::ty_closure(~ty::ClosureTy {
                 store: ty::RegionTraitStore(region, _), ..}) => {
-            let freevars = freevars::get_freevars(tcx, expr.id);
-            if freevars.is_empty() {
-                // No free variables means that the environment
-                // will be NULL at runtime and hence the closure
-                // has static lifetime.
-            } else {
-                // Closure must not outlive the variables it closes over.
-                constrain_free_variables(rcx, region, expr, freevars);
-
-                // Closure cannot outlive the appropriate temporary scope.
-                let s = rcx.repeating_scope;
-                rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
-                                region, ty::ReScope(s));
-            }
+            freevars::with_freevars(tcx, expr.id, |freevars| {
+                if freevars.is_empty() {
+                    // No free variables means that the environment
+                    // will be NULL at runtime and hence the closure
+                    // has static lifetime.
+                } else {
+                    // Closure must not outlive the variables it closes over.
+                    constrain_free_variables(rcx, region, expr, freevars);
+
+                    // Closure cannot outlive the appropriate temporary scope.
+                    let s = rcx.repeating_scope;
+                    rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span),
+                                    region, ty::ReScope(s));
+                }
+            });
         }
         _ => ()
     }
@@ -635,8 +636,9 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 
     match ty::get(function_type).sty {
         ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
-            let freevars = freevars::get_freevars(tcx, expr.id);
-            propagate_upupvar_borrow_kind(rcx, expr, freevars);
+            freevars::with_freevars(tcx, expr.id, |freevars| {
+                propagate_upupvar_borrow_kind(rcx, expr, freevars);
+            });
         }
         _ => ()
     }
@@ -644,7 +646,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
     fn constrain_free_variables(rcx: &mut Rcx,
                                 region: ty::Region,
                                 expr: &ast::Expr,
-                                freevars: freevars::freevar_info) {
+                                freevars: &[freevars::freevar_entry]) {
         /*!
          * Make sure that all free variables referenced inside the closure
          * outlive the closure itself. Also, create an entry in the
@@ -690,7 +692,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
 
     fn propagate_upupvar_borrow_kind(rcx: &mut Rcx,
                                      expr: &ast::Expr,
-                                     freevars: freevars::freevar_info) {
+                                     freevars: &[freevars::freevar_entry]) {
         let tcx = rcx.fcx.ccx.tcx;
         debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx));
         for freevar in freevars.iter() {
@@ -870,7 +872,7 @@ fn constrain_autoderefs(rcx: &mut Rcx,
                                 method.ty.repr(rcx.tcx())))
                 };
                 {
-                    let mut mc = mc::MemCategorizationContext { typer: &mut *rcx };
+                    let mc = mc::MemCategorizationContext { typer: &*rcx };
                     let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
                     link_region(mc.typer, deref_expr.span, r, m, self_cmt);
                 }
@@ -948,8 +950,7 @@ fn constrain_regions_in_type_of_node(
     rcx: &mut Rcx,
     id: ast::NodeId,
     minimum_lifetime: ty::Region,
-    origin: infer::SubregionOrigin) -> bool
-{
+    origin: infer::SubregionOrigin) {
     //! Guarantees that any lifetimes which appear in the type of
     //! the node `id` (after applying adjustments) are valid for at
     //! least `minimum_lifetime`
@@ -960,22 +961,21 @@ fn constrain_regions_in_type_of_node(
     // is going to fail anyway, so just stop here and let typeck
     // report errors later on in the writeback phase.
     let ty0 = rcx.resolve_node_type(id);
-    let adjustment = rcx.fcx.inh.adjustments.borrow().find_copy(&id);
-    let ty = ty::adjust_ty(tcx, origin.span(), id, ty0, adjustment,
+    let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
+                           rcx.fcx.inh.adjustments.borrow().find(&id),
                            |method_call| rcx.resolve_method_type(method_call));
     debug!("constrain_regions_in_type_of_node(\
-            ty={}, ty0={}, id={}, minimum_lifetime={:?}, adjustment={:?})",
+            ty={}, ty0={}, id={}, minimum_lifetime={:?})",
            ty_to_str(tcx, ty), ty_to_str(tcx, ty0),
-           id, minimum_lifetime, adjustment);
-    constrain_regions_in_type(rcx, minimum_lifetime, origin, ty)
+           id, minimum_lifetime);
+    constrain_regions_in_type(rcx, minimum_lifetime, origin, ty);
 }
 
 fn constrain_regions_in_type(
     rcx: &mut Rcx,
     minimum_lifetime: ty::Region,
     origin: infer::SubregionOrigin,
-    ty: ty::t) -> bool
-{
+    ty: ty::t) {
     /*!
      * Requires that any regions which appear in `ty` must be
      * superregions of `minimum_lifetime`.  Also enforces the constraint
@@ -990,7 +990,6 @@ fn constrain_regions_in_type(
      * code that R corresponds to."
      */
 
-    let e = rcx.errors_reported;
     let tcx = rcx.fcx.ccx.tcx;
 
     debug!("constrain_regions_in_type(minimum_lifetime={}, ty={})",
@@ -1009,7 +1008,7 @@ fn constrain_regions_in_type(
             // for regions that are as-yet-unknown.
         } else if r_sub == minimum_lifetime {
             rcx.fcx.mk_subr(
-                true, origin,
+                true, origin.clone(),
                 r_sub, r_sup);
         } else {
             rcx.fcx.mk_subr(
@@ -1017,8 +1016,6 @@ fn constrain_regions_in_type(
                 r_sub, r_sup);
         }
     });
-
-    return e == rcx.errors_reported;
 }
 
 fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
@@ -1032,13 +1029,13 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
     debug!("link_addr_of(base=?)");
 
     let cmt = {
-        let mut mc = mc::MemCategorizationContext { typer: &mut *rcx };
+        let mc = mc::MemCategorizationContext { typer: &*rcx };
         ignore_err!(mc.cat_expr(base))
     };
     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
 }
 
-fn link_local(rcx: &mut Rcx, local: &ast::Local) {
+fn link_local(rcx: &Rcx, local: &ast::Local) {
     /*!
      * Computes the guarantors for any ref bindings in a `let` and
      * then ensures that the lifetime of the resulting pointer is
@@ -1050,12 +1047,12 @@ fn link_local(rcx: &mut Rcx, local: &ast::Local) {
         None => { return; }
         Some(expr) => expr,
     };
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
-    link_pattern(&mut mc, discr_cmt, local.pat);
+    link_pattern(mc, discr_cmt, local.pat);
 }
 
-fn link_match(rcx: &mut Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
+fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
     /*!
      * Computes the guarantors for any ref bindings in a match and
      * then ensures that the lifetime of the resulting pointer is
@@ -1063,19 +1060,19 @@ fn link_match(rcx: &mut Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
      */
 
     debug!("regionck::for_match()");
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let discr_cmt = ignore_err!(mc.cat_expr(discr));
     debug!("discr_cmt={}", discr_cmt.repr(mc.typer.tcx()));
     for arm in arms.iter() {
         for &root_pat in arm.pats.iter() {
-            link_pattern(&mut mc, discr_cmt, root_pat);
+            link_pattern(mc, discr_cmt.clone(), root_pat);
         }
     }
 }
 
-fn link_pattern(mc: &mut mc::MemCategorizationContext<&mut Rcx>,
+fn link_pattern(mc: mc::MemCategorizationContext<&Rcx>,
                 discr_cmt: mc::cmt,
-                root_pat: @ast::Pat) {
+                root_pat: &ast::Pat) {
     /*!
      * Link lifetimes of any ref bindings in `root_pat` to
      * the pointers found in the discriminant, if needed.
@@ -1105,7 +1102,7 @@ fn link_pattern(mc: &mut mc::MemCategorizationContext<&mut Rcx>,
         });
 }
 
-fn link_autoref(rcx: &mut Rcx,
+fn link_autoref(rcx: &Rcx,
                 expr: &ast::Expr,
                 autoderefs: uint,
                 autoref: &ty::AutoRef) {
@@ -1115,7 +1112,7 @@ fn link_autoref(rcx: &mut Rcx,
      */
 
     debug!("link_autoref(autoref={:?})", autoref);
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
     debug!("expr_cmt={}", expr_cmt.repr(mc.typer.tcx()));
 
@@ -1138,7 +1135,7 @@ fn link_autoref(rcx: &mut Rcx,
     }
 }
 
-fn link_by_ref(rcx: &mut Rcx,
+fn link_by_ref(rcx: &Rcx,
                expr: &ast::Expr,
                callee_scope: ast::NodeId) {
     /*!
@@ -1150,13 +1147,13 @@ fn link_by_ref(rcx: &mut Rcx,
     let tcx = rcx.tcx();
     debug!("link_by_ref(expr={}, callee_scope={})",
            expr.repr(tcx), callee_scope);
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let expr_cmt = ignore_err!(mc.cat_expr(expr));
     let region_min = ty::ReScope(callee_scope);
     link_region(mc.typer, expr.span, region_min, ast::MutImmutable, expr_cmt);
 }
 
-fn link_region_from_node_type(rcx: &mut Rcx,
+fn link_region_from_node_type(rcx: &Rcx,
                               span: Span,
                               id: ast::NodeId,
                               mutbl: ast::Mutability,
@@ -1176,7 +1173,7 @@ fn link_region_from_node_type(rcx: &mut Rcx,
     }
 }
 
-fn link_region(rcx: &mut Rcx,
+fn link_region(rcx: &Rcx,
                span: Span,
                region_min: ty::Region,
                mutbl: ast::Mutability,
@@ -1197,7 +1194,7 @@ fn link_region(rcx: &mut Rcx,
                region_min.repr(rcx.tcx()),
                mutbl.repr(rcx.tcx()),
                cmt_borrowed.repr(rcx.tcx()));
-        match cmt_borrowed.cat {
+        match cmt_borrowed.cat.clone() {
             mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => {
                 // References to an upvar `x` are translated to
                 // `*x`, since that is what happens in the
@@ -1287,7 +1284,7 @@ fn link_region(rcx: &mut Rcx,
     }
 }
 
-fn adjust_borrow_kind_for_assignment_lhs(rcx: &mut Rcx,
+fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
                                          lhs: &ast::Expr) {
     /*!
      * Adjusts the inferred borrow_kind as needed to account
@@ -1295,19 +1292,19 @@ fn adjust_borrow_kind_for_assignment_lhs(rcx: &mut Rcx,
      * expression.
      */
 
-    let mut mc = mc::MemCategorizationContext { typer: rcx };
+    let mc = mc::MemCategorizationContext { typer: rcx };
     let cmt = ignore_err!(mc.cat_expr(lhs));
     adjust_upvar_borrow_kind_for_mut(mc.typer, cmt);
 }
 
-fn adjust_upvar_borrow_kind_for_mut(rcx: &mut Rcx,
+fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx,
                                     cmt: mc::cmt) {
     let mut cmt = cmt;
     loop {
         debug!("adjust_upvar_borrow_kind_for_mut(cmt={})",
                cmt.repr(rcx.tcx()));
 
-        match cmt.cat {
+        match cmt.cat.clone() {
             mc::cat_deref(base, _, mc::OwnedPtr) |
             mc::cat_interior(base, _) |
             mc::cat_downcast(base) |
@@ -1331,14 +1328,14 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &mut Rcx,
                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow);
                     }
 
-                    _ => {
-                        // assignment to deref of an `&mut`
-                        // borrowed pointer implies that the
-                        // pointer itself must be unique, but not
-                        // necessarily *mutable*
-                        return adjust_upvar_borrow_kind_for_unique(rcx, base);
-                    }
+                    _ => {}
                 }
+
+                // assignment to deref of an `&mut`
+                // borrowed pointer implies that the
+                // pointer itself must be unique, but not
+                // necessarily *mutable*
+                return adjust_upvar_borrow_kind_for_unique(rcx, base);
             }
 
             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
@@ -1355,14 +1352,13 @@ fn adjust_upvar_borrow_kind_for_mut(rcx: &mut Rcx,
     }
 }
 
-fn adjust_upvar_borrow_kind_for_unique(rcx: &mut Rcx,
-                                       cmt: mc::cmt) {
+fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) {
     let mut cmt = cmt;
     loop {
         debug!("adjust_upvar_borrow_kind_for_unique(cmt={})",
                cmt.repr(rcx.tcx()));
 
-        match cmt.cat {
+        match cmt.cat.clone() {
             mc::cat_deref(base, _, mc::OwnedPtr) |
             mc::cat_interior(base, _) |
             mc::cat_downcast(base) |
@@ -1385,12 +1381,12 @@ fn adjust_upvar_borrow_kind_for_unique(rcx: &mut Rcx,
                         return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow);
                     }
 
-                    _ => {
-                        // for a borrowed pointer to be unique, its
-                        // base must be unique
-                        return adjust_upvar_borrow_kind_for_unique(rcx, base);
-                    }
+                    _ => {}
                 }
+
+                // for a borrowed pointer to be unique, its
+                // base must be unique
+                return adjust_upvar_borrow_kind_for_unique(rcx, base);
             }
 
             mc::cat_deref(_, _, mc::UnsafePtr(..)) |
diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs
index 3f50a64e630..bb57fa2646b 100644
--- a/src/librustc/middle/typeck/check/vtable.rs
+++ b/src/librustc/middle/typeck/check/vtable.rs
@@ -27,9 +27,8 @@ use util::common::indenter;
 use util::ppaux;
 use util::ppaux::Repr;
 
+use std::rc::Rc;
 use collections::HashSet;
-use std::cell::RefCell;
-use std::result;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::codemap::Span;
@@ -112,7 +111,7 @@ fn lookup_vtables(vcx: &VtableContext,
            type_param_defs.repr(vcx.tcx()),
            substs.repr(vcx.tcx()),
            result.repr(vcx.tcx()));
-    @result
+    result
 }
 
 fn lookup_vtables_for_param(vcx: &VtableContext,
@@ -139,7 +138,7 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
 
         // Substitute the values of the type parameters that may
         // appear in the bound.
-        let trait_ref = substs.as_ref().map_or(trait_ref, |substs| {
+        let trait_ref = substs.as_ref().map_or(trait_ref.clone(), |substs| {
             debug!("about to subst: {}, {}",
                    trait_ref.repr(tcx), substs.repr(tcx));
             trait_ref.subst(tcx, *substs)
@@ -147,13 +146,13 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
 
         debug!("after subst: {}", trait_ref.repr(tcx));
 
-        match lookup_vtable(vcx, span, ty, trait_ref, is_early) {
+        match lookup_vtable(vcx, span, ty, trait_ref.clone(), is_early) {
             Some(vtable) => param_result.push(vtable),
             None => {
                 vcx.tcx().sess.span_fatal(span,
                     format!("failed to find an implementation of \
                           trait {} for {}",
-                         vcx.infcx.trait_ref_to_str(trait_ref),
+                         vcx.infcx.trait_ref_to_str(&*trait_ref),
                          vcx.infcx.ty_to_str(ty)));
             }
         }
@@ -170,13 +169,13 @@ fn lookup_vtables_for_param(vcx: &VtableContext,
            ty.repr(vcx.tcx()),
            param_result.repr(vcx.tcx()));
 
-    return @param_result;
+    param_result
 }
 
 fn relate_trait_refs(vcx: &VtableContext,
                      span: Span,
-                     act_trait_ref: @ty::TraitRef,
-                     exp_trait_ref: @ty::TraitRef) {
+                     act_trait_ref: Rc<ty::TraitRef>,
+                     exp_trait_ref: Rc<ty::TraitRef>) {
     /*!
      *
      * Checks that an implementation of `act_trait_ref` is suitable
@@ -187,17 +186,17 @@ fn relate_trait_refs(vcx: &VtableContext,
     match infer::mk_sub_trait_refs(vcx.infcx,
                                    false,
                                    infer::RelateTraitRefs(span),
-                                   act_trait_ref,
-                                   exp_trait_ref) {
-        result::Ok(()) => {} // Ok.
-        result::Err(ref err) => {
+                                   act_trait_ref.clone(),
+                                   exp_trait_ref.clone()) {
+        Ok(()) => {} // Ok.
+        Err(ref err) => {
             // There is an error, but we need to do some work to make
             // the message good.
             // Resolve any type vars in the trait refs
             let r_act_trait_ref =
-                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(act_trait_ref);
+                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(&*act_trait_ref);
             let r_exp_trait_ref =
-                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(exp_trait_ref);
+                vcx.infcx.resolve_type_vars_in_trait_ref_if_possible(&*exp_trait_ref);
             // Only print the message if there aren't any previous type errors
             // inside the types.
             if !ty::trait_ref_contains_error(&r_act_trait_ref) &&
@@ -218,12 +217,12 @@ fn relate_trait_refs(vcx: &VtableContext,
 fn lookup_vtable(vcx: &VtableContext,
                  span: Span,
                  ty: ty::t,
-                 trait_ref: @ty::TraitRef,
+                 trait_ref: Rc<ty::TraitRef>,
                  is_early: bool)
                  -> Option<vtable_origin> {
     debug!("lookup_vtable(ty={}, trait_ref={})",
            vcx.infcx.ty_to_str(ty),
-           vcx.infcx.trait_ref_to_str(trait_ref));
+           vcx.infcx.trait_ref_to_str(&*trait_ref));
     let _i = indenter();
 
     let ty = match fixup_ty(vcx, span, ty, is_early) {
@@ -244,23 +243,23 @@ fn lookup_vtable(vcx: &VtableContext,
         ty::ty_param(param_ty {idx: n, ..}) => {
             let env_bounds = &vcx.param_env.type_param_bounds;
             if env_bounds.len() > n {
-                let type_param_bounds: &[@ty::TraitRef] =
+                let type_param_bounds: &[Rc<ty::TraitRef>] =
                     env_bounds.get(n).trait_bounds.as_slice();
                 lookup_vtable_from_bounds(vcx, span,
                                           type_param_bounds,
                                           param_numbered(n),
-                                          trait_ref)
+                                          trait_ref.clone())
             } else {
                 None
             }
         }
 
         ty::ty_self(_) => {
-            let self_param_bound = vcx.param_env.self_param_bound.unwrap();
+            let self_param_bound = vcx.param_env.self_param_bound.clone().unwrap();
             lookup_vtable_from_bounds(vcx, span,
                                       [self_param_bound],
                                       param_self,
-                                      trait_ref)
+                                      trait_ref.clone())
         }
 
         // Default case just falls through
@@ -278,9 +277,9 @@ fn lookup_vtable(vcx: &VtableContext,
 // of them are the vtable we are looking for.
 fn lookup_vtable_from_bounds(vcx: &VtableContext,
                              span: Span,
-                             bounds: &[@ty::TraitRef],
+                             bounds: &[Rc<ty::TraitRef>],
                              param: param_index,
-                             trait_ref: @ty::TraitRef)
+                             trait_ref: Rc<ty::TraitRef>)
                              -> Option<vtable_origin> {
     let tcx = vcx.tcx();
 
@@ -291,7 +290,7 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext,
                bound_trait_ref.repr(vcx.tcx()));
 
         if bound_trait_ref.def_id == trait_ref.def_id {
-            relate_trait_refs(vcx, span, bound_trait_ref, trait_ref);
+            relate_trait_refs(vcx, span, bound_trait_ref, trait_ref.clone());
             let vtable = vtable_param(param, n_bound);
             debug!("found param vtable: {:?}",
                    vtable);
@@ -308,7 +307,7 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext,
 fn search_for_vtable(vcx: &VtableContext,
                      span: Span,
                      ty: ty::t,
-                     trait_ref: @ty::TraitRef,
+                     trait_ref: Rc<ty::TraitRef>,
                      is_early: bool)
                      -> Option<vtable_origin> {
     let tcx = vcx.tcx();
@@ -320,26 +319,28 @@ fn search_for_vtable(vcx: &VtableContext,
     ty::populate_implementations_for_trait_if_necessary(tcx,
                                                         trait_ref.def_id);
 
-    // FIXME: this is a bad way to do this, since we do
-    // pointless allocations.
-    let impls = tcx.trait_impls.borrow().find(&trait_ref.def_id)
-                               .map_or(@RefCell::new(Vec::new()), |x| *x);
+    let impls = match tcx.trait_impls.borrow().find_copy(&trait_ref.def_id) {
+        Some(impls) => impls,
+        None => {
+            return None;
+        }
+    };
     // impls is the list of all impls in scope for trait_ref.
-    for im in impls.borrow().iter() {
+    for &impl_did in impls.borrow().iter() {
         // im is one specific impl of trait_ref.
 
         // First, ensure we haven't processed this impl yet.
-        if impls_seen.contains(&im.did) {
+        if impls_seen.contains(&impl_did) {
             continue;
         }
-        impls_seen.insert(im.did);
+        impls_seen.insert(impl_did);
 
         // ty::impl_traits gives us the trait im implements.
         //
         // If foo implements a trait t, and if t is the same trait as
         // trait_ref, we need to unify it with trait_ref in order to
         // get all the ty vars sorted out.
-        let r = ty::impl_trait_ref(tcx, im.did);
+        let r = ty::impl_trait_ref(tcx, impl_did);
         let of_trait_ref = r.expect("trait_ref missing on trait impl");
         if of_trait_ref.def_id != trait_ref.def_id { continue; }
 
@@ -362,14 +363,14 @@ fn search_for_vtable(vcx: &VtableContext,
         let ty::ty_param_substs_and_ty {
             substs: substs,
             ty: for_ty
-        } = impl_self_ty(vcx, span, im.did);
+        } = impl_self_ty(vcx, span, impl_did);
         match infer::mk_subty(vcx.infcx,
                               false,
                               infer::RelateSelfType(span),
                               ty,
                               for_ty) {
-            result::Err(_) => continue,
-            result::Ok(()) => ()
+            Err(_) => continue,
+            Ok(()) => ()
         }
 
         // Now, in the previous example, for_ty is bound to
@@ -388,13 +389,13 @@ fn search_for_vtable(vcx: &VtableContext,
         // some value of U) with some_trait<T>. This would fail if T
         // and U weren't compatible.
 
-        debug!("(checking vtable) @2 relating trait \
+        debug!("(checking vtable) \\#2 relating trait \
                 ty {} to of_trait_ref {}",
-               vcx.infcx.trait_ref_to_str(trait_ref),
-               vcx.infcx.trait_ref_to_str(of_trait_ref));
+               vcx.infcx.trait_ref_to_str(&*trait_ref),
+               vcx.infcx.trait_ref_to_str(&*of_trait_ref));
 
         let of_trait_ref = of_trait_ref.subst(tcx, &substs);
-        relate_trait_refs(vcx, span, of_trait_ref, trait_ref);
+        relate_trait_refs(vcx, span, of_trait_ref, trait_ref.clone());
 
 
         // Recall that trait_ref -- the trait type we're casting to --
@@ -405,7 +406,7 @@ fn search_for_vtable(vcx: &VtableContext,
         // type variables in substs. This might still be OK: the
         // process of looking up bounds might constrain some of them.
         let im_generics =
-            ty::lookup_item_type(tcx, im.did).generics;
+            ty::lookup_item_type(tcx, impl_did).generics;
         let subres = lookup_vtables(vcx, span,
                                     im_generics.type_param_defs(), &substs,
                                     is_early);
@@ -429,7 +430,7 @@ fn search_for_vtable(vcx: &VtableContext,
                 they will be unified with the bounds for \
                 the target ty, {}",
                vcx.infcx.tys_to_str(substs_f.tps.as_slice()),
-               vcx.infcx.trait_ref_to_str(trait_ref));
+               vcx.infcx.trait_ref_to_str(&*trait_ref));
 
         // Next, we unify the fixed-up substitutions for the impl self
         // ty with the substitutions from the trait type that we're
@@ -438,12 +439,12 @@ fn search_for_vtable(vcx: &VtableContext,
         // I am a little confused about this, since it seems to be
         // very similar to the relate_trait_refs we already do,
         // but problems crop up if it is removed, so... -sully
-        connect_trait_tps(vcx, span, &substs_f, trait_ref, im.did);
+        connect_trait_tps(vcx, span, &substs_f, trait_ref.clone(), impl_did);
 
         // Finally, we register that we found a matching impl, and
         // record the def ID of the impl as well as the resolved list
         // of type substitutions for the target trait.
-        found.push(vtable_static(im.did, substs_f.tps.clone(), subres));
+        found.push(vtable_static(impl_did, substs_f.tps.clone(), subres));
     }
 
     match found.len() {
@@ -502,7 +503,7 @@ fn fixup_ty(vcx: &VtableContext,
 fn connect_trait_tps(vcx: &VtableContext,
                      span: Span,
                      impl_substs: &ty::substs,
-                     trait_ref: @ty::TraitRef,
+                     trait_ref: Rc<ty::TraitRef>,
                      impl_did: ast::DefId) {
     let tcx = vcx.tcx();
 
@@ -561,14 +562,14 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                     };
 
                       let vcx = fcx.vtable_context();
-                      let target_trait_ref = @ty::TraitRef {
+                      let target_trait_ref = Rc::new(ty::TraitRef {
                           def_id: target_def_id,
                           substs: ty::substs {
                               tps: target_substs.tps.clone(),
                               regions: target_substs.regions.clone(),
                               self_ty: Some(typ)
                           }
-                      };
+                      });
 
                       let param_bounds = ty::ParamBounds {
                           builtin_bounds: ty::EmptyBuiltinBounds(),
@@ -583,7 +584,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
                                                      is_early);
 
                       if !is_early {
-                          insert_vtables(fcx, MethodCall::expr(ex.id), @vec!(vtables));
+                          insert_vtables(fcx, MethodCall::expr(ex.id), vec!(vtables));
                       }
 
                       // Now, if this is &trait, we need to link the
@@ -683,7 +684,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
     // Search for auto-adjustments to find trait coercions
     match fcx.inh.adjustments.borrow().find(&ex.id) {
         Some(adjustment) => {
-            match **adjustment {
+            match *adjustment {
                 AutoDerefRef(adj) => {
                     for autoderef in range(0, adj.autoderefs) {
                         let method_call = MethodCall::autoderef(ex.id, autoderef as u32);
@@ -743,7 +744,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
         [],
         impl_item.id);
 
-    let impl_trait_ref = @impl_trait_ref.subst(tcx, &param_env.free_substs);
+    let impl_trait_ref = impl_trait_ref.subst(tcx, &param_env.free_substs);
 
     let infcx = &infer::new_infer_ctxt(tcx);
     let vcx = VtableContext { infcx: infcx, param_env: &param_env };
@@ -761,7 +762,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
     // but that falls out of doing this.
     let param_bounds = ty::ParamBounds {
         builtin_bounds: ty::EmptyBuiltinBounds(),
-        trait_bounds: vec!(impl_trait_ref)
+        trait_bounds: vec!(Rc::new(impl_trait_ref))
     };
     let t = ty::node_id_to_type(tcx, impl_item.id);
     let t = t.subst(tcx, &param_env.free_substs);
diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs
index 6ad3d380b28..3843c38fd18 100644
--- a/src/librustc/middle/typeck/check/writeback.rs
+++ b/src/librustc/middle/typeck/check/writeback.rs
@@ -51,49 +51,36 @@ fn resolve_type_vars_in_type(fcx: &FnCtxt, sp: Span, typ: ty::t)
     }
 }
 
-fn resolve_type_vars_in_types(fcx: &FnCtxt, sp: Span, tys: &[ty::t])
-                          -> Vec<ty::t> {
-    tys.iter().map(|t| {
-        match resolve_type_vars_in_type(fcx, sp, *t) {
-            Some(t1) => t1,
-            None => ty::mk_err()
-        }
-    }).collect()
-}
-
 fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall) {
     let fcx = wbcx.fcx;
     let tcx = fcx.ccx.tcx;
 
     // Resolve any method map entry
-    match fcx.inh.method_map.borrow().find(&method_call) {
+    match fcx.inh.method_map.borrow_mut().pop(&method_call) {
         Some(method) => {
             debug!("writeback::resolve_method_map_entry(call={:?}, entry={:?})",
                    method_call, method.repr(tcx));
-            let method_ty = match resolve_type_vars_in_type(fcx, sp, method.ty) {
-                Some(t) => t,
-                None => {
-                    wbcx.success = false;
-                    return;
-                }
-            };
-            let mut new_tps = Vec::new();
-            for &subst in method.substs.tps.iter() {
-                match resolve_type_vars_in_type(fcx, sp, subst) {
-                    Some(t) => new_tps.push(t),
-                    None => { wbcx.success = false; return; }
-                }
-            }
             let new_method = MethodCallee {
                 origin: method.origin,
-                ty: method_ty,
+                ty: match resolve_type_vars_in_type(fcx, sp, method.ty) {
+                    Some(t) => t,
+                    None => {
+                        wbcx.success = false;
+                        return;
+                    }
+                },
                 substs: ty::substs {
-                    tps: new_tps,
+                    tps: method.substs.tps.move_iter().map(|subst| {
+                        match resolve_type_vars_in_type(fcx, sp, subst) {
+                            Some(t) => t,
+                            None => { wbcx.success = false; ty::mk_err() }
+                        }
+                    }).collect(),
                     regions: ty::ErasedRegions,
                     self_ty: None
                 }
             };
-            fcx.ccx.method_map.borrow_mut().insert(method_call, new_method);
+            tcx.method_map.borrow_mut().insert(method_call, new_method);
         }
         None => {}
     }
@@ -101,46 +88,46 @@ fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, method_call: MethodCall
 
 fn resolve_vtable_map_entry(fcx: &FnCtxt, sp: Span, vtable_key: MethodCall) {
     // Resolve any vtable map entry
-    match fcx.inh.vtable_map.borrow().find_copy(&vtable_key) {
+    match fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
         Some(origins) => {
             let r_origins = resolve_origins(fcx, sp, origins);
-            fcx.ccx.vtable_map.borrow_mut().insert(vtable_key, r_origins);
             debug!("writeback::resolve_vtable_map_entry(vtable_key={}, vtables={:?})",
                     vtable_key, r_origins.repr(fcx.tcx()));
+            fcx.tcx().vtable_map.borrow_mut().insert(vtable_key, r_origins);
         }
         None => {}
     }
 
     fn resolve_origins(fcx: &FnCtxt, sp: Span,
                        vtbls: vtable_res) -> vtable_res {
-        @vtbls.iter().map(|os| @os.iter().map(|origin| {
+        vtbls.move_iter().map(|os| os.move_iter().map(|origin| {
             match origin {
-                &vtable_static(def_id, ref tys, origins) => {
-                    let r_tys = resolve_type_vars_in_types(fcx,
-                                                           sp,
-                                                           tys.as_slice());
+                vtable_static(def_id, tys, origins) => {
+                    let r_tys = tys.move_iter().map(|t| {
+                        match resolve_type_vars_in_type(fcx, sp, t) {
+                            Some(t1) => t1,
+                            None => ty::mk_err()
+                        }
+                    }).collect();
                     let r_origins = resolve_origins(fcx, sp, origins);
                     vtable_static(def_id, r_tys, r_origins)
                 }
-                &vtable_param(n, b) => {
-                    vtable_param(n, b)
-                }
+                vtable_param(n, b) => vtable_param(n, b)
             }
         }).collect()).collect()
     }
 }
 
-fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
-                           -> Option<ty::t> {
+fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
     let fcx = wbcx.fcx;
     let tcx = fcx.ccx.tcx;
 
     // Resolve any borrowings for the node with id `id`
-    match fcx.inh.adjustments.borrow().find_copy(&id) {
-        None => (),
+    let resolved_adj = match fcx.inh.adjustments.borrow_mut().pop(&id) {
+        None => None,
 
         Some(adjustment) => {
-            match *adjustment {
+            Some(match adjustment {
                 ty::AutoAddEnv(store) => {
                     let r = match store {
                         ty::RegionTraitStore(r, _) => r,
@@ -156,6 +143,8 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                                 format!("cannot resolve bound for closure: \
                                          {}",
                                         infer::fixup_err_to_str(e)));
+                            wbcx.success = false;
+                            return;
                         }
                         Ok(r1) => {
                             // FIXME(eddyb) #2190 Allow only statically resolved
@@ -170,15 +159,12 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                                         "cannot coerce non-statically resolved bare fn")
                             }
 
-                            let resolved_adj = @ty::AutoAddEnv(match store {
+                            ty::AutoAddEnv(match store {
                                 ty::RegionTraitStore(..) => {
                                     ty::RegionTraitStore(r1, ast::MutMutable)
                                 }
                                 ty::UniqTraitStore => ty::UniqTraitStore
-                            });
-                            debug!("Adjustments for node {}: {:?}",
-                                   id, resolved_adj);
-                            tcx.adjustments.borrow_mut().insert(id, resolved_adj);
+                            })
                         }
                     }
                 }
@@ -190,42 +176,38 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
                         resolve_vtable_map_entry(wbcx.fcx, sp, method_call);
                     }
 
-                    let fixup_region = |r| {
-                        match resolve_region(fcx.infcx(),
-                                             r,
-                                             resolve_all | force_all) {
-                            Ok(r1) => r1,
-                            Err(e) => {
-                                // This should not, I think, happen.
-                                tcx.sess.span_err(
-                                    sp,
-                                    format!("cannot resolve scope of borrow: \
-                                             {}",
-                                             infer::fixup_err_to_str(e)));
-                                r
-                            }
-                        }
-                    };
-
-                    let resolved_autoref = match adj.autoref {
-                        None => None,
-                        Some(ref r) => Some(r.map_region(fixup_region))
-                    };
-
-                    let resolved_adj = @ty::AutoDerefRef(ty::AutoDerefRef {
+                    ty::AutoDerefRef(ty::AutoDerefRef {
                         autoderefs: adj.autoderefs,
-                        autoref: resolved_autoref,
-                    });
-                    debug!("Adjustments for node {}: {:?}", id, resolved_adj);
-                    tcx.adjustments.borrow_mut().insert(id, resolved_adj);
+                        autoref: adj.autoref.map(|r| r.map_region(|r| {
+                            match resolve_region(fcx.infcx(), r,
+                                                resolve_all | force_all) {
+                                Ok(r1) => r1,
+                                Err(e) => {
+                                    // This should not, I think, happen.
+                                    tcx.sess.span_err(
+                                        sp,
+                                        format!("cannot resolve scope of borrow: \
+                                                {}",
+                                                infer::fixup_err_to_str(e)));
+                                    r
+                                }
+                            }
+                        })),
+                    })
                 }
 
-                ty::AutoObject(..) => {
-                    debug!("Adjustments for node {}: {:?}", id, adjustment);
-                    tcx.adjustments.borrow_mut().insert(id, adjustment);
-                }
-            }
+                adjustment => adjustment
+            })
         }
+    };
+
+    debug!("Adjustments for node {}: {:?}",
+           id, resolved_adj);
+    match resolved_adj {
+        Some(adj) => {
+            tcx.adjustments.borrow_mut().insert(id, adj);
+        }
+        None => {}
     }
 
     // Resolve the type of the node with id `id`
@@ -233,26 +215,23 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
     match resolve_type_vars_in_type(fcx, sp, n_ty) {
       None => {
         wbcx.success = false;
-        return None;
       }
 
       Some(t) => {
         debug!("resolve_type_vars_for_node(id={}, n_ty={}, t={})",
                id, ppaux::ty_to_str(tcx, n_ty), ppaux::ty_to_str(tcx, t));
         write_ty_to_tcx(tcx, id, t);
-        let mut ret = Some(t);
         fcx.opt_node_ty_substs(id, |substs| {
           let mut new_tps = Vec::new();
           for subst in substs.tps.iter() {
               match resolve_type_vars_in_type(fcx, sp, *subst) {
                 Some(t) => new_tps.push(t),
-                None => { wbcx.success = false; ret = None; break }
+                None => { wbcx.success = false; break }
               }
           }
           write_substs_to_tcx(tcx, id, new_tps);
-          ret.is_some()
+          wbcx.success
         });
-        ret
       }
     }
 }
@@ -401,7 +380,7 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt, decl: &ast::FnDecl,
     for arg in decl.inputs.iter() {
         wbcx.visit_pat(arg.pat, ());
         // Privacy needs the type for the whole pattern, not just each binding
-        if !pat_util::pat_is_binding(fcx.tcx().def_map, arg.pat) {
+        if !pat_util::pat_is_binding(&fcx.tcx().def_map, arg.pat) {
             resolve_type_vars_for_node(wbcx, arg.pat.span, arg.pat.id);
         }
     }
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index c0fd73f4a36..3a50b0681e8 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -27,7 +27,6 @@ use middle::ty::{ty_uint, ty_uniq, ty_bare_fn, ty_closure};
 use middle::ty::type_is_ty_var;
 use middle::subst::Subst;
 use middle::ty;
-use middle::ty::{Impl, Method};
 use middle::typeck::CrateCtxt;
 use middle::typeck::infer::combine::Combine;
 use middle::typeck::infer::InferCtxt;
@@ -252,7 +251,8 @@ impl<'a> CoherenceChecker<'a> {
     fn check_implementation(&self, item: &Item,
                             associated_traits: &[TraitRef]) {
         let tcx = self.crate_context.tcx;
-        let self_type = ty::lookup_item_type(tcx, local_def(item.id));
+        let impl_did = local_def(item.id);
+        let self_type = ty::lookup_item_type(tcx, impl_did);
 
         // If there are no traits, then this implementation must have a
         // base type.
@@ -276,7 +276,7 @@ impl<'a> CoherenceChecker<'a> {
             }
         }
 
-        let implementation = self.create_impl_from_item(item);
+        let impl_methods = self.create_impl_from_item(item);
 
         for associated_trait in associated_traits.iter() {
             let trait_ref = ty::node_id_to_trait_ref(
@@ -285,7 +285,7 @@ impl<'a> CoherenceChecker<'a> {
                    trait_ref.repr(self.crate_context.tcx),
                    token::get_ident(item.ident));
 
-            self.add_trait_impl(trait_ref.def_id, implementation);
+            self.add_trait_impl(trait_ref.def_id, impl_did);
         }
 
         // Add the implementation to the mapping from implementation to base
@@ -300,20 +300,20 @@ impl<'a> CoherenceChecker<'a> {
             Some(base_type_def_id) => {
                 // FIXME: Gather up default methods?
                 if associated_traits.len() == 0 {
-                    self.add_inherent_impl(base_type_def_id, implementation);
+                    self.add_inherent_impl(base_type_def_id, impl_did);
                 }
             }
         }
 
-        tcx.impls.borrow_mut().insert(implementation.did, implementation);
+        tcx.impl_methods.borrow_mut().insert(impl_did, impl_methods);
     }
 
     // Creates default method IDs and performs type substitutions for an impl
     // and trait pair. Then, for each provided method in the trait, inserts a
     // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
-    fn instantiate_default_methods(&self, impl_id: ast::DefId,
+    fn instantiate_default_methods(&self, impl_id: DefId,
                                    trait_ref: &ty::TraitRef,
-                                   all_methods: &mut Vec<@Method> ) {
+                                   all_methods: &mut Vec<DefId>) {
         let tcx = self.crate_context.tcx;
         debug!("instantiate_default_methods(impl_id={:?}, trait_ref={})",
                impl_id, trait_ref.repr(tcx));
@@ -330,16 +330,16 @@ impl<'a> CoherenceChecker<'a> {
 
             // Create substitutions for the various trait parameters.
             let new_method_ty =
-                @subst_receiver_types_in_method_ty(
+                Rc::new(subst_receiver_types_in_method_ty(
                     tcx,
                     impl_id,
                     trait_ref,
                     new_did,
-                    *trait_method,
-                    Some(trait_method.def_id));
+                    &**trait_method,
+                    Some(trait_method.def_id)));
 
             debug!("new_method_ty={}", new_method_ty.repr(tcx));
-            all_methods.push(new_method_ty);
+            all_methods.push(new_did);
 
             // construct the polytype for the method based on the method_ty
             let new_generics = ty::Generics {
@@ -366,40 +366,24 @@ impl<'a> CoherenceChecker<'a> {
         }
     }
 
-    fn add_inherent_impl(&self, base_def_id: DefId,
-                         implementation: @Impl) {
+    fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
         let tcx = self.crate_context.tcx;
-        let implementation_list;
-        let mut inherent_impls = tcx.inherent_impls.borrow_mut();
-        match inherent_impls.find(&base_def_id) {
-            None => {
-                implementation_list = @RefCell::new(Vec::new());
-                inherent_impls.insert(base_def_id, implementation_list);
-            }
-            Some(&existing_implementation_list) => {
-                implementation_list = existing_implementation_list;
+        match tcx.inherent_impls.borrow().find(&base_def_id) {
+            Some(implementation_list) => {
+                implementation_list.borrow_mut().push(impl_def_id);
+                return;
             }
+            None => {}
         }
 
-        implementation_list.borrow_mut().push(implementation);
+        tcx.inherent_impls.borrow_mut().insert(base_def_id,
+                                               Rc::new(RefCell::new(vec!(impl_def_id))));
     }
 
-    fn add_trait_impl(&self, base_def_id: DefId,
-                      implementation: @Impl) {
-        let tcx = self.crate_context.tcx;
-        let implementation_list;
-        let mut trait_impls = tcx.trait_impls.borrow_mut();
-        match trait_impls.find(&base_def_id) {
-            None => {
-                implementation_list = @RefCell::new(Vec::new());
-                trait_impls.insert(base_def_id, implementation_list);
-            }
-            Some(&existing_implementation_list) => {
-                implementation_list = existing_implementation_list;
-            }
-        }
-
-        implementation_list.borrow_mut().push(implementation);
+    fn add_trait_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
+        ty::record_trait_implementation(self.crate_context.tcx,
+                                        base_def_id,
+                                        impl_def_id);
     }
 
     fn check_implementation_coherence(&self) {
@@ -410,34 +394,32 @@ impl<'a> CoherenceChecker<'a> {
 
     fn check_implementation_coherence_of(&self, trait_def_id: DefId) {
         // Unify pairs of polytypes.
-        self.iter_impls_of_trait_local(trait_def_id, |a| {
-            let implementation_a = a;
+        self.iter_impls_of_trait_local(trait_def_id, |impl_a| {
             let polytype_a =
-                self.get_self_type_for_implementation(implementation_a);
+                self.get_self_type_for_implementation(impl_a);
 
             // "We have an impl of trait <trait_def_id> for type <polytype_a>,
-            // and that impl is <implementation_a>"
-            self.iter_impls_of_trait(trait_def_id, |b| {
-                let implementation_b = b;
+            // and that impl is <impl_a>"
+            self.iter_impls_of_trait(trait_def_id, |impl_b| {
 
                 // An impl is coherent with itself
-                if a.did != b.did {
+                if impl_a != impl_b {
                     let polytype_b = self.get_self_type_for_implementation(
-                            implementation_b);
+                            impl_b);
 
                     if self.polytypes_unify(polytype_a.clone(), polytype_b) {
                         let session = &self.crate_context.tcx.sess;
                         session.span_err(
-                            self.span_of_impl(implementation_a),
+                            self.span_of_impl(impl_a),
                             format!("conflicting implementations for trait `{}`",
                                  ty::item_path_str(self.crate_context.tcx,
                                                    trait_def_id)));
-                        if implementation_b.did.krate == LOCAL_CRATE {
-                            session.span_note(self.span_of_impl(implementation_b),
+                        if impl_b.krate == LOCAL_CRATE {
+                            session.span_note(self.span_of_impl(impl_b),
                                               "note conflicting implementation here");
                         } else {
                             let crate_store = &self.crate_context.tcx.sess.cstore;
-                            let cdata = crate_store.get_crate_data(implementation_b.did.krate);
+                            let cdata = crate_store.get_crate_data(impl_b.krate);
                             session.note(
                                 "conflicting implementation in crate `" + cdata.name + "`");
                         }
@@ -447,7 +429,7 @@ impl<'a> CoherenceChecker<'a> {
         })
     }
 
-    fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |@Impl|) {
+    fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |DefId|) {
         self.iter_impls_of_trait_local(trait_def_id, |x| f(x));
 
         if trait_def_id.krate == LOCAL_CRATE {
@@ -456,17 +438,17 @@ impl<'a> CoherenceChecker<'a> {
 
         let crate_store = &self.crate_context.tcx.sess.cstore;
         csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| {
-            let implementation = @csearch::get_impl(self.crate_context.tcx, impl_def_id);
-            let _ = lookup_item_type(self.crate_context.tcx, implementation.did);
-            f(implementation);
+            // Is this actually necessary?
+            let _ = lookup_item_type(self.crate_context.tcx, impl_def_id);
+            f(impl_def_id);
         });
     }
 
-    fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |@Impl|) {
+    fn iter_impls_of_trait_local(&self, trait_def_id: DefId, f: |DefId|) {
         match self.crate_context.tcx.trait_impls.borrow().find(&trait_def_id) {
             Some(impls) => {
-                for &im in impls.borrow().iter() {
-                    f(im);
+                for &impl_did in impls.borrow().iter() {
+                    f(impl_did);
                 }
             }
             None => { /* no impls? */ }
@@ -526,9 +508,9 @@ impl<'a> CoherenceChecker<'a> {
                             b.monotype).is_ok()
     }
 
-    fn get_self_type_for_implementation(&self, implementation: @Impl)
+    fn get_self_type_for_implementation(&self, impl_did: DefId)
                                         -> ty_param_bounds_and_ty {
-        self.crate_context.tcx.tcache.borrow().get_copy(&implementation.did)
+        self.crate_context.tcx.tcache.borrow().get_copy(&impl_did)
     }
 
     // Privileged scope checking
@@ -538,7 +520,7 @@ impl<'a> CoherenceChecker<'a> {
     }
 
     fn trait_ref_to_trait_def_id(&self, trait_ref: &TraitRef) -> DefId {
-        let def_map = self.crate_context.tcx.def_map;
+        let def_map = &self.crate_context.tcx.def_map;
         let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
         let trait_id = def_id_of_def(trait_def);
         return trait_id;
@@ -580,15 +562,13 @@ impl<'a> CoherenceChecker<'a> {
         }
     }
 
-    // Converts an implementation in the AST to an Impl structure.
-    fn create_impl_from_item(&self, item: &Item) -> @Impl {
-        let tcx = self.crate_context.tcx;
+    // Converts an implementation in the AST to a vector of methods.
+    fn create_impl_from_item(&self, item: &Item) -> Vec<DefId> {
         match item.node {
             ItemImpl(_, ref trait_refs, _, ref ast_methods) => {
-                let mut methods = Vec::new();
-                for ast_method in ast_methods.iter() {
-                    methods.push(ty::method(tcx, local_def(ast_method.id)));
-                }
+                let mut methods: Vec<DefId> = ast_methods.iter().map(|ast_method| {
+                    local_def(ast_method.id)
+                }).collect();
 
                 for trait_ref in trait_refs.iter() {
                     let ty_trait_ref = ty::node_id_to_trait_ref(
@@ -596,15 +576,11 @@ impl<'a> CoherenceChecker<'a> {
                         trait_ref.ref_id);
 
                     self.instantiate_default_methods(local_def(item.id),
-                                                     ty_trait_ref,
+                                                     &*ty_trait_ref,
                                                      &mut methods);
                 }
 
-                return @Impl {
-                    did: local_def(item.id),
-                    ident: item.ident,
-                    methods: methods
-                };
+                methods
             }
             _ => {
                 self.crate_context.tcx.sess.span_bug(item.span,
@@ -613,9 +589,9 @@ impl<'a> CoherenceChecker<'a> {
         }
     }
 
-    fn span_of_impl(&self, implementation: @Impl) -> Span {
-        assert_eq!(implementation.did.krate, LOCAL_CRATE);
-        self.crate_context.tcx.map.span(implementation.did.node)
+    fn span_of_impl(&self, impl_did: DefId) -> Span {
+        assert_eq!(impl_did.krate, LOCAL_CRATE);
+        self.crate_context.tcx.map.span(impl_did.node)
     }
 
     // External crate handling
@@ -624,36 +600,35 @@ impl<'a> CoherenceChecker<'a> {
                          impls_seen: &mut HashSet<DefId>,
                          impl_def_id: DefId) {
         let tcx = self.crate_context.tcx;
-        let implementation = @csearch::get_impl(tcx, impl_def_id);
+        let methods = csearch::get_impl_methods(&tcx.sess.cstore, impl_def_id);
 
         // Make sure we don't visit the same implementation multiple times.
-        if !impls_seen.insert(implementation.did) {
+        if !impls_seen.insert(impl_def_id) {
             // Skip this one.
             return
         }
         // Good. Continue.
 
-        let _ = lookup_item_type(tcx, implementation.did);
-        let associated_traits = get_impl_trait(tcx, implementation.did);
+        let _ = lookup_item_type(tcx, impl_def_id);
+        let associated_traits = get_impl_trait(tcx, impl_def_id);
 
         // Do a sanity check.
         assert!(associated_traits.is_some());
 
         // Record all the trait methods.
         for trait_ref in associated_traits.iter() {
-              self.add_trait_impl(trait_ref.def_id, implementation);
+            self.add_trait_impl(trait_ref.def_id, impl_def_id);
         }
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
-        for method in implementation.methods.iter() {
-            for source in method.provided_source.iter() {
-                tcx.provided_method_sources.borrow_mut()
-                   .insert(method.def_id, *source);
+        for &method_def_id in methods.iter() {
+            for &source in ty::method(tcx, method_def_id).provided_source.iter() {
+                tcx.provided_method_sources.borrow_mut().insert(method_def_id, source);
             }
         }
 
-        tcx.impls.borrow_mut().insert(implementation.did, implementation);
+        tcx.impl_methods.borrow_mut().insert(impl_def_id, methods);
     }
 
     // Adds implementations and traits from external crates to the coherence
@@ -680,22 +655,21 @@ impl<'a> CoherenceChecker<'a> {
             Some(id) => id, None => { return }
         };
 
-        let trait_impls = tcx.trait_impls.borrow();
-        let impls_opt = trait_impls.find(&drop_trait);
-        let impls;
-        match impls_opt {
+        let impl_methods = tcx.impl_methods.borrow();
+        let trait_impls = match tcx.trait_impls.borrow().find_copy(&drop_trait) {
             None => return, // No types with (new-style) dtors present.
-            Some(found_impls) => impls = found_impls
-        }
+            Some(found_impls) => found_impls
+        };
 
-        for impl_info in impls.borrow().iter() {
-            if impl_info.methods.len() < 1 {
+        for &impl_did in trait_impls.borrow().iter() {
+            let methods = impl_methods.get(&impl_did);
+            if methods.len() < 1 {
                 // We'll error out later. For now, just don't ICE.
                 continue;
             }
-            let method_def_id = impl_info.methods.get(0).def_id;
+            let method_def_id = *methods.get(0);
 
-            let self_type = self.get_self_type_for_implementation(*impl_info);
+            let self_type = self.get_self_type_for_implementation(impl_did);
             match ty::get(self_type.ty).sty {
                 ty::ty_enum(type_def_id, _) |
                 ty::ty_struct(type_def_id, _) => {
@@ -705,9 +679,9 @@ impl<'a> CoherenceChecker<'a> {
                 }
                 _ => {
                     // Destructors only work on nominal types.
-                    if impl_info.did.krate == ast::LOCAL_CRATE {
+                    if impl_did.krate == ast::LOCAL_CRATE {
                         {
-                            match tcx.map.find(impl_info.did.node) {
+                            match tcx.map.find(impl_did.node) {
                                 Some(ast_map::NodeItem(item)) => {
                                     tcx.sess.span_err((*item).span,
                                                       "the Drop trait may \
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 490a52df2ba..0102001aa3c 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -126,7 +126,7 @@ impl<'a> AstConv for CrateCtxt<'a> {
         }
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> @ty::TraitDef {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
         get_trait_def(self, id)
     }
 
@@ -195,7 +195,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                     // For each method, construct a suitable ty::Method and
                     // store it into the `tcx.methods` table:
                     for m in ms.iter() {
-                        let ty_method = @match m {
+                        let ty_method = Rc::new(match m {
                             &ast::Required(ref m) => {
                                 ty_method_of_trait_method(
                                     ccx, trait_id, &trait_ty_generics,
@@ -209,10 +209,10 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                                     &m.id, &m.ident, &m.explicit_self,
                                     &m.generics, &m.fn_style, m.decl)
                             }
-                        };
+                        });
 
                         if ty_method.explicit_self == ast::SelfStatic {
-                            make_static_method_ty(ccx, trait_id, ty_method,
+                            make_static_method_ty(ccx, trait_id, &*ty_method,
                                                   &trait_ty_generics);
                         }
 
@@ -221,7 +221,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                     }
 
                     // Add an entry mapping
-                    let method_def_ids = @ms.iter().map(|m| {
+                    let method_def_ids = Rc::new(ms.iter().map(|m| {
                         match m {
                             &ast::Required(ref ty_method) => {
                                 local_def(ty_method.id)
@@ -230,7 +230,7 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
                                 local_def(method.id)
                             }
                         }
-                    }).collect();
+                    }).collect());
 
                     let trait_def_id = local_def(trait_id);
                     tcx.trait_method_def_ids.borrow_mut()
@@ -342,10 +342,10 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt, trait_id: ast::NodeId) {
         new_type_param_defs.push(ty::TypeParameterDef {
             ident: special_idents::self_,
             def_id: dummy_defid,
-            bounds: @ty::ParamBounds {
+            bounds: Rc::new(ty::ParamBounds {
                 builtin_bounds: ty::EmptyBuiltinBounds(),
                 trait_bounds: vec!(self_trait_ref)
-            },
+            }),
             default: None
         });
 
@@ -412,7 +412,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
     assert!(!tcx.supertraits.borrow().contains_key(&local_def(id)));
 
     let self_ty = ty::mk_self(ccx.tcx, local_def(id));
-    let mut ty_trait_refs: Vec<@ty::TraitRef> = Vec::new();
+    let mut ty_trait_refs: Vec<Rc<ty::TraitRef>> = Vec::new();
     let mut bounds = ty::EmptyBuiltinBounds();
     for ast_trait_ref in ast_trait_refs.iter() {
         let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, ast_trait_ref);
@@ -434,7 +434,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
         }
     }
 
-    tcx.supertraits.borrow_mut().insert(local_def(id), @ty_trait_refs);
+    tcx.supertraits.borrow_mut().insert(local_def(id), Rc::new(ty_trait_refs));
     bounds
 }
 
@@ -489,12 +489,12 @@ fn convert_methods(ccx: &CrateCtxt,
         let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs().len();
         let m_ty_generics = ty_generics_for_fn_or_method(ccx, &m.generics,
                                                          num_rcvr_ty_params);
-        let mty = @ty_of_method(ccx,
-                                container,
-                                *m,
-                                untransformed_rcvr_ty,
-                                rcvr_ast_generics,
-                                rcvr_visibility);
+        let mty = Rc::new(ty_of_method(ccx,
+                                       container,
+                                       *m,
+                                       untransformed_rcvr_ty,
+                                       rcvr_ast_generics,
+                                       rcvr_visibility));
         let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
         debug!("method {} (id {}) has type {}",
                 m.ident.repr(ccx.tcx),
@@ -726,7 +726,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
         result
     }).collect();
 
-    tcx.struct_fields.borrow_mut().insert(local_def(id), @field_tys);
+    tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
 
     let super_struct = match struct_def.super_struct {
         Some(t) => match t.node {
@@ -813,8 +813,7 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::ForeignItem) {
 
 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
                              ast_trait_ref: &ast::TraitRef,
-                             self_ty: ty::t) -> @ty::TraitRef
-{
+                             self_ty: ty::t) -> Rc<ty::TraitRef> {
     /*!
      * Instantiates the path for the given trait reference, assuming that
      * it's bound to a valid trait type. Returns the def_id for the defining
@@ -831,8 +830,8 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
                     ccx, &rscope, trait_did, Some(self_ty), &ast_trait_ref.path);
 
             ccx.tcx.trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
-                                                   trait_ref);
-            return trait_ref;
+                                                   trait_ref.clone());
+            trait_ref
         }
         _ => {
             ccx.tcx.sess.span_fatal(
@@ -843,7 +842,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
     }
 }
 
-fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
+fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> Rc<ty::TraitDef> {
     if trait_id.krate != ast::LOCAL_CRATE {
         return ty::lookup_trait_def(ccx.tcx, trait_id)
     }
@@ -855,11 +854,11 @@ fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
     }
 }
 
-pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
+pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
     match tcx.trait_defs.borrow().find(&def_id) {
-        Some(&def) => return def,
+        Some(def) => return def.clone(),
         _ => {}
     }
 
@@ -872,13 +871,16 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> @ty::TraitDef {
                                             it.id,
                                             it.span,
                                             supertraits.as_slice());
-            let trait_ref = @ty::TraitRef {def_id: def_id,
-                                           substs: substs};
-            let trait_def = @ty::TraitDef {generics: ty_generics,
-                                           bounds: bounds,
-                                           trait_ref: trait_ref};
-            tcx.trait_defs.borrow_mut().insert(def_id, trait_def);
-            return trait_def;
+            let trait_def = Rc::new(ty::TraitDef {
+                generics: ty_generics,
+                bounds: bounds,
+                trait_ref: Rc::new(ty::TraitRef {
+                    def_id: def_id,
+                    substs: substs
+                })
+            });
+            tcx.trait_defs.borrow_mut().insert(def_id, trait_def.clone());
+            trait_def
         }
         ref s => {
             tcx.sess.span_bug(
@@ -999,24 +1001,24 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
     }
 }
 
-pub fn ty_generics_for_type(ccx: &CrateCtxt,
-                            generics: &ast::Generics)
-                            -> ty::Generics {
+fn ty_generics_for_type(ccx: &CrateCtxt,
+                        generics: &ast::Generics)
+                        -> ty::Generics {
     ty_generics(ccx, &generics.lifetimes, &generics.ty_params, 0)
 }
 
-pub fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
-                                    generics: &ast::Generics,
-                                    base_index: uint)
-                                    -> ty::Generics {
+fn ty_generics_for_fn_or_method(ccx: &CrateCtxt,
+                                generics: &ast::Generics,
+                                base_index: uint)
+                                -> ty::Generics {
     let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
     ty_generics(ccx, &early_lifetimes, &generics.ty_params, base_index)
 }
 
-pub fn ty_generics(ccx: &CrateCtxt,
-                   lifetimes: &Vec<ast::Lifetime>,
-                   ty_params: &OwnedSlice<ast::TyParam>,
-                   base_index: uint) -> ty::Generics {
+fn ty_generics(ccx: &CrateCtxt,
+               lifetimes: &Vec<ast::Lifetime>,
+               ty_params: &OwnedSlice<ast::TyParam>,
+               base_index: uint) -> ty::Generics {
     return ty::Generics {
         region_param_defs: Rc::new(lifetimes.iter().map(|l| {
                 ty::RegionParameterDef { name: l.name,
@@ -1025,12 +1027,12 @@ pub fn ty_generics(ccx: &CrateCtxt,
         type_param_defs: Rc::new(ty_params.iter().enumerate().map(|(offset, param)| {
             let existing_def_opt = {
                 let ty_param_defs = ccx.tcx.ty_param_defs.borrow();
-                ty_param_defs.find(&param.id).map(|&def| def)
+                ty_param_defs.find(&param.id).map(|def| def.clone())
             };
             existing_def_opt.unwrap_or_else(|| {
                 let param_ty = ty::param_ty {idx: base_index + offset,
                                              def_id: local_def(param.id)};
-                let bounds = @compute_bounds(ccx, param_ty, &param.bounds);
+                let bounds = Rc::new(compute_bounds(ccx, param_ty, &param.bounds));
                 let default = param.default.map(|path| {
                     let ty = ast_ty_to_ty(ccx, &ExplicitRscope, path);
                     let cur_idx = param_ty.idx;
@@ -1056,7 +1058,7 @@ pub fn ty_generics(ccx: &CrateCtxt,
                     default: default
                 };
                 debug!("def for param: {}", def.repr(ccx.tcx));
-                ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def);
+                ccx.tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
                 def
             })
         }).collect()),
diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs
index ad0590318ea..e921674ad83 100644
--- a/src/librustc/middle/typeck/infer/coercion.rs
+++ b/src/librustc/middle/typeck/infer/coercion.rs
@@ -195,7 +195,7 @@ impl<'f> Coerce<'f> {
     }
 
     pub fn subtype(&self, a: ty::t, b: ty::t) -> CoerceResult {
-        match Sub(*self.get_ref()).tys(a, b) {
+        match Sub(self.get_ref().clone()).tys(a, b) {
             Ok(_) => Ok(None),         // No coercion required.
             Err(ref e) => Err(*e)
         }
@@ -232,8 +232,9 @@ impl<'f> Coerce<'f> {
         // to type check, we will construct the type that `&M*expr` would
         // yield.
 
-        let sub = Sub(*self.get_ref());
-        let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let sub = Sub(self.get_ref().clone());
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_borrow = self.get_ref().infcx.next_region_var(coercion);
 
         let inner_ty = match *sty_a {
             ty::ty_box(typ) | ty::ty_uniq(typ) => typ,
@@ -247,7 +248,7 @@ impl<'f> Coerce<'f> {
                                      r_borrow,
                                      mt {ty: inner_ty, mutbl: mt_b.mutbl});
         if_ok!(sub.tys(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
             autoref: Some(AutoPtr(r_borrow, mt_b.mutbl))
         })))
@@ -269,10 +270,11 @@ impl<'f> Coerce<'f> {
             }
         };
 
-        let r_a = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_a = self.get_ref().infcx.next_region_var(coercion);
         let a_borrowed = ty::mk_str(self.get_ref().infcx.tcx, VstoreSlice(r_a));
         if_ok!(self.subtype(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
             autoref: Some(AutoBorrowVec(r_a, MutImmutable))
         })))
@@ -288,8 +290,9 @@ impl<'f> Coerce<'f> {
                a.inf_str(self.get_ref().infcx), sty_a,
                b.inf_str(self.get_ref().infcx));
 
-        let sub = Sub(*self.get_ref());
-        let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let sub = Sub(self.get_ref().clone());
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_borrow = self.get_ref().infcx.next_region_var(coercion);
         let ty_inner = match *sty_a {
             ty::ty_uniq(t) | ty::ty_ptr(ty::mt{ty: t, ..}) |
             ty::ty_rptr(_, ty::mt{ty: t, ..}) => match ty::get(t).sty {
@@ -307,7 +310,7 @@ impl<'f> Coerce<'f> {
         let a_borrowed = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
                                       mt {ty: ty_inner, mutbl: mutbl_b});
         if_ok!(sub.tys(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
             autoref: Some(AutoBorrowVec(r_borrow, mutbl_b))
         })))
@@ -324,7 +327,8 @@ impl<'f> Coerce<'f> {
                b.inf_str(self.get_ref().infcx));
 
         let tcx = self.get_ref().infcx.tcx;
-        let r_a = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
+        let coercion = Coercion(self.get_ref().trace.clone());
+        let r_a = self.get_ref().infcx.next_region_var(coercion);
 
         let a_borrowed = match *sty_a {
             ty::ty_trait(~ty::TyTrait { def_id, ref substs, bounds, .. }) => {
@@ -337,7 +341,7 @@ impl<'f> Coerce<'f> {
         };
 
         if_ok!(self.subtype(a_borrowed, b));
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 0,
             autoref: Some(AutoBorrowObj(r_a, b_mutbl))
         })))
@@ -384,7 +388,7 @@ impl<'f> Coerce<'f> {
                 _ => return self.subtype(a, b)
             };
 
-            let adj = @ty::AutoAddEnv(fn_ty_b.store);
+            let adj = ty::AutoAddEnv(fn_ty_b.store);
             let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
                                            ty::ClosureTy {
                                                 sig: fn_ty_a.sig.clone(),
@@ -419,7 +423,7 @@ impl<'f> Coerce<'f> {
         // although references and unsafe ptrs have the same
         // representation, we still register an AutoDerefRef so that
         // regionck knows that the region for `a` must be valid here
-        Ok(Some(@AutoDerefRef(AutoDerefRef {
+        Ok(Some(AutoDerefRef(AutoDerefRef {
             autoderefs: 1,
             autoref: Some(ty::AutoUnsafe(mt_b.mutbl))
         })))
@@ -438,7 +442,7 @@ impl<'f> Coerce<'f> {
                a.inf_str(self.get_ref().infcx), sty_a,
                b.inf_str(self.get_ref().infcx));
 
-        Ok(Some(@ty::AutoObject(trait_store, bounds,
-                                trait_def_id, trait_substs.clone())))
+        Ok(Some(ty::AutoObject(trait_store, bounds,
+                               trait_def_id, trait_substs.clone())))
     }
 }
diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs
index bd3bb18fa33..54cf6524664 100644
--- a/src/librustc/middle/typeck/infer/combine.rs
+++ b/src/librustc/middle/typeck/infer/combine.rs
@@ -235,19 +235,6 @@ pub trait Combine {
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig>;
 
-    fn flds(&self, a: ty::field, b: ty::field) -> cres<ty::field> {
-        if a.ident == b.ident {
-            self.mts(&a.mt, &b.mt)
-                .and_then(|mt| Ok(ty::field {ident: a.ident, mt: mt}) )
-                .or_else(|e| Err(ty::terr_in_field(@e, a.ident)) )
-        } else {
-            Err(ty::terr_record_fields(
-                                       expected_found(self,
-                                                      a.ident,
-                                                      b.ident)))
-        }
-    }
-
     fn args(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         self.contratys(a, b).and_then(|t| Ok(t))
     }
@@ -337,6 +324,7 @@ pub trait Combine {
     }
 }
 
+#[deriving(Clone)]
 pub struct CombineFields<'a> {
     pub infcx: &'a InferCtxt<'a>,
     pub a_is_expected: bool,
diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs
index 6ba727f9d4d..a5d41b15d5d 100644
--- a/src/librustc/middle/typeck/infer/error_reporting.rs
+++ b/src/librustc/middle/typeck/infer/error_reporting.rs
@@ -76,6 +76,7 @@ use middle::typeck::infer::region_inference::ProcessedErrors;
 use middle::typeck::infer::region_inference::SameRegions;
 use std::cell::{Cell, RefCell};
 use std::char::from_u32;
+use std::rc::Rc;
 use std::strbuf::StrBuf;
 use syntax::ast;
 use syntax::ast_map;
@@ -158,7 +159,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
         let p_errors = self.process_errors(errors);
         let errors = if p_errors.is_empty() { errors } else { &p_errors };
         for error in errors.iter() {
-            match *error {
+            match error.clone() {
                 ConcreteFailure(origin, sub, sup) => {
                     self.report_concrete_failure(origin, sub, sup);
                 }
@@ -206,7 +207,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
         let mut same_regions = Vec::new();
         let mut processed_errors = Vec::new();
         for error in errors.iter() {
-            match *error {
+            match error.clone() {
                 ConcreteFailure(origin, sub, sup) => {
                     debug!("processing ConcreteFailure")
                     let trace = match origin {
@@ -661,10 +662,10 @@ impl<'a> ErrorReporting for InferCtxt<'a> {
                                same_regions: &[SameRegions]) {
         self.give_suggestion(same_regions);
         for vo in var_origins.iter() {
-            self.report_inference_failure(*vo);
+            self.report_inference_failure(vo.clone());
         }
-        for &(trace, terr) in trace_origins.iter() {
-            self.report_type_error(trace, &terr);
+        for &(ref trace, terr) in trace_origins.iter() {
+            self.report_type_error(trace.clone(), &terr);
         }
     }
 
@@ -1391,12 +1392,12 @@ impl Resolvable for ty::t {
     }
 }
 
-impl Resolvable for @ty::TraitRef {
-    fn resolve(&self, infcx: &InferCtxt) -> @ty::TraitRef {
-        @infcx.resolve_type_vars_in_trait_ref_if_possible(*self)
+impl Resolvable for Rc<ty::TraitRef> {
+    fn resolve(&self, infcx: &InferCtxt) -> Rc<ty::TraitRef> {
+        Rc::new(infcx.resolve_type_vars_in_trait_ref_if_possible(&**self))
     }
     fn contains_error(&self) -> bool {
-        ty::trait_ref_contains_error(*self)
+        ty::trait_ref_contains_error(&**self)
     }
 }
 
diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs
index 9f87993279c..32bc7eedf2f 100644
--- a/src/librustc/middle/typeck/infer/glb.rs
+++ b/src/librustc/middle/typeck/infer/glb.rs
@@ -38,11 +38,11 @@ impl<'f> Combine for Glb<'f> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { "glb".to_owned() }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace }
+    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(*self.get_ref()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(*self.get_ref()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(*self.get_ref()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
         let tcx = self.get_ref().infcx.tcx;
@@ -78,7 +78,7 @@ impl<'f> Combine for Glb<'f> {
     }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
-        Lub(*self.get_ref()).tys(a, b)
+        self.lub().tys(a, b)
     }
 
     fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
@@ -108,12 +108,12 @@ impl<'f> Combine for Glb<'f> {
                a.inf_str(self.get_ref().infcx),
                b.inf_str(self.get_ref().infcx));
 
-        Ok(self.get_ref().infcx.region_vars.glb_regions(Subtype(self.get_ref().trace), a, b))
+        Ok(self.get_ref().infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
     }
 
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
-        Lub(*self.get_ref()).regions(a, b)
+        self.lub().regions(a, b)
     }
 
     fn tys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
@@ -137,11 +137,11 @@ impl<'f> Combine for Glb<'f> {
         // Instantiate each bound region with a fresh region variable.
         let (a_with_fresh, a_map) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, a);
+                self.trace(), a);
         let a_vars = var_ids(self, &a_map);
         let (b_with_fresh, b_map) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, b);
+                self.trace(), b);
         let b_vars = var_ids(self, &b_map);
 
         // Collect constraints.
diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs
index 83cc9294244..ebfb17a8876 100644
--- a/src/librustc/middle/typeck/infer/lattice.rs
+++ b/src/librustc/middle/typeck/infer/lattice.rs
@@ -47,26 +47,26 @@ use util::common::indenter;
 
 use collections::HashMap;
 
-pub trait LatticeValue {
-    fn sub(cf: &CombineFields, a: &Self, b: &Self) -> ures;
-    fn lub(cf: &CombineFields, a: &Self, b: &Self) -> cres<Self>;
-    fn glb(cf: &CombineFields, a: &Self, b: &Self) -> cres<Self>;
+trait LatticeValue {
+    fn sub(cf: CombineFields, a: &Self, b: &Self) -> ures;
+    fn lub(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
+    fn glb(cf: CombineFields, a: &Self, b: &Self) -> cres<Self>;
 }
 
 pub type LatticeOp<'a, T> =
-    |cf: &CombineFields, a: &T, b: &T|: 'a -> cres<T>;
+    |cf: CombineFields, a: &T, b: &T|: 'a -> cres<T>;
 
 impl LatticeValue for ty::t {
-    fn sub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> ures {
-        Sub(*cf).tys(*a, *b).to_ures()
+    fn sub(cf: CombineFields, a: &ty::t, b: &ty::t) -> ures {
+        Sub(cf).tys(*a, *b).to_ures()
     }
 
-    fn lub(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
-        Lub(*cf).tys(*a, *b)
+    fn lub(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
+        Lub(cf).tys(*a, *b)
     }
 
-    fn glb(cf: &CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
-        Glb(*cf).tys(*a, *b)
+    fn glb(cf: CombineFields, a: &ty::t, b: &ty::t) -> cres<ty::t> {
+        Glb(cf).tys(*a, *b)
     }
 }
 
@@ -142,7 +142,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
         match (&a_bounds.ub, &b_bounds.lb) {
             (&Some(ref a_ub), &Some(ref b_lb)) => {
                 let r = self.infcx.try(
-                    || LatticeValue::sub(self, a_ub, b_lb));
+                    || LatticeValue::sub(self.clone(), a_ub, b_lb));
                 match r {
                     Ok(()) => {
                         return Ok(());
@@ -232,7 +232,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
             (&Some(_),       &None) => Ok((*a).clone()),
             (&None,          &Some(_)) => Ok((*b).clone()),
             (&Some(ref v_a), &Some(ref v_b)) => {
-                lattice_op(self, v_a, v_b).and_then(|v| Ok(Some(v)))
+                lattice_op(self.clone(), v_a, v_b).and_then(|v| Ok(Some(v)))
             }
         }
     }
@@ -314,7 +314,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> {
                 uok()
             }
             (&Some(ref t_a), &Some(ref t_b)) => {
-                LatticeValue::sub(self, t_a, t_b)
+                LatticeValue::sub(self.clone(), t_a, t_b)
             }
         }
     }
@@ -337,7 +337,7 @@ pub trait TyLatticeDir {
 }
 
 impl<'f> LatticeDir for Lub<'f> {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { *self.get_ref() }
+    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
     fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.ub.clone() }
     fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
         Bounds { ub: Some(t), ..(*b).clone() }
@@ -351,7 +351,7 @@ impl<'f> TyLatticeDir for Lub<'f> {
 }
 
 impl<'f> LatticeDir for Glb<'f> {
-    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { *self.get_ref() }
+    fn combine_fields<'a>(&'a self) -> CombineFields<'a> { self.get_ref().clone() }
     fn bnd<T:Clone>(&self, b: &Bounds<T>) -> Option<T> { b.lb.clone() }
     fn with_bnd<T:Clone>(&self, b: &Bounds<T>, t: T) -> Bounds<T> {
         Bounds { lb: Some(t), ..(*b).clone() }
diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs
index d42205f0035..d09bbc4253b 100644
--- a/src/librustc/middle/typeck/infer/lub.rs
+++ b/src/librustc/middle/typeck/infer/lub.rs
@@ -37,11 +37,11 @@ impl<'f> Combine for Lub<'f> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { "lub".to_owned() }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace }
+    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(*self.get_ref()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(*self.get_ref()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(*self.get_ref()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
 
     fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres<ty::mt> {
         let tcx = self.get_ref().infcx.tcx;
@@ -72,7 +72,7 @@ impl<'f> Combine for Lub<'f> {
     }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
-        Glb(*self.get_ref()).tys(a, b)
+        self.glb().tys(a, b)
     }
 
     fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<FnStyle> {
@@ -98,7 +98,7 @@ impl<'f> Combine for Lub<'f> {
 
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
-        return Glb(*self.get_ref()).regions(a, b);
+        self.glb().regions(a, b)
     }
 
     fn regions(&self, a: ty::Region, b: ty::Region) -> cres<ty::Region> {
@@ -107,7 +107,7 @@ impl<'f> Combine for Lub<'f> {
                a.inf_str(self.get_ref().infcx),
                b.inf_str(self.get_ref().infcx));
 
-        Ok(self.get_ref().infcx.region_vars.lub_regions(Subtype(self.get_ref().trace), a, b))
+        Ok(self.get_ref().infcx.region_vars.lub_regions(Subtype(self.trace()), a, b))
     }
 
     fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
@@ -123,10 +123,10 @@ impl<'f> Combine for Lub<'f> {
         // Instantiate each bound region with a fresh region variable.
         let (a_with_fresh, a_map) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, a);
+                self.trace(), a);
         let (b_with_fresh, _) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, b);
+                self.trace(), b);
 
         // Collect constraints.
         let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs
index b2143b7d798..258f286d8f0 100644
--- a/src/librustc/middle/typeck/infer/mod.rs
+++ b/src/librustc/middle/typeck/infer/mod.rs
@@ -38,7 +38,7 @@ use middle::typeck::infer::to_str::InferStr;
 use middle::typeck::infer::unify::{ValsAndBindings, Root};
 use middle::typeck::infer::error_reporting::ErrorReporting;
 use std::cell::{Cell, RefCell};
-use std::result;
+use std::rc::Rc;
 use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
 use syntax::codemap;
@@ -72,7 +72,7 @@ pub struct Bounds<T> {
 pub type cres<T> = Result<T,ty::type_err>; // "combine result"
 pub type ures = cres<()>; // "unify result"
 pub type fres<T> = Result<T, fixup_err>; // "fixup result"
-pub type CoerceResult = cres<Option<@ty::AutoAdjustment>>;
+pub type CoerceResult = cres<Option<ty::AutoAdjustment>>;
 
 pub struct InferCtxt<'a> {
     pub tcx: &'a ty::ctxt,
@@ -129,7 +129,7 @@ pub enum TypeOrigin {
 #[deriving(Clone)]
 pub enum ValuePairs {
     Types(ty::expected_found<ty::t>),
-    TraitRefs(ty::expected_found<@ty::TraitRef>),
+    TraitRefs(ty::expected_found<Rc<ty::TraitRef>>),
 }
 
 /// The trace designates the path through inference that we took to
@@ -301,7 +301,7 @@ pub fn common_supertype(cx: &InferCtxt,
         values: Types(expected_found(a_is_expected, a, b))
     };
 
-    let result = cx.commit(|| cx.lub(a_is_expected, trace).tys(a, b));
+    let result = cx.commit(|| cx.lub(a_is_expected, trace.clone()).tys(a, b));
     match result {
         Ok(t) => t,
         Err(ref err) => {
@@ -375,8 +375,8 @@ pub fn mk_eqty(cx: &InferCtxt,
 pub fn mk_sub_trait_refs(cx: &InferCtxt,
                          a_is_expected: bool,
                          origin: TypeOrigin,
-                         a: @ty::TraitRef,
-                         b: @ty::TraitRef)
+                         a: Rc<ty::TraitRef>,
+                         b: Rc<ty::TraitRef>)
     -> ures
 {
     debug!("mk_sub_trait_refs({} <: {})",
@@ -385,10 +385,10 @@ pub fn mk_sub_trait_refs(cx: &InferCtxt,
         cx.commit(|| {
             let trace = TypeTrace {
                 origin: origin,
-                values: TraitRefs(expected_found(a_is_expected, a, b))
+                values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
             };
             let suber = cx.sub(a_is_expected, trace);
-            suber.trait_refs(a, b)
+            suber.trait_refs(&*a, &*b)
         })
     }).to_ures()
 }
@@ -666,8 +666,8 @@ impl<'a> InferCtxt<'a> {
 
     pub fn resolve_type_vars_if_possible(&self, typ: ty::t) -> ty::t {
         match resolve_type(self, typ, resolve_nested_tvar | resolve_ivar) {
-          result::Ok(new_type) => new_type,
-          result::Err(_) => typ
+            Ok(new_type) => new_type,
+            Err(_) => typ
         }
     }
 
@@ -854,7 +854,7 @@ impl Repr for TypeOrigin {
 impl SubregionOrigin {
     pub fn span(&self) -> Span {
         match *self {
-            Subtype(a) => a.span(),
+            Subtype(ref a) => a.span(),
             InfStackClosure(a) => a,
             InvokeClosure(a) => a,
             DerefPointer(a) => a,
@@ -877,7 +877,7 @@ impl SubregionOrigin {
 impl Repr for SubregionOrigin {
     fn repr(&self, tcx: &ty::ctxt) -> ~str {
         match *self {
-            Subtype(a) => format!("Subtype({})", a.repr(tcx)),
+            Subtype(ref a) => format!("Subtype({})", a.repr(tcx)),
             InfStackClosure(a) => format!("InfStackClosure({})", a.repr(tcx)),
             InvokeClosure(a) => format!("InvokeClosure({})", a.repr(tcx)),
             DerefPointer(a) => format!("DerefPointer({})", a.repr(tcx)),
@@ -907,7 +907,7 @@ impl RegionVariableOrigin {
             AddrOfRegion(a) => a,
             AddrOfSlice(a) => a,
             Autoref(a) => a,
-            Coercion(a) => a.span(),
+            Coercion(ref a) => a.span(),
             EarlyBoundRegion(a, _) => a,
             LateBoundRegion(a, _) => a,
             BoundRegionInFnType(a, _) => a,
@@ -925,7 +925,7 @@ impl Repr for RegionVariableOrigin {
             AddrOfRegion(a) => format!("AddrOfRegion({})", a.repr(tcx)),
             AddrOfSlice(a) => format!("AddrOfSlice({})", a.repr(tcx)),
             Autoref(a) => format!("Autoref({})", a.repr(tcx)),
-            Coercion(a) => format!("Coercion({})", a.repr(tcx)),
+            Coercion(ref a) => format!("Coercion({})", a.repr(tcx)),
             EarlyBoundRegion(a, b) => format!("EarlyBoundRegion({},{})",
                                               a.repr(tcx), b.repr(tcx)),
             LateBoundRegion(a, b) => format!("LateBoundRegion({},{})",
diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs
index a446b94027b..bb6d479870b 100644
--- a/src/librustc/middle/typeck/infer/region_inference/mod.rs
+++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs
@@ -212,7 +212,7 @@ impl<'a> RegionVarBindings<'a> {
 
     pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
         let id = self.num_vars();
-        self.var_origins.borrow_mut().push(origin);
+        self.var_origins.borrow_mut().push(origin.clone());
         let vid = RegionVid { id: id };
         if self.in_snapshot() {
             self.undo_log.borrow_mut().push(AddVar(vid));
@@ -330,9 +330,9 @@ impl<'a> RegionVarBindings<'a> {
 
             _ => {
                 self.combine_vars(
-                    Lub, a, b, origin,
+                    Lub, a, b, origin.clone(),
                     |this, old_r, new_r|
-                    this.make_subregion(origin, old_r, new_r))
+                    this.make_subregion(origin.clone(), old_r, new_r))
             }
         }
     }
@@ -354,9 +354,9 @@ impl<'a> RegionVarBindings<'a> {
 
             _ => {
                 self.combine_vars(
-                    Glb, a, b, origin,
+                    Glb, a, b, origin.clone(),
                     |this, old_r, new_r|
-                    this.make_subregion(origin, new_r, old_r))
+                    this.make_subregion(origin.clone(), new_r, old_r))
             }
         }
     }
@@ -1150,10 +1150,10 @@ impl<'a> RegionVarBindings<'a> {
                 if !self.is_subregion_of(lower_bound.region,
                                          upper_bound.region) {
                     errors.push(SubSupConflict(
-                        *self.var_origins.borrow().get(node_idx.to_uint()),
-                        lower_bound.origin,
+                        self.var_origins.borrow().get(node_idx.to_uint()).clone(),
+                        lower_bound.origin.clone(),
                         lower_bound.region,
-                        upper_bound.origin,
+                        upper_bound.origin.clone(),
                         upper_bound.region));
                     return;
                 }
@@ -1200,10 +1200,10 @@ impl<'a> RegionVarBindings<'a> {
                   Ok(_) => {}
                   Err(_) => {
                     errors.push(SupSupConflict(
-                        *self.var_origins.borrow().get(node_idx.to_uint()),
-                        upper_bound_1.origin,
+                        self.var_origins.borrow().get(node_idx.to_uint()).clone(),
+                        upper_bound_1.origin.clone(),
                         upper_bound_1.region,
-                        upper_bound_2.origin,
+                        upper_bound_2.origin.clone(),
                         upper_bound_2.region));
                     return;
                   }
diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs
index 5348a623d86..9df610dc7bc 100644
--- a/src/librustc/middle/typeck/infer/resolve.rs
+++ b/src/librustc/middle/typeck/infer/resolve.rs
@@ -36,7 +36,7 @@
 // therefore cannot sensibly be mapped to any particular result.  By
 // default, we will leave such variables as is (so you will get back a
 // variable in your result).  The options force_* will cause the
-// resolution to fail in this case intead, except for the case of
+// resolution to fail in this case instead, except for the case of
 // integral variables, which resolve to `int` if forced.
 //
 // # resolve_all and force_all
diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs
index 6d02094669c..2c8acd0573b 100644
--- a/src/librustc/middle/typeck/infer/sub.rs
+++ b/src/librustc/middle/typeck/infer/sub.rs
@@ -37,15 +37,16 @@ impl<'f> Combine for Sub<'f> {
     fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx }
     fn tag(&self) -> ~str { "sub".to_owned() }
     fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected }
-    fn trace(&self) -> TypeTrace { self.get_ref().trace }
+    fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() }
 
-    fn sub<'a>(&'a self) -> Sub<'a> { Sub(*self.get_ref()) }
-    fn lub<'a>(&'a self) -> Lub<'a> { Lub(*self.get_ref()) }
-    fn glb<'a>(&'a self) -> Glb<'a> { Glb(*self.get_ref()) }
+    fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) }
+    fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) }
+    fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) }
 
     fn contratys(&self, a: ty::t, b: ty::t) -> cres<ty::t> {
         let opp = CombineFields {
-            a_is_expected: !self.get_ref().a_is_expected,.. *self.get_ref()
+            a_is_expected: !self.get_ref().a_is_expected,
+            ..self.get_ref().clone()
         };
         Sub(opp).tys(b, a)
     }
@@ -53,7 +54,8 @@ impl<'f> Combine for Sub<'f> {
     fn contraregions(&self, a: ty::Region, b: ty::Region)
                     -> cres<ty::Region> {
         let opp = CombineFields {
-            a_is_expected: !self.get_ref().a_is_expected,.. *self.get_ref()
+            a_is_expected: !self.get_ref().a_is_expected,
+            ..self.get_ref().clone()
         };
         Sub(opp).regions(b, a)
     }
@@ -63,7 +65,7 @@ impl<'f> Combine for Sub<'f> {
                self.tag(),
                a.inf_str(self.get_ref().infcx),
                b.inf_str(self.get_ref().infcx));
-        self.get_ref().infcx.region_vars.make_subregion(Subtype(self.get_ref().trace), a, b);
+        self.get_ref().infcx.region_vars.make_subregion(Subtype(self.trace()), a, b);
         Ok(a)
     }
 
@@ -167,7 +169,7 @@ impl<'f> Combine for Sub<'f> {
         // region variable.
         let (a_sig, _) =
             self.get_ref().infcx.replace_late_bound_regions_with_fresh_regions(
-                self.get_ref().trace, a);
+                self.trace(), a);
 
         // Second, we instantiate each bound region in the supertype with a
         // fresh concrete region.
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index f78f0a8f273..26f0bc7ec72 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -171,11 +171,11 @@ impl MethodCall {
 
 // maps from an expression id that corresponds to a method call to the details
 // of the method to be invoked
-pub type MethodMap = @RefCell<FnvHashMap<MethodCall, MethodCallee>>;
+pub type MethodMap = RefCell<FnvHashMap<MethodCall, MethodCallee>>;
 
-pub type vtable_param_res = @Vec<vtable_origin> ;
+pub type vtable_param_res = Vec<vtable_origin>;
 // Resolutions for bounds of all parameters, left to right, for a given path.
-pub type vtable_res = @Vec<vtable_param_res> ;
+pub type vtable_res = Vec<vtable_param_res>;
 
 #[deriving(Clone)]
 pub enum vtable_origin {
@@ -184,7 +184,7 @@ pub enum vtable_origin {
       from whence comes the vtable, and tys are the type substs.
       vtable_res is the vtable itself
      */
-    vtable_static(ast::DefId, Vec<ty::t> , vtable_res),
+    vtable_static(ast::DefId, Vec<ty::t>, vtable_res),
 
     /*
       Dynamic vtable, comes from a parameter that has a bound on it:
@@ -215,7 +215,7 @@ impl Repr for vtable_origin {
     }
 }
 
-pub type vtable_map = @RefCell<FnvHashMap<MethodCall, vtable_res>>;
+pub type vtable_map = RefCell<FnvHashMap<MethodCall, vtable_res>>;
 
 
 // Information about the vtable resolutions for a trait impl.
@@ -242,8 +242,6 @@ pub type impl_vtable_map = RefCell<DefIdMap<impl_res>>;
 pub struct CrateCtxt<'a> {
     // A mapping from method call sites to traits that have that method.
     trait_map: resolve::TraitMap,
-    method_map: MethodMap,
-    vtable_map: vtable_map,
     tcx: &'a ty::ctxt
 }
 
@@ -315,25 +313,6 @@ pub fn require_same_types(tcx: &ty::ctxt,
     }
 }
 
-// a list of mapping from in-scope-region-names ("isr") to the
-// corresponding ty::Region
-pub type isr_alist = @Vec<(ty::BoundRegion, ty::Region)>;
-
-trait get_region<'a, T:'static> {
-    fn get(&'a self, br: ty::BoundRegion) -> ty::Region;
-}
-
-impl<'a, T:'static> get_region <'a, T> for isr_alist {
-    fn get(&'a self, br: ty::BoundRegion) -> ty::Region {
-        let mut region = None;
-        for isr in self.iter() {
-            let (isr_br, isr_r) = *isr;
-            if isr_br == br { region = Some(isr_r); break; }
-        };
-        region.unwrap()
-    }
-}
-
 fn check_main_fn_ty(ccx: &CrateCtxt,
                     main_id: ast::NodeId,
                     main_span: Span) {
@@ -445,13 +424,10 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
 
 pub fn check_crate(tcx: &ty::ctxt,
                    trait_map: resolve::TraitMap,
-                   krate: &ast::Crate)
-                -> (MethodMap, vtable_map) {
+                   krate: &ast::Crate) {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         trait_map: trait_map,
-        method_map: @RefCell::new(FnvHashMap::new()),
-        vtable_map: @RefCell::new(FnvHashMap::new()),
         tcx: tcx
     };
 
@@ -473,5 +449,4 @@ pub fn check_crate(tcx: &ty::ctxt,
 
     check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
-    (ccx.method_map, ccx.vtable_map)
 }
diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs
index 907153d6cbe..9e7c221d3c5 100644
--- a/src/librustc/middle/typeck/variance.rs
+++ b/src/librustc/middle/typeck/variance.rs
@@ -197,6 +197,7 @@ use arena;
 use arena::Arena;
 use middle::ty;
 use std::fmt;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util;
@@ -254,7 +255,7 @@ struct TermsContext<'a> {
     tcx: &'a ty::ctxt,
     arena: &'a Arena,
 
-    empty_variances: @ty::ItemVariances,
+    empty_variances: Rc<ty::ItemVariances>,
 
     // Maps from the node id of a type/generic parameter to the
     // corresponding inferred index.
@@ -286,9 +287,11 @@ fn determine_parameters_to_be_inferred<'a>(tcx: &'a ty::ctxt,
 
         // cache and share the variance struct used for items with
         // no type/region parameters
-        empty_variances: @ty::ItemVariances { self_param: None,
-                                              type_params: OwnedSlice::empty(),
-                                              region_params: OwnedSlice::empty() }
+        empty_variances: Rc::new(ty::ItemVariances {
+            self_param: None,
+            type_params: OwnedSlice::empty(),
+            region_params: OwnedSlice::empty()
+        })
     };
 
     visit::walk_crate(&mut terms_cx, krate, ());
@@ -362,7 +365,7 @@ impl<'a> Visitor<()> for TermsContext<'a> {
                 if self.num_inferred() == inferreds_on_entry {
                     let newly_added = self.tcx.item_variance_map.borrow_mut().insert(
                         ast_util::local_def(item.id),
-                        self.empty_variances);
+                        self.empty_variances.clone());
                     assert!(newly_added);
                 }
 
@@ -1016,7 +1019,7 @@ impl<'a> SolveContext<'a> {
             }
 
             let newly_added = tcx.item_variance_map.borrow_mut()
-                                 .insert(item_def_id, @item_variances);
+                                 .insert(item_def_id, Rc::new(item_variances));
             assert!(newly_added);
         }
     }
diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs
index ac4db178a00..7d7d5d16d74 100644
--- a/src/librustc/util/nodemap.rs
+++ b/src/librustc/util/nodemap.rs
@@ -16,12 +16,13 @@ use std::io;
 use syntax::ast;
 
 pub type FnvHashMap<K, V> = HashMap<K, V, FnvHasher>;
+pub type FnvHashSet<V> = HashSet<V, FnvHasher>;
 
 pub type NodeMap<T> = FnvHashMap<ast::NodeId, T>;
 pub type DefIdMap<T> = FnvHashMap<ast::DefId, T>;
 
-pub type NodeSet = HashSet<ast::NodeId, FnvHasher>;
-pub type DefIdSet = HashSet<ast::DefId, FnvHasher>;
+pub type NodeSet = FnvHashSet<ast::NodeId>;
+pub type DefIdSet = FnvHashSet<ast::DefId>;
 
 // Hacks to get good names
 pub mod FnvHashMap {
@@ -31,6 +32,13 @@ pub mod FnvHashMap {
         HashMap::with_hasher(super::FnvHasher)
     }
 }
+pub mod FnvHashSet {
+    use std::hash::Hash;
+    use collections::HashSet;
+    pub fn new<V: Hash<super::FnvState> + TotalEq>() -> super::FnvHashSet<V> {
+        HashSet::with_hasher(super::FnvHasher)
+    }
+}
 pub mod NodeMap {
     pub fn new<T>() -> super::NodeMap<T> {
         super::FnvHashMap::new()
@@ -42,15 +50,13 @@ pub mod DefIdMap {
     }
 }
 pub mod NodeSet {
-    use collections::HashSet;
     pub fn new() -> super::NodeSet {
-        HashSet::with_hasher(super::FnvHasher)
+        super::FnvHashSet::new()
     }
 }
 pub mod DefIdSet {
-    use collections::HashSet;
     pub fn new() -> super::DefIdSet {
-        HashSet::with_hasher(super::FnvHasher)
+        super::FnvHashSet::new()
     }
 }
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 1d98cc143de..316b5c6a45a 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 
-use metadata::encoder;
 use middle::ty::{ReSkolemized, ReVar};
 use middle::ty::{BoundRegion, BrAnon, BrNamed};
 use middle::ty::{BrFresh, ctxt};
@@ -23,6 +22,7 @@ use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
 use middle::typeck;
 
+use std::rc::Rc;
 use std::strbuf::StrBuf;
 use syntax::abi;
 use syntax::ast_map;
@@ -469,7 +469,7 @@ pub fn parameterized(cx: &ctxt,
 }
 
 pub fn ty_to_short_str(cx: &ctxt, typ: t) -> ~str {
-    let mut s = encoder::encoded_ty(cx, typ);
+    let mut s = typ.repr(cx);
     if s.len() >= 32u { s = s.slice(0u, 32u).to_owned(); }
     return s;
 }
@@ -498,6 +498,12 @@ impl Repr for () {
     }
 }
 
+impl<T:Repr> Repr for Rc<T> {
+    fn repr(&self, tcx: &ctxt) -> ~str {
+        (&**self).repr(tcx)
+    }
+}
+
 impl<T:Repr> Repr for @T {
     fn repr(&self, tcx: &ctxt) -> ~str {
         (&**self).repr(tcx)
@@ -888,7 +894,7 @@ impl Repr for Span {
     }
 }
 
-impl<A:UserString> UserString for @A {
+impl<A:UserString> UserString for Rc<A> {
     fn user_string(&self, tcx: &ctxt) -> ~str {
         let this: &A = &**self;
         this.user_string(tcx)
diff --git a/src/librustc/util/sha2.rs b/src/librustc/util/sha2.rs
index 8de7cabde0e..cbc3be3f6e1 100644
--- a/src/librustc/util/sha2.rs
+++ b/src/librustc/util/sha2.rs
@@ -146,14 +146,14 @@ impl FixedBuffer for FixedBuffer64 {
             }
         }
 
-        // While we have at least a full buffer size chunks's worth of data, process that data
+        // While we have at least a full buffer size chunk's worth of data, process that data
         // without copying it into the buffer
         while input.len() - i >= size {
             func(input.slice(i, i + size));
             i += size;
         }
 
-        // Copy any input data into the buffer. At this point in the method, the ammount of
+        // Copy any input data into the buffer. At this point in the method, the amount of
         // data left in the input vector will be less than the buffer size and the buffer will
         // be empty.
         let input_remaining = input.len() - i;
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 0b5ca604cc3..d0cfabc8c11 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -32,13 +32,13 @@ pub fn render<T: fmt::Show, S: fmt::Show>(
 r##"<!DOCTYPE html>
 <html lang="en">
 <head>
-    <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="description" content="The {krate} library documentation.">
 
     <title>{title}</title>
 
-    <link href='http://fonts.googleapis.com/css?family=Inconsolata:400,700'
+    <link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600'
           rel='stylesheet' type='text/css'>
     <link rel="stylesheet" type="text/css" href="{root_path}main.css">
 
@@ -54,7 +54,7 @@ r##"<!DOCTYPE html>
 
     <section class="sidebar">
         {logo, select, none{} other{
-            <a href='{root_path}{krate}/index.html'><img src='#' alt='' width='100px' /></a>
+            <a href='{root_path}{krate}/index.html'><img src='#' alt='' width='100'></a>
         }}
 
         {sidebar}
@@ -66,7 +66,7 @@ r##"<!DOCTYPE html>
                 <input class="search-input" name="search"
                        autocomplete="off"
                        placeholder="Search documentation..."
-                       type="search" />
+                       type="search">
             </div>
         </form>
     </nav>
@@ -115,8 +115,7 @@ r##"<!DOCTYPE html>
     <script src="{root_path}main.js"></script>
     <script async src="{root_path}search-index.js"></script>
 </body>
-</html>
-"##,
+</html>"##,
     content   = *t,
     root_path = page.root_path,
     ty        = page.ty,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index aff9a29c838..d65876a1c83 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -975,7 +975,7 @@ impl<'a> fmt::Show for Item<'a> {
                 format!("{}-{}", self.item.source.loline, self.item.source.hiline)
             };
             try!(write!(fmt.buf,
-                          "<a class='source'\
+                          "<a class='source' \
                               href='{root}src/{krate}/{path}.html\\#{href}'>\
                               [src]</a>",
                           root = self.cx.root_path,
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 9a9b00e7d5d..9a0b9912373 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -13,31 +13,31 @@
     font-family: 'Fira Sans';
     font-style: normal;
     font-weight: 400;
-    src: local('Fira Sans'), url("http://rust-lang.org/fonts/FiraSans-Regular.woff") format('woff');
+    src: local('Fira Sans'), url("http://www.rust-lang.org/fonts/FiraSans-Regular.woff") format('woff');
 }
 @font-face {
     font-family: 'Fira Sans';
     font-style: normal;
     font-weight: 500;
-    src: local('Fira Sans Medium'), url("http://rust-lang.org/fonts/FiraSans-Medium.woff") format('woff');
+    src: local('Fira Sans Medium'), url("http://www.rust-lang.org/fonts/FiraSans-Medium.woff") format('woff');
 }
 @font-face {
     font-family: 'Heuristica';
     font-style: normal;
     font-weight: 400;
-    src: local('Heuristica Regular'), url("http://rust-lang.org/fonts/Heuristica-Regular.woff") format('woff');
+    src: local('Heuristica Regular'), url("http://www.rust-lang.org/fonts/Heuristica-Regular.woff") format('woff');
 }
 @font-face {
     font-family: 'Heuristica';
     font-style: italic;
     font-weight: 400;
-    src: local('Heuristica Italic'), url("http://rust-lang.org/fonts/Heuristica-Italic.woff") format('woff');
+    src: local('Heuristica Italic'), url("http://www.rust-lang.org/fonts/Heuristica-Italic.woff") format('woff');
 }
 @font-face {
     font-family: 'Heuristica';
     font-style: normal;
     font-weight: 700;
-    src: local('Heuristica Bold'), url("http://rust-lang.org/fonts/Heuristica-Bold.woff") format('woff');
+    src: local('Heuristica Bold'), url("http://www.rust-lang.org/fonts/Heuristica-Bold.woff") format('woff');
 }
 
 @import "normalize.css";
@@ -58,39 +58,46 @@ body {
     margin: 0;
     position: relative;
     padding: 10px 15px 20px 15px;
-    padding-bottom: 20px;
 }
 
-h1, h2, h3, h4 {
+h1, h2, h3:not(.impl), h4:not(.method) {
     color: black;
     font-weight: 500;
     margin: 30px 0 20px 0;
-    padding-bottom: 15px;
+    padding-bottom: 6px;
 }
 h1.fqn {
     border-bottom: 1px dashed #D5D5D5;
     margin-top: 0;
 }
-h2, h3, h4 {
+h2, h3:not(.impl), h4:not(.method) {
     border-bottom: 1px solid #DDDDDD;
 }
-h2 code, h3 code, h4 code, .block a {
-    font-size: 1.2em;
+h3.impl, h4.method {
+    font-weight: 600;
+    margin-top: 10px;
+    margin-bottom: 10px;
+}
+h3.impl {
+    margin-top: 15px;
 }
-h1, h2, h3, h4, section.sidebar, a.source, .content a, .search-input {
+h1, h2, h3, h4, section.sidebar, a.source, .content a.mod, .search-input {
     font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
 }
 
-ul {
+ol, ul {
     padding-left: 25px;
 }
+ul ul, ol ul, ul ol, ol ol {
+    margin-bottom: 0;
+}
 
 p {
     margin: 0 0 1em 0;
 }
 
 code, pre {
-    font-family: Menlo, Monaco, Consolas, Inconsolata, "DejaVu Sans Mono", monospace;
+    font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
 }
 pre {
     font-size: 15px;
@@ -194,9 +201,8 @@ nav.sub {
 }
 
 .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
-    margin-left: 0;
     margin: 40px 0 10px 0;
-    padding-bottom: 10px;
+    padding: 10px 0;
     border-bottom: 1px solid #DDD;
 }
 
@@ -384,7 +390,7 @@ h3.section-link:hover a:after,
 h4.section-link:hover a:after,
 h5.section-link:hover a:after,
 h6.section-link:hover a:after {
-  content: ' § ';
+  content: '\2002\00a7\2002';
 }
 
 /** Media Queries **/
diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs
index cbda25485c7..69d978b2433 100644
--- a/src/librustuv/net.rs
+++ b/src/librustuv/net.rs
@@ -270,7 +270,14 @@ impl TcpWatcher {
             let req = Request::wrap(req);
             if status == uvll::ECANCELED { return }
 
-            let cx: &mut Ctx = unsafe { req.get_data() };
+            // Apparently on windows when the handle is closed this callback may
+            // not be invoked with ECANCELED but rather another error code.
+            // Either ways, if the data is null, then our timeout has expired
+            // and there's nothing we can do.
+            let data = unsafe { uvll::get_data_for_req(req.handle) };
+            if data.is_null() { return }
+
+            let cx: &mut Ctx = unsafe { &mut *(data as *mut Ctx) };
             cx.status = status;
             match cx.timer {
                 Some(ref mut t) => t.stop(),
diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs
index 0fb6f30e8a1..eb7eb8d1df9 100644
--- a/src/libstd/cast.rs
+++ b/src/libstd/cast.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -28,8 +28,7 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
  * Move a thing into the void
  *
  * The forget function will take ownership of the provided value but neglect
- * to run any required cleanup or memory-management operations on it. This
- * can be used for various acts of magick.
+ * to run any required cleanup or memory-management operations on it.
  */
 #[inline]
 pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }
diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs
index e39ab4144fd..a6d6649aca0 100644
--- a/src/libstd/cmp.rs
+++ b/src/libstd/cmp.rs
@@ -26,7 +26,7 @@
 //!
 //! // Our implementation of `Eq` to support `==` and `!=`.
 //! impl Eq for SketchyNum {
-//!     // Our custom eq allows numbers which are near eachother to be equal! :D
+//!     // Our custom eq allows numbers which are near each other to be equal! :D
 //!     fn eq(&self, other: &SketchyNum) -> bool {
 //!         (self.num - other.num).abs() < 5
 //!     }
@@ -283,7 +283,7 @@ mod test {
 
         // Our implementation of `Eq` to support `==` and `!=`.
         impl Eq for SketchyNum {
-            // Our custom eq allows numbers which are near eachother to be equal! :D
+            // Our custom eq allows numbers which are near each other to be equal! :D
             fn eq(&self, other: &SketchyNum) -> bool {
                 (self.num - other.num).abs() < 5
             }
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
index 1c7579e6b8e..7a04303268b 100644
--- a/src/libstd/iter.rs
+++ b/src/libstd/iter.rs
@@ -937,7 +937,7 @@ impl<A: TotalOrd, T: Iterator<A>> OrdIterator<A> for T {
         loop {
             // `first` and `second` are the two next elements we want to look at.
             // We first compare `first` and `second` (#1). The smaller one is then compared to
-            // current mininum (#2). The larger one is compared to current maximum (#3). This
+            // current minimum (#2). The larger one is compared to current maximum (#3). This
             // way we do 3 comparisons for 2 elements.
             let first = match self.next() {
                 None => break,
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 06a6a6da796..dbaef335804 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -24,7 +24,7 @@
 /// which is transmitted.
 ///
 /// The multi-argument form of this macro fails with a string and has the
-/// `format!` sytnax for building a string.
+/// `format!` syntax for building a string.
 ///
 /// # Example
 ///
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
index 61461096ed9..f70715ed756 100644
--- a/src/libstd/ptr.rs
+++ b/src/libstd/ptr.rs
@@ -15,7 +15,7 @@
 //! an unsafe pointer when safe pointers are unsuitable;
 //! checking for null; and converting back to safe pointers.
 //! As a result, there is not yet an abundance of library code
-//! for working with unsafe poniters, and in particular,
+//! for working with unsafe pointers, and in particular,
 //! since pointer math is fairly uncommon in Rust, it is not
 //! all that convenient.
 //!
diff --git a/src/libstd/raw.rs b/src/libstd/raw.rs
index b285b42ee5e..9b0463089d0 100644
--- a/src/libstd/raw.rs
+++ b/src/libstd/raw.rs
@@ -15,7 +15,7 @@
 //! They can be used as targets of transmutes in unsafe code for manipulating
 //! the raw representations directly.
 //!
-//! Their definitition should always match the ABI defined in `rustc::back::abi`.
+//! Their definition should always match the ABI defined in `rustc::back::abi`.
 
 use cast;
 
diff --git a/src/libstd/result.rs b/src/libstd/result.rs
index 0f993598747..7080da266f6 100644
--- a/src/libstd/result.rs
+++ b/src/libstd/result.rs
@@ -103,7 +103,7 @@
 //! ~~~
 //!
 //! *Note: The actual definition of `Writer` uses `IoResult`, which
-//! is just a synonymn for `Result<T, IoError>`.*
+//! is just a synonym for `Result<T, IoError>`.*
 //!
 //! This method doesn`t produce a value, but the write may
 //! fail. It's crucial to handle the error case, and *not* write
@@ -255,7 +255,7 @@
 //! handling requires encapsulating fallable code in a task. Calling
 //! the `fail!` macro, or invoking `fail!` indirectly should be
 //! avoided as an error reporting strategy. Failure is only for
-//! unrecovereable errors and a failing task is typically the sign of
+//! unrecoverable errors and a failing task is typically the sign of
 //! a bug.
 //!
 //! A module that instead returns `Results` is alerting the caller
diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs
index ff82be97489..f60cfa23e81 100644
--- a/src/libstd/rt/local_ptr.rs
+++ b/src/libstd/rt/local_ptr.rs
@@ -374,7 +374,7 @@ pub mod native {
     pub fn maybe_tls_key() -> Option<tls::Key> {
         unsafe {
             // NB: This is a little racy because, while the key is
-            // initalized under a mutex and it's assumed to be initalized
+            // initialized under a mutex and it's assumed to be initialized
             // in the Scheduler ctor by any thread that needs to use it,
             // we are not accessing the key under a mutex.  Threads that
             // are not using the new Scheduler but still *want to check*
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index f537022cdf6..9d91545bc12 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -666,7 +666,7 @@ impl<'a> Iterator<char> for Normalizations<'a> {
 ///
 /// # Return value
 ///
-/// The original string with all occurances of `from` replaced with `to`
+/// The original string with all occurrences of `from` replaced with `to`
 pub fn replace(s: &str, from: &str, to: &str) -> ~str {
     let mut result = StrBuf::new();
     let mut last_end = 0;
@@ -1447,7 +1447,7 @@ pub mod raw {
     /// Sets the length of a string
     ///
     /// This will explicitly set the size of the string, without actually
-    /// modifing its buffers, so it is up to the caller to ensure that
+    /// modifying its buffers, so it is up to the caller to ensure that
     /// the string is actually the specified size.
     #[test]
     fn test_from_buf_len() {
@@ -2026,7 +2026,7 @@ pub trait StrSlice<'a> {
     ///
     /// # Return value
     ///
-    /// The original string with all occurances of `from` replaced with `to`.
+    /// The original string with all occurrences of `from` replaced with `to`.
     ///
     /// # Example
     ///
diff --git a/src/libstd/strbuf.rs b/src/libstd/strbuf.rs
index 873b7293032..86da11aceda 100644
--- a/src/libstd/strbuf.rs
+++ b/src/libstd/strbuf.rs
@@ -31,7 +31,7 @@ pub struct StrBuf {
 }
 
 impl StrBuf {
-    /// Creates a new string buffer initalized with the empty string.
+    /// Creates a new string buffer initialized with the empty string.
     #[inline]
     pub fn new() -> StrBuf {
         StrBuf {
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 585bed83101..c5f3206d9d5 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -135,7 +135,7 @@ impl<T> Vec<T> {
         Vec { len: length, cap: capacity, ptr: ptr }
     }
 
-    /// Consumes the `Vec`, partitioning it based on a predcate.
+    /// Consumes the `Vec`, partitioning it based on a predicate.
     ///
     /// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
     /// satisfy `f` and all elements of `B` do not. The order of elements is
@@ -279,7 +279,7 @@ impl<T: Clone> Vec<T> {
         *self.get_mut(index) = value;
     }
 
-    /// Partitions a vector based on a predcate.
+    /// Partitions a vector based on a predicate.
     ///
     /// Clones the elements of the vector, partitioning them into two `Vec`s
     /// `(A,B)`, where all elements of `A` satisfy `f` and all elements of `B`
diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs
index 792673e3298..693407b854f 100644
--- a/src/libsyntax/util/small_vector.rs
+++ b/src/libsyntax/util/small_vector.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::mem;
+use std::slice;
 use std::vec;
 
 /// A vector type optimized for cases where the size is almost always 0 or 1
@@ -61,6 +62,14 @@ impl<T> SmallVector<T> {
         SmallVector { repr: Many(vs) }
     }
 
+    pub fn as_slice<'a>(&'a self) -> &'a [T] {
+        match self.repr {
+            Zero => &[],
+            One(ref v) => slice::ref_slice(v),
+            Many(ref vs) => vs.as_slice()
+        }
+    }
+
     pub fn push(&mut self, v: T) {
         match self.repr {
             Zero => self.repr = One(v),
diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs
index 096279316d8..7587a21a9df 100644
--- a/src/test/bench/shootout-chameneos-redux.rs
+++ b/src/test/bench/shootout-chameneos-redux.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,89 +8,87 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// chameneos
+#![feature(phase)]
+#[phase(syntax)] extern crate green;
 
-use std::option;
-use std::os;
 use std::strbuf::StrBuf;
-use std::task;
+use std::fmt;
+
+green_start!(main)
 
 fn print_complements() {
     let all = [Blue, Red, Yellow];
     for aa in all.iter() {
         for bb in all.iter() {
-            println!("{} + {} -> {}", show_color(*aa), show_color(*bb),
-                show_color(transform(*aa, *bb)));
+            println!("{} + {} -> {}", *aa, *bb, transform(*aa, *bb));
         }
     }
 }
 
-enum color { Red, Yellow, Blue }
+enum Color { Red, Yellow, Blue }
+impl fmt::Show for Color {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let str = match *self {
+            Red => "red",
+            Yellow => "yellow",
+            Blue => "blue",
+        };
+        f.buf.write(str.as_bytes())
+    }
+}
 
 struct CreatureInfo {
     name: uint,
-    color: color
+    color: Color
 }
 
-fn show_color(cc: color) -> &'static str {
-    match cc {
-        Red    => "red",
-        Yellow => "yellow",
-        Blue   => "blue"
-    }
-}
-
-fn show_color_list(set: Vec<color>) -> StrBuf {
+fn show_color_list(set: Vec<Color>) -> StrBuf {
     let mut out = StrBuf::new();
     for col in set.iter() {
         out.push_char(' ');
-        out.push_str(show_color(*col));
+        out.push_str(col.to_str());
     }
     out
 }
 
 fn show_digit(nn: uint) -> &'static str {
     match nn {
-        0 => {"zero"}
-        1 => {"one"}
-        2 => {"two"}
-        3 => {"three"}
-        4 => {"four"}
-        5 => {"five"}
-        6 => {"six"}
-        7 => {"seven"}
-        8 => {"eight"}
-        9 => {"nine"}
+        0 => {" zero"}
+        1 => {" one"}
+        2 => {" two"}
+        3 => {" three"}
+        4 => {" four"}
+        5 => {" five"}
+        6 => {" six"}
+        7 => {" seven"}
+        8 => {" eight"}
+        9 => {" nine"}
         _ => {fail!("expected digits from 0 to 9...")}
     }
 }
 
-fn show_number(nn: uint) -> StrBuf {
-    let mut out = vec![];
-    let mut num = nn;
-    let mut dig;
-    let mut len = 0;
-    if num == 0 { out.push(show_digit(0)) };
-
-    while num != 0 {
-        dig = num % 10;
-        num = num / 10;
-        out.push(" ");
-        let s = show_digit(dig);
-        out.push(s);
-        len += 1 + s.len();
-    }
-    len += 1;
-    out.push(" ");
+struct Number(uint);
+impl fmt::Show for Number {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut out = vec![];
+        let Number(mut num) = *self;
+        if num == 0 { out.push(show_digit(0)) };
+
+        while num != 0 {
+            let dig = num % 10;
+            num = num / 10;
+            let s = show_digit(dig);
+            out.push(s);
+        }
 
-    let mut ret = StrBuf::with_capacity(len);
-    for s in out.iter().rev() {
-        ret.push_str(*s);
+        for s in out.iter().rev() {
+            try!(f.buf.write(s.as_bytes()));
+        }
+        Ok(())
     }
-    ret
 }
 
-fn transform(aa: color, bb: color) -> color {
+fn transform(aa: Color, bb: Color) -> Color {
     match (aa, bb) {
         (Red,    Red   ) => { Red    }
         (Red,    Yellow) => { Blue   }
@@ -106,23 +104,22 @@ fn transform(aa: color, bb: color) -> color {
 
 fn creature(
     name: uint,
-    color: color,
-    from_rendezvous: Receiver<Option<CreatureInfo>>,
+    mut color: Color,
+    from_rendezvous: Receiver<CreatureInfo>,
     to_rendezvous: Sender<CreatureInfo>,
     to_rendezvous_log: Sender<~str>
 ) {
-    let mut color = color;
     let mut creatures_met = 0;
     let mut evil_clones_met = 0;
+    let mut rendezvous = from_rendezvous.iter();
 
     loop {
         // ask for a pairing
         to_rendezvous.send(CreatureInfo {name: name, color: color});
-        let resp = from_rendezvous.recv();
 
-        // log and change, or print and quit
-        match resp {
-            option::Some(other_creature) => {
+        // log and change, or quit
+        match rendezvous.next() {
+            Some(other_creature) => {
                 color = transform(color, other_creature.color);
 
                 // track some statistics
@@ -131,41 +128,35 @@ fn creature(
                    evil_clones_met += 1;
                 }
             }
-            option::None => {
-                // log creatures met and evil clones of self
-                let report = format!("{} {}",
-                                     creatures_met, show_number(evil_clones_met).as_slice());
-                to_rendezvous_log.send(report);
-                break;
-            }
+            None => break
         }
     }
+    // log creatures met and evil clones of self
+    let report = format!("{}{}", creatures_met, Number(evil_clones_met));
+    to_rendezvous_log.send(report);
 }
 
-fn rendezvous(nn: uint, set: Vec<color>) {
-
+fn rendezvous(nn: uint, set: Vec<Color>) {
     // these ports will allow us to hear from the creatures
     let (to_rendezvous, from_creatures) = channel::<CreatureInfo>();
-    let (to_rendezvous_log, from_creatures_log) = channel::<~str>();
 
     // these channels will be passed to the creatures so they can talk to us
+    let (to_rendezvous_log, from_creatures_log) = channel::<~str>();
 
     // these channels will allow us to talk to each creature by 'name'/index
-    let mut to_creature: Vec<Sender<Option<CreatureInfo>>> =
-        set.iter().enumerate().map(|(ii, col)| {
+    let mut to_creature: Vec<Sender<CreatureInfo>> =
+        set.iter().enumerate().map(|(ii, &col)| {
             // create each creature as a listener with a port, and
             // give us a channel to talk to each
-            let ii = ii;
-            let col = *col;
             let to_rendezvous = to_rendezvous.clone();
             let to_rendezvous_log = to_rendezvous_log.clone();
             let (to_creature, from_rendezvous) = channel();
-            task::spawn(proc() {
+            spawn(proc() {
                 creature(ii,
                          col,
                          from_rendezvous,
-                         to_rendezvous.clone(),
-                         to_rendezvous_log.clone());
+                         to_rendezvous,
+                         to_rendezvous_log);
             });
             to_creature
         }).collect();
@@ -174,55 +165,42 @@ fn rendezvous(nn: uint, set: Vec<color>) {
 
     // set up meetings...
     for _ in range(0, nn) {
-        let mut fst_creature: CreatureInfo = from_creatures.recv();
-        let mut snd_creature: CreatureInfo = from_creatures.recv();
+        let fst_creature = from_creatures.recv();
+        let snd_creature = from_creatures.recv();
 
         creatures_met += 2;
 
-        to_creature.get_mut(fst_creature.name).send(Some(snd_creature));
-        to_creature.get_mut(snd_creature.name).send(Some(fst_creature));
+        to_creature.get_mut(fst_creature.name).send(snd_creature);
+        to_creature.get_mut(snd_creature.name).send(fst_creature);
     }
 
     // tell each creature to stop
-    for to_one in to_creature.iter() {
-        to_one.send(None);
-    }
-
-    // save each creature's meeting stats
-    let mut report = Vec::new();
-    for _to_one in to_creature.iter() {
-        report.push(from_creatures_log.recv());
-    }
+    drop(to_creature);
 
     // print each color in the set
     println!("{}", show_color_list(set));
 
     // print each creature's stats
-    for rep in report.iter() {
-        println!("{}", *rep);
+    drop(to_rendezvous_log);
+    for rep in from_creatures_log.iter() {
+        println!("{}", rep);
     }
 
     // print the total number of creatures met
-    println!("{}", show_number(creatures_met));
+    println!("{}\n", Number(creatures_met));
 }
 
 fn main() {
-    let args = os::args();
-    let args = if os::getenv("RUST_BENCH").is_some() {
-        vec!("".to_owned(), "200000".to_owned())
-    } else if args.len() <= 1u {
-        vec!("".to_owned(), "600".to_owned())
+    let nn = if std::os::getenv("RUST_BENCH").is_some() {
+        200000
     } else {
-        args.move_iter().collect()
+        std::os::args().get(1).and_then(|arg| from_str(*arg)).unwrap_or(600)
     };
 
-    let nn = from_str::<uint>(*args.get(1)).unwrap();
-
     print_complements();
     println!("");
 
     rendezvous(nn, vec!(Blue, Red, Yellow));
-    println!("");
 
     rendezvous(nn,
         vec!(Blue, Red, Yellow, Red, Yellow, Blue, Red, Yellow, Red, Blue));
diff --git a/src/test/compile-fail/issue-13599.rs b/src/test/compile-fail/issue-13599.rs
new file mode 100644
index 00000000000..de1a9e13f9e
--- /dev/null
+++ b/src/test/compile-fail/issue-13599.rs
@@ -0,0 +1,23 @@
+// Copyright 2012-2014 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.
+
+// Test that a mismatched proc / closure type is correctly reported.
+
+fn expect_closure(_: ||) {}
+
+fn expect_proc(_: proc()) {}
+
+fn main() {
+    expect_closure(proc() {});
+    //~^ ERROR mismatched types: expected `||` but found `proc()` (expected closure, found proc)
+
+    expect_proc(|| {});
+    //~^ ERROR mismatched types: expected `proc()` but found `||` (expected proc, found closure)
+}
diff --git a/src/test/compile-fail/typeck-unsafe-always-share.rs b/src/test/compile-fail/typeck-unsafe-always-share.rs
new file mode 100644
index 00000000000..6dec86ddf62
--- /dev/null
+++ b/src/test/compile-fail/typeck-unsafe-always-share.rs
@@ -0,0 +1,43 @@
+// Copyright 2014 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.
+
+// Verify that Unsafe is *always* share regardles `T` is share.
+
+// ignore-tidy-linelength
+
+use std::ty::Unsafe;
+use std::kinds::marker;
+
+struct MyShare<T> {
+    u: Unsafe<T>
+}
+
+struct NoShare {
+    m: marker::NoShare
+}
+
+fn test<T: Share>(s: T){
+
+}
+
+fn main() {
+    let us = Unsafe::new(MyShare{u: Unsafe::new(0)});
+    test(us);
+
+    let uns = Unsafe::new(NoShare{m: marker::NoShare});
+    test(uns);
+
+    let ms = MyShare{u: uns};
+    test(ms);
+
+    let ns = NoShare{m: marker::NoShare};
+    test(ns);
+    //~^ ERROR instantiating a type parameter with an incompatible type `NoShare`, which does not fulfill `Share`
+}