about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-12-27 16:09:29 -0800
committerPatrick Walton <pcwalton@mimiga.net>2014-01-03 14:01:58 -0800
commit449ebeea08a3e0c50b3487bc6d561f49caf57b7e (patch)
tree3898e84510f8eebf2fa15e5fe815d5dee52afc2c
parent12ad1b0662aed1f2f1b23d6c4a0a2cf43c92200a (diff)
downloadrust-449ebeea08a3e0c50b3487bc6d561f49caf57b7e.tar.gz
rust-449ebeea08a3e0c50b3487bc6d561f49caf57b7e.zip
librustc: De-`@mut` the AST map
-rw-r--r--src/librustc/metadata/encoder.rs9
-rw-r--r--src/librustc/middle/borrowck/mod.rs3
-rw-r--r--src/librustc/middle/check_const.rs8
-rw-r--r--src/librustc/middle/const_eval.rs45
-rw-r--r--src/librustc/middle/dead.rs8
-rw-r--r--src/librustc/middle/entry.rs29
-rw-r--r--src/librustc/middle/lint.rs3
-rw-r--r--src/librustc/middle/privacy.rs6
-rw-r--r--src/librustc/middle/reachable.rs21
-rw-r--r--src/librustc/middle/trans/base.rs16
-rw-r--r--src/librustc/middle/trans/callee.rs25
-rw-r--r--src/librustc/middle/trans/consts.rs8
-rw-r--r--src/librustc/middle/trans/debuginfo.rs60
-rw-r--r--src/librustc/middle/trans/foreign.rs15
-rw-r--r--src/librustc/middle/trans/intrinsic.rs9
-rw-r--r--src/librustc/middle/trans/meth.rs11
-rw-r--r--src/librustc/middle/trans/monomorphize.rs16
-rw-r--r--src/librustc/middle/ty.rs281
-rw-r--r--src/librustc/middle/typeck/check/method.rs15
-rw-r--r--src/librustc/middle/typeck/coherence.rs30
-rw-r--r--src/librustc/middle/typeck/collect.rs42
-rw-r--r--src/librustc/middle/typeck/mod.rs6
-rw-r--r--src/librustc/util/ppaux.rs32
-rw-r--r--src/libsyntax/ast_map.rs94
24 files changed, 471 insertions, 321 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index fd2deb80984..4592b88a0fa 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -489,7 +489,8 @@ fn encode_reexported_static_methods(ecx: &EncodeContext,
                                     ebml_w: &mut writer::Encoder,
                                     mod_path: &[ast_map::path_elt],
                                     exp: &middle::resolve::Export2) {
-    match ecx.tcx.items.find(&exp.def_id.node) {
+    let items = ecx.tcx.items.borrow();
+    match items.get().find(&exp.def_id.node) {
         Some(&ast_map::node_item(item, path)) => {
             let original_name = ecx.tcx.sess.str_of(item.ident);
 
@@ -1338,7 +1339,8 @@ fn my_visit_item(i: @item,
                  ebml_w: &mut writer::Encoder,
                  ecx_ptr: *int,
                  index: @RefCell<~[entry<i64>]>) {
-    match items.get_copy(&i.id) {
+    let items = items.borrow();
+    match items.get().get_copy(&i.id) {
         ast_map::node_item(_, pt) => {
             let mut ebml_w = unsafe {
                 ebml_w.unsafe_clone()
@@ -1356,7 +1358,8 @@ fn my_visit_foreign_item(ni: @foreign_item,
                          ebml_w: &mut writer::Encoder,
                          ecx_ptr:*int,
                          index: @RefCell<~[entry<i64>]>) {
-    match items.get_copy(&ni.id) {
+    let items = items.borrow();
+    match items.get().get_copy(&ni.id) {
         ast_map::node_foreign_item(_, abi, _, pt) => {
             debug!("writing foreign item {}::{}",
                    ast_map::path_to_str(
diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs
index ddc31598d67..44b967aade6 100644
--- a/src/librustc/middle/borrowck/mod.rs
+++ b/src/librustc/middle/borrowck/mod.rs
@@ -788,7 +788,8 @@ impl BorrowckCtxt {
                                    out: &mut ~str) {
         match *loan_path {
             LpVar(id) => {
-                match self.tcx.items.find(&id) {
+                let items = self.tcx.items.borrow();
+                match items.get().find(&id) {
                     Some(&ast_map::node_local(ref ident)) => {
                         out.push_str(token::ident_to_str(ident));
                     }
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 4dfdd00c27a..a6a51e95083 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -266,13 +266,15 @@ impl Visitor<()> for CheckItemRecursionVisitor {
                 let def_map = self.env.def_map.borrow();
                 match def_map.get().find(&e.id) {
                     Some(&DefStatic(def_id, _)) if
-                            ast_util::is_local(def_id) =>
-                        match self.env.ast_map.get_copy(&def_id.node) {
+                            ast_util::is_local(def_id) => {
+                        let ast_map = self.env.ast_map.borrow();
+                        match ast_map.get().get_copy(&def_id.node) {
                             ast_map::node_item(it, _) => {
                                 self.visit_item(it, ());
                             }
                             _ => fail!("const not bound to an item")
-                        },
+                        }
+                    }
                     _ => ()
                 }
             },
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index d0dd36cda96..b9b0b807e6e 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -107,15 +107,18 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
     }
 
     if ast_util::is_local(enum_def) {
-        match tcx.items.find(&enum_def.node) {
-            None => None,
-            Some(&ast_map::node_item(it, _)) => match it.node {
-                item_enum(ast::enum_def { variants: ref variants }, _) => {
-                    variant_expr(*variants, variant_def.node)
-                }
-                _ => None
-            },
-            Some(_) => None
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&enum_def.node) {
+                None => None,
+                Some(&ast_map::node_item(it, _)) => match it.node {
+                    item_enum(ast::enum_def { variants: ref variants }, _) => {
+                        variant_expr(*variants, variant_def.node)
+                    }
+                    _ => None
+                },
+                Some(_) => None
+            }
         }
     } else {
         {
@@ -155,17 +158,21 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
     }
 }
 
-pub fn lookup_const_by_id(tcx: ty::ctxt,
-                          def_id: ast::DefId)
-                       -> Option<@Expr> {
+pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
+                          -> Option<@Expr> {
     if ast_util::is_local(def_id) {
-        match tcx.items.find(&def_id.node) {
-            None => None,
-            Some(&ast_map::node_item(it, _)) => match it.node {
-                item_static(_, ast::MutImmutable, const_expr) => Some(const_expr),
-                _ => None
-            },
-            Some(_) => None
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&def_id.node) {
+                None => None,
+                Some(&ast_map::node_item(it, _)) => match it.node {
+                    item_static(_, ast::MutImmutable, const_expr) => {
+                        Some(const_expr)
+                    }
+                    _ => None
+                },
+                Some(_) => None
+            }
         }
     } else {
         {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 727360a361f..2bdbce9b763 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -34,7 +34,9 @@ fn should_explore(tcx: ty::ctxt, def_id: ast::DefId) -> bool {
     if !is_local(def_id) {
         return false;
     }
-    match tcx.items.find(&def_id.node) {
+
+    let items = tcx.items.borrow();
+    match items.get().find(&def_id.node) {
         Some(&ast_map::node_item(..))
         | Some(&ast_map::node_method(..))
         | Some(&ast_map::node_foreign_item(..))
@@ -130,7 +132,9 @@ impl MarkSymbolVisitor {
                 continue
             }
             scanned.insert(id);
-            match self.tcx.items.find(&id) {
+
+            let items = self.tcx.items.borrow();
+            match items.get().find(&id) {
                 Some(node) => {
                     self.live_symbols.insert(id);
                     self.visit_node(node);
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 53a8b93c232..89cb902cf10 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -74,23 +74,26 @@ fn find_item(item: @item, ctxt: &mut EntryContext) {
     match item.node {
         item_fn(..) => {
             if item.ident.name == special_idents::main.name {
-                match ctxt.ast_map.find(&item.id) {
-                    Some(&ast_map::node_item(_, path)) => {
-                        if path.len() == 0 {
-                            // This is a top-level function so can be 'main'
-                            if ctxt.main_fn.is_none() {
-                                ctxt.main_fn = Some((item.id, item.span));
+                {
+                    let ast_map = ctxt.ast_map.borrow();
+                    match ast_map.get().find(&item.id) {
+                        Some(&ast_map::node_item(_, path)) => {
+                            if path.len() == 0 {
+                                // This is a top-level function so can be 'main'
+                                if ctxt.main_fn.is_none() {
+                                    ctxt.main_fn = Some((item.id, item.span));
+                                } else {
+                                    ctxt.session.span_err(
+                                        item.span,
+                                        "multiple 'main' functions");
+                                }
                             } else {
-                                ctxt.session.span_err(
-                                    item.span,
-                                    "multiple 'main' functions");
+                                // This isn't main
+                                ctxt.non_main_fns.push((item.id, item.span));
                             }
-                        } else {
-                            // This isn't main
-                            ctxt.non_main_fns.push((item.id, item.span));
                         }
+                        _ => unreachable!()
                     }
-                    _ => unreachable!()
                 }
             }
 
diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs
index de6a133eaac..7503419f8b6 100644
--- a/src/librustc/middle/lint.rs
+++ b/src/librustc/middle/lint.rs
@@ -1238,7 +1238,8 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
 
     let stability = if ast_util::is_local(id) {
         // this crate
-        match cx.tcx.items.find(&id.node) {
+        let items = cx.tcx.items.borrow();
+        match items.get().find(&id.node) {
             Some(ast_node) => {
                 let s = ast_node.with_attrs(|attrs| {
                     attrs.map(|a| {
diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs
index a0da1680d00..435bdcc2607 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -413,7 +413,8 @@ impl<'a> PrivacyVisitor<'a> {
         let mut closest_private_id = did.node;
         loop {
             debug!("privacy - examining {}", self.nodestr(closest_private_id));
-            let vis = match self.tcx.items.find(&closest_private_id) {
+            let items = self.tcx.items.borrow();
+            let vis = match items.get().find(&closest_private_id) {
                 // If this item is a method, then we know for sure that it's an
                 // actual method and not a static method. The reason for this is
                 // that these cases are only hit in the ExprMethodCall
@@ -519,7 +520,8 @@ impl<'a> PrivacyVisitor<'a> {
                     self.tcx.sess.span_err(span, format!("{} is inaccessible",
                                                          msg));
                 }
-                match self.tcx.items.find(&id) {
+                let items = self.tcx.items.borrow();
+                match items.get().find(&id) {
                     Some(&ast_map::node_item(item, _)) => {
                         let desc = match item.node {
                             ast::item_mod(..) => "module",
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index bbf366c0b06..5e50017b93e 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -65,10 +65,15 @@ fn method_might_be_inlined(tcx: ty::ctxt, method: &ast::method,
         return true
     }
     if is_local(impl_src) {
-        match tcx.items.find(&impl_src.node) {
-            Some(&ast_map::node_item(item, _)) => item_might_be_inlined(item),
-            Some(..) | None => {
-                tcx.sess.span_bug(method.span, "impl did is not an item")
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&impl_src.node) {
+                Some(&ast_map::node_item(item, _)) => {
+                    item_might_be_inlined(item)
+                }
+                Some(..) | None => {
+                    tcx.sess.span_bug(method.span, "impl did is not an item")
+                }
             }
         }
     } else {
@@ -208,7 +213,8 @@ impl ReachableContext {
         }
 
         let node_id = def_id.node;
-        match tcx.items.find(&node_id) {
+        let items = tcx.items.borrow();
+        match items.get().find(&node_id) {
             Some(&ast_map::node_item(item, _)) => {
                 match item.node {
                     ast::item_fn(..) => item_might_be_inlined(item),
@@ -229,7 +235,7 @@ impl ReachableContext {
                     // Check the impl. If the generics on the self type of the
                     // impl require inlining, this method does too.
                     assert!(impl_did.crate == ast::LOCAL_CRATE);
-                    match tcx.items.find(&impl_did.node) {
+                    match items.get().find(&impl_did.node) {
                         Some(&ast_map::node_item(item, _)) => {
                             match item.node {
                                 ast::item_impl(ref generics, _, _, _) => {
@@ -288,7 +294,8 @@ impl ReachableContext {
             };
 
             scanned.insert(search_item);
-            match self.tcx.items.find(&search_item) {
+            let items = self.tcx.items.borrow();
+            match items.get().find(&search_item) {
                 Some(item) => self.propagate_node(item, search_item,
                                                   &mut visitor),
                 None if search_item == ast::CRATE_NODE_ID => {}
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index ad953440316..59f6fede198 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2210,10 +2210,13 @@ impl Visitor<()> for TransItemVisitor {
 
 pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
     let _icx = push_ctxt("trans_item");
-    let path = match ccx.tcx.items.get_copy(&item.id) {
-        ast_map::node_item(_, p) => p,
-        // tjc: ?
-        _ => fail!("trans_item"),
+    let path = {
+        let items = ccx.tcx.items.borrow();
+        match items.get().get_copy(&item.id) {
+            ast_map::node_item(_, p) => p,
+            // tjc: ?
+            _ => fail!("trans_item"),
+        }
     };
     match item.node {
       ast::item_fn(decl, purity, _abis, ref generics, body) => {
@@ -2508,7 +2511,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
         Some(v) => v,
         None => {
             let mut foreign = false;
-            let item = ccx.tcx.items.get_copy(&id);
+            let item = {
+                let items = ccx.tcx.items.borrow();
+                items.get().get_copy(&id)
+            };
             let val = match item {
                 ast_map::node_item(i, pth) => {
 
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index df916f0463b..05b3e8275a3 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -360,17 +360,20 @@ pub fn trans_fn_ref_with_vtables(
     if type_params.len() > 0 || is_default {
         must_monomorphise = true;
     } else if def_id.crate == ast::LOCAL_CRATE {
-        let map_node = session::expect(
-            ccx.sess,
-            ccx.tcx.items.find(&def_id.node),
-            || format!("local item should be in ast map"));
-
-        match *map_node {
-            ast_map::node_foreign_item(_, abis, _, _) => {
-                must_monomorphise = abis.is_intrinsic()
-            }
-            _ => {
-                must_monomorphise = false;
+        {
+            let items = ccx.tcx.items.borrow();
+            let map_node = session::expect(
+                ccx.sess,
+                items.get().find(&def_id.node),
+                || format!("local item should be in ast map"));
+
+            match *map_node {
+                ast_map::node_foreign_item(_, abis, _, _) => {
+                    must_monomorphise = abis.is_intrinsic()
+                }
+                _ => {
+                    must_monomorphise = false;
+                }
             }
         }
     } else {
diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs
index c9d30ec1994..0dd8b841bcf 100644
--- a/src/librustc/middle/trans/consts.rs
+++ b/src/librustc/middle/trans/consts.rs
@@ -165,7 +165,13 @@ pub fn get_const_val(cx: @CrateContext,
         if !ast_util::is_local(def_id) {
             def_id = inline::maybe_instantiate_inline(cx, def_id);
         }
-        match cx.tcx.items.get_copy(&def_id.node) {
+
+        let opt_item = {
+            let items = cx.tcx.items.borrow();
+            items.get().get_copy(&def_id.node)
+        };
+
+        match opt_item {
             ast_map::node_item(@ast::item {
                 node: ast::item_static(_, ast::MutImmutable, _), ..
             }, _) => {
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 88dc4928164..3170a290a41 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -323,7 +323,10 @@ pub fn create_captured_var_metadata(bcx: @Block,
 
     let cx = bcx.ccx();
 
-    let ast_item = cx.tcx.items.find_copy(&node_id);
+    let ast_item = {
+        let items = cx.tcx.items.borrow();
+        items.get().find_copy(&node_id)
+    };
     let variable_ident = match ast_item {
         None => {
             cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
@@ -422,7 +425,10 @@ pub fn create_self_argument_metadata(bcx: @Block,
     }
 
     // Extract the span of the self argument from the method's AST
-    let fnitem = bcx.ccx().tcx.items.get_copy(&bcx.fcx.id);
+    let fnitem = {
+        let items = bcx.ccx().tcx.items.borrow();
+        items.get().get_copy(&bcx.fcx.id)
+    };
     let span = match fnitem {
         ast_map::node_method(@ast::method { explicit_self: explicit_self, .. }, _, _) => {
             explicit_self.span
@@ -609,7 +615,10 @@ pub fn create_function_debug_context(cx: &CrateContext,
 
     let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty };
 
-    let fnitem = cx.tcx.items.get_copy(&fn_ast_id);
+    let fnitem = {
+        let items = cx.tcx.items.borrow();
+        items.get().get_copy(&fn_ast_id)
+    };
     let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
         ast_map::node_item(ref item, _) => {
             match item.node {
@@ -1092,7 +1101,8 @@ fn scope_metadata(fcx: &FunctionContext,
     match scope_map.get().find_copy(&node_id) {
         Some(scope_metadata) => scope_metadata,
         None => {
-            let node = fcx.ccx.tcx.items.get_copy(&node_id);
+            let items = fcx.ccx.tcx.items.borrow();
+            let node = items.get().get_copy(&node_id);
 
             fcx.ccx.sess.span_bug(span,
                 format!("debuginfo: Could not find scope info for node {:?}", node));
@@ -1411,13 +1421,17 @@ fn describe_enum_variant(cx: &CrateContext,
 
     // Find the source code location of the variant's definition
     let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
-        match cx.tcx.items.find(&variant_info.id.node) {
-            Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
-            ref node => {
-                cx.sess.span_warn(span,
-                    format!("debuginfo::enum_metadata()::adt_struct_metadata() - Unexpected node \
-                          type: {:?}. This is a bug.", node));
-                codemap::DUMMY_SP
+        {
+            let items = cx.tcx.items.borrow();
+            match items.get().find(&variant_info.id.node) {
+                Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
+                ref node => {
+                    cx.sess.span_warn(span,
+                        format!("debuginfo::enum_metadata()::\
+                                 adt_struct_metadata() - Unexpected node \
+                                 type: {:?}. This is a bug.", node));
+                    codemap::DUMMY_SP
+                }
             }
         }
     } else {
@@ -2296,16 +2310,20 @@ fn get_namespace_and_span_for_item(cx: &CrateContext,
                                 -> (DIScope, Span) {
     let containing_scope = namespace_for_item(cx, def_id, warning_span).scope;
     let definition_span = if def_id.crate == ast::LOCAL_CRATE {
-        let definition_span = match cx.tcx.items.find(&def_id.node) {
-            Some(&ast_map::node_item(@ast::item { span, .. }, _)) => span,
-            ref node => {
-                cx.sess.span_warn(warning_span,
-                    format!("debuginfo::get_namespace_and_span_for_item() \
-                             - Unexpected node type: {:?}", *node));
-                codemap::DUMMY_SP
-            }
-        };
-        definition_span
+        {
+            let items = cx.tcx.items.borrow();
+            let definition_span = match items.get().find(&def_id.node) {
+                Some(&ast_map::node_item(@ast::item { span, .. }, _)) => span,
+                ref node => {
+                    cx.sess.span_warn(warning_span,
+                        format!("debuginfo::\
+                                 get_namespace_and_span_for_item() \
+                                 - Unexpected node type: {:?}", *node));
+                    codemap::DUMMY_SP
+                }
+            };
+            definition_span
+        }
     } else {
         // For external items there is no span information
         codemap::DUMMY_SP
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 21f268fb947..7c4c9f8937f 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -355,10 +355,17 @@ pub fn trans_foreign_mod(ccx: @CrateContext,
     for &foreign_item in foreign_mod.items.iter() {
         match foreign_item.node {
             ast::foreign_item_fn(..) => {
-                let (abis, mut path) = match ccx.tcx.items.get_copy(&foreign_item.id) {
-                    ast_map::node_foreign_item(_, abis, _, path) => (abis, (*path).clone()),
-                    _ => fail!("Unable to find foreign item in tcx.items table.")
-                };
+                let items = ccx.tcx.items.borrow();
+                let (abis, mut path) =
+                    match items.get().get_copy(&foreign_item.id) {
+                        ast_map::node_foreign_item(_, abis, _, path) => {
+                            (abis, (*path).clone())
+                        }
+                        _ => {
+                            fail!("Unable to find foreign item in tcx.items \
+                                   table.")
+                        }
+                    };
                 if !(abis.is_rust() || abis.is_intrinsic()) {
                     path.push(ast_map::path_name(foreign_item.ident));
                     register_foreign_item_fn(ccx, abis, &path, foreign_item);
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index f652fbec228..c1096f73322 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -346,9 +346,12 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             let in_type_size = machine::llbitsize_of_real(ccx, llintype);
             let out_type_size = machine::llbitsize_of_real(ccx, llouttype);
             if in_type_size != out_type_size {
-                let sp = match ccx.tcx.items.get_copy(&ref_id.unwrap()) {
-                    ast_map::node_expr(e) => e.span,
-                    _ => fail!("transmute has non-expr arg"),
+                let sp = {
+                    let items = ccx.tcx.items.borrow();
+                    match items.get().get_copy(&ref_id.unwrap()) {
+                        ast_map::node_expr(e) => e.span,
+                        _ => fail!("transmute has non-expr arg"),
+                    }
                 };
                 let pluralize = |n| if 1u == n { "" } else { "s" };
                 ccx.sess.span_fatal(sp,
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index d16cf6f1c3b..d54dd23af96 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -246,11 +246,14 @@ pub fn trans_static_method_callee(bcx: @Block,
         generics.type_param_defs.len();
 
     let mname = if method_id.crate == ast::LOCAL_CRATE {
-        match bcx.tcx().items.get_copy(&method_id.node) {
-            ast_map::node_trait_method(trait_method, _, _) => {
-                ast_util::trait_method_to_ty_method(trait_method).ident
+        {
+            let items = bcx.tcx().items.borrow();
+            match items.get().get_copy(&method_id.node) {
+                ast_map::node_trait_method(trait_method, _, _) => {
+                    ast_util::trait_method_to_ty_method(trait_method).ident
+                }
+                _ => fail!("callee is not a trait method")
             }
-            _ => fail!("callee is not a trait method")
         }
     } else {
         let path = csearch::get_item_path(bcx.tcx(), method_id);
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index cf6bebbb1a2..a60ddc9d8b6 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -95,12 +95,16 @@ pub fn monomorphic_fn(ccx: @CrateContext,
     // calling a static provided method. This is sort of unfortunate.
     let mut is_static_provided = None;
 
-    let map_node = session::expect(
-        ccx.sess,
-        ccx.tcx.items.find_copy(&fn_id.node),
-        || format!("While monomorphizing {:?}, couldn't find it in the item map \
-                 (may have attempted to monomorphize an item \
-                 defined in a different crate?)", fn_id));
+    let map_node = {
+        let items = ccx.tcx.items.borrow();
+        session::expect(
+            ccx.sess,
+            items.get().find_copy(&fn_id.node),
+            || format!("While monomorphizing {:?}, couldn't find it in the \
+                        item map (may have attempted to monomorphize an item \
+                        defined in a different crate?)", fn_id))
+    };
+
     // Get the path so that we can create a symbol
     let (pt, name, span) = match map_node {
       ast_map::node_item(i, pt) => (pt, i.ident, i.span),
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index f1f653a6900..7abc2a34a1f 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3556,16 +3556,19 @@ pub fn provided_source(cx: ctxt, id: ast::DefId) -> Option<ast::DefId> {
 
 pub fn provided_trait_methods(cx: ctxt, id: ast::DefId) -> ~[@Method] {
     if is_local(id) {
-        match cx.items.find(&id.node) {
-            Some(&ast_map::node_item(@ast::item {
-                        node: item_trait(_, _, ref ms),
-                        ..
-                    }, _)) =>
-                match ast_util::split_trait_methods(*ms) {
-                   (_, p) => p.map(|m| method(cx, ast_util::local_def(m.id)))
-                },
-            _ => cx.sess.bug(format!("provided_trait_methods: {:?} is not a trait",
-                                  id))
+        {
+            let items = cx.items.borrow();
+            match items.get().find(&id.node) {
+                Some(&ast_map::node_item(@ast::item {
+                            node: item_trait(_, _, ref ms),
+                            ..
+                        }, _)) =>
+                    match ast_util::split_trait_methods(*ms) {
+                       (_, p) => p.map(|m| method(cx, ast_util::local_def(m.id)))
+                    },
+                _ => cx.sess.bug(format!("provided_trait_methods: {:?} is not a trait",
+                                      id))
+            }
         }
     } else {
         csearch::get_provided_trait_methods(cx, id)
@@ -3675,17 +3678,20 @@ pub fn impl_trait_ref(cx: ctxt, id: ast::DefId) -> Option<@TraitRef> {
 
     let ret = if id.crate == ast::LOCAL_CRATE {
         debug!("(impl_trait_ref) searching for trait impl {:?}", id);
-        match cx.items.find(&id.node) {
-            Some(&ast_map::node_item(@ast::item {
-                                     node: ast::item_impl(_, ref opt_trait, _, _),
-                                     ..},
-                                     _)) => {
-                match opt_trait {
-                    &Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
-                    &None => None
+        {
+            let items = cx.items.borrow();
+            match items.get().find(&id.node) {
+                Some(&ast_map::node_item(@ast::item {
+                     node: ast::item_impl(_, ref opt_trait, _, _),
+                     ..},
+                     _)) => {
+                    match opt_trait {
+                        &Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
+                        &None => None
+                    }
                 }
+                _ => None
             }
-            _ => None
         }
     } else {
         csearch::get_impl_trait(cx, id)
@@ -3857,54 +3863,55 @@ pub fn has_dtor(cx: ctxt, struct_id: DefId) -> bool {
 
 pub fn item_path(cx: ctxt, id: ast::DefId) -> ast_map::path {
     if id.crate != ast::LOCAL_CRATE {
-        csearch::get_item_path(cx, id)
-    } else {
-        // FIXME (#5521): uncomment this code and don't have a catch-all at the
-        //                end of the match statement. Favor explicitly listing
-        //                each variant.
-        // let node = cx.items.get(&id.node);
-        // match *node {
-        match *cx.items.get(&id.node) {
-          ast_map::node_item(item, path) => {
-            let item_elt = match item.node {
-              item_mod(_) | item_foreign_mod(_) => {
-                ast_map::path_mod(item.ident)
-              }
-              _ => {
-                ast_map::path_name(item.ident)
-              }
-            };
-            vec::append_one((*path).clone(), item_elt)
+        return csearch::get_item_path(cx, id)
+    }
+
+    // FIXME (#5521): uncomment this code and don't have a catch-all at the
+    //                end of the match statement. Favor explicitly listing
+    //                each variant.
+    // let node = cx.items.get(&id.node);
+    // match *node {
+    let items = cx.items.borrow();
+    match *items.get().get(&id.node) {
+      ast_map::node_item(item, path) => {
+        let item_elt = match item.node {
+          item_mod(_) | item_foreign_mod(_) => {
+            ast_map::path_mod(item.ident)
           }
-
-          ast_map::node_foreign_item(nitem, _, _, path) => {
-            vec::append_one((*path).clone(),
-                            ast_map::path_name(nitem.ident))
+          _ => {
+            ast_map::path_name(item.ident)
           }
+        };
+        vec::append_one((*path).clone(), item_elt)
+      }
 
-          ast_map::node_method(method, _, path) => {
-            vec::append_one((*path).clone(),
-                            ast_map::path_name(method.ident))
-          }
-          ast_map::node_trait_method(trait_method, _, path) => {
-            let method = ast_util::trait_method_to_ty_method(&*trait_method);
-            vec::append_one((*path).clone(),
-                            ast_map::path_name(method.ident))
-          }
+      ast_map::node_foreign_item(nitem, _, _, path) => {
+        vec::append_one((*path).clone(),
+                        ast_map::path_name(nitem.ident))
+      }
 
-          ast_map::node_variant(ref variant, _, path) => {
-            vec::append_one(path.init().to_owned(),
-                            ast_map::path_name((*variant).node.name))
-          }
+      ast_map::node_method(method, _, path) => {
+        vec::append_one((*path).clone(),
+                        ast_map::path_name(method.ident))
+      }
+      ast_map::node_trait_method(trait_method, _, path) => {
+        let method = ast_util::trait_method_to_ty_method(&*trait_method);
+        vec::append_one((*path).clone(),
+                        ast_map::path_name(method.ident))
+      }
 
-          ast_map::node_struct_ctor(_, item, path) => {
-            vec::append_one((*path).clone(), ast_map::path_name(item.ident))
-          }
+      ast_map::node_variant(ref variant, _, path) => {
+        vec::append_one(path.init().to_owned(),
+                        ast_map::path_name((*variant).node.name))
+      }
 
-          ref node => {
-            cx.sess.bug(format!("cannot find item_path for node {:?}", node));
-          }
-        }
+      ast_map::node_struct_ctor(_, item, path) => {
+        vec::append_one((*path).clone(), ast_map::path_name(item.ident))
+      }
+
+      ref node => {
+        cx.sess.bug(format!("cannot find item_path for node {:?}", node));
+      }
     }
 }
 
@@ -3936,40 +3943,43 @@ pub fn enum_variants(cx: ctxt, id: ast::DefId) -> @~[@VariantInfo] {
           call eval_const_expr, it should never get called twice for the same
           expr, since check_enum_variants also updates the enum_var_cache
          */
-        match cx.items.get_copy(&id.node) {
-          ast_map::node_item(@ast::item {
-                    node: ast::item_enum(ref enum_definition, _),
-                    ..
-                }, _) => {
-            let mut last_discriminant: Option<Disr> = None;
-            @enum_definition.variants.iter().map(|&variant| {
-
-                let mut discriminant = match last_discriminant {
-                    Some(val) => val + 1,
-                    None => INITIAL_DISCRIMINANT_VALUE
-                };
-
-                match variant.node.disr_expr {
-                    Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
-                        Ok(const_eval::const_int(val)) => discriminant = val as Disr,
-                        Ok(const_eval::const_uint(val)) => discriminant = val as Disr,
-                        Ok(_) => {
-                            cx.sess.span_err(e.span, "expected signed integer constant");
-                        }
-                        Err(ref err) => {
-                            cx.sess.span_err(e.span, format!("expected constant: {}", (*err)));
-                        }
-                    },
-                    None => {}
-                };
-
-                let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
-                last_discriminant = Some(discriminant);
-                variant_info
-
-            }).collect()
-          }
-          _ => cx.sess.bug("enum_variants: id not bound to an enum")
+        {
+            let items = cx.items.borrow();
+            match items.get().get_copy(&id.node) {
+              ast_map::node_item(@ast::item {
+                        node: ast::item_enum(ref enum_definition, _),
+                        ..
+                    }, _) => {
+                let mut last_discriminant: Option<Disr> = None;
+                @enum_definition.variants.iter().map(|&variant| {
+
+                    let mut discriminant = match last_discriminant {
+                        Some(val) => val + 1,
+                        None => INITIAL_DISCRIMINANT_VALUE
+                    };
+
+                    match variant.node.disr_expr {
+                        Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
+                            Ok(const_eval::const_int(val)) => discriminant = val as Disr,
+                            Ok(const_eval::const_uint(val)) => discriminant = val as Disr,
+                            Ok(_) => {
+                                cx.sess.span_err(e.span, "expected signed integer constant");
+                            }
+                            Err(ref err) => {
+                                cx.sess.span_err(e.span, format!("expected constant: {}", (*err)));
+                            }
+                        },
+                        None => {}
+                    };
+
+                    let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
+                    last_discriminant = Some(discriminant);
+                    variant_info
+
+                }).collect()
+              }
+              _ => cx.sess.bug("enum_variants: id not bound to an enum")
+            }
         }
     };
 
@@ -4040,11 +4050,17 @@ pub fn lookup_trait_def(cx: ctxt, did: ast::DefId) -> @ty::TraitDef {
 // decoder to use iterators instead of higher-order functions.)
 pub fn each_attr(tcx: ctxt, did: DefId, f: |@MetaItem| -> bool) -> bool {
     if is_local(did) {
-        match tcx.items.find(&did.node) {
-            Some(&ast_map::node_item(@ast::item {attrs: ref attrs, ..}, _)) =>
-                attrs.iter().advance(|attr| f(attr.node.value)),
-            _ => tcx.sess.bug(format!("has_attr: {:?} is not an item",
-                                      did))
+        {
+            let items = tcx.items.borrow();
+            match items.get().find(&did.node) {
+                Some(&ast_map::node_item(@ast::item {
+                    attrs: ref attrs,
+                    ..
+                }, _)) =>
+                    attrs.iter().advance(|attr| f(attr.node.value)),
+                _ => tcx.sess.bug(format!("has_attr: {:?} is not an item",
+                                          did))
+            }
         }
     } else {
         let mut cont = true;
@@ -4120,37 +4136,39 @@ pub fn lookup_field_type(tcx: ctxt,
 // Fails if the id is not bound to a struct.
 pub fn lookup_struct_fields(cx: ctxt, did: ast::DefId) -> ~[field_ty] {
   if did.crate == ast::LOCAL_CRATE {
-    match cx.items.find(&did.node) {
-       Some(&ast_map::node_item(i,_)) => {
-         match i.node {
-            ast::item_struct(struct_def, _) => {
-               struct_field_tys(struct_def.fields)
-            }
-            _ => cx.sess.bug("struct ID bound to non-struct")
-         }
-       }
-       Some(&ast_map::node_variant(ref variant, _, _)) => {
-          match (*variant).node.kind {
-            ast::struct_variant_kind(struct_def) => {
-              struct_field_tys(struct_def.fields)
-            }
-            _ => {
-              cx.sess.bug("struct ID bound to enum variant that isn't \
-                           struct-like")
-            }
+      {
+          let items = cx.items.borrow();
+          match items.get().find(&did.node) {
+           Some(&ast_map::node_item(i,_)) => {
+             match i.node {
+                ast::item_struct(struct_def, _) => {
+                   struct_field_tys(struct_def.fields)
+                }
+                _ => cx.sess.bug("struct ID bound to non-struct")
+             }
+           }
+           Some(&ast_map::node_variant(ref variant, _, _)) => {
+              match (*variant).node.kind {
+                ast::struct_variant_kind(struct_def) => {
+                  struct_field_tys(struct_def.fields)
+                }
+                _ => {
+                  cx.sess.bug("struct ID bound to enum variant that isn't \
+                               struct-like")
+                }
+              }
+           }
+           _ => {
+               cx.sess.bug(
+                   format!("struct ID not bound to an item: {}",
+                        ast_map::node_id_to_str(cx.items, did.node,
+                                                token::get_ident_interner())));
+           }
           }
-       }
-       _ => {
-           cx.sess.bug(
-               format!("struct ID not bound to an item: {}",
-                    ast_map::node_id_to_str(cx.items, did.node,
-                                            token::get_ident_interner())));
-       }
-    }
-        }
-  else {
-        return csearch::get_struct_fields(cx.sess.cstore, did);
-    }
+      }
+  } else {
+    return csearch::get_struct_fields(cx.sess.cstore, did);
+  }
 }
 
 pub fn lookup_struct_field(cx: ctxt,
@@ -4658,7 +4676,8 @@ pub fn populate_implementations_for_trait_if_necessary(
 /// If it implements no trait, return `None`.
 pub fn trait_id_of_impl(tcx: ctxt,
                         def_id: ast::DefId) -> Option<ast::DefId> {
-    let node = match tcx.items.find(&def_id.node) {
+    let items = tcx.items.borrow();
+    let node = match items.get().find(&def_id.node) {
         Some(node) => node,
         None => return None
     };
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 7fc2798c7aa..6e2afb1d2e7 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -1309,10 +1309,17 @@ impl<'a> LookupContext<'a> {
 
     fn report_static_candidate(&self, idx: uint, did: DefId) {
         let span = if did.crate == ast::LOCAL_CRATE {
-            match self.tcx().items.find(&did.node) {
-              Some(&ast_map::node_method(m, _, _))
-              | Some(&ast_map::node_trait_method(@ast::provided(m), _, _)) => m.span,
-              _ => fail!("report_static_candidate: bad item {:?}", did)
+            {
+                let items = self.tcx().items.borrow();
+                match items.get().find(&did.node) {
+                  Some(&ast_map::node_method(m, _, _))
+                  | Some(&ast_map::node_trait_method(@ast::provided(m),
+                                                     _,
+                                                     _)) => {
+                      m.span
+                  }
+                  _ => fail!("report_static_candidate: bad item {:?}", did)
+                }
             }
         } else {
             self.expr.span
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 50459cd176b..d18c2419735 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -568,10 +568,8 @@ impl CoherenceChecker {
 
                         // Make sure that this type precisely names a nominal
                         // type.
-                        match self.crate_context
-                                  .tcx
-                                  .items
-                                  .find(&def_id.node) {
+                        let items = self.crate_context.tcx.items.borrow();
+                        match items.get().find(&def_id.node) {
                             None => {
                                 self.crate_context.tcx.sess.span_bug(
                                     original_type.span,
@@ -628,7 +626,8 @@ impl CoherenceChecker {
 
     pub fn span_of_impl(&self, implementation: @Impl) -> Span {
         assert_eq!(implementation.did.crate, LOCAL_CRATE);
-        match self.crate_context.tcx.items.find(&implementation.did.node) {
+        let items = self.crate_context.tcx.items.borrow();
+        match items.get().find(&implementation.did.node) {
             Some(&node_item(item, _)) => {
                 return item.span;
             }
@@ -732,14 +731,19 @@ impl CoherenceChecker {
                 _ => {
                     // Destructors only work on nominal types.
                     if impl_info.did.crate == ast::LOCAL_CRATE {
-                        match tcx.items.find(&impl_info.did.node) {
-                            Some(&ast_map::node_item(@ref item, _)) => {
-                                tcx.sess.span_err((*item).span,
-                                                  "the Drop trait may only be implemented on \
-                                                   structures");
-                            }
-                            _ => {
-                                tcx.sess.bug("didn't find impl in ast map");
+                        {
+                            let items = tcx.items.borrow();
+                            match items.get().find(&impl_info.did.node) {
+                                Some(&ast_map::node_item(@ref item, _)) => {
+                                    tcx.sess.span_err((*item).span,
+                                                      "the Drop trait may \
+                                                       only be implemented \
+                                                       on structures");
+                                }
+                                _ => {
+                                    tcx.sess.bug("didn't find impl in ast \
+                                                  map");
+                                }
                             }
                         }
                     } else {
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index 3dfcf15e024..410c94a9a67 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -106,19 +106,18 @@ impl AstConv for CrateCtxt {
 
     fn get_item_ty(&self, id: ast::DefId) -> ty::ty_param_bounds_and_ty {
         if id.crate != ast::LOCAL_CRATE {
-            csearch::get_type(self.tcx, id)
-        } else {
-            match self.tcx.items.find(&id.node) {
-              Some(&ast_map::node_item(item, _)) => {
-                ty_of_item(self, item)
-              }
-              Some(&ast_map::node_foreign_item(foreign_item, abis, _, _)) => {
+            return csearch::get_type(self.tcx, id)
+        }
+
+        let items = self.tcx.items.borrow();
+        match items.get().find(&id.node) {
+            Some(&ast_map::node_item(item, _)) => ty_of_item(self, item),
+            Some(&ast_map::node_foreign_item(foreign_item, abis, _, _)) => {
                 ty_of_foreign_item(self, foreign_item, abis)
-              }
-              ref x => {
+            }
+            ref x => {
                 self.tcx.sess.bug(format!("unexpected sort of item \
-                                        in get_item_ty(): {:?}", (*x)));
-              }
+                                           in get_item_ty(): {:?}", (*x)));
             }
         }
     }
@@ -187,7 +186,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                             trait_id: ast::NodeId)
 {
     let tcx = ccx.tcx;
-    match tcx.items.get_copy(&trait_id) {
+    let items = tcx.items.borrow();
+    match items.get().get_copy(&trait_id) {
         ast_map::node_item(@ast::item {
             node: ast::item_trait(ref generics, _, ref ms),
             ..
@@ -715,7 +715,8 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::foreign_item) {
     // map, and I regard each time that I use it as a personal and
     // moral failing, but at the moment it seems like the only
     // convenient way to extract the ABI. - ndm
-    let abis = match ccx.tcx.items.find(&i.id) {
+    let items = ccx.tcx.items.borrow();
+    let abis = match items.get().find(&i.id) {
         Some(&ast_map::node_foreign_item(_, abis, _, _)) => abis,
         ref x => {
             ccx.tcx.sess.bug(format!("unexpected sort of item \
@@ -765,13 +766,14 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
 
 fn get_trait_def(ccx: &CrateCtxt, trait_id: ast::DefId) -> @ty::TraitDef {
     if trait_id.crate != ast::LOCAL_CRATE {
-        ty::lookup_trait_def(ccx.tcx, trait_id)
-    } else {
-        match ccx.tcx.items.get(&trait_id.node) {
-            &ast_map::node_item(item, _) => trait_def_of_item(ccx, item),
-            _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
-                                       trait_id.node))
-        }
+        return ty::lookup_trait_def(ccx.tcx, trait_id)
+    }
+
+    let items = ccx.tcx.items.borrow();
+    match items.get().get(&trait_id.node) {
+        &ast_map::node_item(item, _) => trait_def_of_item(ccx, item),
+        _ => ccx.tcx.sess.bug(format!("get_trait_def({}): not an item",
+                                   trait_id.node))
     }
 }
 
diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs
index 835c739c085..982e2ca0685 100644
--- a/src/librustc/middle/typeck/mod.rs
+++ b/src/librustc/middle/typeck/mod.rs
@@ -350,7 +350,8 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
     let main_t = ty::node_id_to_type(tcx, main_id);
     match ty::get(main_t).sty {
         ty::ty_bare_fn(..) => {
-            match tcx.items.find(&main_id) {
+            let items = tcx.items.borrow();
+            match items.get().find(&main_id) {
                 Some(&ast_map::node_item(it,_)) => {
                     match it.node {
                         ast::item_fn(_, _, _, ref ps, _)
@@ -395,7 +396,8 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
     let start_t = ty::node_id_to_type(tcx, start_id);
     match ty::get(start_t).sty {
         ty::ty_bare_fn(_) => {
-            match tcx.items.find(&start_id) {
+            let items = tcx.items.borrow();
+            match items.get().find(&start_id) {
                 Some(&ast_map::node_item(it,_)) => {
                     match it.node {
                         ast::item_fn(_,_,_,ref ps,_)
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index ac88018a3c4..ee77685cf5a 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -72,7 +72,8 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
                             -> (~str, Option<Span>) {
     return match region {
       ReScope(node_id) => {
-        match cx.items.find(&node_id) {
+        let items = cx.items.borrow();
+        match items.get().find(&node_id) {
           Some(&ast_map::node_block(ref blk)) => {
             explain_span(cx, "block", blk.span)
           }
@@ -113,7 +114,8 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
                     bound_region_ptr_to_str(cx, fr.bound_region))
         };
 
-        match cx.items.find(&fr.scope_id) {
+        let items = cx.items.borrow();
+        match items.get().find(&fr.scope_id) {
           Some(&ast_map::node_block(ref blk)) => {
             let (msg, opt_span) = explain_span(cx, "block", blk.span);
             (format!("{} {}", prefix, msg), opt_span)
@@ -172,7 +174,8 @@ pub fn bound_region_to_str(cx: ctxt,
 }
 
 pub fn ReScope_id_to_str(cx: ctxt, node_id: ast::NodeId) -> ~str {
-    match cx.items.find(&node_id) {
+    let items = cx.items.borrow();
+    match items.get().find(&node_id) {
       Some(&ast_map::node_block(ref blk)) => {
         format!("<block at {}>",
              cx.sess.codemap.span_to_str(blk.span))
@@ -740,16 +743,21 @@ impl Repr for ast::DefId {
         // a path for a def-id, so I'll just make a best effort for now
         // and otherwise fallback to just printing the crate/node pair
         if self.crate == ast::LOCAL_CRATE {
-            match tcx.items.find(&self.node) {
-                Some(&ast_map::node_item(..)) |
-                Some(&ast_map::node_foreign_item(..)) |
-                Some(&ast_map::node_method(..)) |
-                Some(&ast_map::node_trait_method(..)) |
-                Some(&ast_map::node_variant(..)) |
-                Some(&ast_map::node_struct_ctor(..)) => {
-                    return format!("{:?}:{}", *self, ty::item_path_str(tcx, *self));
+            {
+                let items = tcx.items.borrow();
+                match items.get().find(&self.node) {
+                    Some(&ast_map::node_item(..)) |
+                    Some(&ast_map::node_foreign_item(..)) |
+                    Some(&ast_map::node_method(..)) |
+                    Some(&ast_map::node_trait_method(..)) |
+                    Some(&ast_map::node_variant(..)) |
+                    Some(&ast_map::node_struct_ctor(..)) => {
+                        return format!("{:?}:{}",
+                                       *self,
+                                       ty::item_path_str(tcx, *self));
+                    }
+                    _ => {}
                 }
-                _ => {}
             }
         }
         return format!("{:?}", *self);
diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs
index b7532ad72cb..3897c4c2854 100644
--- a/src/libsyntax/ast_map.rs
+++ b/src/libsyntax/ast_map.rs
@@ -23,6 +23,7 @@ use print::pprust;
 use visit::{Visitor, fn_kind};
 use visit;
 
+use std::cell::RefCell;
 use std::hashmap::HashMap;
 use std::vec;
 
@@ -192,7 +193,7 @@ impl ast_node {
     }
 }
 
-pub type map = @mut HashMap<NodeId, ast_node>;
+pub type map = @RefCell<HashMap<NodeId, ast_node>>;
 
 pub struct Ctx {
     map: map,
@@ -215,8 +216,10 @@ impl Ctx {
         } else {
             node_method(m, impl_did, impl_path)
         };
-        self.map.insert(m.id, entry);
-        self.map.insert(m.self_id, node_local(special_idents::self_));
+
+        let mut map = self.map.borrow_mut();
+        map.get().insert(m.id, entry);
+        map.get().insert(m.self_id, node_local(special_idents::self_));
     }
 
     fn map_struct_def(&mut self,
@@ -231,10 +234,11 @@ impl Ctx {
             Some(ctor_id) => {
                 match parent_node {
                     node_item(item, _) => {
-                        self.map.insert(ctor_id,
-                                        node_struct_ctor(struct_def,
-                                                         item,
-                                                         p));
+                        let mut map = self.map.borrow_mut();
+                        map.get().insert(ctor_id,
+                                         node_struct_ctor(struct_def,
+                                                          item,
+                                                          p));
                     }
                     _ => fail!("struct def parent wasn't an item")
                 }
@@ -243,13 +247,17 @@ impl Ctx {
     }
 
     fn map_expr(&mut self, ex: @Expr) {
-        self.map.insert(ex.id, node_expr(ex));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(ex.id, node_expr(ex));
+        }
 
         // Expressions which are or might be calls:
         {
             let r = ex.get_callee_id();
             for callee_id in r.iter() {
-                self.map.insert(*callee_id, node_callee_scope(ex));
+                let mut map = self.map.borrow_mut();
+                map.get().insert(*callee_id, node_callee_scope(ex));
             }
         }
 
@@ -263,7 +271,8 @@ impl Ctx {
               sp: codemap::Span,
               id: NodeId) {
         for a in decl.inputs.iter() {
-            self.map.insert(a.id, node_arg(a.pat));
+            let mut map = self.map.borrow_mut();
+            map.get().insert(a.id, node_arg(a.pat));
         }
         match *fk {
             visit::fk_method(name, _, _) => { self.path.push(path_name(name)) }
@@ -277,12 +286,19 @@ impl Ctx {
     }
 
     fn map_stmt(&mut self, stmt: @Stmt) {
-        self.map.insert(stmt_id(stmt), node_stmt(stmt));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(stmt_id(stmt), node_stmt(stmt));
+        }
         visit::walk_stmt(self, stmt, ());
     }
 
     fn map_block(&mut self, b: P<Block>) {
-        self.map.insert(b.id, node_block(b));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(b.id, node_block(b));
+        }
+
         visit::walk_block(self, b, ());
     }
 
@@ -290,8 +306,9 @@ impl Ctx {
         match pat.node {
             PatIdent(_, ref path, _) => {
                 // Note: this is at least *potentially* a pattern...
-                self.map.insert(pat.id,
-                                node_local(ast_util::path_to_ident(path)));
+                let mut map = self.map.borrow_mut();
+                map.get().insert(pat.id,
+                                 node_local(ast_util::path_to_ident(path)));
             }
             _ => ()
         }
@@ -304,7 +321,10 @@ impl Visitor<()> for Ctx {
     fn visit_item(&mut self, i: @item, _: ()) {
         // clone is FIXME #2543
         let item_path = @self.path.clone();
-        self.map.insert(i.id, node_item(i, item_path));
+        {
+            let mut map = self.map.borrow_mut();
+            map.get().insert(i.id, node_item(i, item_path));
+        }
         match i.node {
             item_impl(_, ref maybe_trait, ty, ref ms) => {
                 // Right now the ident on impls is __extensions__ which isn't
@@ -323,8 +343,9 @@ impl Visitor<()> for Ctx {
             item_enum(ref enum_definition, _) => {
                 for &v in enum_definition.variants.iter() {
                     let elt = path_name(i.ident);
-                    self.map.insert(v.node.id,
-                                    node_variant(v, i, self.extend(elt)));
+                    let mut map = self.map.borrow_mut();
+                    map.get().insert(v.node.id,
+                                     node_variant(v, i, self.extend(elt)));
                 }
             }
             item_foreign_mod(ref nm) => {
@@ -336,16 +357,17 @@ impl Visitor<()> for Ctx {
                         inherited => i.vis
                     };
 
-                    self.map.insert(nitem.id,
-                                    node_foreign_item(*nitem,
-                                                      nm.abis,
-                                                      visibility,
-                                                      // FIXME (#2543)
+                    let mut map = self.map.borrow_mut();
+                    map.get().insert(nitem.id,
+                                     node_foreign_item(*nitem,
+                                                       nm.abis,
+                                                       visibility,
+                                                       // FIXME (#2543)
                                                         // Anonymous extern
                                                         // mods go in the
                                                         // parent scope.
                                                         @self.path.clone()
-                                                      ));
+                                                       ));
                 }
             }
             item_struct(struct_def, _) => {
@@ -355,7 +377,8 @@ impl Visitor<()> for Ctx {
             }
             item_trait(_, ref traits, ref methods) => {
                 for p in traits.iter() {
-                    self.map.insert(p.ref_id, node_item(i, item_path));
+                    let mut map = self.map.borrow_mut();
+                    map.get().insert(p.ref_id, node_item(i, item_path));
                 }
                 for tm in methods.iter() {
                     let ext = { self.extend(path_name(i.ident)) };
@@ -364,7 +387,8 @@ impl Visitor<()> for Ctx {
                         required(ref m) => {
                             let entry =
                                 node_trait_method(@(*tm).clone(), d_id, ext);
-                            self.map.insert(m.id, entry);
+                            let mut map = self.map.borrow_mut();
+                            map.get().insert(m.id, entry);
                         }
                         provided(m) => {
                             self.map_method(d_id, ext, m, true);
@@ -420,7 +444,7 @@ impl Visitor<()> for Ctx {
 
 pub fn map_crate(diag: @SpanHandler, c: &Crate) -> map {
     let cx = @mut Ctx {
-        map: @mut HashMap::new(),
+        map: @RefCell::new(HashMap::new()),
         path: ~[],
         diag: diag,
     };
@@ -450,10 +474,11 @@ pub fn map_decoded_item(diag: @SpanHandler,
     match *ii {
         ii_item(..) => {} // fallthrough
         ii_foreign(i) => {
-            cx.map.insert(i.id, node_foreign_item(i,
-                                                  AbiSet::Intrinsic(),
-                                                  i.vis,    // Wrong but OK
-                                                  @path));
+            let mut map = cx.map.borrow_mut();
+            map.get().insert(i.id, node_foreign_item(i,
+                                                     AbiSet::Intrinsic(),
+                                                     i.vis,    // Wrong but OK
+                                                     @path));
         }
         ii_method(impl_did, is_provided, m) => {
             cx.map_method(impl_did, @path, m, is_provided);
@@ -465,7 +490,8 @@ pub fn map_decoded_item(diag: @SpanHandler,
 }
 
 pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
-    match map.find(&id) {
+    let map = map.borrow();
+    match map.get().find(&id) {
       None => {
         format!("unknown node (id={})", id)
       }
@@ -529,7 +555,8 @@ pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
 
 pub fn node_item_query<Result>(items: map, id: NodeId, query: |@item| -> Result, error_msg: ~str)
                        -> Result {
-    match items.find(&id) {
+    let items = items.borrow();
+    match items.get().find(&id) {
         Some(&node_item(it, _)) => query(it),
         _ => fail!("{}", error_msg)
     }
@@ -538,7 +565,8 @@ pub fn node_item_query<Result>(items: map, id: NodeId, query: |@item| -> Result,
 pub fn node_span(items: map,
                  id: ast::NodeId)
                  -> Span {
-    match items.find(&id) {
+    let items = items.borrow();
+    match items.get().find(&id) {
         Some(&node_item(item, _)) => item.span,
         Some(&node_foreign_item(foreign_item, _, _, _)) => foreign_item.span,
         Some(&node_trait_method(@required(ref type_method), _, _)) => type_method.span,