about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-08 09:47:58 +0000
committerbors <bors@rust-lang.org>2017-09-08 09:47:58 +0000
commitdead08cb331343b84564628b139b657f93548320 (patch)
treeed670fa4db3d6ee3b74301b1728cbb37ecc424c4
parentd6ad402a644d9e57f1a6d6c579fe04acf00e0e2e (diff)
parentfd0aa647f3abaf6667dcde5b44e673e172c8a63b (diff)
downloadrust-dead08cb331343b84564628b139b657f93548320.tar.gz
rust-dead08cb331343b84564628b139b657f93548320.zip
Auto merge of #44142 - alexcrichton:dllimport-query, r=nikomatsakis
Migrate a slew of metadata methods to queries

This PR intends to make more progress on #41417, knocking off some low-hanging fruit.

Closes #44190
cc #44137
-rw-r--r--src/librustc/dep_graph/dep_node.rs58
-rw-r--r--src/librustc/dep_graph/graph.rs9
-rw-r--r--src/librustc/hir/lowering.rs4
-rw-r--r--src/librustc/hir/map/def_collector.rs32
-rw-r--r--src/librustc/hir/map/definitions.rs36
-rw-r--r--src/librustc/hir/map/mod.rs12
-rw-r--r--src/librustc/infer/error_reporting/anon_anon_conflict.rs26
-rw-r--r--src/librustc/infer/error_reporting/mod.rs2
-rw-r--r--src/librustc/middle/cstore.rs201
-rw-r--r--src/librustc/middle/dead.rs2
-rw-r--r--src/librustc/middle/dependency_format.rs75
-rw-r--r--src/librustc/middle/expr_use_visitor.rs6
-rw-r--r--src/librustc/middle/lang_items.rs76
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc/middle/stability.rs251
-rw-r--r--src/librustc/middle/weak_lang_items.rs40
-rw-r--r--src/librustc/traits/error_reporting.rs4
-rw-r--r--src/librustc/traits/object_safety.rs2
-rw-r--r--src/librustc/traits/on_unimplemented.rs4
-rw-r--r--src/librustc/traits/project.rs4
-rw-r--r--src/librustc/traits/select.rs24
-rw-r--r--src/librustc/traits/util.rs2
-rw-r--r--src/librustc/ty/adjustment.rs4
-rw-r--r--src/librustc/ty/context.rs165
-rw-r--r--src/librustc/ty/item_path.rs11
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/maps.rs327
-rw-r--r--src/librustc/ty/mod.rs33
-rw-r--r--src/librustc/ty/trait_def.rs17
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc/util/ppaux.rs4
-rw-r--r--src/librustc_const_eval/eval.rs6
-rw-r--r--src/librustc_const_eval/pattern.rs2
-rw-r--r--src/librustc_driver/driver.rs15
-rw-r--r--src/librustc_driver/test.rs6
-rw-r--r--src/librustc_incremental/persist/fs.rs2
-rw-r--r--src/librustc_incremental/persist/hash.rs2
-rw-r--r--src/librustc_lint/builtin.rs7
-rw-r--r--src/librustc_metadata/creader.rs225
-rw-r--r--src/librustc_metadata/cstore.rs90
-rw-r--r--src/librustc_metadata/cstore_impl.rs441
-rw-r--r--src/librustc_metadata/decoder.rs25
-rw-r--r--src/librustc_metadata/diagnostics.rs6
-rw-r--r--src/librustc_metadata/encoder.rs20
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_metadata/link_args.rs65
-rw-r--r--src/librustc_metadata/native_libs.rs217
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/matches/test.rs2
-rw-r--r--src/librustc_mir/shim.rs6
-rw-r--r--src/librustc_mir/transform/generator.rs2
-rw-r--r--src/librustc_mir/transform/inline.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs6
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs2
-rw-r--r--src/librustc_passes/consts.rs2
-rw-r--r--src/librustc_privacy/lib.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs27
-rw-r--r--src/librustc_resolve/macros.rs2
-rw-r--r--src/librustc_resolve/resolve_imports.rs2
-rw-r--r--src/librustc_save_analysis/lib.rs4
-rw-r--r--src/librustc_trans/back/link.rs100
-rw-r--r--src/librustc_trans/back/rpath.rs4
-rw-r--r--src/librustc_trans/back/symbol_export.rs11
-rw-r--r--src/librustc_trans/back/symbol_names.rs4
-rw-r--r--src/librustc_trans/back/write.rs11
-rw-r--r--src/librustc_trans/base.rs51
-rw-r--r--src/librustc_trans/callee.rs16
-rw-r--r--src/librustc_trans/collector.rs4
-rw-r--r--src/librustc_trans/common.rs4
-rw-r--r--src/librustc_trans/consts.rs15
-rw-r--r--src/librustc_trans/context.rs4
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs2
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs2
-rw-r--r--src/librustc_trans/intrinsic.rs4
-rw-r--r--src/librustc_trans/lib.rs25
-rw-r--r--src/librustc_trans/mir/analyze.rs2
-rw-r--r--src/librustc_trans/mir/block.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs4
-rw-r--r--src/librustc_trans/mir/rvalue.rs2
-rw-r--r--src/librustc_trans/monomorphize.rs10
-rw-r--r--src/librustc_typeck/astconv.rs22
-rw-r--r--src/librustc_typeck/check/autoderef.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs8
-rw-r--r--src/librustc_typeck/check/closure.rs6
-rw-r--r--src/librustc_typeck/check/coercion.rs4
-rw-r--r--src/librustc_typeck/check/method/confirm.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs39
-rw-r--r--src/librustc_typeck/check/method/suggest.rs6
-rw-r--r--src/librustc_typeck/check/mod.rs8
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/check/wfcheck.rs2
-rw-r--r--src/librustc_typeck/check_unused.rs30
-rw-r--r--src/librustc_typeck/coherence/builtin.rs10
-rw-r--r--src/librustc_typeck/coherence/inherent_impls.rs39
-rw-r--r--src/librustc_typeck/coherence/mod.rs2
-rw-r--r--src/librustc_typeck/collect.rs19
-rw-r--r--src/librustc_typeck/variance/terms.rs17
-rw-r--r--src/librustdoc/clean/inline.rs55
-rw-r--r--src/librustdoc/clean/mod.rs67
-rw-r--r--src/librustdoc/visit_ast.rs9
-rw-r--r--src/librustdoc/visit_lib.rs7
-rw-r--r--src/test/compile-fail/empty-linkname.rs2
-rw-r--r--src/test/compile-fail/feature-gate-static-nobundle.rs2
-rw-r--r--src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs3
-rw-r--r--src/test/compile-fail/lint-output-format-2.rs8
-rw-r--r--src/test/compile-fail/lint-unknown-feature-default.rs8
-rw-r--r--src/test/compile-fail/lint-unknown-feature.rs10
-rw-r--r--src/test/compile-fail/stable-features.rs5
-rw-r--r--src/test/compile-fail/weak-lang-item.rs2
-rw-r--r--src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs1
-rw-r--r--src/test/incremental/remapped_paths_cc/main.rs1
-rw-r--r--src/test/incremental/remove-private-item-cross-crate/main.rs4
114 files changed, 1854 insertions, 1460 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index c438944cf01..caa912c7c8b 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -511,8 +511,8 @@ define_dep_nodes!( <'tcx>
     [] ParamEnv(DefId),
     [] DescribeDef(DefId),
     [] DefSpan(DefId),
-    [] Stability(DefId),
-    [] Deprecation(DefId),
+    [] LookupStability(DefId),
+    [] LookupDeprecationEntry(DefId),
     [] ItemBodyNestedBodies(DefId),
     [] ConstIsRvaluePromotableToStatic(DefId),
     [] ImplParent(DefId),
@@ -521,16 +521,60 @@ define_dep_nodes!( <'tcx>
     [] IsMirAvailable(DefId),
     [] ItemAttrs(DefId),
     [] FnArgNames(DefId),
-    [] DylibDepFormats(DefId),
-    [] IsAllocator(DefId),
-    [] IsPanicRuntime(DefId),
-    [] IsCompilerBuiltins(DefId),
-    [] HasGlobalAllocator(DefId),
+    [] DylibDepFormats(CrateNum),
+    [] IsPanicRuntime(CrateNum),
+    [] IsCompilerBuiltins(CrateNum),
+    [] HasGlobalAllocator(CrateNum),
     [] ExternCrate(DefId),
     [] LintLevels,
     [] Specializes { impl1: DefId, impl2: DefId },
     [] InScopeTraits(HirId),
     [] ModuleExports(HirId),
+    [] IsSanitizerRuntime(CrateNum),
+    [] IsProfilerRuntime(CrateNum),
+    [] GetPanicStrategy(CrateNum),
+    [] IsNoBuiltins(CrateNum),
+    [] ImplDefaultness(DefId),
+    [] ExportedSymbols(CrateNum),
+    [] NativeLibraries(CrateNum),
+    [] PluginRegistrarFn(CrateNum),
+    [] DeriveRegistrarFn(CrateNum),
+    [] CrateDisambiguator(CrateNum),
+    [] CrateHash(CrateNum),
+    [] OriginalCrateName(CrateNum),
+
+    [] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
+    [] AllTraitImplementations(CrateNum),
+
+    [] IsDllimportForeignItem(DefId),
+    [] IsStaticallyIncludedForeignItem(DefId),
+    [] NativeLibraryKind(DefId),
+    [] LinkArgs,
+
+    [] NamedRegion(HirId),
+    [] IsLateBound(HirId),
+    [] ObjectLifetimeDefaults(HirId),
+
+    [] Visibility(DefId),
+    [] DepKind(CrateNum),
+    [] CrateName(CrateNum),
+    [] ItemChildren(DefId),
+    [] ExternModStmtCnum(HirId),
+    [] GetLangItems,
+    [] DefinedLangItems(CrateNum),
+    [] MissingLangItems(CrateNum),
+    [] ExternConstBody(DefId),
+    [] VisibleParentMap,
+    [] IsDirectExternCrate(CrateNum),
+    [] MissingExternCrateItem(CrateNum),
+    [] UsedCrateSource(CrateNum),
+    [] PostorderCnums,
+
+    [] Freevars(HirId),
+    [] MaybeUnusedTraitImport(HirId),
+    [] MaybeUnusedExternCrates,
+    [] StabilityIndex,
+    [] AllCrateNums,
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index c487fc963ca..34cb1d2a6d7 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -235,10 +235,13 @@ impl DepGraph {
                                           debug_str_gen: F)
         where F: FnOnce() -> String
     {
-        let mut dep_node_debug = self.data.as_ref().unwrap().dep_node_debug.borrow_mut();
+        let dep_node_debug = &self.data.as_ref().unwrap().dep_node_debug;
 
-        dep_node_debug.entry(dep_node)
-                      .or_insert_with(debug_str_gen);
+        if dep_node_debug.borrow().contains_key(&dep_node) {
+            return
+        }
+        let debug_str = debug_str_gen();
+        dep_node_debug.borrow_mut().insert(dep_node, debug_str);
     }
 
     pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option<String> {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 0f69c06c417..db86c4f93ee 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -787,7 +787,7 @@ impl<'a> LoweringContext<'a> {
                         return n;
                     }
                     assert!(!def_id.is_local());
-                    let n = self.sess.cstore.item_generics_cloned(def_id).regions.len();
+                    let n = self.sess.cstore.item_generics_cloned_untracked(def_id).regions.len();
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
@@ -2863,7 +2863,7 @@ impl<'a> LoweringContext<'a> {
         let parent_def = self.parent_def.unwrap();
         let def_id = {
             let defs = self.resolver.definitions();
-            let def_path_data = DefPathData::Binding(name);
+            let def_path_data = DefPathData::Binding(name.as_str());
             let def_index = defs.create_def_with_parent(parent_def,
                                                         node_id,
                                                         def_path_data,
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index d348a5db051..af027e321c6 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -104,14 +104,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                 DefPathData::Impl,
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.name),
+                DefPathData::TypeNs(i.ident.name.as_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
-            ItemKind::Mod(..) => DefPathData::Module(i.ident.name),
+            ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
-                DefPathData::ValueNs(i.ident.name),
-            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name),
+                DefPathData::ValueNs(i.ident.name.as_str()),
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::GlobalAsm(..) => DefPathData::Misc,
             ItemKind::Use(ref view_path) => {
@@ -139,13 +139,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     for v in &enum_definition.variants {
                         let variant_def_index =
                             this.create_def(v.node.data.id(),
-                                            DefPathData::EnumVariant(v.node.name.name),
+                                            DefPathData::EnumVariant(v.node.name.name.as_str()),
                                             REGULAR_SPACE);
                         this.with_parent(variant_def_index, |this| {
                             for (index, field) in v.node.data.fields().iter().enumerate() {
                                 let name = field.ident.map(|ident| ident.name)
                                     .unwrap_or_else(|| Symbol::intern(&index.to_string()));
-                                this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
+                                this.create_def(field.id,
+                                                DefPathData::Field(name.as_str()),
+                                                REGULAR_SPACE);
                             }
 
                             if let Some(ref expr) = v.node.disr_expr {
@@ -165,7 +167,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
                     for (index, field) in struct_def.fields().iter().enumerate() {
                         let name = field.ident.map(|ident| ident.name)
                             .unwrap_or_else(|| Symbol::intern(&index.to_string()));
-                        this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
+                        this.create_def(field.id, DefPathData::Field(name.as_str()), REGULAR_SPACE);
                     }
                 }
                 _ => {}
@@ -176,7 +178,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
         let def = self.create_def(foreign_item.id,
-                                  DefPathData::ValueNs(foreign_item.ident.name),
+                                  DefPathData::ValueNs(foreign_item.ident.name.as_str()),
                                   REGULAR_SPACE);
 
         self.with_parent(def, |this| {
@@ -187,7 +189,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_generics(&mut self, generics: &'a Generics) {
         for ty_param in generics.ty_params.iter() {
             self.create_def(ty_param.id,
-                            DefPathData::TypeParam(ty_param.ident.name),
+                            DefPathData::TypeParam(ty_param.ident.name.as_str()),
                             REGULAR_SPACE);
         }
 
@@ -197,8 +199,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_trait_item(&mut self, ti: &'a TraitItem) {
         let def_data = match ti.node {
             TraitItemKind::Method(..) | TraitItemKind::Const(..) =>
-                DefPathData::ValueNs(ti.ident.name),
-            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name),
+                DefPathData::ValueNs(ti.ident.name.as_str()),
+            TraitItemKind::Type(..) => DefPathData::TypeNs(ti.ident.name.as_str()),
             TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
         };
 
@@ -215,8 +217,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
-                DefPathData::ValueNs(ii.ident.name),
-            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name),
+                DefPathData::ValueNs(ii.ident.name.as_str()),
+            ImplItemKind::Type(..) => DefPathData::TypeNs(ii.ident.name.as_str()),
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
         };
 
@@ -237,7 +239,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
             PatKind::Ident(_, id, _) => {
                 let def = self.create_def(pat.id,
-                                          DefPathData::Binding(id.node.name),
+                                          DefPathData::Binding(id.node.name.as_str()),
                                           REGULAR_SPACE);
                 self.parent_def = Some(def);
             }
@@ -282,7 +284,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
 
     fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
         self.create_def(def.lifetime.id,
-                        DefPathData::LifetimeDef(def.lifetime.ident.name),
+                        DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()),
                         REGULAR_SPACE);
     }
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index b371366bc5d..7bd2e5eceae 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -80,8 +80,10 @@ impl DefPathTable {
 
     #[inline(always)]
     pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
-        self.def_path_hashes[index.address_space().index()]
-                            [index.as_array_index()]
+        let ret = self.def_path_hashes[index.address_space().index()]
+                                      [index.as_array_index()];
+        debug!("def_path_hash({:?}) = {:?}", index, ret);
+        return ret
     }
 
     pub fn add_def_path_hashes_to(&self,
@@ -213,7 +215,7 @@ impl DefKey {
             DefPathData::Binding(name) |
             DefPathData::Field(name) |
             DefPathData::GlobalMetaData(name) => {
-                (*name.as_str()).hash(&mut hasher);
+                name.hash(&mut hasher);
             }
 
             DefPathData::Impl |
@@ -347,31 +349,31 @@ pub enum DefPathData {
     /// An impl
     Impl,
     /// Something in the type NS
-    TypeNs(Symbol),
+    TypeNs(InternedString),
     /// Something in the value NS
-    ValueNs(Symbol),
+    ValueNs(InternedString),
     /// A module declaration
-    Module(Symbol),
+    Module(InternedString),
     /// A macro rule
-    MacroDef(Symbol),
+    MacroDef(InternedString),
     /// A closure expression
     ClosureExpr,
 
     // Subportions of items
     /// A type parameter (generic parameter)
-    TypeParam(Symbol),
+    TypeParam(InternedString),
     /// A lifetime definition
-    LifetimeDef(Symbol),
+    LifetimeDef(InternedString),
     /// A variant of a enum
-    EnumVariant(Symbol),
+    EnumVariant(InternedString),
     /// A struct field
-    Field(Symbol),
+    Field(InternedString),
     /// Implicit ctor for a tuple-like struct
     StructCtor,
     /// Initializer for a const
     Initializer,
     /// Pattern binding
-    Binding(Symbol),
+    Binding(InternedString),
     /// An `impl Trait` type node.
     ImplTrait,
     /// A `typeof` type node.
@@ -380,7 +382,7 @@ pub enum DefPathData {
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
     /// are only supposed to show up right below the crate root.
-    GlobalMetaData(Symbol)
+    GlobalMetaData(InternedString)
 }
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -601,7 +603,7 @@ impl Definitions {
 }
 
 impl DefPathData {
-    pub fn get_opt_name(&self) -> Option<Symbol> {
+    pub fn get_opt_name(&self) -> Option<InternedString> {
         use self::DefPathData::*;
         match *self {
             TypeNs(name) |
@@ -639,7 +641,7 @@ impl DefPathData {
             Binding(name) |
             Field(name) |
             GlobalMetaData(name) => {
-                return name.as_str();
+                return name
             }
 
             // note that this does not show up in user printouts
@@ -684,7 +686,7 @@ macro_rules! define_global_metadata_kind {
                     definitions.create_def_with_parent(
                         CRATE_DEF_INDEX,
                         ast::DUMMY_NODE_ID,
-                        DefPathData::GlobalMetaData(instance.name()),
+                        DefPathData::GlobalMetaData(instance.name().as_str()),
                         GLOBAL_MD_ADDRESS_SPACE,
                         Mark::root()
                     );
@@ -698,7 +700,7 @@ macro_rules! define_global_metadata_kind {
                 let def_key = DefKey {
                     parent: Some(CRATE_DEF_INDEX),
                     disambiguated_data: DisambiguatedDefPathData {
-                        data: DefPathData::GlobalMetaData(self.name()),
+                        data: DefPathData::GlobalMetaData(self.name().as_str()),
                         disambiguator: 0,
                     }
                 };
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index e54df2d50d8..d043d8346e6 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -878,7 +878,17 @@ impl<'hir> Map<'hir> {
 
             Some(RootCrate(_)) => self.forest.krate.span,
             Some(NotPresent) | None => {
-                bug!("hir::map::Map::span: id not in map: {:?}", id)
+                // Some nodes, notably macro definitions, are not
+                // present in the map for whatever reason, but
+                // they *do* have def-ids. So if we encounter an
+                // empty hole, check for that case.
+                if let Some(def_index) = self.definitions.opt_def_index(id) {
+                    let def_path_hash = self.definitions.def_path_hash(def_index);
+                    self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
+                    DUMMY_SP
+                } else {
+                    bug!("hir::map::Map::span: id not in map: {:?}", id)
+                }
             }
         }
     }
diff --git a/src/librustc/infer/error_reporting/anon_anon_conflict.rs b/src/librustc/infer/error_reporting/anon_anon_conflict.rs
index c80ce3c96f1..d3fff4c66af 100644
--- a/src/librustc/infer/error_reporting/anon_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/anon_anon_conflict.rs
@@ -209,18 +209,19 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> {
 
         match arg.node {
             hir::TyRptr(ref lifetime, _) => {
-                match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
+                let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
+                match self.infcx.tcx.named_region(hir_id) {
                     // the lifetime of the TyRptr
-                    Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+                    Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
                         if debruijn_index.depth == 1 && anon_index == br_index {
                             self.found_type = Some(arg);
                             return; // we can stop visiting now
                         }
                     }
-                    Some(&rl::Region::Static) |
-                    Some(&rl::Region::EarlyBound(_, _)) |
-                    Some(&rl::Region::LateBound(_, _)) |
-                    Some(&rl::Region::Free(_, _)) |
+                    Some(rl::Region::Static) |
+                    Some(rl::Region::EarlyBound(_, _)) |
+                    Some(rl::Region::LateBound(_, _)) |
+                    Some(rl::Region::Free(_, _)) |
                     None => {
                         debug!("no arg found");
                     }
@@ -272,17 +273,18 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
             _ => return,
         };
 
-        match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
+        let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
+        match self.infcx.tcx.named_region(hir_id) {
             // the lifetime of the TyPath!
-            Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+            Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
                 if debruijn_index.depth == 1 && anon_index == br_index {
                     self.found_it = true;
                 }
             }
-            Some(&rl::Region::Static) |
-            Some(&rl::Region::EarlyBound(_, _)) |
-            Some(&rl::Region::LateBound(_, _)) |
-            Some(&rl::Region::Free(_, _)) |
+            Some(rl::Region::Static) |
+            Some(rl::Region::EarlyBound(_, _)) |
+            Some(rl::Region::LateBound(_, _)) |
+            Some(rl::Region::Free(_, _)) |
             None => {
                 debug!("no arg found");
             }
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 476bf947142..ff52f1e4e39 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -357,7 +357,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 // for imported and non-imported crates
                 if exp_path == found_path
                 || exp_abs_path == found_abs_path {
-                    let crate_name = self.tcx.sess.cstore.crate_name(did1.krate);
+                    let crate_name = self.tcx.crate_name(did1.krate);
                     err.span_note(sp, &format!("Perhaps two different versions \
                                                 of crate `{}` are being used?",
                                                crate_name));
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 288390cb5e7..a7d874386d1 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -23,16 +23,15 @@
 //! probably get a better home if someone can find one.
 
 use hir::def;
-use hir::def_id::{CrateNum, DefId, DefIndex};
+use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
 use hir::map::definitions::{Definitions, DefKey, DefPathTable};
 use hir::svh::Svh;
 use ich;
-use middle::lang_items;
 use ty::{self, TyCtxt};
 use session::Session;
 use session::search_paths::PathKind;
-use util::nodemap::{NodeSet, DefIdMap};
+use util::nodemap::NodeSet;
 
 use std::any::Any;
 use std::path::{Path, PathBuf};
@@ -43,8 +42,6 @@ use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_back::target::Target;
-use hir;
-use rustc_back::PanicStrategy;
 
 pub use self::NativeLibraryKind::*;
 
@@ -223,75 +220,44 @@ pub trait MetadataLoader {
 
 /// A store of Rust crates, through with their metadata
 /// can be accessed.
+///
+/// Note that this trait should probably not be expanding today. All new
+/// functionality should be driven through queries instead!
+///
+/// If you find a method on this trait named `{name}_untracked` it signifies
+/// that it's *not* tracked for dependency information throughout compilation
+/// (it'd break incremental compilation) and should only be called pre-HIR (e.g.
+/// during resolve)
 pub trait CrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>;
 
     // access to the metadata loader
     fn metadata_loader(&self) -> &MetadataLoader;
 
-    // item info
-    fn visibility(&self, def: DefId) -> ty::Visibility;
-    fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
-    fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
-
-    // trait info
-    fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
-
-    // impl info
-    fn impl_defaultness(&self, def: DefId) -> hir::Defaultness;
-
-    // trait/impl-item info
-    fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem;
-
-    // flags
-    fn is_dllimport_foreign_item(&self, def: DefId) -> bool;
-    fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool;
-
-    // crate metadata
-    fn dep_kind(&self, cnum: CrateNum) -> DepKind;
-    fn export_macros(&self, cnum: CrateNum);
-    fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>;
-    fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>;
-    fn is_compiler_builtins(&self, cnum: CrateNum) -> bool;
-    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool;
-    fn is_profiler_runtime(&self, cnum: CrateNum) -> bool;
-    fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy;
-    /// The name of the crate as it is referred to in source code of the current
-    /// crate.
-    fn crate_name(&self, cnum: CrateNum) -> Symbol;
-    /// The name of the crate as it is stored in the crate's metadata.
-    fn original_crate_name(&self, cnum: CrateNum) -> Symbol;
-    fn crate_hash(&self, cnum: CrateNum) -> Svh;
-    fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol;
-    fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>;
-    fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>;
-    fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>;
-    fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId>;
-    fn is_no_builtins(&self, cnum: CrateNum) -> bool;
-
     // resolve
     fn def_key(&self, def: DefId) -> DefKey;
     fn def_path(&self, def: DefId) -> hir_map::DefPath;
     fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash;
     fn def_path_table(&self, cnum: CrateNum) -> Rc<DefPathTable>;
-    fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>;
-    fn item_children(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
-    fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro;
 
-    // misc. metadata
-    fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                           -> &'tcx hir::Body;
+    // "queries" used in resolve that aren't tracked for incremental compilation
+    fn visibility_untracked(&self, def: DefId) -> ty::Visibility;
+    fn export_macros_untracked(&self, cnum: CrateNum);
+    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind;
+    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol;
+    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>;
+    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export>;
+    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro;
+    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
+    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics;
+    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem;
+    fn postorder_cnums_untracked(&self) -> Vec<CrateNum>;
 
     // This is basically a 1-based range of ints, which is a little
     // silly - I may fix that.
-    fn crates(&self) -> Vec<CrateNum>;
-    fn used_libraries(&self) -> Vec<NativeLibrary>;
-    fn used_link_args(&self) -> Vec<String>;
+    fn crates_untracked(&self) -> Vec<CrateNum>;
 
     // utility functions
-    fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
-    fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
-    fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
@@ -336,57 +302,18 @@ impl CrateStore for DummyCrateStore {
     fn crate_data_as_rc_any(&self, krate: CrateNum) -> Rc<Any>
         { bug!("crate_data_as_rc_any") }
     // item info
-    fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
-    fn visible_parent_map<'a>(&'a self, session: &Session)
-        -> ::std::cell::Ref<'a, DefIdMap<DefId>>
-    {
-        bug!("visible_parent_map")
-    }
-    fn item_generics_cloned(&self, def: DefId) -> ty::Generics
+    fn visibility_untracked(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
+    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics
         { bug!("item_generics_cloned") }
 
-    // trait info
-    fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
-
-    // impl info
-    fn impl_defaultness(&self, def: DefId) -> hir::Defaultness { bug!("impl_defaultness") }
-
     // trait/impl-item info
-    fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem
+    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
         { bug!("associated_item_cloned") }
 
-    // flags
-    fn is_dllimport_foreign_item(&self, id: DefId) -> bool { false }
-    fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool { false }
-
     // crate metadata
-    fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
-        { bug!("lang_items") }
-    fn missing_lang_items(&self, cnum: CrateNum) -> Vec<lang_items::LangItem>
-        { bug!("missing_lang_items") }
-    fn dep_kind(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
-    fn export_macros(&self, cnum: CrateNum) { bug!("export_macros") }
-    fn is_compiler_builtins(&self, cnum: CrateNum) -> bool { bug!("is_compiler_builtins") }
-    fn is_profiler_runtime(&self, cnum: CrateNum) -> bool { bug!("is_profiler_runtime") }
-    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool { bug!("is_sanitizer_runtime") }
-    fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
-        bug!("panic_strategy")
-    }
-    fn crate_name(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
-    fn original_crate_name(&self, cnum: CrateNum) -> Symbol {
-        bug!("original_crate_name")
-    }
-    fn crate_hash(&self, cnum: CrateNum) -> Svh { bug!("crate_hash") }
-    fn crate_disambiguator(&self, cnum: CrateNum)
-                           -> Symbol { bug!("crate_disambiguator") }
-    fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
-        { bug!("plugin_registrar_fn") }
-    fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
-        { bug!("derive_registrar_fn") }
-    fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
-        { bug!("native_libraries") }
-    fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId> { bug!("exported_symbols") }
-    fn is_no_builtins(&self, cnum: CrateNum) -> bool { bug!("is_no_builtins") }
+    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { bug!("is_explicitly_linked") }
+    fn export_macros_untracked(&self, cnum: CrateNum) { bug!("export_macros") }
+    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol { bug!("crate_name") }
 
     // resolve
     fn def_key(&self, def: DefId) -> DefKey { bug!("def_key") }
@@ -399,29 +326,18 @@ impl CrateStore for DummyCrateStore {
     fn def_path_table(&self, cnum: CrateNum) -> Rc<DefPathTable> {
         bug!("def_path_table")
     }
-    fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
-    fn item_children(&self, did: DefId, sess: &Session) -> Vec<def::Export> {
+    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name> {
+        bug!("struct_field_names")
+    }
+    fn item_children_untracked(&self, did: DefId, sess: &Session) -> Vec<def::Export> {
         bug!("item_children")
     }
-    fn load_macro(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
+    fn load_macro_untracked(&self, did: DefId, sess: &Session) -> LoadedMacro { bug!("load_macro") }
 
-    // misc. metadata
-    fn item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
-                           -> &'tcx hir::Body {
-        bug!("item_body")
-    }
-
-    // This is basically a 1-based range of ints, which is a little
-    // silly - I may fix that.
-    fn crates(&self) -> Vec<CrateNum> { vec![] }
-    fn used_libraries(&self) -> Vec<NativeLibrary> { vec![] }
-    fn used_link_args(&self) -> Vec<String> { vec![] }
+    fn crates_untracked(&self) -> Vec<CrateNum> { vec![] }
 
     // utility functions
-    fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
-        { vec![] }
-    fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
-    fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
+    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
     fn encode_metadata<'a, 'tcx>(&self,
                                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
@@ -430,6 +346,7 @@ impl CrateStore for DummyCrateStore {
         bug!("encode_metadata")
     }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
+    fn postorder_cnums_untracked(&self) -> Vec<CrateNum> { bug!("postorder_cnums_untracked") }
 
     // access to the metadata loader
     fn metadata_loader(&self) -> &MetadataLoader { bug!("metadata_loader") }
@@ -439,3 +356,47 @@ pub trait CrateLoader {
     fn process_item(&mut self, item: &ast::Item, defs: &Definitions);
     fn postprocess(&mut self, krate: &ast::Crate);
 }
+
+// This method is used when generating the command line to pass through to
+// system linker. The linker expects undefined symbols on the left of the
+// command line to be defined in libraries on the right, not the other way
+// around. For more info, see some comments in the add_used_library function
+// below.
+//
+// In order to get this left-to-right dependency ordering, we perform a
+// topological sort of all crates putting the leaves at the right-most
+// positions.
+pub fn used_crates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> {
+    let mut libs = tcx.crates()
+        .iter()
+        .cloned()
+        .filter_map(|cnum| {
+            if tcx.dep_kind(cnum).macros_only() {
+                return None
+            }
+            let source = tcx.used_crate_source(cnum);
+            let path = match prefer {
+                LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0),
+                LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0),
+            };
+            let path = match path {
+                Some(p) => LibSource::Some(p),
+                None => {
+                    if source.rmeta.is_some() {
+                        LibSource::MetadataOnly
+                    } else {
+                        LibSource::None
+                    }
+                }
+            };
+            Some((cnum, path))
+        })
+        .collect::<Vec<_>>();
+    let mut ordering = tcx.postorder_cnums(LOCAL_CRATE);
+    Rc::make_mut(&mut ordering).reverse();
+    libs.sort_by_key(|&(a, _)| {
+        ordering.iter().position(|x| *x == a)
+    });
+    libs
+}
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index b8624722692..d79e90690ca 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -469,7 +469,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
     fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool {
         let field_type = self.tcx.type_of(self.tcx.hir.local_def_id(field.id));
         let is_marker_field = match field_type.ty_to_def_id() {
-            Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)),
+            Some(def_id) => self.tcx.lang_items().items().iter().any(|item| *item == Some(def_id)),
             _ => false
         };
         !field.is_positional()
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 837ab4fd4a3..1c7d0b76a64 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -66,7 +66,7 @@ use hir::def_id::CrateNum;
 use session;
 use session::config;
 use ty::TyCtxt;
-use middle::cstore::DepKind;
+use middle::cstore::{self, DepKind};
 use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
 use util::nodemap::FxHashMap;
 use rustc_back::PanicStrategy;
@@ -132,12 +132,12 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             if let Some(v) = attempt_static(tcx) {
                 return v;
             }
-            for cnum in sess.cstore.crates() {
-                if sess.cstore.dep_kind(cnum).macros_only() { continue }
-                let src = sess.cstore.used_crate_source(cnum);
+            for &cnum in tcx.crates().iter() {
+                if tcx.dep_kind(cnum).macros_only() { continue }
+                let src = tcx.used_crate_source(cnum);
                 if src.rlib.is_some() { continue }
                 sess.err(&format!("dependency `{}` not found in rlib format",
-                                  sess.cstore.crate_name(cnum)));
+                                  tcx.crate_name(cnum)));
             }
             return Vec::new();
         }
@@ -165,24 +165,23 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Sweep all crates for found dylibs. Add all dylibs, as well as their
     // dependencies, ensuring there are no conflicts. The only valid case for a
     // dependency to be relied upon twice is for both cases to rely on a dylib.
-    for cnum in sess.cstore.crates() {
-        if sess.cstore.dep_kind(cnum).macros_only() { continue }
-        let name = sess.cstore.crate_name(cnum);
-        let src = sess.cstore.used_crate_source(cnum);
+    for &cnum in tcx.crates().iter() {
+        if tcx.dep_kind(cnum).macros_only() { continue }
+        let name = tcx.crate_name(cnum);
+        let src = tcx.used_crate_source(cnum);
         if src.dylib.is_some() {
             info!("adding dylib: {}", name);
-            add_library(sess, cnum, RequireDynamic, &mut formats);
-            let deps = tcx.dylib_dependency_formats(cnum.as_def_id());
+            add_library(tcx, cnum, RequireDynamic, &mut formats);
+            let deps = tcx.dylib_dependency_formats(cnum);
             for &(depnum, style) in deps.iter() {
-                info!("adding {:?}: {}", style,
-                      sess.cstore.crate_name(depnum));
-                add_library(sess, depnum, style, &mut formats);
+                info!("adding {:?}: {}", style, tcx.crate_name(depnum));
+                add_library(tcx, depnum, style, &mut formats);
             }
         }
     }
 
     // Collect what we've got so far in the return vector.
-    let last_crate = sess.cstore.crates().len();
+    let last_crate = tcx.crates().len();
     let mut ret = (1..last_crate+1).map(|cnum| {
         match formats.get(&CrateNum::new(cnum)) {
             Some(&RequireDynamic) => Linkage::Dynamic,
@@ -196,14 +195,14 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     //
     // If the crate hasn't been included yet and it's not actually required
     // (e.g. it's an allocator) then we skip it here as well.
-    for cnum in sess.cstore.crates() {
-        let src = sess.cstore.used_crate_source(cnum);
+    for &cnum in tcx.crates().iter() {
+        let src = tcx.used_crate_source(cnum);
         if src.dylib.is_none() &&
            !formats.contains_key(&cnum) &&
-           sess.cstore.dep_kind(cnum) == DepKind::Explicit {
+           tcx.dep_kind(cnum) == DepKind::Explicit {
             assert!(src.rlib.is_some() || src.rmeta.is_some());
-            info!("adding staticlib: {}", sess.cstore.crate_name(cnum));
-            add_library(sess, cnum, RequireStatic, &mut formats);
+            info!("adding staticlib: {}", tcx.crate_name(cnum));
+            add_library(tcx, cnum, RequireStatic, &mut formats);
             ret[cnum.as_usize() - 1] = Linkage::Static;
         }
     }
@@ -215,7 +214,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // Things like allocators and panic runtimes may not have been activated
     // quite yet, so do so here.
     activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
-                          &|cnum| tcx.is_panic_runtime(cnum.as_def_id()));
+                          &|cnum| tcx.is_panic_runtime(cnum));
     activate_injected_allocator(sess, &mut ret);
 
     // When dylib B links to dylib A, then when using B we must also link to A.
@@ -226,7 +225,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // making sure that everything is available in the requested format.
     for (cnum, kind) in ret.iter().enumerate() {
         let cnum = CrateNum::new(cnum + 1);
-        let src = sess.cstore.used_crate_source(cnum);
+        let src = tcx.used_crate_source(cnum);
         match *kind {
             Linkage::NotLinked |
             Linkage::IncludedFromDylib => {}
@@ -237,7 +236,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     Linkage::Static => "rlib",
                     _ => "dylib",
                 };
-                let name = sess.cstore.crate_name(cnum);
+                let name = tcx.crate_name(cnum);
                 sess.err(&format!("crate `{}` required to be available in {}, \
                                   but it was not available in this form",
                                   name, kind));
@@ -248,7 +247,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     return ret;
 }
 
-fn add_library(sess: &session::Session,
+fn add_library(tcx: TyCtxt,
                cnum: CrateNum,
                link: LinkagePreference,
                m: &mut FxHashMap<CrateNum, LinkagePreference>) {
@@ -262,8 +261,8 @@ fn add_library(sess: &session::Session,
             // This error is probably a little obscure, but I imagine that it
             // can be refined over time.
             if link2 != link || link == RequireStatic {
-                sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \
-                                          shows up once", sess.cstore.crate_name(cnum)))
+                tcx.sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \
+                                              shows up once", tcx.crate_name(cnum)))
                     .help("having upstream crates all available in one format \
                            will likely make this go away")
                     .emit();
@@ -275,16 +274,16 @@ fn add_library(sess: &session::Session,
 
 fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyList> {
     let sess = &tcx.sess;
-    let crates = sess.cstore.used_crates(RequireStatic);
+    let crates = cstore::used_crates(tcx, RequireStatic);
     if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) {
         return None
     }
 
     // All crates are available in an rlib format, so we're just going to link
     // everything in explicitly so long as it's actually required.
-    let last_crate = sess.cstore.crates().len();
+    let last_crate = tcx.crates().len();
     let mut ret = (1..last_crate+1).map(|cnum| {
-        if sess.cstore.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit {
+        if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit {
             Linkage::Static
         } else {
             Linkage::NotLinked
@@ -295,7 +294,7 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyLis
     // explicitly linked, which is the case for any injected dependency. Handle
     // that here and activate them.
     activate_injected_dep(sess.injected_panic_runtime.get(), &mut ret,
-                          &|cnum| tcx.is_panic_runtime(cnum.as_def_id()));
+                          &|cnum| tcx.is_panic_runtime(cnum));
     activate_injected_allocator(sess, &mut ret);
 
     Some(ret)
@@ -355,15 +354,15 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
         }
         let cnum = CrateNum::new(i + 1);
 
-        if tcx.is_panic_runtime(cnum.as_def_id()) {
+        if tcx.is_panic_runtime(cnum) {
             if let Some((prev, _)) = panic_runtime {
-                let prev_name = sess.cstore.crate_name(prev);
-                let cur_name = sess.cstore.crate_name(cnum);
+                let prev_name = tcx.crate_name(prev);
+                let cur_name = tcx.crate_name(cnum);
                 sess.err(&format!("cannot link together two \
                                    panic runtimes: {} and {}",
                                   prev_name, cur_name));
             }
-            panic_runtime = Some((cnum, sess.cstore.panic_strategy(cnum)));
+            panic_runtime = Some((cnum, tcx.panic_strategy(cnum)));
         }
     }
 
@@ -379,7 +378,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
             sess.err(&format!("the linked panic runtime `{}` is \
                                not compiled with this crate's \
                                panic strategy `{}`",
-                              sess.cstore.crate_name(cnum),
+                              tcx.crate_name(cnum),
                               desired_strategy.desc()));
         }
 
@@ -395,8 +394,8 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
                 continue
             }
             let cnum = CrateNum::new(i + 1);
-            let found_strategy = sess.cstore.panic_strategy(cnum);
-            let is_compiler_builtins = sess.cstore.is_compiler_builtins(cnum);
+            let found_strategy = tcx.panic_strategy(cnum);
+            let is_compiler_builtins = tcx.is_compiler_builtins(cnum);
             if is_compiler_builtins || desired_strategy == found_strategy {
                 continue
             }
@@ -405,7 +404,7 @@ fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
                                panic strategy `{}` which is \
                                incompatible with this crate's \
                                strategy of `{}`",
-                              sess.cstore.crate_name(cnum),
+                              tcx.crate_name(cnum),
                               found_strategy.desc(),
                               desired_strategy.desc()));
         }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 374b02125a1..73f78477b0a 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -211,9 +211,9 @@ enum OverloadedCallType {
 impl OverloadedCallType {
     fn from_trait_id(tcx: TyCtxt, trait_id: DefId) -> OverloadedCallType {
         for &(maybe_function_trait, overloaded_call_type) in &[
-            (tcx.lang_items.fn_once_trait(), FnOnceOverloadedCall),
-            (tcx.lang_items.fn_mut_trait(), FnMutOverloadedCall),
-            (tcx.lang_items.fn_trait(), FnOverloadedCall)
+            (tcx.lang_items().fn_once_trait(), FnOnceOverloadedCall),
+            (tcx.lang_items().fn_mut_trait(), FnMutOverloadedCall),
+            (tcx.lang_items().fn_trait(), FnOverloadedCall)
         ] {
             match maybe_function_trait {
                 Some(function_trait) if function_trait == trait_id => {
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index ae3e3a30f37..cb59d9870fa 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -21,10 +21,8 @@
 
 pub use self::LangItem::*;
 
-use hir::map as hir_map;
-use session::Session;
 use hir::def_id::DefId;
-use ty;
+use ty::{self, TyCtxt};
 use middle::weak_lang_items;
 use util::nodemap::FxHashMap;
 
@@ -116,9 +114,7 @@ impl LanguageItems {
 struct LanguageItemCollector<'a, 'tcx: 'a> {
     items: LanguageItems,
 
-    hir_map: &'a hir_map::Map<'tcx>,
-
-    session: &'a Session,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     item_refs: FxHashMap<&'static str, usize>,
 }
@@ -129,10 +125,11 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
             let item_index = self.item_refs.get(&*value.as_str()).cloned();
 
             if let Some(item_index) = item_index {
-                self.collect_item(item_index, self.hir_map.local_def_id(item.id))
+                let def_id = self.tcx.hir.local_def_id(item.id);
+                self.collect_item(item_index, def_id);
             } else {
-                let span = self.hir_map.span(item.id);
-                span_err!(self.session, span, E0522,
+                let span = self.tcx.hir.span(item.id);
+                span_err!(self.tcx.sess, span, E0522,
                           "definition of an unknown language item: `{}`.",
                           value);
             }
@@ -149,45 +146,41 @@ impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LanguageItemCollector<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
-    pub fn new(session: &'a Session, hir_map: &'a hir_map::Map<'tcx>)
-               -> LanguageItemCollector<'a, 'tcx> {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> {
         let mut item_refs = FxHashMap();
 
         $( item_refs.insert($name, $variant as usize); )*
 
         LanguageItemCollector {
-            session,
-            hir_map,
+            tcx,
             items: LanguageItems::new(),
             item_refs,
         }
     }
 
-    pub fn collect_item(&mut self, item_index: usize,
-                        item_def_id: DefId) {
+    fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
         // Check for duplicates.
         match self.items.items[item_index] {
             Some(original_def_id) if original_def_id != item_def_id => {
-                let cstore = &self.session.cstore;
                 let name = LanguageItems::item_name(item_index);
-                let mut err = match self.hir_map.span_if_local(item_def_id) {
+                let mut err = match self.tcx.hir.span_if_local(item_def_id) {
                     Some(span) => struct_span_err!(
-                        self.session,
+                        self.tcx.sess,
                         span,
                         E0152,
                         "duplicate lang item found: `{}`.",
                         name),
-                    None => self.session.struct_err(&format!(
+                    None => self.tcx.sess.struct_err(&format!(
                             "duplicate lang item in crate `{}`: `{}`.",
-                            cstore.crate_name(item_def_id.krate),
+                            self.tcx.crate_name(item_def_id.krate),
                             name)),
                 };
-                if let Some(span) = self.hir_map.span_if_local(original_def_id) {
+                if let Some(span) = self.tcx.hir.span_if_local(original_def_id) {
                     span_note!(&mut err, span,
                                "first defined here.");
                 } else {
                     err.note(&format!("first defined in crate `{}`.",
-                                      cstore.crate_name(original_def_id.krate)));
+                                      self.tcx.crate_name(original_def_id.krate)));
                 }
                 err.emit();
             }
@@ -199,26 +192,6 @@ impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
         // Matched.
         self.items.items[item_index] = Some(item_def_id);
     }
-
-    pub fn collect_local_language_items(&mut self, krate: &hir::Crate) {
-        krate.visit_all_item_likes(self);
-    }
-
-    pub fn collect_external_language_items(&mut self) {
-        let cstore = &self.session.cstore;
-
-        for cnum in cstore.crates() {
-            for (index, item_index) in cstore.lang_items(cnum) {
-                let def_id = DefId { krate: cnum, index: index };
-                self.collect_item(item_index, def_id);
-            }
-        }
-    }
-
-    pub fn collect(&mut self, krate: &hir::Crate) {
-        self.collect_external_language_items();
-        self.collect_local_language_items(krate);
-    }
 }
 
 pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
@@ -233,14 +206,17 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<Symbol> {
     return None;
 }
 
-pub fn collect_language_items(session: &Session,
-                              map: &hir_map::Map)
-                              -> LanguageItems {
-    let krate: &hir::Crate = map.krate();
-    let mut collector = LanguageItemCollector::new(session, map);
-    collector.collect(krate);
+pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
+    let mut collector = LanguageItemCollector::new(tcx);
+    for &cnum in tcx.crates().iter() {
+        for &(index, item_index) in tcx.defined_lang_items(cnum).iter() {
+            let def_id = DefId { krate: cnum, index: index };
+            collector.collect_item(item_index, def_id);
+        }
+    }
+    tcx.hir.krate().visit_all_item_likes(&mut collector);
     let LanguageItemCollector { mut items, .. } = collector;
-    weak_lang_items::check_crate(krate, session, &mut items);
+    weak_lang_items::check_crate(tcx, &mut items);
     items
 }
 
@@ -366,7 +342,7 @@ language_item_table! {
 
 impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> {
     pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
-        self.lang_items.require(lang_item).unwrap_or_else(|msg| {
+        self.lang_items().require(lang_item).unwrap_or_else(|msg| {
             self.sess.fatal(&msg)
         })
     }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 3efc696f2a5..33f4d4093fe 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -392,7 +392,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) ->
     for (id, _) in &access_levels.map {
         reachable_context.worklist.push(*id);
     }
-    for item in tcx.lang_items.items().iter() {
+    for item in tcx.lang_items().items().iter() {
         if let Some(did) = *item {
             if let Some(node_id) = tcx.hir.as_local_node_id(did) {
                 reachable_context.worklist.push(node_id);
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index a8e98e53db3..c53e255f0cd 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -978,7 +978,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
             } else {
                 let cstore = &self.sess.cstore;
                 self.xcrate_object_lifetime_defaults.entry(def_id).or_insert_with(|| {
-                    cstore.item_generics_cloned(def_id).types.into_iter().map(|def| {
+                    cstore.item_generics_cloned_untracked(def_id).types.into_iter().map(|def| {
                         def.object_lifetime_default
                     }).collect()
                 })
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index d2ed29a3a0f..ecf3aab05d8 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -15,20 +15,19 @@ pub use self::StabilityLevel::*;
 
 use lint;
 use hir::def::Def;
-use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, DefIndex, LOCAL_CRATE};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
 use ty::{self, TyCtxt};
 use middle::privacy::AccessLevels;
-use session::Session;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::ast;
 use syntax::ast::{NodeId, Attribute};
 use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version};
 use syntax::attr::{self, Stability, Deprecation};
-use util::nodemap::{DefIdMap, FxHashSet, FxHashMap};
+use util::nodemap::{FxHashSet, FxHashMap};
 
 use hir;
-use hir::{Item, Generics, StructField, Variant};
+use hir::{Item, Generics, StructField, Variant, HirId};
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 
 use std::mem::replace;
@@ -63,19 +62,18 @@ pub struct DeprecationEntry {
     pub attr: Deprecation,
     /// The def id where the attr was originally attached. `None` for non-local
     /// `DefId`'s.
-    origin: Option<DefIndex>,
+    origin: Option<HirId>,
 }
 
 impl DeprecationEntry {
-    fn local(attr: Deprecation, id: DefId) -> DeprecationEntry {
-        assert!(id.is_local());
+    fn local(attr: Deprecation, id: HirId) -> DeprecationEntry {
         DeprecationEntry {
             attr,
-            origin: Some(id.index),
+            origin: Some(id),
         }
     }
 
-    fn external(attr: Deprecation) -> DeprecationEntry {
+    pub fn external(attr: Deprecation) -> DeprecationEntry {
         DeprecationEntry {
             attr,
             origin: None,
@@ -94,17 +92,14 @@ impl DeprecationEntry {
 pub struct Index<'tcx> {
     /// This is mostly a cache, except the stabilities of local items
     /// are filled by the annotator.
-    stab_map: DefIdMap<Option<&'tcx Stability>>,
-    depr_map: DefIdMap<Option<DeprecationEntry>>,
+    stab_map: FxHashMap<HirId, &'tcx Stability>,
+    depr_map: FxHashMap<HirId, DeprecationEntry>,
 
     /// Maps for each crate whether it is part of the staged API.
     staged_api: FxHashMap<CrateNum, bool>,
 
     /// Features enabled for this crate.
     active_features: FxHashSet<Symbol>,
-
-    /// Features used by this crate. Updated before and during typeck.
-    used_features: FxHashMap<Symbol, attr::StabilityLevel>
 }
 
 // A private tree-walker for producing an Index.
@@ -178,8 +173,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                     }
                 }
 
-                let def_id = self.tcx.hir.local_def_id(id);
-                self.index.stab_map.insert(def_id, Some(stab));
+                let hir_id = self.tcx.hir.node_to_hir_id(id);
+                self.index.stab_map.insert(hir_id, stab);
 
                 let orig_parent_stab = replace(&mut self.parent_stab, Some(stab));
                 visit_children(self);
@@ -188,8 +183,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                 debug!("annotate: not found, parent = {:?}", self.parent_stab);
                 if let Some(stab) = self.parent_stab {
                     if stab.level.is_unstable() {
-                        let def_id = self.tcx.hir.local_def_id(id);
-                        self.index.stab_map.insert(def_id, Some(stab));
+                        let hir_id = self.tcx.hir.node_to_hir_id(id);
+                        self.index.stab_map.insert(hir_id, stab);
                     }
                 }
                 visit_children(self);
@@ -209,8 +204,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
             // -Zforce-unstable-if-unmarked is set.
             if let Some(stab) = self.parent_stab {
                 if stab.level.is_unstable() {
-                    let def_id = self.tcx.hir.local_def_id(id);
-                    self.index.stab_map.insert(def_id, Some(stab));
+                    let hir_id = self.tcx.hir.node_to_hir_id(id);
+                    self.index.stab_map.insert(hir_id, stab);
                 }
             }
 
@@ -220,16 +215,17 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                 }
 
                 // `Deprecation` is just two pointers, no need to intern it
-                let def_id = self.tcx.hir.local_def_id(id);
-                let depr_entry = Some(DeprecationEntry::local(depr, def_id));
-                self.index.depr_map.insert(def_id, depr_entry.clone());
+                let hir_id = self.tcx.hir.node_to_hir_id(id);
+                let depr_entry = DeprecationEntry::local(depr, hir_id);
+                self.index.depr_map.insert(hir_id, depr_entry.clone());
 
-                let orig_parent_depr = replace(&mut self.parent_depr, depr_entry);
+                let orig_parent_depr = replace(&mut self.parent_depr,
+                                               Some(depr_entry));
                 visit_children(self);
                 self.parent_depr = orig_parent_depr;
-            } else if let parent_depr @ Some(_) = self.parent_depr.clone() {
-                let def_id = self.tcx.hir.local_def_id(id);
-                self.index.depr_map.insert(def_id, parent_depr);
+            } else if let Some(parent_depr) = self.parent_depr.clone() {
+                let hir_id = self.tcx.hir.node_to_hir_id(id);
+                self.index.depr_map.insert(hir_id, parent_depr);
                 visit_children(self);
             } else {
                 visit_children(self);
@@ -322,10 +318,10 @@ struct MissingStabilityAnnotations<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx: 'a> MissingStabilityAnnotations<'a, 'tcx> {
     fn check_missing_stability(&self, id: NodeId, span: Span) {
-        let def_id = self.tcx.hir.local_def_id(id);
-        let stab = self.tcx.stability.borrow().stab_map.get(&def_id).cloned();
+        let hir_id = self.tcx.hir.node_to_hir_id(id);
+        let stab = self.tcx.stability().local_stability(hir_id);
         let is_error = !self.tcx.sess.opts.test &&
-                        (stab == None || stab == Some(None)) &&
+                        stab.is_none() &&
                         self.access_levels.is_reachable(id);
         if is_error {
             self.tcx.sess.span_err(span, "This node does not have a stability attribute");
@@ -386,60 +382,70 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Index<'tcx> {
-    /// Construct the stability index for a crate being compiled.
-    pub fn build(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
+        let is_staged_api =
+            tcx.sess.opts.debugging_opts.force_unstable_if_unmarked ||
+            tcx.sess.features.borrow().staged_api;
+        let mut staged_api = FxHashMap();
+        staged_api.insert(LOCAL_CRATE, is_staged_api);
+        let mut index = Index {
+            staged_api,
+            stab_map: FxHashMap(),
+            depr_map: FxHashMap(),
+            active_features: FxHashSet(),
+        };
+
         let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
 
         // Put the active features into a map for quick lookup
-        self.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect();
+        index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect();
+
+        {
+            let krate = tcx.hir.krate();
+            let mut annotator = Annotator {
+                tcx,
+                index: &mut index,
+                parent_stab: None,
+                parent_depr: None,
+                in_trait_impl: false,
+            };
 
-        let krate = tcx.hir.krate();
-        let mut annotator = Annotator {
-            tcx,
-            index: self,
-            parent_stab: None,
-            parent_depr: None,
-            in_trait_impl: false,
-        };
+            // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
+            // a parent stability annotation which indicates that this is private
+            // with the `rustc_private` feature. This is intended for use when
+            // compiling librustc crates themselves so we can leverage crates.io
+            // while maintaining the invariant that all sysroot crates are unstable
+            // by default and are unable to be used.
+            if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked {
+                let reason = "this crate is being loaded from the sysroot, and \
+                              unstable location; did you mean to load this crate \
+                              from crates.io via `Cargo.toml` instead?";
+                let stability = tcx.intern_stability(Stability {
+                    level: attr::StabilityLevel::Unstable {
+                        reason: Some(Symbol::intern(reason)),
+                        issue: 27812,
+                    },
+                    feature: Symbol::intern("rustc_private"),
+                    rustc_depr: None,
+                });
+                annotator.parent_stab = Some(stability);
+            }
 
-        // If the `-Z force-unstable-if-unmarked` flag is passed then we provide
-        // a parent stability annotation which indicates that this is private
-        // with the `rustc_private` feature. This is intended for use when
-        // compiling librustc crates themselves so we can leverage crates.io
-        // while maintaining the invariant that all sysroot crates are unstable
-        // by default and are unable to be used.
-        if tcx.sess.opts.debugging_opts.force_unstable_if_unmarked {
-            let reason = "this crate is being loaded from the sysroot, and \
-                          unstable location; did you mean to load this crate \
-                          from crates.io via `Cargo.toml` instead?";
-            let stability = tcx.intern_stability(Stability {
-                level: attr::StabilityLevel::Unstable {
-                    reason: Some(Symbol::intern(reason)),
-                    issue: 27812,
-                },
-                feature: Symbol::intern("rustc_private"),
-                rustc_depr: None,
-            });
-            annotator.parent_stab = Some(stability);
+            annotator.annotate(ast::CRATE_NODE_ID,
+                               &krate.attrs,
+                               krate.span,
+                               AnnotationKind::Required,
+                               |v| intravisit::walk_crate(v, krate));
         }
+        return index
+    }
 
-        annotator.annotate(ast::CRATE_NODE_ID, &krate.attrs, krate.span, AnnotationKind::Required,
-                           |v| intravisit::walk_crate(v, krate));
+    pub fn local_stability(&self, id: HirId) -> Option<&'tcx Stability> {
+        self.stab_map.get(&id).cloned()
     }
 
-    pub fn new(sess: &Session) -> Index<'tcx> {
-        let is_staged_api =
-            sess.opts.debugging_opts.force_unstable_if_unmarked ||
-            sess.features.borrow().staged_api;
-        let mut staged_api = FxHashMap();
-        staged_api.insert(LOCAL_CRATE, is_staged_api);
-        Index {
-            staged_api,
-            stab_map: DefIdMap(),
-            depr_map: DefIdMap(),
-            active_features: FxHashSet(),
-            used_features: FxHashMap(),
-        }
+    pub fn local_deprecation_entry(&self, id: HirId) -> Option<DeprecationEntry> {
+        self.depr_map.get(&id).cloned()
     }
 }
 
@@ -476,7 +482,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             _ => {}
         }
 
-        let visibility = self.sess.cstore.visibility(def_id);
+        let visibility = self.visibility(def_id);
 
         match visibility {
             // must check stability for pub items.
@@ -547,10 +553,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             return
         }
 
-        if let Some(&Stability { ref level, ref feature, .. }) = stability {
-            self.stability.borrow_mut().used_features.insert(feature.clone(), level.clone());
-        }
-
         // Issue 38412: private items lack stability markers.
         if self.skip_stability_check_due_to_privacy(def_id) {
             return
@@ -558,7 +560,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
         match stability {
             Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
-                if self.stability.borrow().active_features.contains(feature) {
+                if self.stability().active_features.contains(feature) {
                     return
                 }
 
@@ -610,7 +612,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                 // compiler-generated `extern crate` items have a dummy span.
                 if item.span == DUMMY_SP { return }
 
-                let cnum = match self.tcx.sess.cstore.extern_mod_stmt_cnum(item.id) {
+                let hir_id = self.tcx.hir.node_to_hir_id(item.id);
+                let cnum = match self.tcx.extern_mod_stmt_cnum(hir_id) {
                     Some(cnum) => cnum,
                     None => return,
                 };
@@ -671,49 +674,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    /// Lookup the stability for a node, loading external crate
-    /// metadata as necessary.
-    pub fn lookup_stability(self, id: DefId) -> Option<&'gcx Stability> {
-        if let Some(st) = self.stability.borrow().stab_map.get(&id) {
-            return *st;
-        }
-
-        let st = self.lookup_stability_uncached(id);
-        self.stability.borrow_mut().stab_map.insert(id, st);
-        st
-    }
-
     pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {
         self.lookup_deprecation_entry(id).map(|depr| depr.attr)
     }
-
-    pub fn lookup_deprecation_entry(self, id: DefId) -> Option<DeprecationEntry> {
-        if let Some(depr) = self.stability.borrow().depr_map.get(&id) {
-            return depr.clone();
-        }
-
-        let depr = self.lookup_deprecation_uncached(id);
-        self.stability.borrow_mut().depr_map.insert(id, depr.clone());
-        depr
-    }
-
-    fn lookup_stability_uncached(self, id: DefId) -> Option<&'gcx Stability> {
-        debug!("lookup(id={:?})", id);
-        if id.is_local() {
-            None // The stability cache is filled partially lazily
-        } else {
-            self.stability(id).map(|st| self.intern_stability(st))
-        }
-    }
-
-    fn lookup_deprecation_uncached(self, id: DefId) -> Option<DeprecationEntry> {
-        debug!("lookup(id={:?})", id);
-        if id.is_local() {
-            None // The stability cache is filled partially lazily
-        } else {
-            self.deprecation(id).map(DeprecationEntry::external)
-        }
-    }
 }
 
 /// Given the list of enabled features that were not language features (i.e. that
@@ -724,7 +687,7 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
 
-    if tcx.stability.borrow().staged_api[&LOCAL_CRATE] {
+    if tcx.stability().staged_api[&LOCAL_CRATE] {
         let krate = tcx.hir.krate();
         let mut missing = MissingStabilityAnnotations {
             tcx,
@@ -740,10 +703,6 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         = declared_lib_features.clone().into_iter().collect();
     remaining_lib_features.remove(&Symbol::intern("proc_macro"));
 
-    fn format_stable_since_msg(version: &str) -> String {
-        format!("this feature has been stable since {}. Attribute no longer needed", version)
-    }
-
     for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features {
         let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str())
             .expect("unexpectedly couldn't find version feature was stabilized");
@@ -753,25 +712,23 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
                       &format_stable_since_msg(version));
     }
 
-    let index = tcx.stability.borrow();
-    for (used_lib_feature, level) in &index.used_features {
-        match remaining_lib_features.remove(used_lib_feature) {
-            Some(span) => {
-                if let &attr::StabilityLevel::Stable { since: ref version } = level {
-                    tcx.lint_node(lint::builtin::STABLE_FEATURES,
-                                  ast::CRATE_NODE_ID,
-                                  span,
-                                  &format_stable_since_msg(&version.as_str()));
-                }
-            }
-            None => ( /* used but undeclared, handled during the previous ast visit */ )
-        }
-    }
+    // FIXME(#44232) the `used_features` table no longer exists, so we don't
+    //               lint about unknown or unused features. We should reenable
+    //               this one day!
+    //
+    // let index = tcx.stability();
+    // for (used_lib_feature, level) in &index.used_features {
+    //     remaining_lib_features.remove(used_lib_feature);
+    // }
+    //
+    // for &span in remaining_lib_features.values() {
+    //     tcx.lint_node(lint::builtin::UNUSED_FEATURES,
+    //                   ast::CRATE_NODE_ID,
+    //                   span,
+    //                   "unused or unknown feature");
+    // }
+}
 
-    for &span in remaining_lib_features.values() {
-        tcx.lint_node(lint::builtin::UNUSED_FEATURES,
-                      ast::CRATE_NODE_ID,
-                      span,
-                      "unused or unknown feature");
-    }
+fn format_stable_since_msg(version: &str) -> String {
+    format!("this feature has been stable since {}. Attribute no longer needed", version)
 }
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index acb506878e6..50fb5840702 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -11,7 +11,6 @@
 //! Validity checking for weak lang items
 
 use session::config;
-use session::Session;
 use middle::lang_items;
 
 use rustc_back::PanicStrategy;
@@ -21,38 +20,38 @@ use syntax_pos::Span;
 use hir::intravisit::{Visitor, NestedVisitorMap};
 use hir::intravisit;
 use hir;
+use ty::TyCtxt;
 
 use std::collections::HashSet;
 
 macro_rules! weak_lang_items {
     ($($name:ident, $item:ident, $sym:ident;)*) => (
 
-struct Context<'a> {
-    sess: &'a Session,
+struct Context<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     items: &'a mut lang_items::LanguageItems,
 }
 
 /// Checks the crate for usage of weak lang items, returning a vector of all the
 /// language items required by this crate, but not defined yet.
-pub fn check_crate(krate: &hir::Crate,
-                   sess: &Session,
-                   items: &mut lang_items::LanguageItems) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             items: &mut lang_items::LanguageItems) {
     // These are never called by user code, they're generated by the compiler.
     // They will never implicitly be added to the `missing` array unless we do
     // so here.
     if items.eh_personality().is_none() {
         items.missing.push(lang_items::EhPersonalityLangItem);
     }
-    if sess.target.target.options.custom_unwind_resume &
+    if tcx.sess.target.target.options.custom_unwind_resume &
        items.eh_unwind_resume().is_none() {
         items.missing.push(lang_items::EhUnwindResumeLangItem);
     }
 
     {
-        let mut cx = Context { sess: sess, items: items };
-        krate.visit_all_item_likes(&mut cx.as_deep_visitor());
+        let mut cx = Context { tcx, items };
+        tcx.hir.krate().visit_all_item_likes(&mut cx.as_deep_visitor());
     }
-    verify(sess, items);
+    verify(tcx, items);
 }
 
 pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> {
@@ -65,10 +64,11 @@ pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol> {
     })
 }
 
-fn verify(sess: &Session, items: &lang_items::LanguageItems) {
+fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    items: &lang_items::LanguageItems) {
     // We only need to check for the presence of weak lang items if we're
     // emitting something that's not an rlib.
-    let needs_check = sess.crate_types.borrow().iter().any(|kind| {
+    let needs_check = tcx.sess.crate_types.borrow().iter().any(|kind| {
         match *kind {
             config::CrateTypeDylib |
             config::CrateTypeProcMacro |
@@ -83,8 +83,8 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) {
     }
 
     let mut missing = HashSet::new();
-    for cnum in sess.cstore.crates() {
-        for item in sess.cstore.missing_lang_items(cnum) {
+    for &cnum in tcx.crates().iter() {
+        for &item in tcx.missing_lang_items(cnum).iter() {
             missing.insert(item);
         }
     }
@@ -93,7 +93,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) {
     // symbols. Other panic runtimes ensure that the relevant symbols are
     // available to link things together, but they're never exercised.
     let mut whitelisted = HashSet::new();
-    if sess.panic_strategy() != PanicStrategy::Unwind {
+    if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
         whitelisted.insert(lang_items::EhPersonalityLangItem);
         whitelisted.insert(lang_items::EhUnwindResumeLangItem);
     }
@@ -102,28 +102,28 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) {
         if missing.contains(&lang_items::$item) &&
            !whitelisted.contains(&lang_items::$item) &&
            items.$name().is_none() {
-            sess.err(&format!("language item required, but not found: `{}`",
-                              stringify!($name)));
+            tcx.sess.err(&format!("language item required, but not found: `{}`",
+                                  stringify!($name)));
 
         }
     )*
 }
 
-impl<'a> Context<'a> {
+impl<'a, 'tcx> Context<'a, 'tcx> {
     fn register(&mut self, name: &str, span: Span) {
         $(if name == stringify!($name) {
             if self.items.$name().is_none() {
                 self.items.missing.push(lang_items::$item);
             }
         } else)* {
-            span_err!(self.sess, span, E0264,
+            span_err!(self.tcx.sess, span, E0264,
                       "unknown external lang item: `{}`",
                       name);
         }
     }
 }
 
-impl<'a, 'v> Visitor<'v> for Context<'a> {
+impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'v> {
         NestedVisitorMap::None
     }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index ce6da55fec3..cfbd4ba055e 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -348,7 +348,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             //
             // Currently I'm leaving it for what I need for `try`.
             if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) {
-                method = self.tcx.item_name(item).as_str();
+                method = self.tcx.item_name(item);
                 flags.push(("from_method", None));
                 flags.push(("from_method", Some(&*method)));
             }
@@ -919,7 +919,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 // anyway. In that case, why inundate the user.
                 if !self.tcx.sess.has_errors() {
                     if
-                        self.tcx.lang_items.sized_trait()
+                        self.tcx.lang_items().sized_trait()
                         .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                     {
                         self.need_type_info(body_id, span, self_ty);
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 9c04c013c4b..fd6d5a86a7f 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -181,7 +181,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     fn generics_require_sized_self(self, def_id: DefId) -> bool {
-        let sized_def_id = match self.lang_items.sized_trait() {
+        let sized_def_id = match self.lang_items().sized_trait() {
             Some(def_id) => def_id,
             None => { return false; /* No Sized trait, can't require it! */ }
         };
diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs
index 7dd3fc70b1e..94f6efcad4a 100644
--- a/src/librustc/traits/on_unimplemented.rs
+++ b/src/librustc/traits/on_unimplemented.rs
@@ -227,7 +227,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
               span: Span)
               -> Result<(), ErrorReported>
     {
-        let name = tcx.item_name(trait_def_id).as_str();
+        let name = tcx.item_name(trait_def_id);
         let generics = tcx.generics_of(trait_def_id);
         let parser = Parser::new(&self.0);
         let types = &generics.types;
@@ -272,7 +272,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
                   trait_ref: ty::TraitRef<'tcx>)
                   -> String
     {
-        let name = tcx.item_name(trait_ref.def_id).as_str();
+        let name = tcx.item_name(trait_ref.def_id);
         let trait_str = tcx.item_path_str(trait_ref.def_id);
         let generics = tcx.generics_of(trait_ref.def_id);
         let generic_map = generics.types.iter().map(|param| {
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 512cfee12b0..1088ada667f 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -1155,7 +1155,7 @@ fn confirm_generator_candidate<'cx, 'gcx, 'tcx>(
 
     let tcx = selcx.tcx();
 
-    let gen_def_id = tcx.lang_items.gen_trait().unwrap();
+    let gen_def_id = tcx.lang_items().gen_trait().unwrap();
 
     // Note: we unwrap the binder here but re-create it below (1)
     let ty::Binder((trait_ref, yield_ty, return_ty)) =
@@ -1252,7 +1252,7 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
            fn_sig);
 
     // the `Output` associated type is declared on `FnOnce`
-    let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap();
+    let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap();
 
     // Note: we unwrap the binder here but re-create it below (1)
     let ty::Binder((trait_ref, ret_type)) =
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index cd259fc2528..98bb3fb0ba9 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1315,7 +1315,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         // and applicable impls. There is a certain set of precedence rules here.
 
         let def_id = obligation.predicate.def_id();
-        if self.tcx().lang_items.copy_trait() == Some(def_id) {
+        let lang_items = self.tcx().lang_items();
+        if lang_items.copy_trait() == Some(def_id) {
             debug!("obligation self ty is {:?}",
                    obligation.predicate.0.self_ty());
 
@@ -1326,16 +1327,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             // For other types, we'll use the builtin rules.
             let copy_conditions = self.copy_conditions(obligation);
             self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
-        } else if self.tcx().lang_items.sized_trait() == Some(def_id) {
+        } else if lang_items.sized_trait() == Some(def_id) {
             // Sized is never implementable by end-users, it is
             // always automatically computed.
             let sized_conditions = self.sized_conditions(obligation);
             self.assemble_builtin_bound_candidates(sized_conditions,
                                                    &mut candidates)?;
-         } else if self.tcx().lang_items.unsize_trait() == Some(def_id) {
+         } else if lang_items.unsize_trait() == Some(def_id) {
              self.assemble_candidates_for_unsizing(obligation, &mut candidates);
          } else {
-             if self.tcx().lang_items.clone_trait() == Some(def_id) {
+             if lang_items.clone_trait() == Some(def_id) {
                  // Same builtin conditions as `Copy`, i.e. every type which has builtin support
                  // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone`
                  // types have builtin support for `Clone`.
@@ -1533,7 +1534,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                    candidates: &mut SelectionCandidateSet<'tcx>)
                                    -> Result<(),SelectionError<'tcx>>
     {
-        if self.tcx().lang_items.gen_trait() != Some(obligation.predicate.def_id()) {
+        if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
             return Ok(());
         }
 
@@ -1570,7 +1571,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                    candidates: &mut SelectionCandidateSet<'tcx>)
                                    -> Result<(),SelectionError<'tcx>>
     {
-        let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
+        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) {
             Some(k) => k,
             None => { return Ok(()); }
         };
@@ -1612,7 +1613,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                                       -> Result<(),SelectionError<'tcx>>
     {
         // We provide impl of all fn traits for fn pointers.
-        if self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()).is_none() {
+        if self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()).is_none() {
             return Ok(());
         }
 
@@ -2346,16 +2347,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         debug!("confirm_builtin_candidate({:?}, {:?})",
                obligation, has_nested);
 
+        let lang_items = self.tcx().lang_items();
         let obligations = if has_nested {
             let trait_def = obligation.predicate.def_id();
             let conditions = match trait_def {
-                _ if Some(trait_def) == self.tcx().lang_items.sized_trait() => {
+                _ if Some(trait_def) == lang_items.sized_trait() => {
                     self.sized_conditions(obligation)
                 }
-                _ if Some(trait_def) == self.tcx().lang_items.copy_trait() => {
+                _ if Some(trait_def) == lang_items.copy_trait() => {
                     self.copy_conditions(obligation)
                 }
-                _ if Some(trait_def) == self.tcx().lang_items.clone_trait() => {
+                _ if Some(trait_def) == lang_items.clone_trait() => {
                     self.copy_conditions(obligation)
                 }
                 _ => bug!("unexpected builtin trait {:?}", trait_def)
@@ -2658,7 +2660,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
     {
         debug!("confirm_closure_candidate({:?})", obligation);
 
-        let kind = match self.tcx().lang_items.fn_trait_kind(obligation.predicate.0.def_id()) {
+        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.0.def_id()) {
             Some(k) => k,
             None => bug!("closure candidate for non-fn trait {:?}", obligation)
         };
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 28abd1577da..b0d6f4d5a31 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -538,8 +538,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             }
             None => {
                 self.global_tcx()
-                    .sess
-                    .cstore
                     .impl_defaultness(node_item_def_id)
                     .is_default()
             }
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 51436660779..349d77cfc1b 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -110,8 +110,8 @@ impl<'a, 'gcx, 'tcx> OverloadedDeref<'tcx> {
     pub fn method_call(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, source: Ty<'tcx>)
                        -> (DefId, &'tcx Substs<'tcx>) {
         let trait_def_id = match self.mutbl {
-            hir::MutImmutable => tcx.lang_items.deref_trait(),
-            hir::MutMutable => tcx.lang_items.deref_mut_trait()
+            hir::MutImmutable => tcx.lang_items().deref_trait(),
+            hir::MutMutable => tcx.lang_items().deref_mut_trait()
         };
         let method_def_id = tcx.associated_items(trait_def_id.unwrap())
             .find(|m| m.kind == ty::AssociatedKind::Method).unwrap().def_id;
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index f475baf1994..18f286ebf55 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -23,7 +23,7 @@ use lint::{self, Lint};
 use ich::{self, StableHashingContext, NodeIdHashingMode};
 use middle::free_region::FreeRegionMap;
 use middle::lang_items;
-use middle::resolve_lifetime;
+use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
 use mir::Mir;
 use mir::transform::Passes;
@@ -33,7 +33,6 @@ use traits;
 use ty::{self, Ty, TypeAndMut};
 use ty::{TyS, TypeVariants, Slice};
 use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region};
-use hir::FreevarMap;
 use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
 use ty::RegionKind;
 use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
@@ -822,7 +821,7 @@ pub struct GlobalCtxt<'tcx> {
     /// Export map produced by name resolution.
     export_map: FxHashMap<HirId, Rc<Vec<Export>>>,
 
-    pub named_region_map: resolve_lifetime::NamedRegionMap,
+    named_region_map: NamedRegionMap,
 
     pub hir: hir_map::Map<'tcx>,
 
@@ -837,11 +836,11 @@ pub struct GlobalCtxt<'tcx> {
     // Records the free variables refrenced by every closure
     // expression. Do not track deps for this, just recompute it from
     // scratch every time.
-    pub freevars: RefCell<FreevarMap>,
+    freevars: FxHashMap<HirId, Rc<Vec<hir::Freevar>>>,
 
-    pub maybe_unused_trait_imports: NodeSet,
+    maybe_unused_trait_imports: FxHashSet<HirId>,
 
-    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
+    maybe_unused_extern_crates: Vec<(HirId, Span)>,
 
     // Internal cache for metadata decoding. No need to track deps on this.
     pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
@@ -851,16 +850,11 @@ pub struct GlobalCtxt<'tcx> {
 
     pub inhabitedness_cache: RefCell<FxHashMap<Ty<'tcx>, DefIdForest>>,
 
-    pub lang_items: middle::lang_items::LanguageItems,
-
     /// Set of nodes which mark locals as mutable which end up getting used at
     /// some point. Local variable definitions not in this set can be warned
     /// about.
     pub used_mut_nodes: RefCell<NodeSet>,
 
-    /// Maps any item's def-id to its stability index.
-    pub stability: RefCell<stability::Index<'tcx>>,
-
     /// Caches the results of trait selection. This cache is used
     /// for things that do not have to do with the parameters in scope.
     pub selection_cache: traits::SelectionCache<'tcx>,
@@ -909,30 +903,6 @@ impl<'tcx> GlobalCtxt<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn crate_name(self, cnum: CrateNum) -> Symbol {
-        if cnum == LOCAL_CRATE {
-            self.crate_name
-        } else {
-            self.sess.cstore.crate_name(cnum)
-        }
-    }
-
-    pub fn original_crate_name(self, cnum: CrateNum) -> Symbol {
-        if cnum == LOCAL_CRATE {
-            self.crate_name.clone()
-        } else {
-            self.sess.cstore.original_crate_name(cnum)
-        }
-    }
-
-    pub fn crate_disambiguator(self, cnum: CrateNum) -> Symbol {
-        if cnum == LOCAL_CRATE {
-            self.sess.local_crate_disambiguator()
-        } else {
-            self.sess.cstore.crate_disambiguator(cnum)
-        }
-    }
-
     pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
         self.global_arenas.generics.alloc(generics)
     }
@@ -1016,8 +986,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   resolutions: ty::Resolutions,
                                   named_region_map: resolve_lifetime::NamedRegionMap,
                                   hir: hir_map::Map<'tcx>,
-                                  lang_items: middle::lang_items::LanguageItems,
-                                  stability: stability::Index<'tcx>,
                                   crate_name: &str,
                                   f: F) -> R
                                   where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
@@ -1026,14 +994,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let interners = CtxtInterners::new(arena);
         let common_types = CommonTypes::new(&interners);
         let dep_graph = hir.dep_graph.clone();
-        let max_cnum = s.cstore.crates().iter().map(|c| c.as_usize()).max().unwrap_or(0);
+        let max_cnum = s.cstore.crates_untracked().iter().map(|c| c.as_usize()).max().unwrap_or(0);
         let mut providers = IndexVec::from_elem_n(extern_providers, max_cnum + 1);
         providers[LOCAL_CRATE] = local_providers;
 
         let def_path_hash_to_def_id = if s.opts.build_dep_graph() {
             let upstream_def_path_tables: Vec<(CrateNum, Rc<_>)> = s
                 .cstore
-                .crates()
+                .crates_untracked()
                 .iter()
                 .map(|&cnum| (cnum, s.cstore.def_path_table(cnum)))
                 .collect();
@@ -1070,26 +1038,50 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             global_interners: interners,
             dep_graph: dep_graph.clone(),
             types: common_types,
-            named_region_map,
+            named_region_map: NamedRegionMap {
+                defs:
+                    named_region_map.defs
+                        .into_iter()
+                        .map(|(k, v)| (hir.node_to_hir_id(k), v))
+                        .collect(),
+                late_bound:
+                    named_region_map.late_bound
+                        .into_iter()
+                        .map(|k| hir.node_to_hir_id(k))
+                        .collect(),
+                object_lifetime_defaults:
+                    named_region_map.object_lifetime_defaults
+                        .into_iter()
+                        .map(|(k, v)| (hir.node_to_hir_id(k), Rc::new(v)))
+                        .collect(),
+            },
             trait_map: resolutions.trait_map.into_iter().map(|(k, v)| {
                 (hir.node_to_hir_id(k), Rc::new(v))
             }).collect(),
             export_map: resolutions.export_map.into_iter().map(|(k, v)| {
                 (hir.node_to_hir_id(k), Rc::new(v))
             }).collect(),
+            freevars: resolutions.freevars.into_iter().map(|(k, v)| {
+                (hir.node_to_hir_id(k), Rc::new(v))
+            }).collect(),
+            maybe_unused_trait_imports:
+                resolutions.maybe_unused_trait_imports
+                    .into_iter()
+                    .map(|id| hir.node_to_hir_id(id))
+                    .collect(),
+            maybe_unused_extern_crates:
+                resolutions.maybe_unused_extern_crates
+                    .into_iter()
+                    .map(|(id, sp)| (hir.node_to_hir_id(id), sp))
+                    .collect(),
             hir,
             def_path_hash_to_def_id,
             maps: maps::Maps::new(providers),
             mir_passes,
-            freevars: RefCell::new(resolutions.freevars),
-            maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
-            maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
             rcache: RefCell::new(FxHashMap()),
             normalized_cache: RefCell::new(FxHashMap()),
             inhabitedness_cache: RefCell::new(FxHashMap()),
-            lang_items,
             used_mut_nodes: RefCell::new(NodeSet()),
-            stability: RefCell::new(stability),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             rvalue_promotable_to_static: RefCell::new(NodeMap()),
@@ -1107,6 +1099,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let cname = self.crate_name(LOCAL_CRATE).as_str();
         self.sess.consider_optimizing(&cname, msg)
     }
+
+    pub fn lang_items(self) -> Rc<middle::lang_items::LanguageItems> {
+        // FIXME(#42293) Right now we insert a `with_ignore` node in the dep
+        // graph here to ignore the fact that `get_lang_items` below depends on
+        // the entire crate.  For now this'll prevent false positives of
+        // recompiling too much when anything changes.
+        //
+        // Once red/green incremental compilation lands we should be able to
+        // remove this because while the crate changes often the lint level map
+        // will change rarely.
+        self.dep_graph.with_ignore(|| {
+            self.get_lang_items(LOCAL_CRATE)
+        })
+    }
+
+    pub fn stability(self) -> Rc<stability::Index<'tcx>> {
+        // FIXME(#42293) we should actually track this, but fails too many tests
+        // today.
+        self.dep_graph.with_ignore(|| {
+            self.stability_index(LOCAL_CRATE)
+        })
+    }
+
+    pub fn crates(self) -> Rc<Vec<CrateNum>> {
+        self.all_crate_nums(LOCAL_CRATE)
+    }
 }
 
 impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
@@ -1994,19 +2012,52 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
     }
 }
 
-fn in_scope_traits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: HirId)
-    -> Option<Rc<Vec<TraitCandidate>>>
-{
-    tcx.gcx.trait_map.get(&id).cloned()
-}
-
-fn module_exports<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: HirId)
-    -> Option<Rc<Vec<Export>>>
-{
-    tcx.gcx.export_map.get(&id).cloned()
+struct NamedRegionMap {
+    defs: FxHashMap<HirId, resolve_lifetime::Region>,
+    late_bound: FxHashSet<HirId>,
+    object_lifetime_defaults: FxHashMap<HirId, Rc<Vec<ObjectLifetimeDefault>>>,
 }
 
 pub fn provide(providers: &mut ty::maps::Providers) {
-    providers.in_scope_traits = in_scope_traits;
-    providers.module_exports = module_exports;
+    // FIXME(#44234) - almost all of these queries have no sub-queries and
+    // therefore no actual inputs, they're just reading tables calculated in
+    // resolve! Does this work? Unsure! That's what the issue is about
+    providers.in_scope_traits = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
+    providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();
+    providers.named_region = |tcx, id| tcx.gcx.named_region_map.defs.get(&id).cloned();
+    providers.is_late_bound = |tcx, id| tcx.gcx.named_region_map.late_bound.contains(&id);
+    providers.object_lifetime_defaults = |tcx, id| {
+        tcx.gcx.named_region_map.object_lifetime_defaults.get(&id).cloned()
+    };
+    providers.crate_name = |tcx, id| {
+        assert_eq!(id, LOCAL_CRATE);
+        tcx.crate_name
+    };
+    providers.get_lang_items = |tcx, id| {
+        assert_eq!(id, LOCAL_CRATE);
+        Rc::new(middle::lang_items::collect(tcx))
+    };
+    providers.freevars = |tcx, id| tcx.gcx.freevars.get(&id).cloned();
+    providers.maybe_unused_trait_import = |tcx, id| {
+        tcx.maybe_unused_trait_imports.contains(&id)
+    };
+    providers.maybe_unused_extern_crates = |tcx, cnum| {
+        assert_eq!(cnum, LOCAL_CRATE);
+        Rc::new(tcx.maybe_unused_extern_crates.clone())
+    };
+
+    providers.stability_index = |tcx, cnum| {
+        assert_eq!(cnum, LOCAL_CRATE);
+        Rc::new(stability::Index::new(tcx))
+    };
+    providers.lookup_stability = |tcx, id| {
+        assert_eq!(id.krate, LOCAL_CRATE);
+        let id = tcx.hir.definitions().def_index_to_hir_id(id.index);
+        tcx.stability().local_stability(id)
+    };
+    providers.lookup_deprecation_entry = |tcx, id| {
+        assert_eq!(id.krate, LOCAL_CRATE);
+        let id = tcx.hir.definitions().def_index_to_hir_id(id.index);
+        tcx.stability().local_deprecation_entry(id)
+    };
 }
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index eadf80871fc..d9d311b14a3 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -13,6 +13,7 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use ty::{self, Ty, TyCtxt};
 use syntax::ast;
 use syntax::symbol::Symbol;
+use syntax::symbol::InternedString;
 
 use std::cell::Cell;
 
@@ -128,9 +129,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn try_push_visible_item_path<T>(self, buffer: &mut T, external_def_id: DefId) -> bool
         where T: ItemPathBuffer
     {
-        let visible_parent_map = self.sess.cstore.visible_parent_map(self.sess);
+        let visible_parent_map = self.visible_parent_map(LOCAL_CRATE);
 
-        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<ast::Name>::new());
+        let (mut cur_def, mut cur_path) = (external_def_id, Vec::<InternedString>::new());
         loop {
             // If `cur_def` is a direct or injected extern crate, push the path to the crate
             // followed by the path to the item within the crate and return.
@@ -138,12 +139,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 match *self.extern_crate(cur_def) {
                     Some(ref extern_crate) if extern_crate.direct => {
                         self.push_item_path(buffer, extern_crate.def_id);
-                        cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
+                        cur_path.iter().rev().map(|segment| buffer.push(&segment)).count();
                         return true;
                     }
                     None => {
                         buffer.push(&self.crate_name(cur_def.krate).as_str());
-                        cur_path.iter().rev().map(|segment| buffer.push(&segment.as_str())).count();
+                        cur_path.iter().rev().map(|segment| buffer.push(&segment)).count();
                         return true;
                     }
                     _ => {},
@@ -152,7 +153,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
             cur_path.push(self.sess.cstore.def_key(cur_def)
                               .disambiguated_data.data.get_opt_name().unwrap_or_else(||
-                Symbol::intern("<unnamed>")));
+                Symbol::intern("<unnamed>").as_str()));
             match visible_parent_map.get(&cur_def) {
                 Some(&def) => cur_def = def,
                 None => return false,
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index cf21a66d515..2348c4ae767 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1344,7 +1344,7 @@ impl<'a, 'tcx> Layout {
                     } else {
                         let st = Struct::new(dl, &fields, &def.repr,
                           kind, ty)?;
-                        let non_zero = Some(def.did) == tcx.lang_items.non_zero();
+                        let non_zero = Some(def.did) == tcx.lang_items().non_zero();
                         Univariant { variant: st, non_zero: non_zero }
                     };
                     return success(layout);
@@ -2043,7 +2043,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
                     if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
                         return Ok(SizeSkeleton::Pointer {
                             non_zero: non_zero ||
-                                Some(def.did) == tcx.lang_items.non_zero(),
+                                Some(def.did) == tcx.lang_items().non_zero(),
                             tail,
                         });
                     } else {
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index 5a372dbf89f..48b92d101ed 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -10,14 +10,19 @@
 
 use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
 use errors::{Diagnostic, DiagnosticBuilder};
-use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
 use hir::def::{Def, Export};
 use hir::{self, TraitCandidate, HirId};
+use hir::svh::Svh;
 use lint;
 use middle::const_val;
-use middle::cstore::{ExternCrate, LinkagePreference};
+use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary};
+use middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
 use middle::privacy::AccessLevels;
 use middle::region;
+use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
+use middle::stability::{self, DeprecationEntry};
+use middle::lang_items::{LanguageItems, LangItem};
 use mir;
 use mir::transform::{MirSuite, MirPassIndex};
 use session::CompileResult;
@@ -28,10 +33,11 @@ use ty::item_path;
 use ty::steal::Steal;
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
-use util::nodemap::{DefIdSet, NodeSet};
+use util::nodemap::{DefIdSet, NodeSet, DefIdMap};
 use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
+use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
 use std::cell::{RefCell, RefMut, Cell};
@@ -428,13 +434,13 @@ impl<'tcx> QueryDescription for queries::def_span<'tcx> {
 }
 
 
-impl<'tcx> QueryDescription for queries::stability<'tcx> {
+impl<'tcx> QueryDescription for queries::lookup_stability<'tcx> {
     fn describe(_: TyCtxt, _: DefId) -> String {
         bug!("stability")
     }
 }
 
-impl<'tcx> QueryDescription for queries::deprecation<'tcx> {
+impl<'tcx> QueryDescription for queries::lookup_deprecation_entry<'tcx> {
     fn describe(_: TyCtxt, _: DefId) -> String {
         bug!("deprecation")
     }
@@ -509,31 +515,25 @@ impl<'tcx> QueryDescription for queries::is_const_fn<'tcx> {
 }
 
 impl<'tcx> QueryDescription for queries::dylib_dependency_formats<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "dylib dependency formats of crate".to_string()
     }
 }
 
-impl<'tcx> QueryDescription for queries::is_allocator<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
-        "checking if the crate is_allocator".to_string()
-    }
-}
-
 impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "checking if the crate is_panic_runtime".to_string()
     }
 }
 
 impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "checking if the crate is_compiler_builtins".to_string()
     }
 }
 
 impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> {
-    fn describe(_: TyCtxt, _: DefId) -> String {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
         "checking if the crate has_global_allocator".to_string()
     }
 }
@@ -568,6 +568,198 @@ impl<'tcx> QueryDescription for queries::module_exports<'tcx> {
     }
 }
 
+impl<'tcx> QueryDescription for queries::is_no_builtins<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("test whether a crate has #![no_builtins]")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::panic_strategy<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("query a crate's configured panic strategy")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_profiler_runtime<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("query a crate is #![profiler_runtime]")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_sanitizer_runtime<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("query a crate is #![sanitizer_runtime]")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::exported_symbols<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the exported symbols of a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::native_libraries<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the native libraries of a linked crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::plugin_registrar_fn<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the plugin registrar for a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::derive_registrar_fn<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the derive registrar for a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::crate_disambiguator<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the disambiguator a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::crate_hash<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the hash a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::original_crate_name<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up the original name a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::implementations_of_trait<'tcx> {
+    fn describe(_tcx: TyCtxt, _: (CrateNum, DefId)) -> String {
+        format!("looking up implementations of a trait in a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::all_trait_implementations<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up all (?) trait implementations")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::link_args<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up link arguments for a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::named_region<'tcx> {
+    fn describe(_tcx: TyCtxt, _: HirId) -> String {
+        format!("fetching info about a named region")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::is_late_bound<'tcx> {
+    fn describe(_tcx: TyCtxt, _: HirId) -> String {
+        format!("testing whether a lifetime is late bound")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::object_lifetime_defaults<'tcx> {
+    fn describe(_tcx: TyCtxt, _: HirId) -> String {
+        format!("fetching a list of ObjectLifetimeDefault for a lifetime")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::dep_kind<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("fetching what a dependency looks like")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::crate_name<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("fetching what a crate is named")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::extern_mod_stmt_cnum<'tcx> {
+    fn describe(_tcx: TyCtxt, _: HirId) -> String {
+        format!("looking up the CrateNum for an `extern mod` statement")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::get_lang_items<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("calculating the lang items map")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::defined_lang_items<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("calculating the lang items defined in a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::missing_lang_items<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("calculating the missing lang items in a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::visible_parent_map<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("calculating the visible parent map")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::missing_extern_crate_item<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("seeing if we're missing an `extern crate` item for this crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::used_crate_source<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking at the source for a crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::postorder_cnums<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("generating a postorder list of CrateNums")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::freevars<'tcx> {
+    fn describe(_tcx: TyCtxt, _: HirId) -> String {
+        format!("looking up free variables for a node")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::maybe_unused_trait_import<'tcx> {
+    fn describe(_tcx: TyCtxt, _: HirId) -> String {
+        format!("testing if a trait import is unused")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::maybe_unused_extern_crates<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("looking up all possibly unused extern crates")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::stability_index<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("calculating the stability index for the local crate")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::all_crate_nums<'tcx> {
+    fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
+        format!("fetching all foreign CrateNum instances")
+    }
+}
+
 // If enabled, send a message to the profile-queries thread
 macro_rules! profq_msg {
     ($tcx:expr, $msg:expr) => {
@@ -1092,8 +1284,8 @@ define_maps! { <'tcx>
 
     [] fn describe_def: DescribeDef(DefId) -> Option<Def>,
     [] fn def_span: DefSpan(DefId) -> Span,
-    [] fn stability: Stability(DefId) -> Option<attr::Stability>,
-    [] fn deprecation: Deprecation(DefId) -> Option<attr::Deprecation>,
+    [] fn lookup_stability: LookupStability(DefId) -> Option<&'tcx attr::Stability>,
+    [] fn lookup_deprecation_entry: LookupDeprecationEntry(DefId) -> Option<DeprecationEntry>,
     [] fn item_attrs: ItemAttrs(DefId) -> Rc<[ast::Attribute]>,
     [] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
     [] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
@@ -1125,21 +1317,72 @@ define_maps! { <'tcx>
     [] fn layout_raw: layout_dep_node(ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
                                   -> Result<&'tcx Layout, LayoutError<'tcx>>,
 
-    [] fn dylib_dependency_formats: DylibDepFormats(DefId)
+    [] fn dylib_dependency_formats: DylibDepFormats(CrateNum)
                                     -> Rc<Vec<(CrateNum, LinkagePreference)>>,
 
-    [] fn is_allocator: IsAllocator(DefId) -> bool,
-    [] fn is_panic_runtime: IsPanicRuntime(DefId) -> bool,
-    [] fn is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool,
-    [] fn has_global_allocator: HasGlobalAllocator(DefId) -> bool,
+    [] fn is_panic_runtime: IsPanicRuntime(CrateNum) -> bool,
+    [] fn is_compiler_builtins: IsCompilerBuiltins(CrateNum) -> bool,
+    [] fn has_global_allocator: HasGlobalAllocator(CrateNum) -> bool,
+    [] fn is_sanitizer_runtime: IsSanitizerRuntime(CrateNum) -> bool,
+    [] fn is_profiler_runtime: IsProfilerRuntime(CrateNum) -> bool,
+    [] fn panic_strategy: GetPanicStrategy(CrateNum) -> PanicStrategy,
+    [] fn is_no_builtins: IsNoBuiltins(CrateNum) -> bool,
 
     [] fn extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
 
-    [] fn lint_levels: lint_levels(CrateNum) -> Rc<lint::LintLevelMap>,
-
     [] fn specializes: specializes_node((DefId, DefId)) -> bool,
     [] fn in_scope_traits: InScopeTraits(HirId) -> Option<Rc<Vec<TraitCandidate>>>,
     [] fn module_exports: ModuleExports(HirId) -> Option<Rc<Vec<Export>>>,
+    [] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,
+
+    [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
+    [] fn exported_symbols: ExportedSymbols(CrateNum) -> Rc<Vec<DefId>>,
+    [] fn native_libraries: NativeLibraries(CrateNum) -> Rc<Vec<NativeLibrary>>,
+    [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
+    [] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
+    [] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> Symbol,
+    [] fn crate_hash: CrateHash(CrateNum) -> Svh,
+    [] fn original_crate_name: OriginalCrateName(CrateNum) -> Symbol,
+
+    [] fn implementations_of_trait: implementations_of_trait_node((CrateNum, DefId))
+        -> Rc<Vec<DefId>>,
+    [] fn all_trait_implementations: AllTraitImplementations(CrateNum)
+        -> Rc<Vec<DefId>>,
+
+    [] fn is_dllimport_foreign_item: IsDllimportForeignItem(DefId) -> bool,
+    [] fn is_statically_included_foreign_item: IsStaticallyIncludedForeignItem(DefId) -> bool,
+    [] fn native_library_kind: NativeLibraryKind(DefId)
+        -> Option<NativeLibraryKind>,
+    [] fn link_args: link_args_node(CrateNum) -> Rc<Vec<String>>,
+
+    [] fn named_region: NamedRegion(HirId) -> Option<Region>,
+    [] fn is_late_bound: IsLateBound(HirId) -> bool,
+    [] fn object_lifetime_defaults: ObjectLifetimeDefaults(HirId)
+        -> Option<Rc<Vec<ObjectLifetimeDefault>>>,
+
+    [] fn visibility: Visibility(DefId) -> ty::Visibility,
+    [] fn dep_kind: DepKind(CrateNum) -> DepKind,
+    [] fn crate_name: CrateName(CrateNum) -> Symbol,
+    [] fn item_children: ItemChildren(DefId) -> Rc<Vec<Export>>,
+    [] fn extern_mod_stmt_cnum: ExternModStmtCnum(HirId) -> Option<CrateNum>,
+
+    [] fn get_lang_items: get_lang_items_node(CrateNum) -> Rc<LanguageItems>,
+    [] fn defined_lang_items: DefinedLangItems(CrateNum) -> Rc<Vec<(DefIndex, usize)>>,
+    [] fn missing_lang_items: MissingLangItems(CrateNum) -> Rc<Vec<LangItem>>,
+    [] fn extern_const_body: ExternConstBody(DefId) -> &'tcx hir::Body,
+    [] fn visible_parent_map: visible_parent_map_node(CrateNum)
+        -> Rc<DefIdMap<DefId>>,
+    [] fn missing_extern_crate_item: MissingExternCrateItem(CrateNum) -> bool,
+    [] fn used_crate_source: UsedCrateSource(CrateNum) -> Rc<CrateSource>,
+    [] fn postorder_cnums: postorder_cnums_node(CrateNum) -> Rc<Vec<CrateNum>>,
+
+    [] fn freevars: Freevars(HirId) -> Option<Rc<Vec<hir::Freevar>>>,
+    [] fn maybe_unused_trait_import: MaybeUnusedTraitImport(HirId) -> bool,
+    [] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum)
+        -> Rc<Vec<(HirId, Span)>>,
+
+    [] fn stability_index: stability_index_node(CrateNum) -> Rc<stability::Index<'tcx>>,
+    [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc<Vec<CrateNum>>,
 }
 
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
@@ -1212,10 +1455,44 @@ fn layout_dep_node<'tcx>(_: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> DepConstructor<'
     DepConstructor::Layout
 }
 
-fn lint_levels<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+fn lint_levels_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::LintLevels
 }
 
 fn specializes_node<'tcx>((a, b): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::Specializes { impl1: a, impl2: b }
 }
+
+fn implementations_of_trait_node<'tcx>((krate, trait_id): (CrateNum, DefId))
+    -> DepConstructor<'tcx>
+{
+    DepConstructor::ImplementationsOfTrait { krate, trait_id }
+}
+
+fn link_args_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::LinkArgs
+}
+
+fn get_lang_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::GetLangItems
+}
+
+fn visible_parent_map_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::VisibleParentMap
+}
+
+fn postorder_cnums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::PostorderCnums
+}
+
+fn maybe_unused_extern_crates_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::MaybeUnusedExternCrates
+}
+
+fn stability_index_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::StabilityIndex
+}
+
+fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
+    DepConstructor::AllCrateNums
+}
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 1851e1b8d34..ef0d844be95 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1447,10 +1447,10 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         if attr::contains_name(&attrs, "fundamental") {
             flags = flags | AdtFlags::IS_FUNDAMENTAL;
         }
-        if Some(did) == tcx.lang_items.phantom_data() {
+        if Some(did) == tcx.lang_items().phantom_data() {
             flags = flags | AdtFlags::IS_PHANTOM_DATA;
         }
-        if Some(did) == tcx.lang_items.owned_box() {
+        if Some(did) == tcx.lang_items().owned_box() {
             flags = flags | AdtFlags::IS_BOX;
         }
         match kind {
@@ -1746,7 +1746,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 // we know that `T` is Sized and do not need to check
                 // it on the impl.
 
-                let sized_trait = match tcx.lang_items.sized_trait() {
+                let sized_trait = match tcx.lang_items().sized_trait() {
                     Some(x) => x,
                     _ => return vec![ty]
                 };
@@ -2206,11 +2206,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn item_name(self, id: DefId) -> ast::Name {
+    pub fn item_name(self, id: DefId) -> InternedString {
         if let Some(id) = self.hir.as_local_node_id(id) {
-            self.hir.name(id)
+            self.hir.name(id).as_str()
         } else if id.index == CRATE_DEF_INDEX {
-            self.sess.cstore.original_crate_name(id.krate)
+            self.original_crate_name(id.krate).as_str()
         } else {
             let def_key = self.sess.cstore.def_key(id);
             // The name of a StructCtor is that of its struct parent.
@@ -2315,7 +2315,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             let node_id = self.hir.as_local_node_id(impl_did).unwrap();
             Ok(self.hir.span(node_id))
         } else {
-            Err(self.sess.cstore.crate_name(impl_did.krate))
+            Err(self.crate_name(impl_did.krate))
         }
     }
 
@@ -2340,9 +2340,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
         F: FnOnce(&[hir::Freevar]) -> T,
     {
-        match self.freevars.borrow().get(&fid) {
+        let hir_id = self.hir.node_to_hir_id(fid);
+        match self.freevars(hir_id) {
             None => f(&[]),
-            Some(d) => f(&d[..])
+            Some(d) => f(&d),
         }
     }
 }
@@ -2510,6 +2511,18 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     traits::normalize_param_env_or_error(tcx, def_id, unnormalized_env, cause)
 }
 
+fn crate_disambiguator<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 crate_num: CrateNum) -> Symbol {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.sess.local_crate_disambiguator()
+}
+
+fn original_crate_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 crate_num: CrateNum) -> Symbol {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    tcx.crate_name.clone()
+}
+
 pub fn provide(providers: &mut ty::maps::Providers) {
     util::provide(providers);
     context::provide(providers);
@@ -2521,6 +2534,8 @@ pub fn provide(providers: &mut ty::maps::Providers) {
         def_span,
         param_env,
         trait_of_item,
+        crate_disambiguator,
+        original_crate_name,
         trait_impls_of: trait_def::trait_impls_of_provider,
         ..*providers
     };
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 9990472c6b4..3aadacfe826 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -141,13 +141,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 trait_id: DefId)
                                                 -> Rc<TraitImpls> {
-    let remote_impls = if trait_id.is_local() {
-        // Traits defined in the current crate can't have impls in upstream
-        // crates, so we don't bother querying the cstore.
-        Vec::new()
-    } else {
-        tcx.sess.cstore.implementations_of_trait(Some(trait_id))
-    };
+    let mut remote_impls = Vec::new();
+
+    // Traits defined in the current crate can't have impls in upstream
+    // crates, so we don't bother querying the cstore.
+    if !trait_id.is_local() {
+        for &cnum in tcx.crates().iter() {
+            let impls = tcx.implementations_of_trait((cnum, trait_id));
+            remote_impls.extend(impls.iter().cloned());
+        }
+    }
 
     let mut blanket_impls = Vec::new();
     let mut non_blanket_impls = FxHashMap();
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 4e4c7b107c4..f21fc8414e7 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -418,7 +418,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         adt_did: DefId,
         validate: &mut FnMut(Self, DefId) -> Result<(), ErrorReported>
     ) -> Option<ty::Destructor> {
-        let drop_trait = if let Some(def_id) = self.lang_items.drop_trait() {
+        let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() {
             def_id
         } else {
             return None;
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index cc581b07de5..c48bd5ac5be 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -159,7 +159,7 @@ pub fn parameterized(f: &mut fmt::Formatter,
         }
 
         write!(f, "{}", tcx.item_path_str(path_def_id))?;
-        Ok(tcx.lang_items.fn_trait_kind(path_def_id))
+        Ok(tcx.lang_items().fn_trait_kind(path_def_id))
     })?;
 
     if !verbose && fn_trait_kind.is_some() && projections.len() == 1 {
@@ -802,7 +802,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
                     for predicate in bounds.predicates {
                         if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
                             // Don't print +Sized, but rather +?Sized if absent.
-                            if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() {
+                            if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() {
                                 is_sized = true;
                                 continue;
                             }
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index c7def0b834c..ea6e1d4cddc 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -327,7 +327,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
                     ConstEvalErr { span: e.span, kind: LayoutError(err) }
                 })
             };
-            match &tcx.item_name(def_id).as_str()[..] {
+            match &tcx.item_name(def_id)[..] {
                 "size_of" => {
                     let size = layout_of(substs.type_at(0))?.size(tcx);
                     return Ok(Integral(Usize(ConstUsize::new(size.bytes(),
@@ -354,7 +354,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
             }
           } else {
             if tcx.is_const_fn(def_id) {
-                tcx.sess.cstore.item_body(tcx, def_id)
+                tcx.extern_const_body(def_id)
             } else {
                 signal!(e, TypeckError)
             }
@@ -774,7 +774,7 @@ fn const_eval<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         tcx.mir_const_qualif(def_id);
         tcx.hir.body(tcx.hir.body_owned_by(id))
     } else {
-        tcx.sess.cstore.item_body(tcx, def_id)
+        tcx.extern_const_body(def_id)
     };
     ConstContext::new(tcx, key.param_env.and(substs), tables).eval(&body.value)
 }
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index ba79f775ef7..5e1fbbc9ca2 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -609,7 +609,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                         let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
                             self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
                         } else {
-                            self.tcx.sess.cstore.item_body(self.tcx, def_id)
+                            self.tcx.extern_const_body(def_id)
                         };
                         let pat = self.lower_const_expr(&body.value, pat_id, span);
                         self.tables = old_tables;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 000d89241a4..b4dde2120a8 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -694,7 +694,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     // this back at some point.
     let _ignore = sess.dep_graph.in_ignore();
     let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
-    crate_loader.preprocess(&krate);
     let resolver_arenas = Resolver::arenas();
     let mut resolver = Resolver::new(sess,
                                      &krate,
@@ -914,12 +913,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     let time_passes = sess.time_passes();
 
-    let lang_items = time(time_passes, "language item collection", || {
-        sess.track_errors(|| {
-            middle::lang_items::collect_language_items(&sess, &hir_map)
-        })
-    })?;
-
     let named_region_map = time(time_passes,
                                 "lifetime resolution",
                                 || middle::resolve_lifetime::krate(sess, &hir_map))?;
@@ -941,8 +934,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
               "static item recursion checking",
               || static_recursion::check_crate(sess, &hir_map))?;
 
-    let index = stability::Index::new(&sess);
-
     let mut local_providers = ty::maps::Providers::default();
     borrowck::provide(&mut local_providers);
     mir::provide(&mut local_providers);
@@ -1029,8 +1020,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                              resolutions,
                              named_region_map,
                              hir_map,
-                             lang_items,
-                             index,
                              name,
                              |tcx| {
         let incremental_hashes_map =
@@ -1042,10 +1031,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
              "load_dep_graph",
              || rustc_incremental::load_dep_graph(tcx, &incremental_hashes_map));
 
-        time(time_passes, "stability index", || {
-            tcx.stability.borrow_mut().build(tcx)
-        });
-
         time(time_passes,
              "stability checking",
              || stability::check_unstable_api_usage(tcx));
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 552130e8a47..de710942ca1 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -15,11 +15,9 @@ use rustc::dep_graph::DepGraph;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
 use rustc_trans;
-use rustc::middle::lang_items;
 use rustc::middle::free_region::FreeRegionMap;
 use rustc::middle::region;
 use rustc::middle::resolve_lifetime;
-use rustc::middle::stability;
 use rustc::ty::subst::{Kind, Subst};
 use rustc::traits::{ObligationCause, Reveal};
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -140,9 +138,7 @@ fn test_env<F>(source_string: &str,
     let hir_map = hir_map::map_crate(&mut hir_forest, defs);
 
     // run just enough stuff to build a tcx:
-    let lang_items = lang_items::collect_language_items(&sess, &hir_map);
     let named_region_map = resolve_lifetime::krate(&sess, &hir_map);
-    let index = stability::Index::new(&sess);
     TyCtxt::create_and_enter(&sess,
                              ty::maps::Providers::default(),
                              ty::maps::Providers::default(),
@@ -152,8 +148,6 @@ fn test_env<F>(source_string: &str,
                              resolutions,
                              named_region_map.unwrap(),
                              hir_map,
-                             lang_items,
-                             index,
                              "test_crate",
                              |tcx| {
         tcx.infer_ctxt().enter(|infcx| {
diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs
index 28d33d95286..434c82095bd 100644
--- a/src/librustc_incremental/persist/fs.rs
+++ b/src/librustc_incremental/persist/fs.rs
@@ -632,7 +632,7 @@ pub fn find_metadata_hashes_for(tcx: TyCtxt, cnum: CrateNum) -> Option<PathBuf>
         }
     };
 
-    let target_svh = tcx.sess.cstore.crate_hash(cnum);
+    let target_svh = tcx.crate_hash(cnum);
     let target_svh = base_n::encode(target_svh.as_u64(), INT_ENCODE_BASE);
 
     let sub_dir = find_metadata_hashes_iter(&target_svh, dir_entries.filter_map(|e| {
diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs
index 9d762a74bfe..44d6788c773 100644
--- a/src/librustc_incremental/persist/hash.rs
+++ b/src/librustc_incremental/persist/hash.rs
@@ -133,7 +133,7 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> {
     fn load_data(&mut self, cnum: CrateNum) {
         debug!("load_data(cnum={})", cnum);
 
-        let svh = self.tcx.sess.cstore.crate_hash(cnum);
+        let svh = self.tcx.crate_hash(cnum);
         let old = self.crate_hashes.insert(cnum, svh);
         debug!("load_data: svh={}", svh);
         assert!(old.is_none(), "loaded data for crate {:?} twice", cnum);
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 780d34d5701..e0d82f3dafc 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -547,7 +547,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
             _ => return,
         }
 
-        let debug = match cx.tcx.lang_items.debug_trait() {
+        let debug = match cx.tcx.lang_items().debug_trait() {
             Some(debug) => debug,
             None => return,
         };
@@ -1063,8 +1063,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary {
             _ => return,
         };
 
-        let prfn = match cx.sess().cstore.extern_mod_stmt_cnum(it.id) {
-            Some(cnum) => cx.sess().cstore.plugin_registrar_fn(cnum),
+        let hir_id = cx.tcx.hir.node_to_hir_id(it.id);
+        let prfn = match cx.tcx.extern_mod_stmt_cnum(hir_id) {
+            Some(cnum) => cx.tcx.plugin_registrar_fn(cnum),
             None => {
                 // Probably means we aren't linking the crate for some reason.
                 //
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 4c25d03b441..7f018a7f5a6 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -12,6 +12,7 @@
 
 use cstore::{self, CStore, CrateSource, MetadataBlob};
 use locator::{self, CratePaths};
+use native_libs::relevant_lib;
 use schema::{CrateRoot, Tracked};
 
 use rustc::hir::def_id::{CrateNum, DefIndex};
@@ -23,10 +24,9 @@ use rustc::session::config::{Sanitizer, self};
 use rustc_back::PanicStrategy;
 use rustc::session::search_paths::PathKind;
 use rustc::middle;
-use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
+use rustc::middle::cstore::{validate_crate_name, ExternCrate};
 use rustc::util::common::record_time;
 use rustc::util::nodemap::FxHashSet;
-use rustc::middle::cstore::NativeLibrary;
 use rustc::hir::map::Definitions;
 
 use std::cell::{RefCell, Cell};
@@ -36,10 +36,8 @@ use std::rc::Rc;
 use std::{cmp, fs};
 
 use syntax::ast;
-use syntax::abi::Abi;
 use syntax::attr;
 use syntax::ext::base::SyntaxExtension;
-use syntax::feature_gate::{self, GateIssue};
 use syntax::symbol::Symbol;
 use syntax::visit;
 use syntax_pos::{Span, DUMMY_SP};
@@ -81,56 +79,6 @@ struct ExternCrateInfo {
     dep_kind: DepKind,
 }
 
-fn register_native_lib(sess: &Session,
-                       cstore: &CStore,
-                       span: Option<Span>,
-                       lib: NativeLibrary) {
-    if lib.name.as_str().is_empty() {
-        match span {
-            Some(span) => {
-                struct_span_err!(sess, span, E0454,
-                                 "#[link(name = \"\")] given with empty name")
-                    .span_label(span, "empty name given")
-                    .emit();
-            }
-            None => {
-                sess.err("empty library name given via `-l`");
-            }
-        }
-        return
-    }
-    let is_osx = sess.target.target.options.is_like_osx;
-    if lib.kind == cstore::NativeFramework && !is_osx {
-        let msg = "native frameworks are only available on macOS targets";
-        match span {
-            Some(span) => span_err!(sess, span, E0455, "{}", msg),
-            None => sess.err(msg),
-        }
-    }
-    if lib.cfg.is_some() && !sess.features.borrow().link_cfg {
-        feature_gate::emit_feature_err(&sess.parse_sess,
-                                       "link_cfg",
-                                       span.unwrap(),
-                                       GateIssue::Language,
-                                       "is feature gated");
-    }
-    if lib.kind == cstore::NativeStaticNobundle && !sess.features.borrow().static_nobundle {
-        feature_gate::emit_feature_err(&sess.parse_sess,
-                                       "static_nobundle",
-                                       span.unwrap(),
-                                       GateIssue::Language,
-                                       "kind=\"static-nobundle\" is feature gated");
-    }
-    cstore.add_used_library(lib);
-}
-
-fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
-    match lib.cfg {
-        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
-        None => true,
-    }
-}
-
 // Extra info about a crate loaded for plugins or exported macros.
 struct ExtensionCrate {
     metadata: PMDSource,
@@ -218,7 +166,7 @@ impl<'a> CrateLoader<'a> {
             // We're also sure to compare *paths*, not actual byte slices. The
             // `source` stores paths which are normalized which may be different
             // from the strings on the command line.
-            let source = self.cstore.used_crate_source(cnum);
+            let source = &self.cstore.get_crate_data(cnum).source;
             if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
                 let found = locs.iter().any(|l| {
                     let l = fs::canonicalize(l).ok();
@@ -721,33 +669,6 @@ impl<'a> CrateLoader<'a> {
         }
     }
 
-    fn get_foreign_items_of_kind(&self, kind: cstore::NativeLibraryKind) -> Vec<DefIndex> {
-        let mut items = vec![];
-        let libs = self.cstore.get_used_libraries();
-        for lib in libs.borrow().iter() {
-            if relevant_lib(self.sess, lib) && lib.kind == kind {
-                items.extend(&lib.foreign_items);
-            }
-        }
-        items
-    }
-
-    fn register_statically_included_foreign_items(&mut self) {
-        for id in self.get_foreign_items_of_kind(cstore::NativeStatic) {
-            self.cstore.add_statically_included_foreign_item(id);
-        }
-        for id in self.get_foreign_items_of_kind(cstore::NativeStaticNobundle) {
-            self.cstore.add_statically_included_foreign_item(id);
-        }
-    }
-
-    fn register_dllimport_foreign_items(&mut self) {
-        let mut dllimports = self.cstore.dllimport_foreign_items.borrow_mut();
-        for id in self.get_foreign_items_of_kind(cstore::NativeUnknown) {
-            dllimports.insert(id);
-        }
-    }
-
     fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
         // If we're only compiling an rlib, then there's no need to select a
         // panic runtime, so we just skip this section entirely.
@@ -1152,84 +1073,6 @@ impl<'a> CrateLoader<'a> {
     }
 }
 
-impl<'a> CrateLoader<'a> {
-    pub fn preprocess(&mut self, krate: &ast::Crate) {
-        for attr in &krate.attrs {
-            if attr.path == "link_args" {
-                if let Some(linkarg) = attr.value_str() {
-                    self.cstore.add_used_link_args(&linkarg.as_str());
-                }
-            }
-        }
-    }
-
-    fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod,
-                           definitions: &Definitions) {
-        if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
-            return;
-        }
-
-        // First, add all of the custom #[link_args] attributes
-        for m in i.attrs.iter().filter(|a| a.check_name("link_args")) {
-            if let Some(linkarg) = m.value_str() {
-                self.cstore.add_used_link_args(&linkarg.as_str());
-            }
-        }
-
-        // Next, process all of the #[link(..)]-style arguments
-        for m in i.attrs.iter().filter(|a| a.check_name("link")) {
-            let items = match m.meta_item_list() {
-                Some(item) => item,
-                None => continue,
-            };
-            let kind = items.iter().find(|k| {
-                k.check_name("kind")
-            }).and_then(|a| a.value_str()).map(Symbol::as_str);
-            let kind = match kind.as_ref().map(|s| &s[..]) {
-                Some("static") => cstore::NativeStatic,
-                Some("static-nobundle") => cstore::NativeStaticNobundle,
-                Some("dylib") => cstore::NativeUnknown,
-                Some("framework") => cstore::NativeFramework,
-                Some(k) => {
-                    struct_span_err!(self.sess, m.span, E0458,
-                              "unknown kind: `{}`", k)
-                        .span_label(m.span, "unknown kind").emit();
-                    cstore::NativeUnknown
-                }
-                None => cstore::NativeUnknown
-            };
-            let n = items.iter().find(|n| {
-                n.check_name("name")
-            }).and_then(|a| a.value_str());
-            let n = match n {
-                Some(n) => n,
-                None => {
-                    struct_span_err!(self.sess, m.span, E0459,
-                                     "#[link(...)] specified without `name = \"foo\"`")
-                        .span_label(m.span, "missing `name` argument").emit();
-                    Symbol::intern("foo")
-                }
-            };
-            let cfg = items.iter().find(|k| {
-                k.check_name("cfg")
-            }).and_then(|a| a.meta_item_list());
-            let cfg = cfg.map(|list| {
-                list[0].meta_item().unwrap().clone()
-            });
-            let foreign_items = fm.items.iter()
-                .map(|it| definitions.opt_def_index(it.id).unwrap())
-                .collect();
-            let lib = NativeLibrary {
-                name: n,
-                kind,
-                cfg,
-                foreign_items,
-            };
-            register_native_lib(self.sess, self.cstore, Some(m.span), lib);
-        }
-    }
-}
-
 impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
     fn postprocess(&mut self, krate: &ast::Crate) {
         // inject the sanitizer runtime before the allocator runtime because all
@@ -1242,72 +1085,10 @@ impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
         if log_enabled!(log::LogLevel::Info) {
             dump_crates(&self.cstore);
         }
-
-        // Process libs passed on the command line
-        // First, check for errors
-        let mut renames = FxHashSet();
-        for &(ref name, ref new_name, _) in &self.sess.opts.libs {
-            if let &Some(ref new_name) = new_name {
-                if new_name.is_empty() {
-                    self.sess.err(
-                        &format!("an empty renaming target was specified for library `{}`",name));
-                } else if !self.cstore.get_used_libraries().borrow().iter()
-                                                           .any(|lib| lib.name == name as &str) {
-                    self.sess.err(&format!("renaming of the library `{}` was specified, \
-                                            however this crate contains no #[link(...)] \
-                                            attributes referencing this library.", name));
-                } else if renames.contains(name) {
-                    self.sess.err(&format!("multiple renamings were specified for library `{}` .",
-                                            name));
-                } else {
-                    renames.insert(name);
-                }
-            }
-        }
-        // Update kind and, optionally, the name of all native libaries
-        // (there may be more than one) with the specified name.
-        for &(ref name, ref new_name, kind) in &self.sess.opts.libs {
-            let mut found = false;
-            for lib in self.cstore.get_used_libraries().borrow_mut().iter_mut() {
-                if lib.name == name as &str {
-                    let mut changed = false;
-                    if let Some(k) = kind {
-                        lib.kind = k;
-                        changed = true;
-                    }
-                    if let &Some(ref new_name) = new_name {
-                        lib.name = Symbol::intern(new_name);
-                        changed = true;
-                    }
-                    if !changed {
-                        self.sess.warn(&format!("redundant linker flag specified for library `{}`",
-                                                name));
-                    }
-
-                    found = true;
-                }
-            }
-            if !found {
-                // Add if not found
-                let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
-                let lib = NativeLibrary {
-                    name: Symbol::intern(new_name.unwrap_or(name)),
-                    kind: if let Some(k) = kind { k } else { cstore::NativeUnknown },
-                    cfg: None,
-                    foreign_items: Vec::new(),
-                };
-                register_native_lib(self.sess, self.cstore, None, lib);
-            }
-        }
-        self.register_statically_included_foreign_items();
-        self.register_dllimport_foreign_items();
     }
 
     fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
         match item.node {
-            ast::ItemKind::ForeignMod(ref fm) => {
-                self.process_foreign_mod(item, fm, definitions)
-            },
             ast::ItemKind::ExternCrate(_) => {
                 let info = self.extract_crate_info(item).unwrap();
                 let (cnum, ..) = self.resolve_crate(
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 0ed8ab2bc55..2d10dadaf64 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -14,13 +14,13 @@
 use schema::{self, Tracked};
 
 use rustc::dep_graph::DepGraph;
-use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefIndex, DefId};
+use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex, DefId};
 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
 use rustc_back::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap, DefIdMap};
+use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
 
 use std::cell::{RefCell, Cell};
 use std::rc::Rc;
@@ -95,11 +95,6 @@ pub struct CStore {
     metas: RefCell<FxHashMap<CrateNum, Rc<CrateMetadata>>>,
     /// Map from NodeId's of local extern crate statements to crate numbers
     extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
-    used_libraries: RefCell<Vec<NativeLibrary>>,
-    used_link_args: RefCell<Vec<String>>,
-    statically_included_foreign_items: RefCell<FxHashSet<DefIndex>>,
-    pub dllimport_foreign_items: RefCell<FxHashSet<DefIndex>>,
-    pub visible_parent_map: RefCell<DefIdMap<DefId>>,
     pub metadata_loader: Box<MetadataLoader>,
 }
 
@@ -109,11 +104,6 @@ impl CStore {
             dep_graph: dep_graph.clone(),
             metas: RefCell::new(FxHashMap()),
             extern_mod_crate_map: RefCell::new(FxHashMap()),
-            used_libraries: RefCell::new(Vec::new()),
-            used_link_args: RefCell::new(Vec::new()),
-            statically_included_foreign_items: RefCell::new(FxHashSet()),
-            dllimport_foreign_items: RefCell::new(FxHashSet()),
-            visible_parent_map: RefCell::new(FxHashMap()),
             metadata_loader,
         }
     }
@@ -126,10 +116,6 @@ impl CStore {
         self.metas.borrow().get(&cnum).unwrap().clone()
     }
 
-    pub fn get_crate_hash(&self, cnum: CrateNum) -> Svh {
-        self.get_crate_data(cnum).hash()
-    }
-
     pub fn set_crate_data(&self, cnum: CrateNum, data: Rc<CrateMetadata>) {
         self.metas.borrow_mut().insert(cnum, data);
     }
@@ -164,86 +150,18 @@ impl CStore {
         ordering.push(krate);
     }
 
-    // This method is used when generating the command line to pass through to
-    // system linker. The linker expects undefined symbols on the left of the
-    // command line to be defined in libraries on the right, not the other way
-    // around. For more info, see some comments in the add_used_library function
-    // below.
-    //
-    // In order to get this left-to-right dependency ordering, we perform a
-    // topological sort of all crates putting the leaves at the right-most
-    // positions.
-    pub fn do_get_used_crates(&self,
-                              prefer: LinkagePreference)
-                              -> Vec<(CrateNum, LibSource)> {
+    pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
         let mut ordering = Vec::new();
         for (&num, _) in self.metas.borrow().iter() {
             self.push_dependencies_in_postorder(&mut ordering, num);
         }
-        info!("topological ordering: {:?}", ordering);
-        ordering.reverse();
-        let mut libs = self.metas
-            .borrow()
-            .iter()
-            .filter_map(|(&cnum, data)| {
-                if data.dep_kind.get().macros_only() { return None; }
-                let path = match prefer {
-                    LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
-                    LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
-                };
-                let path = match path {
-                    Some(p) => LibSource::Some(p),
-                    None => {
-                        if data.source.rmeta.is_some() {
-                            LibSource::MetadataOnly
-                        } else {
-                            LibSource::None
-                        }
-                    }
-                };
-                Some((cnum, path))
-            })
-            .collect::<Vec<_>>();
-        libs.sort_by(|&(a, _), &(b, _)| {
-            let a = ordering.iter().position(|x| *x == a);
-            let b = ordering.iter().position(|x| *x == b);
-            a.cmp(&b)
-        });
-        libs
-    }
-
-    pub fn add_used_library(&self, lib: NativeLibrary) {
-        assert!(!lib.name.as_str().is_empty());
-        self.used_libraries.borrow_mut().push(lib);
-    }
-
-    pub fn get_used_libraries(&self) -> &RefCell<Vec<NativeLibrary>> {
-        &self.used_libraries
-    }
-
-    pub fn add_used_link_args(&self, args: &str) {
-        for s in args.split(' ').filter(|s| !s.is_empty()) {
-            self.used_link_args.borrow_mut().push(s.to_string());
-        }
-    }
-
-    pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String>> {
-        &self.used_link_args
+        return ordering
     }
 
     pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
         self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
     }
 
-    pub fn add_statically_included_foreign_item(&self, id: DefIndex) {
-        self.statically_included_foreign_items.borrow_mut().insert(id);
-    }
-
-    pub fn do_is_statically_included_foreign_item(&self, def_id: DefId) -> bool {
-        assert!(def_id.krate == LOCAL_CRATE);
-        self.statically_included_foreign_items.borrow().contains(&def_id.index)
-    }
-
     pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
         self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
     }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 537e1208614..776fd358290 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -10,24 +10,25 @@
 
 use cstore;
 use encoder;
+use link_args;
+use native_libs;
 use schema;
 
 use rustc::ty::maps::QueryConfig;
-use rustc::middle::cstore::{CrateStore, CrateSource, LibSource, DepKind,
-                            NativeLibrary, MetadataLoader, LinkMeta,
-                            LinkagePreference, LoadedMacro, EncodedMetadata,
-                            EncodedMetadataHashes};
+use rustc::middle::cstore::{CrateStore, DepKind,
+                            MetadataLoader, LinkMeta,
+                            LoadedMacro, EncodedMetadata,
+                            EncodedMetadataHashes, NativeLibraryKind};
+use rustc::middle::stability::DeprecationEntry;
 use rustc::hir::def;
-use rustc::middle::lang_items;
 use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::maps::Providers;
-use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
 use rustc::hir::map::{DefKey, DefPath, DefPathHash};
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::hir::map::definitions::{DefPathTable, GlobalMetaDataKind};
 use rustc::util::nodemap::{NodeSet, DefIdMap};
-use rustc_back::PanicStrategy;
 
 use std::any::Any;
 use std::rc::Rc;
@@ -39,15 +40,19 @@ use syntax::parse::filemap_to_stream;
 use syntax::symbol::Symbol;
 use syntax_pos::{Span, NO_EXPANSION};
 use rustc_data_structures::indexed_set::IdxSetBuf;
-use rustc::hir::svh::Svh;
 use rustc::hir;
 
 macro_rules! provide {
-    (<$lt:tt> $tcx:ident, $def_id:ident, $cdata:ident, $($name:ident => $compute:block)*) => {
+    (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident,
+      $($name:ident => $compute:block)*) => {
         pub fn provide<$lt>(providers: &mut Providers<$lt>) {
-            $(fn $name<'a, $lt:$lt>($tcx: TyCtxt<'a, $lt, $lt>, $def_id: DefId)
+            $(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T)
                                     -> <ty::queries::$name<$lt> as
-                                        QueryConfig>::Value {
+                                        QueryConfig>::Value
+                where T: IntoArgs,
+            {
+                #[allow(unused_variables)]
+                let ($def_id, $other) = def_id_arg.into_args();
                 assert!(!$def_id.is_local());
 
                 let def_path_hash = $tcx.def_path_hash($def_id);
@@ -69,7 +74,25 @@ macro_rules! provide {
     }
 }
 
-provide! { <'tcx> tcx, def_id, cdata,
+// small trait to work around different signature queries all being defined via
+// the macro above.
+trait IntoArgs {
+    fn into_args(self) -> (DefId, DefId);
+}
+
+impl IntoArgs for DefId {
+    fn into_args(self) -> (DefId, DefId) { (self, self) }
+}
+
+impl IntoArgs for CrateNum {
+    fn into_args(self) -> (DefId, DefId) { (self.as_def_id(), self.as_def_id()) }
+}
+
+impl IntoArgs for (CrateNum, DefId) {
+    fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
+}
+
+provide! { <'tcx> tcx, def_id, other, cdata,
     type_of => { cdata.get_type(def_id.index, tcx) }
     generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index)) }
     predicates_of => { cdata.get_predicates(def_id.index, tcx) }
@@ -119,8 +142,12 @@ provide! { <'tcx> tcx, def_id, cdata,
     is_default_impl => { cdata.is_default_impl(def_id.index) }
     describe_def => { cdata.get_def(def_id.index) }
     def_span => { cdata.get_span(def_id.index, &tcx.sess) }
-    stability => { cdata.get_stability(def_id.index) }
-    deprecation => { cdata.get_deprecation(def_id.index) }
+    lookup_stability => {
+        cdata.get_stability(def_id.index).map(|s| tcx.intern_stability(s))
+    }
+    lookup_deprecation_entry => {
+        cdata.get_deprecation(def_id.index).map(DeprecationEntry::external)
+    }
     item_attrs => { cdata.get_item_attrs(def_id.index, &tcx.dep_graph) }
     // FIXME(#38501) We've skipped a `read` on the `HirBody` of
     // a `fn` when encoding, so the dep-tracking wouldn't work.
@@ -143,7 +170,68 @@ provide! { <'tcx> tcx, def_id, cdata,
     is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) }
     is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) }
     has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) }
+    is_sanitizer_runtime => { cdata.is_sanitizer_runtime(&tcx.dep_graph) }
+    is_profiler_runtime => { cdata.is_profiler_runtime(&tcx.dep_graph) }
+    panic_strategy => { cdata.panic_strategy(&tcx.dep_graph) }
     extern_crate => { Rc::new(cdata.extern_crate.get()) }
+    is_no_builtins => { cdata.is_no_builtins(&tcx.dep_graph) }
+    impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
+    exported_symbols => { Rc::new(cdata.get_exported_symbols(&tcx.dep_graph)) }
+    native_libraries => { Rc::new(cdata.get_native_libraries(&tcx.dep_graph)) }
+    plugin_registrar_fn => {
+        cdata.root.plugin_registrar_fn.map(|index| {
+            DefId { krate: def_id.krate, index }
+        })
+    }
+    derive_registrar_fn => {
+        cdata.root.macro_derive_registrar.map(|index| {
+            DefId { krate: def_id.krate, index }
+        })
+    }
+    crate_disambiguator => { cdata.disambiguator() }
+    crate_hash => { cdata.hash() }
+    original_crate_name => { cdata.name() }
+
+    implementations_of_trait => {
+        let mut result = vec![];
+        let filter = Some(other);
+        cdata.get_implementations_for_trait(filter, &tcx.dep_graph, &mut result);
+        Rc::new(result)
+    }
+
+    all_trait_implementations => {
+        let mut result = vec![];
+        cdata.get_implementations_for_trait(None, &tcx.dep_graph, &mut result);
+        Rc::new(result)
+    }
+
+    is_dllimport_foreign_item => {
+        cdata.is_dllimport_foreign_item(def_id.index, &tcx.dep_graph)
+    }
+    visibility => { cdata.get_visibility(def_id.index) }
+    dep_kind => { cdata.dep_kind.get() }
+    crate_name => { cdata.name }
+    item_children => {
+        let mut result = vec![];
+        cdata.each_child_of_item(def_id.index, |child| result.push(child), tcx.sess);
+        Rc::new(result)
+    }
+    defined_lang_items => { Rc::new(cdata.get_lang_items(&tcx.dep_graph)) }
+    missing_lang_items => { Rc::new(cdata.get_missing_lang_items(&tcx.dep_graph)) }
+
+    extern_const_body => {
+        debug!("item_body({:?}): inlining item", def_id);
+        cdata.extern_const_body(tcx, def_id.index)
+    }
+
+    missing_extern_crate_item => {
+        match cdata.extern_crate.get() {
+            Some(extern_crate) if !extern_crate.direct => true,
+            _ => false,
+        }
+    }
+
+    used_crate_source => { Rc::new(cdata.source.clone()) }
 }
 
 pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
@@ -158,8 +246,108 @@ pub fn provide_local<'tcx>(providers: &mut Providers<'tcx>) {
         }
     }
 
+    // FIXME(#44234) - almost all of these queries have no sub-queries and
+    // therefore no actual inputs, they're just reading tables calculated in
+    // resolve! Does this work? Unsure! That's what the issue is about
     *providers = Providers {
         is_const_fn,
+        is_dllimport_foreign_item: |tcx, id| {
+            tcx.native_library_kind(id) == Some(NativeLibraryKind::NativeUnknown)
+        },
+        is_statically_included_foreign_item: |tcx, id| {
+            match tcx.native_library_kind(id) {
+                Some(NativeLibraryKind::NativeStatic) |
+                Some(NativeLibraryKind::NativeStaticNobundle) => true,
+                _ => false,
+            }
+        },
+        native_library_kind: |tcx, id| {
+            tcx.native_libraries(id.krate)
+                .iter()
+                .filter(|lib| native_libs::relevant_lib(&tcx.sess, lib))
+                .find(|l| l.foreign_items.contains(&id.index))
+                .map(|l| l.kind)
+        },
+        native_libraries: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            Rc::new(native_libs::collect(tcx))
+        },
+        link_args: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            Rc::new(link_args::collect(tcx))
+        },
+        extern_mod_stmt_cnum: |tcx, id| {
+            let id = tcx.hir.definitions().find_node_for_hir_id(id);
+            tcx.sess.cstore.extern_mod_stmt_cnum_untracked(id)
+        },
+
+        all_crate_nums: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            Rc::new(tcx.sess.cstore.crates_untracked())
+        },
+
+        // Returns a map from a sufficiently visible external item (i.e. an
+        // external item that is visible from at least one local module) to a
+        // sufficiently visible parent (considering modules that re-export the
+        // external item to be parents).
+        visible_parent_map: |tcx, cnum| {
+            use std::collections::vec_deque::VecDeque;
+            use std::collections::hash_map::Entry;
+
+            assert_eq!(cnum, LOCAL_CRATE);
+            let mut visible_parent_map: DefIdMap<DefId> = DefIdMap();
+
+            for &cnum in tcx.crates().iter() {
+                // Ignore crates without a corresponding local `extern crate` item.
+                if tcx.missing_extern_crate_item(cnum) {
+                    continue
+                }
+
+                let bfs_queue = &mut VecDeque::new();
+                let visible_parent_map = &mut visible_parent_map;
+                let mut add_child = |bfs_queue: &mut VecDeque<_>,
+                                     child: &def::Export,
+                                     parent: DefId| {
+                    let child = child.def.def_id();
+
+                    if tcx.visibility(child) != ty::Visibility::Public {
+                        return;
+                    }
+
+                    match visible_parent_map.entry(child) {
+                        Entry::Occupied(mut entry) => {
+                            // If `child` is defined in crate `cnum`, ensure
+                            // that it is mapped to a parent in `cnum`.
+                            if child.krate == cnum && entry.get().krate != cnum {
+                                entry.insert(parent);
+                            }
+                        }
+                        Entry::Vacant(entry) => {
+                            entry.insert(parent);
+                            bfs_queue.push_back(child);
+                        }
+                    }
+                };
+
+                bfs_queue.push_back(DefId {
+                    krate: cnum,
+                    index: CRATE_DEF_INDEX
+                });
+                while let Some(def) = bfs_queue.pop_front() {
+                    for child in tcx.item_children(def).iter() {
+                        add_child(bfs_queue, child, def);
+                    }
+                }
+            }
+
+            Rc::new(visible_parent_map)
+        },
+
+        postorder_cnums: |tcx, cnum| {
+            assert_eq!(cnum, LOCAL_CRATE);
+            Rc::new(tcx.sess.cstore.postorder_cnums_untracked())
+        },
+
         ..*providers
     };
 }
@@ -173,53 +361,23 @@ impl CrateStore for cstore::CStore {
         &*self.metadata_loader
     }
 
-    fn visibility(&self, def: DefId) -> ty::Visibility {
+    fn visibility_untracked(&self, def: DefId) -> ty::Visibility {
         self.read_dep_node(def);
         self.get_crate_data(def.krate).get_visibility(def.index)
     }
 
-    fn item_generics_cloned(&self, def: DefId) -> ty::Generics {
+    fn item_generics_cloned_untracked(&self, def: DefId) -> ty::Generics {
         self.read_dep_node(def);
         self.get_crate_data(def.krate).get_generics(def.index)
     }
 
-    fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
-    {
-        let mut result = vec![];
-
-        self.iter_crate_data(|_, cdata| {
-            cdata.get_implementations_for_trait(filter, &self.dep_graph, &mut result)
-        });
-        result
-    }
-
-    fn impl_defaultness(&self, def: DefId) -> hir::Defaultness
-    {
-        self.read_dep_node(def);
-        self.get_crate_data(def.krate).get_impl_defaultness(def.index)
-    }
-
-    fn associated_item_cloned(&self, def: DefId) -> ty::AssociatedItem
+    fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssociatedItem
     {
         self.read_dep_node(def);
         self.get_crate_data(def.krate).get_associated_item(def.index)
     }
 
-    fn is_statically_included_foreign_item(&self, def_id: DefId) -> bool
-    {
-        self.do_is_statically_included_foreign_item(def_id)
-    }
-
-    fn is_dllimport_foreign_item(&self, def_id: DefId) -> bool {
-        if def_id.krate == LOCAL_CRATE {
-            self.dllimport_foreign_items.borrow().contains(&def_id.index)
-        } else {
-            self.get_crate_data(def_id.krate)
-                .is_dllimport_foreign_item(def_id.index, &self.dep_graph)
-        }
-    }
-
-    fn dep_kind(&self, cnum: CrateNum) -> DepKind
+    fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
     {
         let data = self.get_crate_data(cnum);
         let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps);
@@ -227,7 +385,7 @@ impl CrateStore for cstore::CStore {
         data.dep_kind.get()
     }
 
-    fn export_macros(&self, cnum: CrateNum) {
+    fn export_macros_untracked(&self, cnum: CrateNum) {
         let data = self.get_crate_data(cnum);
         let dep_node = data.metadata_dep_node(GlobalMetaDataKind::CrateDeps);
 
@@ -237,83 +395,11 @@ impl CrateStore for cstore::CStore {
         }
     }
 
-    fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)>
-    {
-        self.get_crate_data(cnum).get_lang_items(&self.dep_graph)
-    }
-
-    fn missing_lang_items(&self, cnum: CrateNum)
-                          -> Vec<lang_items::LangItem>
-    {
-        self.get_crate_data(cnum).get_missing_lang_items(&self.dep_graph)
-    }
-
-    fn is_compiler_builtins(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_compiler_builtins(&self.dep_graph)
-    }
-
-    fn is_sanitizer_runtime(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_sanitizer_runtime(&self.dep_graph)
-    }
-
-    fn is_profiler_runtime(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_profiler_runtime(&self.dep_graph)
-    }
-
-    fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy {
-        self.get_crate_data(cnum).panic_strategy(&self.dep_graph)
-    }
-
-    fn crate_name(&self, cnum: CrateNum) -> Symbol
+    fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol
     {
         self.get_crate_data(cnum).name
     }
 
-    fn original_crate_name(&self, cnum: CrateNum) -> Symbol
-    {
-        self.get_crate_data(cnum).name()
-    }
-
-    fn crate_hash(&self, cnum: CrateNum) -> Svh
-    {
-        self.get_crate_hash(cnum)
-    }
-
-    fn crate_disambiguator(&self, cnum: CrateNum) -> Symbol
-    {
-        self.get_crate_data(cnum).disambiguator()
-    }
-
-    fn plugin_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
-    {
-        self.get_crate_data(cnum).root.plugin_registrar_fn.map(|index| DefId {
-            krate: cnum,
-            index,
-        })
-    }
-
-    fn derive_registrar_fn(&self, cnum: CrateNum) -> Option<DefId>
-    {
-        self.get_crate_data(cnum).root.macro_derive_registrar.map(|index| DefId {
-            krate: cnum,
-            index,
-        })
-    }
-
-    fn native_libraries(&self, cnum: CrateNum) -> Vec<NativeLibrary>
-    {
-        self.get_crate_data(cnum).get_native_libraries(&self.dep_graph)
-    }
-
-    fn exported_symbols(&self, cnum: CrateNum) -> Vec<DefId>
-    {
-        self.get_crate_data(cnum).get_exported_symbols(&self.dep_graph)
-    }
-
-    fn is_no_builtins(&self, cnum: CrateNum) -> bool {
-        self.get_crate_data(cnum).is_no_builtins(&self.dep_graph)
-    }
-
     /// Returns the `DefKey` for a given `DefId`. This indicates the
     /// parent `DefId` as well as some idea of what kind of data the
     /// `DefId` refers to.
@@ -343,13 +429,13 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(cnum).def_path_table.clone()
     }
 
-    fn struct_field_names(&self, def: DefId) -> Vec<ast::Name>
+    fn struct_field_names_untracked(&self, def: DefId) -> Vec<ast::Name>
     {
         self.read_dep_node(def);
         self.get_crate_data(def.krate).get_struct_field_names(def.index)
     }
 
-    fn item_children(&self, def_id: DefId, sess: &Session) -> Vec<def::Export>
+    fn item_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<def::Export>
     {
         self.read_dep_node(def_id);
         let mut result = vec![];
@@ -358,7 +444,7 @@ impl CrateStore for cstore::CStore {
         result
     }
 
-    fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
+    fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
         let data = self.get_crate_data(id.krate);
         if let Some(ref proc_macros) = data.proc_macros {
             return LoadedMacro::ProcMacro(proc_macros[id.index.as_usize() - 1].1.clone());
@@ -387,7 +473,7 @@ impl CrateStore for cstore::CStore {
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
         LoadedMacro::MacroDef(ast::Item {
-            ident: ast::Ident::with_empty_ctxt(name),
+            ident: ast::Ident::from_str(&name),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs.iter().cloned().collect(),
@@ -400,50 +486,20 @@ impl CrateStore for cstore::CStore {
         })
     }
 
-    fn item_body<'a, 'tcx>(&self,
-                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           def_id: DefId)
-                           -> &'tcx hir::Body {
-        self.read_dep_node(def_id);
-
-        if let Some(cached) = tcx.hir.get_inlined_body_untracked(def_id) {
-            return cached;
-        }
-
-        debug!("item_body({:?}): inlining item", def_id);
-
-        self.get_crate_data(def_id.krate).item_body(tcx, def_id.index)
-    }
-
-    fn crates(&self) -> Vec<CrateNum>
+    fn crates_untracked(&self) -> Vec<CrateNum>
     {
         let mut result = vec![];
         self.iter_crate_data(|cnum, _| result.push(cnum));
         result
     }
 
-    fn used_libraries(&self) -> Vec<NativeLibrary>
-    {
-        self.get_used_libraries().borrow().clone()
-    }
-
-    fn used_link_args(&self) -> Vec<String>
-    {
-        self.get_used_link_args().borrow().clone()
-    }
-    fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
-    {
-        self.do_get_used_crates(prefer)
-    }
-
-    fn used_crate_source(&self, cnum: CrateNum) -> CrateSource
+    fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum>
     {
-        self.get_crate_data(cnum).source.clone()
+        self.do_extern_mod_stmt_cnum(emod_id)
     }
 
-    fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>
-    {
-        self.do_extern_mod_stmt_cnum(emod_id)
+    fn postorder_cnums_untracked(&self) -> Vec<CrateNum> {
+        self.do_postorder_cnums_untracked()
     }
 
     fn encode_metadata<'a, 'tcx>(&self,
@@ -459,67 +515,4 @@ impl CrateStore for cstore::CStore {
     {
         schema::METADATA_HEADER
     }
-
-    /// Returns a map from a sufficiently visible external item (i.e. an external item that is
-    /// visible from at least one local module) to a sufficiently visible parent (considering
-    /// modules that re-export the external item to be parents).
-    fn visible_parent_map<'a>(&'a self, sess: &Session) -> ::std::cell::Ref<'a, DefIdMap<DefId>> {
-        {
-            let visible_parent_map = self.visible_parent_map.borrow();
-            if !visible_parent_map.is_empty() {
-                return visible_parent_map;
-            }
-        }
-
-        use std::collections::vec_deque::VecDeque;
-        use std::collections::hash_map::Entry;
-
-        let mut visible_parent_map = self.visible_parent_map.borrow_mut();
-
-        for cnum in (1 .. self.next_crate_num().as_usize()).map(CrateNum::new) {
-            let cdata = self.get_crate_data(cnum);
-
-            match cdata.extern_crate.get() {
-                // Ignore crates without a corresponding local `extern crate` item.
-                Some(extern_crate) if !extern_crate.direct => continue,
-                _ => {},
-            }
-
-            let bfs_queue = &mut VecDeque::new();
-            let mut add_child = |bfs_queue: &mut VecDeque<_>, child: def::Export, parent: DefId| {
-                let child = child.def.def_id();
-
-                if self.visibility(child) != ty::Visibility::Public {
-                    return;
-                }
-
-                match visible_parent_map.entry(child) {
-                    Entry::Occupied(mut entry) => {
-                        // If `child` is defined in crate `cnum`, ensure
-                        // that it is mapped to a parent in `cnum`.
-                        if child.krate == cnum && entry.get().krate != cnum {
-                            entry.insert(parent);
-                        }
-                    }
-                    Entry::Vacant(entry) => {
-                        entry.insert(parent);
-                        bfs_queue.push_back(child);
-                    }
-                }
-            };
-
-            bfs_queue.push_back(DefId {
-                krate: cnum,
-                index: CRATE_DEF_INDEX
-            });
-            while let Some(def) = bfs_queue.pop_front() {
-                for child in self.item_children(def, sess) {
-                    add_child(bfs_queue, child, def);
-                }
-            }
-        }
-
-        drop(visible_parent_map);
-        self.visible_parent_map.borrow()
-    }
 }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 1e2f167f199..324bab369dc 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -41,6 +41,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
 use syntax::attr;
 use syntax::ast::{self, Ident};
 use syntax::codemap;
+use syntax::symbol::{InternedString, Symbol};
 use syntax::ext::base::MacroKind;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION};
 
@@ -473,7 +474,7 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn item_name(&self, item_index: DefIndex) -> ast::Name {
+    pub fn item_name(&self, item_index: DefIndex) -> InternedString {
         self.def_key(item_index)
             .disambiguated_data
             .data
@@ -520,12 +521,12 @@ impl<'a, 'tcx> CrateMetadata {
 
         ty::VariantDef {
             did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
-            name: self.item_name(index),
+            name: Symbol::intern(&self.item_name(index)),
             fields: item.children.decode(self).map(|index| {
                 let f = self.entry(index);
                 ty::FieldDef {
                     did: self.local_def_id(index),
-                    name: self.item_name(index),
+                    name: Symbol::intern(&self.item_name(index)),
                     vis: f.visibility.decode(self)
                 }
             }).collect(),
@@ -705,7 +706,7 @@ impl<'a, 'tcx> CrateMetadata {
                             if let Some(def) = self.get_def(child_index) {
                                 callback(def::Export {
                                     def,
-                                    ident: Ident::with_empty_ctxt(self.item_name(child_index)),
+                                    ident: Ident::from_str(&self.item_name(child_index)),
                                     span: self.entry(child_index).span.decode((self, sess)),
                                 });
                             }
@@ -722,7 +723,7 @@ impl<'a, 'tcx> CrateMetadata {
                 let span = child.span.decode((self, sess));
                 if let (Some(def), Some(name)) =
                     (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) {
-                    let ident = Ident::with_empty_ctxt(name);
+                    let ident = Ident::from_str(&name);
                     callback(def::Export { def: def, ident: ident, span: span });
                     // For non-reexport structs and variants add their constructors to children.
                     // Reexport lists automatically contain constructors when necessary.
@@ -759,10 +760,10 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn item_body(&self,
-                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                     id: DefIndex)
-                     -> &'tcx hir::Body {
+    pub fn extern_const_body(&self,
+                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             id: DefIndex)
+                             -> &'tcx hir::Body {
         assert!(!self.is_proc_macro(id));
         let ast = self.entry(id).ast.unwrap();
         let def_id = self.local_def_id(id);
@@ -836,7 +837,7 @@ impl<'a, 'tcx> CrateMetadata {
         };
 
         ty::AssociatedItem {
-            name,
+            name: Symbol::intern(&name),
             kind,
             vis: item.visibility.decode(self),
             defaultness: container.defaultness(),
@@ -906,7 +907,7 @@ impl<'a, 'tcx> CrateMetadata {
         self.entry(id)
             .children
             .decode(self)
-            .map(|index| self.item_name(index))
+            .map(|index| Symbol::intern(&self.item_name(index)))
             .collect()
     }
 
@@ -1038,7 +1039,7 @@ impl<'a, 'tcx> CrateMetadata {
             .collect()
     }
 
-    pub fn get_macro(&self, id: DefIndex) -> (ast::Name, MacroDef) {
+    pub fn get_macro(&self, id: DefIndex) -> (InternedString, MacroDef) {
         let entry = self.entry(id);
         match entry.kind {
             EntryKind::MacroDef(macro_def) => (self.item_name(id), macro_def.decode(self)),
diff --git a/src/librustc_metadata/diagnostics.rs b/src/librustc_metadata/diagnostics.rs
index 1fa1a896dd6..0a1662dd42d 100644
--- a/src/librustc_metadata/diagnostics.rs
+++ b/src/librustc_metadata/diagnostics.rs
@@ -14,7 +14,7 @@ register_long_diagnostics! {
 E0454: r##"
 A link name was given with an empty name. Erroneous code example:
 
-```compile_fail,E0454
+```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-trans)
 #[link(name = "")] extern {} // error: #[link(name = "")] given with empty name
 ```
 
@@ -51,7 +51,7 @@ https://doc.rust-lang.org/book/first-edition/conditional-compilation.html
 E0458: r##"
 An unknown "kind" was specified for a link attribute. Erroneous code example:
 
-```compile_fail,E0458
+```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-trans)
 #[link(kind = "wonderful_unicorn")] extern {}
 // error: unknown kind: `wonderful_unicorn`
 ```
@@ -67,7 +67,7 @@ Please specify a valid "kind" value, from one of the following:
 E0459: r##"
 A link was used without a name parameter. Erroneous code example:
 
-```compile_fail,E0459
+```ignore (cannot-test-this-because-rustdoc-stops-compile-fail-before-trans)
 #[link(kind = "dylib")] extern {}
 // error: #[link(...)] specified without `name = "foo"`
 ```
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index d36aebe38eb..a27a85a63e8 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -991,7 +991,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 // "unsized info", else just store None
                 let coerce_unsized_info =
                     trait_ref.and_then(|t| {
-                        if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() {
+                        if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() {
                             Some(tcx.at(item.span).coerce_unsized_info(def_id))
                         } else {
                             None
@@ -1283,21 +1283,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> {
-        let used_libraries = self.tcx.sess.cstore.used_libraries();
-        self.lazy_seq(used_libraries)
+        let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
+        self.lazy_seq(used_libraries.iter().cloned())
     }
 
     fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
-        let cstore = &*self.tcx.sess.cstore;
-        let crates = cstore.crates();
+        let crates = self.tcx.crates();
 
         let mut deps = crates
             .iter()
             .map(|&cnum| {
                 let dep = CrateDep {
-                    name: cstore.original_crate_name(cnum),
-                    hash: cstore.crate_hash(cnum),
-                    kind: cstore.dep_kind(cnum),
+                    name: self.tcx.original_crate_name(cnum),
+                    hash: self.tcx.crate_hash(cnum),
+                    kind: self.tcx.dep_kind(cnum),
                 };
                 (cnum, dep)
             })
@@ -1323,7 +1322,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
         let tcx = self.tcx;
-        let lang_items = tcx.lang_items.items().iter();
+        let lang_items = tcx.lang_items();
+        let lang_items = lang_items.items().iter();
         self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
             if let Some(def_id) = opt_def_id {
                 if def_id.is_local() {
@@ -1336,7 +1336,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> {
         let tcx = self.tcx;
-        self.lazy_seq_ref(&tcx.lang_items.missing)
+        self.lazy_seq_ref(&tcx.lang_items().missing)
     }
 
     /// Encodes an index, mapping each trait to its (local) implementations.
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index f4e6f57c437..54dbb68667b 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -50,6 +50,8 @@ mod decoder;
 mod cstore_impl;
 mod isolated_encoder;
 mod schema;
+mod native_libs;
+mod link_args;
 
 pub mod creader;
 pub mod cstore;
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
new file mode 100644
index 00000000000..6fafde0d09c
--- /dev/null
+++ b/src/librustc_metadata/link_args.rs
@@ -0,0 +1,65 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir;
+use rustc::ty::TyCtxt;
+use syntax::abi::Abi;
+
+pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<String> {
+    let mut collector = Collector {
+        args: Vec::new(),
+    };
+    tcx.hir.krate().visit_all_item_likes(&mut collector);
+
+    for attr in tcx.hir.krate().attrs.iter() {
+        if attr.path == "link_args" {
+            if let Some(linkarg) = attr.value_str() {
+                collector.add_link_args(&linkarg.as_str());
+            }
+        }
+    }
+
+    return collector.args
+}
+
+struct Collector {
+    args: Vec<String>,
+}
+
+impl<'tcx> ItemLikeVisitor<'tcx> for Collector {
+    fn visit_item(&mut self, it: &'tcx hir::Item) {
+        let fm = match it.node {
+            hir::ItemForeignMod(ref fm) => fm,
+            _ => return,
+        };
+        if fm.abi == Abi::Rust ||
+            fm.abi == Abi::RustIntrinsic ||
+            fm.abi == Abi::PlatformIntrinsic {
+            return
+        }
+
+        // First, add all of the custom #[link_args] attributes
+        for m in it.attrs.iter().filter(|a| a.check_name("link_args")) {
+            if let Some(linkarg) = m.value_str() {
+                self.add_link_args(&linkarg.as_str());
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {}
+    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {}
+}
+
+impl Collector {
+    fn add_link_args(&mut self, args: &str) {
+        self.args.extend(args.split(' ').filter(|s| !s.is_empty()).map(|s| s.to_string()))
+    }
+}
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
new file mode 100644
index 00000000000..669681d2aad
--- /dev/null
+++ b/src/librustc_metadata/native_libs.rs
@@ -0,0 +1,217 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir;
+use rustc::middle::cstore::{self, NativeLibrary};
+use rustc::session::Session;
+use rustc::ty::TyCtxt;
+use rustc::util::nodemap::FxHashSet;
+use syntax::abi::Abi;
+use syntax::attr;
+use syntax::codemap::Span;
+use syntax::feature_gate::{self, GateIssue};
+use syntax::symbol::Symbol;
+
+pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<NativeLibrary> {
+    let mut collector = Collector {
+        tcx,
+        libs: Vec::new(),
+    };
+    tcx.hir.krate().visit_all_item_likes(&mut collector);
+    collector.process_command_line();
+    return collector.libs
+}
+
+pub fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
+    match lib.cfg {
+        Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None),
+        None => true,
+    }
+}
+
+struct Collector<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    libs: Vec<NativeLibrary>,
+}
+
+impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
+    fn visit_item(&mut self, it: &'tcx hir::Item) {
+        let fm = match it.node {
+            hir::ItemForeignMod(ref fm) => fm,
+            _ => return,
+        };
+
+        if fm.abi == Abi::Rust ||
+            fm.abi == Abi::RustIntrinsic ||
+            fm.abi == Abi::PlatformIntrinsic {
+            return
+        }
+
+        // Process all of the #[link(..)]-style arguments
+        for m in it.attrs.iter().filter(|a| a.check_name("link")) {
+            let items = match m.meta_item_list() {
+                Some(item) => item,
+                None => continue,
+            };
+            let kind = items.iter().find(|k| {
+                k.check_name("kind")
+            }).and_then(|a| a.value_str()).map(Symbol::as_str);
+            let kind = match kind.as_ref().map(|s| &s[..]) {
+                Some("static") => cstore::NativeStatic,
+                Some("static-nobundle") => cstore::NativeStaticNobundle,
+                Some("dylib") => cstore::NativeUnknown,
+                Some("framework") => cstore::NativeFramework,
+                Some(k) => {
+                    struct_span_err!(self.tcx.sess, m.span, E0458,
+                              "unknown kind: `{}`", k)
+                        .span_label(m.span, "unknown kind").emit();
+                    cstore::NativeUnknown
+                }
+                None => cstore::NativeUnknown
+            };
+            let n = items.iter().find(|n| {
+                n.check_name("name")
+            }).and_then(|a| a.value_str());
+            let n = match n {
+                Some(n) => n,
+                None => {
+                    struct_span_err!(self.tcx.sess, m.span, E0459,
+                                     "#[link(...)] specified without `name = \"foo\"`")
+                        .span_label(m.span, "missing `name` argument").emit();
+                    Symbol::intern("foo")
+                }
+            };
+            let cfg = items.iter().find(|k| {
+                k.check_name("cfg")
+            }).and_then(|a| a.meta_item_list());
+            let cfg = cfg.map(|list| {
+                list[0].meta_item().unwrap().clone()
+            });
+            let foreign_items = fm.items.iter()
+                .map(|it| self.tcx.hir.local_def_id(it.id).index)
+                .collect();
+            let lib = NativeLibrary {
+                name: n,
+                kind,
+                cfg,
+                foreign_items,
+            };
+            self.register_native_lib(Some(m.span), lib);
+        }
+    }
+
+    fn visit_trait_item(&mut self, _it: &'tcx hir::TraitItem) {}
+    fn visit_impl_item(&mut self, _it: &'tcx hir::ImplItem) {}
+}
+
+impl<'a, 'tcx> Collector<'a, 'tcx> {
+    fn register_native_lib(&mut self, span: Option<Span>, lib: NativeLibrary) {
+        if lib.name.as_str().is_empty() {
+            match span {
+                Some(span) => {
+                    struct_span_err!(self.tcx.sess, span, E0454,
+                                     "#[link(name = \"\")] given with empty name")
+                        .span_label(span, "empty name given")
+                        .emit();
+                }
+                None => {
+                    self.tcx.sess.err("empty library name given via `-l`");
+                }
+            }
+            return
+        }
+        let is_osx = self.tcx.sess.target.target.options.is_like_osx;
+        if lib.kind == cstore::NativeFramework && !is_osx {
+            let msg = "native frameworks are only available on macOS targets";
+            match span {
+                Some(span) => span_err!(self.tcx.sess, span, E0455, "{}", msg),
+                None => self.tcx.sess.err(msg),
+            }
+        }
+        if lib.cfg.is_some() && !self.tcx.sess.features.borrow().link_cfg {
+            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
+                                           "link_cfg",
+                                           span.unwrap(),
+                                           GateIssue::Language,
+                                           "is feature gated");
+        }
+        if lib.kind == cstore::NativeStaticNobundle &&
+           !self.tcx.sess.features.borrow().static_nobundle {
+            feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
+                                           "static_nobundle",
+                                           span.unwrap(),
+                                           GateIssue::Language,
+                                           "kind=\"static-nobundle\" is feature gated");
+        }
+        self.libs.push(lib);
+    }
+
+    // Process libs passed on the command line
+    fn process_command_line(&mut self) {
+        // First, check for errors
+        let mut renames = FxHashSet();
+        for &(ref name, ref new_name, _) in &self.tcx.sess.opts.libs {
+            if let &Some(ref new_name) = new_name {
+                if new_name.is_empty() {
+                    self.tcx.sess.err(
+                        &format!("an empty renaming target was specified for library `{}`",name));
+                } else if !self.libs.iter().any(|lib| lib.name == name as &str) {
+                    self.tcx.sess.err(&format!("renaming of the library `{}` was specified, \
+                                                however this crate contains no #[link(...)] \
+                                                attributes referencing this library.", name));
+                } else if renames.contains(name) {
+                    self.tcx.sess.err(&format!("multiple renamings were \
+                                                specified for library `{}` .",
+                                               name));
+                } else {
+                    renames.insert(name);
+                }
+            }
+        }
+
+        // Update kind and, optionally, the name of all native libaries
+        // (there may be more than one) with the specified name.
+        for &(ref name, ref new_name, kind) in &self.tcx.sess.opts.libs {
+            let mut found = false;
+            for lib in self.libs.iter_mut() {
+                if lib.name == name as &str {
+                    let mut changed = false;
+                    if let Some(k) = kind {
+                        lib.kind = k;
+                        changed = true;
+                    }
+                    if let &Some(ref new_name) = new_name {
+                        lib.name = Symbol::intern(new_name);
+                        changed = true;
+                    }
+                    if !changed {
+                        let msg = format!("redundant linker flag specified for \
+                                           library `{}`", name);
+                        self.tcx.sess.warn(&msg);
+                    }
+
+                    found = true;
+                }
+            }
+            if !found {
+                // Add if not found
+                let new_name = new_name.as_ref().map(|s| &**s); // &Option<String> -> Option<&str>
+                let lib = NativeLibrary {
+                    name: Symbol::intern(new_name.unwrap_or(name)),
+                    kind: if let Some(k) = kind { k } else { cstore::NativeUnknown },
+                    cfg: None,
+                    foreign_items: Vec::new(),
+                };
+                self.register_native_lib(None, lib);
+            }
+        }
+    }
+}
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 80a126dc425..ec06e474980 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -209,7 +209,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         let f = ty.fn_sig(this.hir.tcx());
                         if f.abi() == Abi::RustIntrinsic ||
                            f.abi() == Abi::PlatformIntrinsic {
-                            Some(this.hir.tcx().item_name(def_id).as_str())
+                            Some(this.hir.tcx().item_name(def_id))
                         } else {
                             None
                         }
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index dc15163ecc1..0b91e08fc6d 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -299,7 +299,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let fail = self.cfg.start_new_block();
                 if let ty::TyRef(_, mt) = ty.sty {
                     assert!(ty.is_slice());
-                    let eq_def_id = self.hir.tcx().lang_items.eq_trait().unwrap();
+                    let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
                     let ty = mt.ty;
                     let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty]);
 
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index d3c886dab4e..ec545443bcd 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -47,7 +47,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             bug!("item {:?} passed to make_shim", instance),
         ty::InstanceDef::FnPtrShim(def_id, ty) => {
             let trait_ = tcx.trait_of_item(def_id).unwrap();
-            let adjustment = match tcx.lang_items.fn_trait_kind(trait_) {
+            let adjustment = match tcx.lang_items().fn_trait_kind(trait_) {
                 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
                 Some(ty::ClosureKind::FnMut) |
                 Some(ty::ClosureKind::Fn) => Adjustment::Deref,
@@ -82,7 +82,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             )
         }
         ty::InstanceDef::ClosureOnceShim { call_once } => {
-            let fn_mut = tcx.lang_items.fn_mut_trait().unwrap();
+            let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
             let call_mut = tcx.global_tcx()
                 .associated_items(fn_mut)
                 .find(|it| it.kind == ty::AssociatedKind::Method)
@@ -100,7 +100,7 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             build_drop_shim(tcx, def_id, ty)
         }
         ty::InstanceDef::CloneShim(def_id, ty) => {
-            let name = tcx.item_name(def_id).as_str();
+            let name = tcx.item_name(def_id);
             if name == "clone" {
                 build_clone_shim(tcx, def_id, ty)
             } else if name == "clone_from" {
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index d1e0465f555..0fb34c96b06 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -715,7 +715,7 @@ impl MirPass for StateTransform {
         let gen_ty = mir.local_decls.raw[1].ty;
 
         // Compute GeneratorState<yield_ty, return_ty>
-        let state_did = tcx.lang_items.gen_state().unwrap();
+        let state_did = tcx.lang_items().gen_state().unwrap();
         let state_adt_ref = tcx.adt_def(state_did);
         let state_substs = tcx.mk_substs([Kind::from(yield_ty),
             Kind::from(mir.return_ty)].iter());
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index b2572b2d0ab..6e49c444195 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -338,7 +338,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
             TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
                 debug!("Inlined {:?} into {:?}", callsite.callee, self.source);
 
-                let is_box_free = Some(callsite.callee) == self.tcx.lang_items.box_free_fn();
+                let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn();
 
                 let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len());
                 let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len());
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 415421757c5..ded97275468 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -252,7 +252,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
     }
 
     fn find_drop_implementation_method_span(&self) -> Option<Span> {
-        self.tcx.lang_items
+        self.tcx.lang_items()
             .drop_trait()
             .and_then(|drop_trait_id| {
                 let mut span = None;
@@ -795,7 +795,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                         self.deny_drop();
                     }
 
-                    if Some(def.did) == self.tcx.lang_items.unsafe_cell_type() {
+                    if Some(def.did) == self.tcx.lang_items().unsafe_cell_type() {
                         let ty = rvalue.ty(self.mir, self.tcx);
                         self.add_type(ty);
                         assert!(self.qualif.intersects(Qualif::MUTABLE_INTERIOR));
@@ -824,7 +824,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
                         assert!(!self.tcx.is_const_fn(def_id));
-                        match &self.tcx.item_name(def_id).as_str()[..] {
+                        match &self.tcx.item_name(def_id)[..] {
                             "size_of" | "min_align_of" => is_const_fn = true,
 
                             name if name.starts_with("simd_shuffle") => {
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index d4da14ea96e..7fbeb9610f4 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -575,7 +575,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     value: ConstVal::Function(def_id, _), ..
                 }, ..
             }) => {
-                Some(def_id) == self.tcx().lang_items.box_free_fn()
+                Some(def_id) == self.tcx().lang_items().box_free_fn()
             }
             _ => false,
         }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index f3b121f2eed..8ea47c29910 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -515,7 +515,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
     {
         debug!("destructor_call_block({:?}, {:?})", self, succ);
         let tcx = self.tcx();
-        let drop_trait = tcx.lang_items.drop_trait().unwrap();
+        let drop_trait = tcx.lang_items().drop_trait().unwrap();
         let drop_fn = tcx.associated_items(drop_trait).next().unwrap();
         let ty = self.lvalue_ty(self.lvalue);
         let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index b4f4f565191..6f2c448ceb6 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -401,7 +401,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
         hir::ExprStruct(..) => {
             if let ty::TyAdt(adt, ..) = v.tables.expr_ty(e).sty {
                 // unsafe_cell_type doesn't necessarily exist with no_core
-                if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() {
+                if Some(adt.did) == v.tcx.lang_items().unsafe_cell_type() {
                     v.promotable = false;
                 }
             }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 872a29e7bc0..139cb61bd9b 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -630,7 +630,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
                 };
                 ty::Visibility::from_hir(vis, node_id, self.tcx)
             }
-            None => self.tcx.sess.cstore.visibility(did),
+            None => self.tcx.visibility(did),
         }
     }
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 47fa5357abf..35e7522db01 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -42,6 +42,7 @@ use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::parse::token;
 use syntax::symbol::keywords;
+use syntax::symbol::Symbol;
 use syntax::visit::{self, Visitor};
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -253,7 +254,7 @@ impl<'a> Resolver<'a> {
                 self.crate_loader.process_item(item, &self.definitions);
 
                 // n.b. we don't need to look at the path option here, because cstore already did
-                let crate_id = self.session.cstore.extern_mod_stmt_cnum(item.id).unwrap();
+                let crate_id = self.session.cstore.extern_mod_stmt_cnum_untracked(item.id).unwrap();
                 let module =
                     self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
                 self.populate_module_if_necessary(module);
@@ -449,7 +450,7 @@ impl<'a> Resolver<'a> {
         let ident = child.ident;
         let def = child.def;
         let def_id = def.def_id();
-        let vis = self.session.cstore.visibility(def_id);
+        let vis = self.session.cstore.visibility_untracked(def_id);
         let span = child.span;
         let expansion = Mark::root(); // FIXME(jseyfried) intercrate hygiene
         match def {
@@ -485,12 +486,12 @@ impl<'a> Resolver<'a> {
                                              span);
                 self.define(parent, ident, TypeNS, (module, vis, DUMMY_SP, expansion));
 
-                for child in self.session.cstore.item_children(def_id, self.session) {
+                for child in self.session.cstore.item_children_untracked(def_id, self.session) {
                     let ns = if let Def::AssociatedTy(..) = child.def { TypeNS } else { ValueNS };
                     self.define(module, child.ident, ns,
                                 (child.def, ty::Visibility::Public, DUMMY_SP, expansion));
 
-                    if self.session.cstore.associated_item_cloned(child.def.def_id())
+                    if self.session.cstore.associated_item_cloned_untracked(child.def.def_id())
                            .method_has_self_argument {
                         self.has_self.insert(child.def.def_id());
                     }
@@ -501,7 +502,7 @@ impl<'a> Resolver<'a> {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
 
                 // Record field names for error reporting.
-                let field_names = self.session.cstore.struct_field_names(def_id);
+                let field_names = self.session.cstore.struct_field_names_untracked(def_id);
                 self.insert_field_names(def_id, field_names);
             }
             Def::Macro(..) => {
@@ -516,20 +517,20 @@ impl<'a> Resolver<'a> {
             return self.module_map[&def_id]
         }
 
-        let macros_only = self.session.cstore.dep_kind(def_id.krate).macros_only();
+        let macros_only = self.session.cstore.dep_kind_untracked(def_id.krate).macros_only();
         if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) {
             return module;
         }
 
         let (name, parent) = if def_id.index == CRATE_DEF_INDEX {
-            (self.session.cstore.crate_name(def_id.krate), None)
+            (self.session.cstore.crate_name_untracked(def_id.krate).as_str(), None)
         } else {
             let def_key = self.session.cstore.def_key(def_id);
             (def_key.disambiguated_data.data.get_opt_name().unwrap(),
              Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })))
         };
 
-        let kind = ModuleKind::Def(Def::Mod(def_id), name);
+        let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name));
         let module =
             self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP));
         self.extern_module_map.insert((def_id, macros_only), module);
@@ -558,7 +559,7 @@ impl<'a> Resolver<'a> {
             return ext.clone();
         }
 
-        let macro_def = match self.session.cstore.load_macro(def_id, &self.session) {
+        let macro_def = match self.session.cstore.load_macro_untracked(def_id, &self.session) {
             LoadedMacro::MacroDef(macro_def) => macro_def,
             LoadedMacro::ProcMacro(ext) => return ext,
         };
@@ -574,7 +575,8 @@ impl<'a> Resolver<'a> {
     /// is built, building it if it is not.
     pub fn populate_module_if_necessary(&mut self, module: Module<'a>) {
         if module.populated.get() { return }
-        for child in self.session.cstore.item_children(module.def_id().unwrap(), self.session) {
+        let def_id = module.def_id().unwrap();
+        for child in self.session.cstore.item_children_untracked(def_id, self.session) {
             self.build_reduced_graph_for_external_crate_def(module, child);
         }
         module.populated.set(true)
@@ -605,7 +607,8 @@ impl<'a> Resolver<'a> {
             span_err!(self.session, item.span, E0468,
                       "an `extern crate` loading macros must be at the crate root");
         } else if !self.use_extern_macros && !used &&
-                  self.session.cstore.dep_kind(module.def_id().unwrap().krate).macros_only() {
+                  self.session.cstore.dep_kind_untracked(module.def_id().unwrap().krate)
+                      .macros_only() {
             let msg = "proc macro crates and `#[no_link]` crates have no effect without \
                        `#[macro_use]`";
             self.session.span_warn(item.span, msg);
@@ -648,7 +651,7 @@ impl<'a> Resolver<'a> {
             }
         }
         for (name, span) in legacy_imports.reexports {
-            self.session.cstore.export_macros(module.def_id().unwrap().krate);
+            self.session.cstore.export_macros_untracked(module.def_id().unwrap().krate);
             let ident = Ident::with_empty_ctxt(name);
             let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span);
             if let Ok(binding) = result {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 9531c8baa0b..c083a0ff588 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -778,7 +778,7 @@ impl<'a> Resolver<'a> {
             _ => return,
         };
 
-        let crate_name = self.session.cstore.crate_name(krate);
+        let crate_name = self.session.cstore.crate_name_untracked(krate);
 
         self.session.struct_span_err(use_span, warn_msg)
             .help(&format!("instead, import the procedural macro like any other item: \
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index 71bcee56ecc..7524b7e8c6c 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -844,7 +844,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
                 let def = binding.def();
                 if def != Def::Err {
                     if !def.def_id().is_local() {
-                        self.session.cstore.export_macros(def.def_id().krate);
+                        self.session.cstore.export_macros_untracked(def.def_id().krate);
                     }
                     if let Def::Macro(..) = def {
                         if let Some(&span) = exported_macro_names.get(&ident.modern()) {
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 9ee38dd86c1..3de5fda0d45 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -109,7 +109,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
         let mut result = Vec::new();
 
-        for n in self.tcx.sess.cstore.crates() {
+        for &n in self.tcx.crates().iter() {
             let span = match *self.tcx.extern_crate(n.as_def_id()) {
                 Some(ref c) => c.span,
                 None => {
@@ -119,7 +119,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             };
             let lo_loc = self.span_utils.sess.codemap().lookup_char_pos(span.lo());
             result.push(ExternalCrateData {
-                name: self.tcx.sess.cstore.crate_name(n).to_string(),
+                name: self.tcx.crate_name(n).to_string(),
                 num: n.as_u32(),
                 file_name: SpanUtils::make_path_string(&lo_loc.file.name),
             });
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index ff95acf5d98..5d45aafe78d 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -20,10 +20,9 @@ use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, Pri
 use rustc::session::filesearch;
 use rustc::session::search_paths::PathKind;
 use rustc::session::Session;
-use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference,
-                            NativeLibraryKind};
+use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, NativeLibraryKind};
 use rustc::middle::dependency_format::Linkage;
-use CrateTranslation;
+use {CrateTranslation, CrateInfo};
 use rustc::util::common::time;
 use rustc::util::fs::fix_windows_verbatim_for_gcc;
 use rustc::dep_graph::{DepKind, DepNode};
@@ -223,8 +222,9 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen
 }
 
 pub fn each_linked_rlib(sess: &Session,
+                        info: &CrateInfo,
                         f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
-    let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter();
+    let crates = info.used_crates_static.iter();
     let fmts = sess.dependency_formats.borrow();
     let fmts = fmts.get(&config::CrateTypeExecutable)
                    .or_else(|| fmts.get(&config::CrateTypeStaticlib))
@@ -234,16 +234,16 @@ pub fn each_linked_rlib(sess: &Session,
         Some(f) => f,
         None => return Err(format!("could not find formats for rlibs"))
     };
-    for (cnum, path) in crates {
+    for &(cnum, ref path) in crates {
         match fmts.get(cnum.as_usize() - 1) {
             Some(&Linkage::NotLinked) |
             Some(&Linkage::IncludedFromDylib) => continue,
             Some(_) => {}
             None => return Err(format!("could not find formats for rlibs"))
         }
-        let name = sess.cstore.crate_name(cnum).clone();
-        let path = match path {
-            LibSource::Some(p) => p,
+        let name = &info.crate_name[&cnum];
+        let path = match *path {
+            LibSource::Some(ref p) => p,
             LibSource::MetadataOnly => {
                 return Err(format!("could not find rlib for: `{}`, found rmeta (metadata) file",
                                    name))
@@ -267,12 +267,12 @@ pub fn each_linked_rlib(sess: &Session,
 /// It's unusual for a crate to not participate in LTO. Typically only
 /// compiler-specific and unstable crates have a reason to not participate in
 /// LTO.
-pub fn ignored_for_lto(sess: &Session, cnum: CrateNum) -> bool {
+pub fn ignored_for_lto(info: &CrateInfo, cnum: CrateNum) -> bool {
     // `#![no_builtins]` crates don't participate in LTO because the state
     // of builtins gets messed up (our crate isn't tagged with no builtins).
     // Similarly `#![compiler_builtins]` doesn't participate because we want
     // those builtins!
-    sess.cstore.is_no_builtins(cnum) || sess.cstore.is_compiler_builtins(cnum)
+    info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum)
 }
 
 fn out_filename(sess: &Session,
@@ -438,7 +438,7 @@ fn link_rlib<'a>(sess: &'a Session,
     // feature then we'll need to figure out how to record what objects were
     // loaded from the libraries found here and then encode that into the
     // metadata of the rlib we're generating somehow.
-    for lib in sess.cstore.used_libraries() {
+    for lib in trans.crate_info.used_libraries.iter() {
         match lib.kind {
             NativeLibraryKind::NativeStatic => {}
             NativeLibraryKind::NativeStaticNobundle |
@@ -618,9 +618,9 @@ fn link_staticlib(sess: &Session,
                            tempdir);
     let mut all_native_libs = vec![];
 
-    let res = each_linked_rlib(sess, &mut |cnum, path| {
-        let name = sess.cstore.crate_name(cnum);
-        let native_libs = sess.cstore.native_libraries(cnum);
+    let res = each_linked_rlib(sess, &trans.crate_info, &mut |cnum, path| {
+        let name = &trans.crate_info.crate_name[&cnum];
+        let native_libs = &trans.crate_info.native_libraries[&cnum];
 
         // Here when we include the rlib into our staticlib we need to make a
         // decision whether to include the extra object files along the way.
@@ -641,10 +641,10 @@ fn link_staticlib(sess: &Session,
         });
         ab.add_rlib(path,
                     &name.as_str(),
-                    sess.lto() && !ignored_for_lto(sess, cnum),
+                    sess.lto() && !ignored_for_lto(&trans.crate_info, cnum),
                     skip_object_files).unwrap();
 
-        all_native_libs.extend(sess.cstore.native_libraries(cnum));
+        all_native_libs.extend(trans.crate_info.native_libraries[&cnum].iter().cloned());
     });
     if let Err(e) = res {
         sess.fatal(&e);
@@ -1031,7 +1031,7 @@ fn link_args(cmd: &mut Linker,
         cmd.gc_sections(keep_metadata);
     }
 
-    let used_link_args = sess.cstore.used_link_args();
+    let used_link_args = &trans.crate_info.link_args;
 
     if crate_type == config::CrateTypeExecutable &&
        t.options.position_independent_executables {
@@ -1101,9 +1101,9 @@ fn link_args(cmd: &mut Linker,
     // link line. And finally upstream native libraries can't depend on anything
     // in this DAG so far because they're only dylibs and dylibs can only depend
     // on other dylibs (e.g. other native deps).
-    add_local_native_libraries(cmd, sess);
-    add_upstream_rust_crates(cmd, sess, crate_type, tmpdir);
-    add_upstream_native_libraries(cmd, sess, crate_type);
+    add_local_native_libraries(cmd, sess, trans);
+    add_upstream_rust_crates(cmd, sess, trans, crate_type, tmpdir);
+    add_upstream_native_libraries(cmd, sess, trans, crate_type);
 
     // Tell the linker what we're doing.
     if crate_type != config::CrateTypeExecutable {
@@ -1128,7 +1128,7 @@ fn link_args(cmd: &mut Linker,
             path
         };
         let mut rpath_config = RPathConfig {
-            used_crates: sess.cstore.used_crates(LinkagePreference::RequireDynamic),
+            used_crates: &trans.crate_info.used_crates_dynamic,
             out_filename: out_filename.to_path_buf(),
             has_rpath: sess.target.target.options.has_rpath,
             is_like_osx: sess.target.target.options.is_like_osx,
@@ -1158,7 +1158,9 @@ fn link_args(cmd: &mut Linker,
 // Also note that the native libraries linked here are only the ones located
 // in the current crate. Upstream crates with native library dependencies
 // may have their native library pulled in above.
-fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
+fn add_local_native_libraries(cmd: &mut Linker,
+                              sess: &Session,
+                              trans: &CrateTranslation) {
     sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| {
         match k {
             PathKind::Framework => { cmd.framework_path(path); }
@@ -1166,7 +1168,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
         }
     });
 
-    let relevant_libs = sess.cstore.used_libraries().into_iter().filter(|l| {
+    let relevant_libs = trans.crate_info.used_libraries.iter().filter(|l| {
         relevant_lib(sess, l)
     });
 
@@ -1189,6 +1191,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
 // the intermediate rlib version)
 fn add_upstream_rust_crates(cmd: &mut Linker,
                             sess: &Session,
+                            trans: &CrateTranslation,
                             crate_type: config::CrateType,
                             tmpdir: &Path) {
     // All of the heavy lifting has previously been accomplished by the
@@ -1204,35 +1207,35 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
 
     // Invoke get_used_crates to ensure that we get a topological sorting of
     // crates.
-    let deps = sess.cstore.used_crates(LinkagePreference::RequireDynamic);
+    let deps = &trans.crate_info.used_crates_dynamic;
 
     let mut compiler_builtins = None;
 
-    for &(cnum, _) in &deps {
+    for &(cnum, _) in deps.iter() {
         // We may not pass all crates through to the linker. Some crates may
         // appear statically in an existing dylib, meaning we'll pick up all the
         // symbols from the dylib.
-        let src = sess.cstore.used_crate_source(cnum);
+        let src = &trans.crate_info.used_crate_source[&cnum];
         match data[cnum.as_usize() - 1] {
-            _ if sess.cstore.is_profiler_runtime(cnum) => {
-                add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
+            _ if trans.crate_info.profiler_runtime == Some(cnum) => {
+                add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
             }
-            _ if sess.cstore.is_sanitizer_runtime(cnum) => {
-                link_sanitizer_runtime(cmd, sess, tmpdir, cnum);
+            _ if trans.crate_info.sanitizer_runtime == Some(cnum) => {
+                link_sanitizer_runtime(cmd, sess, trans, tmpdir, cnum);
             }
             // compiler-builtins are always placed last to ensure that they're
             // linked correctly.
-            _ if sess.cstore.is_compiler_builtins(cnum) => {
+            _ if trans.crate_info.compiler_builtins == Some(cnum) => {
                 assert!(compiler_builtins.is_none());
                 compiler_builtins = Some(cnum);
             }
             Linkage::NotLinked |
             Linkage::IncludedFromDylib => {}
             Linkage::Static => {
-                add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
+                add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
             }
             Linkage::Dynamic => {
-                add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0)
+                add_dynamic_crate(cmd, sess, &src.dylib.as_ref().unwrap().0)
             }
         }
     }
@@ -1243,7 +1246,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
     // was already "included" in a dylib (e.g. `libstd` when `-C prefer-dynamic`
     // is used)
     if let Some(cnum) = compiler_builtins {
-        add_static_crate(cmd, sess, tmpdir, crate_type, cnum);
+        add_static_crate(cmd, sess, trans, tmpdir, crate_type, cnum);
     }
 
     // Converts a library file-stem into a cc -l argument
@@ -1261,10 +1264,11 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
     // linking it.
     fn link_sanitizer_runtime(cmd: &mut Linker,
                               sess: &Session,
+                              trans: &CrateTranslation,
                               tmpdir: &Path,
                               cnum: CrateNum) {
-        let src = sess.cstore.used_crate_source(cnum);
-        let cratepath = &src.rlib.unwrap().0;
+        let src = &trans.crate_info.used_crate_source[&cnum];
+        let cratepath = &src.rlib.as_ref().unwrap().0;
 
         if sess.target.target.options.is_like_osx {
             // On Apple platforms, the sanitizer is always built as a dylib, and
@@ -1329,21 +1333,22 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
     // we're at the end of the dependency chain.
     fn add_static_crate(cmd: &mut Linker,
                         sess: &Session,
+                        trans: &CrateTranslation,
                         tmpdir: &Path,
                         crate_type: config::CrateType,
                         cnum: CrateNum) {
-        let src = sess.cstore.used_crate_source(cnum);
-        let cratepath = &src.rlib.unwrap().0;
+        let src = &trans.crate_info.used_crate_source[&cnum];
+        let cratepath = &src.rlib.as_ref().unwrap().0;
 
         // See the comment above in `link_staticlib` and `link_rlib` for why if
         // there's a static library that's not relevant we skip all object
         // files.
-        let native_libs = sess.cstore.native_libraries(cnum);
+        let native_libs = &trans.crate_info.native_libraries[&cnum];
         let skip_native = native_libs.iter().any(|lib| {
             lib.kind == NativeLibraryKind::NativeStatic && !relevant_lib(sess, lib)
         });
 
-        if (!sess.lto() || ignored_for_lto(sess, cnum)) &&
+        if (!sess.lto() || ignored_for_lto(&trans.crate_info, cnum)) &&
            crate_type != config::CrateTypeDylib &&
            !skip_native {
             cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
@@ -1385,7 +1390,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
                 // LTO module. Note that `#![no_builtins]` is excluded from LTO,
                 // though, so we let that object file slide.
                 let skip_because_lto = sess.lto() && is_rust_object &&
-                                        !sess.cstore.is_no_builtins(cnum);
+                                        !trans.crate_info.is_no_builtins.contains(&cnum);
 
                 if skip_because_cfg_say_so || skip_because_lto {
                     archive.remove_file(&f);
@@ -1407,7 +1412,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
             // compiler-builtins crate (e.g. compiler-rt) because it'll get
             // repeatedly linked anyway.
             if crate_type == config::CrateTypeDylib &&
-               !sess.cstore.is_compiler_builtins(cnum) {
+                trans.crate_info.compiler_builtins != Some(cnum) {
                 cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
             } else {
                 cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
@@ -1451,7 +1456,10 @@ fn add_upstream_rust_crates(cmd: &mut Linker,
 // generic function calls a native function, then the generic function must
 // be instantiated in the target crate, meaning that the native symbol must
 // also be resolved in the target crate.
-fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: config::CrateType) {
+fn add_upstream_native_libraries(cmd: &mut Linker,
+                                 sess: &Session,
+                                 trans: &CrateTranslation,
+                                 crate_type: config::CrateType) {
     // 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
@@ -1464,9 +1472,9 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session, crate_type: c
     let formats = sess.dependency_formats.borrow();
     let data = formats.get(&crate_type).unwrap();
 
-    let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic);
-    for (cnum, _) in crates {
-        for lib in sess.cstore.native_libraries(cnum) {
+    let crates = &trans.crate_info.used_crates_static;
+    for &(cnum, _) in crates {
+        for lib in trans.crate_info.native_libraries[&cnum].iter() {
             if !relevant_lib(sess, &lib) {
                 continue
             }
diff --git a/src/librustc_trans/back/rpath.rs b/src/librustc_trans/back/rpath.rs
index 104e7bc6a52..8e5e7d37648 100644
--- a/src/librustc_trans/back/rpath.rs
+++ b/src/librustc_trans/back/rpath.rs
@@ -17,7 +17,7 @@ use rustc::hir::def_id::CrateNum;
 use rustc::middle::cstore::LibSource;
 
 pub struct RPathConfig<'a> {
-    pub used_crates: Vec<(CrateNum, LibSource)>,
+    pub used_crates: &'a [(CrateNum, LibSource)],
     pub out_filename: PathBuf,
     pub is_like_osx: bool,
     pub has_rpath: bool,
@@ -36,7 +36,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
     debug!("preparing the RPATH!");
 
     let libs = config.used_crates.clone();
-    let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
+    let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::<Vec<_>>();
     let rpaths = get_rpaths(config, &libs);
     flags.extend_from_slice(&rpaths_to_flags(&rpaths));
 
diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs
index 971483e91b6..b546059b4c5 100644
--- a/src/librustc_trans/back/symbol_export.rs
+++ b/src/librustc_trans/back/symbol_export.rs
@@ -110,13 +110,13 @@ impl ExportedSymbols {
         let mut exports = FxHashMap();
         exports.insert(LOCAL_CRATE, local_crate);
 
-        for cnum in tcx.sess.cstore.crates() {
+        for &cnum in tcx.crates().iter() {
             debug_assert!(cnum != LOCAL_CRATE);
 
             // If this crate is a plugin and/or a custom derive crate, then
             // we're not even going to link those in so we skip those crates.
-            if tcx.sess.cstore.plugin_registrar_fn(cnum).is_some() ||
-               tcx.sess.cstore.derive_registrar_fn(cnum).is_some() {
+            if tcx.plugin_registrar_fn(cnum).is_some() ||
+               tcx.derive_registrar_fn(cnum).is_some() {
                 continue;
             }
 
@@ -128,12 +128,9 @@ impl ExportedSymbols {
             // Down below we'll hardwire all of the symbols to the `Rust` export
             // level instead.
             let special_runtime_crate =
-                tcx.is_panic_runtime(cnum.as_def_id()) ||
-                tcx.sess.cstore.is_compiler_builtins(cnum);
+                tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
 
             let crate_exports = tcx
-                .sess
-                .cstore
                 .exported_symbols(cnum)
                 .iter()
                 .map(|&def_id| {
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs
index 10b66fb1991..abeb2568cbe 100644
--- a/src/librustc_trans/back/symbol_names.rs
+++ b/src/librustc_trans/back/symbol_names.rs
@@ -242,7 +242,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
             return name.to_string();
         }
         // Don't mangle foreign items.
-        return tcx.item_name(def_id).as_str().to_string();
+        return tcx.item_name(def_id).to_string();
     }
 
     if let Some(name) = attr::find_export_name_attr(tcx.sess.diagnostic(), &attrs) {
@@ -252,7 +252,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
 
     if attr::contains_name(&attrs, "no_mangle") {
         // Don't mangle
-        return tcx.item_name(def_id).as_str().to_string();
+        return tcx.item_name(def_id).to_string();
     }
 
     // We want to compute the "type" of this item. Unfortunately, some
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 3f9b28d3d61..72e1fc34789 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -22,6 +22,7 @@ use llvm;
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
 use llvm::SMDiagnosticRef;
 use {CrateTranslation, ModuleSource, ModuleTranslation, CompiledModule, ModuleKind};
+use CrateInfo;
 use rustc::hir::def_id::CrateNum;
 use rustc::util::common::{time, time_depth, set_time_depth, path2cstr, print_time_passes_entry};
 use rustc::util::fs::{link_or_copy, rename_or_copy_remove};
@@ -675,6 +676,7 @@ pub fn start_async_translation(sess: &Session,
                                no_builtins: bool,
                                windows_subsystem: Option<String>,
                                linker_info: LinkerInfo,
+                               crate_info: CrateInfo,
                                no_integrated_as: bool)
                                -> OngoingCrateTranslation {
     let output_types_override = if no_integrated_as {
@@ -774,6 +776,7 @@ pub fn start_async_translation(sess: &Session,
     let (coordinator_send, coordinator_receive) = channel();
 
     let coordinator_thread = start_executing_work(sess,
+                                                  &crate_info,
                                                   shared_emitter,
                                                   trans_worker_send,
                                                   coordinator_send.clone(),
@@ -788,6 +791,7 @@ pub fn start_async_translation(sess: &Session,
         windows_subsystem,
         linker_info,
         no_integrated_as,
+        crate_info,
 
         regular_module_config: modules_config,
         metadata_module_config: metadata_config,
@@ -1101,6 +1105,7 @@ enum MainThreadWorkerState {
 }
 
 fn start_executing_work(sess: &Session,
+                        crate_info: &CrateInfo,
                         shared_emitter: SharedEmitter,
                         trans_worker_send: Sender<Message>,
                         coordinator_send: Sender<Message>,
@@ -1125,8 +1130,8 @@ fn start_executing_work(sess: &Session,
     }).expect("failed to spawn helper thread");
 
     let mut each_linked_rlib_for_lto = Vec::new();
-    drop(link::each_linked_rlib(sess, &mut |cnum, path| {
-        if link::ignored_for_lto(sess, cnum) {
+    drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
+        if link::ignored_for_lto(crate_info, cnum) {
             return
         }
         each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
@@ -1802,6 +1807,7 @@ pub struct OngoingCrateTranslation {
     windows_subsystem: Option<String>,
     linker_info: LinkerInfo,
     no_integrated_as: bool,
+    crate_info: CrateInfo,
 
     output_filenames: OutputFilenames,
     regular_module_config: ModuleConfig,
@@ -1850,6 +1856,7 @@ impl OngoingCrateTranslation {
             metadata: self.metadata,
             windows_subsystem: self.windows_subsystem,
             linker_info: self.linker_info,
+            crate_info: self.crate_info,
 
             modules: compiled_modules.modules,
             allocator_module: compiled_modules.allocator_module,
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index a6c6b0efcfa..6cfde9c7bbc 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -41,7 +41,7 @@ use rustc::middle::lang_items::StartFnLangItem;
 use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::dep_graph::AssertDepGraphSafe;
-use rustc::middle::cstore::LinkMeta;
+use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::hir::map as hir_map;
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
@@ -75,6 +75,7 @@ use type_::Type;
 use type_of;
 use value::Value;
 use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet};
+use CrateInfo;
 
 use libc::c_uint;
 use std::ffi::{CStr, CString};
@@ -904,7 +905,7 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: &NodeSet) -> NodeSet {
         match tcx.hir.get(id) {
             hir_map::NodeForeignItem(..) => {
                 let def_id = tcx.hir.local_def_id(id);
-                tcx.sess.cstore.is_statically_included_foreign_item(def_id)
+                tcx.is_statically_included_foreign_item(def_id)
             }
 
             // Only consider nodes that actually have exported symbols.
@@ -970,6 +971,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     } else {
         None
     };
+    let crate_info = CrateInfo::new(tcx);
 
     // Skip crate items and just output metadata in -Z no-trans mode.
     if tcx.sess.opts.debugging_opts.no_trans ||
@@ -987,6 +989,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             no_builtins,
             None,
             linker_info,
+            crate_info,
             false);
 
         ongoing_translation.submit_pre_translated_module_to_llvm(tcx.sess, metadata_module, true);
@@ -1039,6 +1042,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         no_builtins,
         windows_subsystem,
         linker_info,
+        crate_info,
         no_integrated_as);
 
     // Translate an allocator shim, if any
@@ -1502,3 +1506,46 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
 
     (translation_items, codegen_units)
 }
+
+impl CrateInfo {
+    pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CrateInfo {
+        let mut info = CrateInfo {
+            panic_runtime: None,
+            compiler_builtins: None,
+            profiler_runtime: None,
+            sanitizer_runtime: None,
+            is_no_builtins: FxHashSet(),
+            native_libraries: FxHashMap(),
+            used_libraries: tcx.native_libraries(LOCAL_CRATE),
+            link_args: tcx.link_args(LOCAL_CRATE),
+            crate_name: FxHashMap(),
+            used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
+            used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
+            used_crate_source: FxHashMap(),
+        };
+
+        for &cnum in tcx.crates().iter() {
+            info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
+            info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
+            info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
+            if tcx.is_panic_runtime(cnum) {
+                info.panic_runtime = Some(cnum);
+            }
+            if tcx.is_compiler_builtins(cnum) {
+                info.compiler_builtins = Some(cnum);
+            }
+            if tcx.is_profiler_runtime(cnum) {
+                info.profiler_runtime = Some(cnum);
+            }
+            if tcx.is_sanitizer_runtime(cnum) {
+                info.sanitizer_runtime = Some(cnum);
+            }
+            if tcx.is_no_builtins(cnum) {
+                info.is_no_builtins.insert(cnum);
+            }
+        }
+
+
+        return info
+    }
+}
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 76f94565bae..246eb49ffa6 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -124,13 +124,17 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             }
         }
 
-        if ccx.use_dll_storage_attrs() &&
-            ccx.sess().cstore.is_dllimport_foreign_item(instance_def_id)
-        {
-            unsafe {
-                llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
+        // FIXME(#42293) we should actually track this, but fails too many tests
+        // today.
+        tcx.dep_graph.with_ignore(|| {
+            if ccx.use_dll_storage_attrs() &&
+                tcx.is_dllimport_foreign_item(instance_def_id)
+            {
+                unsafe {
+                    llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
+                }
             }
-        }
+        });
         llfn
     };
 
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 8b864a7fdcf..b56fa34e348 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -432,7 +432,7 @@ fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
     debug!(" => recursion depth={}", recursion_depth);
 
-    let recursion_depth = if Some(def_id) == tcx.lang_items.drop_in_place_fn() {
+    let recursion_depth = if Some(def_id) == tcx.lang_items().drop_in_place_fn() {
         // HACK: drop_in_place creates tight monomorphization loops. Give
         // it more margin.
         recursion_depth / 4
@@ -550,7 +550,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => {
                 let tcx = self.scx.tcx();
                 let exchange_malloc_fn_def_id = tcx
-                    .lang_items
+                    .lang_items()
                     .require(ExchangeMallocFnLangItem)
                     .unwrap_or_else(|e| self.scx.sess().fatal(&e));
                 let instance = Instance::mono(tcx, exchange_malloc_fn_def_id);
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 261792735dc..d947cd8e719 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -423,7 +423,7 @@ pub fn langcall(tcx: TyCtxt,
                 msg: &str,
                 li: LangItem)
                 -> DefId {
-    match tcx.lang_items.require(li) {
+    match tcx.lang_items().require(li) {
         Ok(id) => id,
         Err(s) => {
             let msg = format!("{} {}", msg, s);
@@ -530,7 +530,7 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
 
             sig.map_bound(|sig| {
-                let state_did = tcx.lang_items.gen_state().unwrap();
+                let state_did = tcx.lang_items().gen_state().unwrap();
                 let state_adt_ref = tcx.adt_def(state_did);
                 let state_substs = tcx.mk_substs([Kind::from(sig.yield_ty),
                     Kind::from(sig.return_ty)].iter());
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 310cd6fe955..a30a15f75b3 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -211,12 +211,17 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
         g
     };
 
-    if ccx.use_dll_storage_attrs() && ccx.sess().cstore.is_dllimport_foreign_item(def_id) {
-        // For foreign (native) libs we know the exact storage type to use.
-        unsafe {
-            llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+
+    // FIXME(#42293) we should actually track this, but fails too many tests
+    // today.
+    ccx.tcx().dep_graph.with_ignore(|| {
+        if ccx.use_dll_storage_attrs() && ccx.tcx().is_dllimport_foreign_item(def_id) {
+            // For foreign (native) libs we know the exact storage type to use.
+            unsafe {
+                llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
+            }
         }
-    }
+    });
     ccx.instances().borrow_mut().insert(instance, g);
     ccx.statics().borrow_mut().insert(g, def_id);
     g
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index f2b07cf6a58..a5830eb17ed 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -616,7 +616,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
             return llpersonality
         }
         let tcx = self.tcx();
-        let llfn = match tcx.lang_items.eh_personality() {
+        let llfn = match tcx.lang_items().eh_personality() {
             Some(def_id) if !base::wants_msvc_seh(self.sess()) => {
                 callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]))
             }
@@ -645,7 +645,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
 
         let tcx = self.tcx();
         assert!(self.sess().target.target.options.custom_unwind_resume);
-        if let Some(def_id) = tcx.lang_items.eh_unwind_resume() {
+        if let Some(def_id) = tcx.lang_items().eh_unwind_resume() {
             let llfn = callee::resolve_and_get_fn(self, def_id, tcx.intern_substs(&[]));
             unwresume.set(Some(llfn));
             return llfn;
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index bcc6aca6149..8bd835ac5d1 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -1612,7 +1612,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     fn get_enum_discriminant_name(cx: &CrateContext,
                                   def_id: DefId)
                                   -> InternedString {
-        cx.tcx().item_name(def_id).as_str()
+        cx.tcx().item_name(def_id)
     }
 }
 
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 5dd1c15fd2d..6eda8657519 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -189,7 +189,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 output.push_str(&path_element.data.as_interned_str());
             }
         } else {
-            output.push_str(&cx.tcx().item_name(def_id).as_str());
+            output.push_str(&cx.tcx().item_name(def_id));
         }
     }
 
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 9a3c8a5079a..8f968a8a6c6 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -104,7 +104,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
     let sig = tcx.erase_late_bound_regions_and_normalize(&sig);
     let arg_tys = sig.inputs();
     let ret_ty = sig.output();
-    let name = &*tcx.item_name(def_id).as_str();
+    let name = &*tcx.item_name(def_id);
 
     let llret_ty = type_of::type_of(ccx, ret_ty);
 
@@ -822,7 +822,7 @@ fn trans_msvc_try<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
         catchswitch.add_handler(cs, catchpad.llbb());
 
         let tcx = ccx.tcx();
-        let tydesc = match tcx.lang_items.msvc_try_filter() {
+        let tydesc = match tcx.lang_items().msvc_try_filter() {
             Some(did) => ::consts::get_static(ccx, did),
             None => bug!("msvc_try_filter not defined"),
         };
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 1bb9ce432df..63fd37c2b98 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -66,6 +66,12 @@ pub use back::symbol_names::provide;
 pub use metadata::LlvmMetadataLoader;
 pub use llvm_util::{init, target_features, print_version, print_passes, print, enable_llvm_debug};
 
+use std::rc::Rc;
+
+use rustc::hir::def_id::CrateNum;
+use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
+
 pub mod back {
     mod archive;
     mod command;
@@ -217,7 +223,24 @@ pub struct CrateTranslation {
     pub link: rustc::middle::cstore::LinkMeta,
     pub metadata: rustc::middle::cstore::EncodedMetadata,
     windows_subsystem: Option<String>,
-    linker_info: back::linker::LinkerInfo
+    linker_info: back::linker::LinkerInfo,
+    crate_info: CrateInfo,
+}
+
+// Misc info we load from metadata to persist beyond the tcx
+pub struct CrateInfo {
+    panic_runtime: Option<CrateNum>,
+    compiler_builtins: Option<CrateNum>,
+    profiler_runtime: Option<CrateNum>,
+    sanitizer_runtime: Option<CrateNum>,
+    is_no_builtins: FxHashSet<CrateNum>,
+    native_libraries: FxHashMap<CrateNum, Rc<Vec<NativeLibrary>>>,
+    crate_name: FxHashMap<CrateNum, String>,
+    used_libraries: Rc<Vec<NativeLibrary>>,
+    link_args: Rc<Vec<String>>,
+    used_crate_source: FxHashMap<CrateNum, Rc<CrateSource>>,
+    used_crates_static: Vec<(CrateNum, LibSource)>,
+    used_crates_dynamic: Vec<(CrateNum, LibSource)>,
 }
 
 __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index 95b76d32bf8..949b9fe71ca 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -114,7 +114,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
                     }, ..
                 }),
                 ref args, ..
-            } if Some(def_id) == self.cx.ccx.tcx().lang_items.box_free_fn() => {
+            } if Some(def_id) == self.cx.ccx.tcx().lang_items().box_free_fn() => {
                 // box_free(x) shares with `drop x` the property that it
                 // is not guaranteed to be statically dominated by the
                 // definition of x, so x must always be in an alloca.
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index bba3b1fa5ba..0f42a244a1f 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -445,7 +445,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 // Handle intrinsics old trans wants Expr's for, ourselves.
                 let intrinsic = match def {
                     Some(ty::InstanceDef::Intrinsic(def_id))
-                        => Some(bcx.tcx().item_name(def_id).as_str()),
+                        => Some(bcx.tcx().item_name(def_id)),
                     _ => None
                 };
                 let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 9987c9c3310..1109f34a148 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -365,7 +365,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                     }
                     if let Some((ref dest, target)) = *destination {
                         let result = if fn_ty.fn_sig(tcx).abi() == Abi::RustIntrinsic {
-                            match &tcx.item_name(def_id).as_str()[..] {
+                            match &tcx.item_name(def_id)[..] {
                                 "size_of" => {
                                     let llval = C_uint(self.ccx,
                                         self.ccx.size_of(substs.type_at(0)));
@@ -610,7 +610,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                         match operand.ty.sty {
                             ty::TyClosure(def_id, substs) => {
                                 // Get the def_id for FnOnce::call_once
-                                let fn_once = tcx.lang_items.fn_once_trait().unwrap();
+                                let fn_once = tcx.lang_items().fn_once_trait().unwrap();
                                 let call_once = tcx
                                     .global_tcx().associated_items(fn_once)
                                     .find(|it| it.kind == ty::AssociatedKind::Method)
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 096f43e44ab..34dec57543a 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -482,7 +482,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                 let box_ty = bcx.tcx().mk_box(content_ty);
 
                 // Allocate space:
-                let def_id = match bcx.tcx().lang_items.require(ExchangeMallocFnLangItem) {
+                let def_id = match bcx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
                     Ok(id) => id,
                     Err(s) => {
                         bcx.sess().fatal(&format!("allocation of `{}` {}", box_ty, s));
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 4989ca8cc93..9a7f1524d20 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -31,7 +31,7 @@ fn fn_once_adapter_instance<'a, 'tcx>(
     debug!("fn_once_adapter_shim({:?}, {:?})",
            closure_did,
            substs);
-    let fn_once = tcx.lang_items.fn_once_trait().unwrap();
+    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
     let call_once = tcx.associated_items(fn_once)
         .find(|it| it.kind == ty::AssociatedKind::Method)
         .unwrap().def_id;
@@ -132,7 +132,7 @@ fn resolve_associated_item<'a, 'tcx>(
             }
         }
         traits::VtableClosure(closure_data) => {
-            let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
+            let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
             resolve_closure(scx, closure_data.closure_def_id, closure_data.substs,
                             trait_closure_kind)
         }
@@ -149,7 +149,7 @@ fn resolve_associated_item<'a, 'tcx>(
                 substs: rcvr_substs
             }
         }
-        traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items.clone_trait() => {
+        traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items().clone_trait() => {
             Instance {
                 def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()),
                 substs: rcvr_substs
@@ -187,7 +187,7 @@ pub fn resolve<'a, 'tcx>(
                 ty::InstanceDef::Intrinsic(def_id)
             }
             _ => {
-                if Some(def_id) == scx.tcx().lang_items.drop_in_place_fn() {
+                if Some(def_id) == scx.tcx().lang_items().drop_in_place_fn() {
                     let ty = substs.type_at(0);
                     if glue::needs_drop_glue(scx, ty) {
                         debug!(" => nontrivial drop glue");
@@ -224,7 +224,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx
                                              target_ty: Ty<'tcx>)
                                              -> CustomCoerceUnsized {
     let trait_ref = ty::Binder(ty::TraitRef {
-        def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
+        def_id: scx.tcx().lang_items().coerce_unsized_trait().unwrap(),
         substs: scx.tcx().mk_substs_trait(source_ty, &[target_ty])
     });
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index ee1e6bd950f..2583d18652d 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -96,22 +96,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
         -> ty::Region<'tcx>
     {
         let tcx = self.tcx();
-        let r = match tcx.named_region_map.defs.get(&lifetime.id) {
-            Some(&rl::Region::Static) => {
+        let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
+        let r = match tcx.named_region(hir_id) {
+            Some(rl::Region::Static) => {
                 tcx.types.re_static
             }
 
-            Some(&rl::Region::LateBound(debruijn, id)) => {
+            Some(rl::Region::LateBound(debruijn, id)) => {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReLateBound(debruijn,
                     ty::BrNamed(tcx.hir.local_def_id(id), name)))
             }
 
-            Some(&rl::Region::LateBoundAnon(debruijn, index)) => {
+            Some(rl::Region::LateBoundAnon(debruijn, index)) => {
                 tcx.mk_region(ty::ReLateBound(debruijn, ty::BrAnon(index)))
             }
 
-            Some(&rl::Region::EarlyBound(index, id)) => {
+            Some(rl::Region::EarlyBound(index, id)) => {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
                     def_id: tcx.hir.local_def_id(id),
@@ -120,7 +121,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
                 }))
             }
 
-            Some(&rl::Region::Free(scope, id)) => {
+            Some(rl::Region::Free(scope, id)) => {
                 let name = tcx.hir.name(id);
                 tcx.mk_region(ty::ReFree(ty::FreeRegion {
                     scope,
@@ -627,7 +628,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             self.ast_region_to_region(lifetime, None)
         } else {
             self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| {
-                if tcx.named_region_map.defs.contains_key(&lifetime.id) {
+                let hir_id = tcx.hir.node_to_hir_id(lifetime.id);
+                if tcx.named_region(hir_id).is_some() {
                     self.ast_region_to_region(lifetime, None)
                 } else {
                     self.re_infer(span, None).unwrap_or_else(|| {
@@ -1286,8 +1288,8 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             Def::Trait(trait_did) => {
                 // Checks whether `trait_did` refers to one of the builtin
                 // traits, like `Send`, and adds it to `auto_traits` if so.
-                if Some(trait_did) == tcx.lang_items.send_trait() ||
-                    Some(trait_did) == tcx.lang_items.sync_trait() {
+                if Some(trait_did) == tcx.lang_items().send_trait() ||
+                    Some(trait_did) == tcx.lang_items().sync_trait() {
                     let segments = &bound.trait_ref.path.segments;
                     let parameters = &segments[segments.len() - 1].parameters;
                     if !parameters.types.is_empty() {
@@ -1400,7 +1402,7 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
 
         // If it could be sized, and is, add the sized predicate
         if self.implicitly_sized {
-            if let Some(sized) = tcx.lang_items.sized_trait() {
+            if let Some(sized) = tcx.lang_items().sized_trait() {
                 let trait_ref = ty::TraitRef {
                     def_id: sized,
                     substs: tcx.mk_substs_trait(param_ty, &[])
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index e0e946a9c63..a25deb7685a 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -108,7 +108,7 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> {
 
         // <cur_ty as Deref>
         let trait_ref = TraitRef {
-            def_id: match tcx.lang_items.deref_trait() {
+            def_id: match tcx.lang_items().deref_trait() {
                 Some(f) => f,
                 None => return None,
             },
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 5b9d4af08e0..866949220b5 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -28,7 +28,7 @@ use rustc::hir;
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called)
 pub fn check_legal_trait_for_method_call(tcx: TyCtxt, span: Span, trait_id: DefId) {
-    if tcx.lang_items.drop_trait() == Some(trait_id) {
+    if tcx.lang_items().drop_trait() == Some(trait_id) {
         struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
             .span_label(span, "explicit destructor calls not allowed")
             .emit();
@@ -157,9 +157,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                              MethodCallee<'tcx>)> {
         // Try the options that are least restrictive on the caller first.
         for &(opt_trait_def_id, method_name, borrow) in
-            &[(self.tcx.lang_items.fn_trait(), Symbol::intern("call"), true),
-              (self.tcx.lang_items.fn_mut_trait(), Symbol::intern("call_mut"), true),
-              (self.tcx.lang_items.fn_once_trait(), Symbol::intern("call_once"), false)] {
+            &[(self.tcx.lang_items().fn_trait(), Symbol::intern("call"), true),
+              (self.tcx.lang_items().fn_mut_trait(), Symbol::intern("call_mut"), true),
+              (self.tcx.lang_items().fn_once_trait(), Symbol::intern("call_once"), false)] {
             let trait_def_id = match opt_trait_def_id {
                 Some(def_id) => def_id,
                 None => continue,
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index a768271f3b8..aa2b9c1e038 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -139,7 +139,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     })
                     .next();
                 let kind = object_type.principal()
-                    .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id()));
+                    .and_then(|p| self.tcx.lang_items().fn_trait_kind(p.def_id()));
                 (sig, kind)
             }
             ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),
@@ -204,7 +204,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     ty::Predicate::ClosureKind(..) => None,
                 };
                 opt_trait_ref.and_then(|tr| self.self_type_matches_expected_vid(tr, expected_vid))
-                    .and_then(|tr| self.tcx.lang_items.fn_trait_kind(tr.def_id()))
+                    .and_then(|tr| self.tcx.lang_items().fn_trait_kind(tr.def_id()))
             })
             .fold(None,
                   |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
@@ -223,7 +223,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let trait_ref = projection.to_poly_trait_ref(tcx);
 
-        if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
+        if tcx.lang_items().fn_trait_kind(trait_ref.def_id()).is_none() {
             return None;
         }
 
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index e406ce845a6..cfcdbcc1195 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -438,8 +438,8 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
     fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> {
         debug!("coerce_unsized(source={:?}, target={:?})", source, target);
 
-        let traits = (self.tcx.lang_items.unsize_trait(),
-                      self.tcx.lang_items.coerce_unsized_trait());
+        let traits = (self.tcx.lang_items().unsize_trait(),
+                      self.tcx.lang_items().coerce_unsized_trait());
         let (unsize_did, coerce_unsized_did) = if let (Some(u), Some(cu)) = traits {
             (u, cu)
         } else {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 08ec3bf74a7..852134bbee3 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -540,7 +540,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
     fn predicates_require_illegal_sized_bound(&self,
                                               predicates: &ty::InstantiatedPredicates<'tcx>)
                                               -> bool {
-        let sized_def_id = match self.tcx.lang_items.sized_trait() {
+        let sized_def_id = match self.tcx.lang_items().sized_trait() {
             Some(def_id) => def_id,
             None => return false,
         };
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index ba74c902f55..3771d330f6d 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -393,6 +393,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
 
     fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
         debug!("assemble_probe: self_ty={:?}", self_ty);
+        let lang_items = self.tcx.lang_items();
 
         match self_ty.sty {
             ty::TyDynamic(ref data, ..) => {
@@ -408,79 +409,79 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 self.assemble_inherent_candidates_from_param(self_ty, p);
             }
             ty::TyChar => {
-                let lang_def_id = self.tcx.lang_items.char_impl();
+                let lang_def_id = lang_items.char_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyStr => {
-                let lang_def_id = self.tcx.lang_items.str_impl();
+                let lang_def_id = lang_items.str_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TySlice(_) => {
-                let lang_def_id = self.tcx.lang_items.slice_impl();
+                let lang_def_id = lang_items.slice_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
-                let lang_def_id = self.tcx.lang_items.const_ptr_impl();
+                let lang_def_id = lang_items.const_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
-                let lang_def_id = self.tcx.lang_items.mut_ptr_impl();
+                let lang_def_id = lang_items.mut_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyInt(ast::IntTy::I8) => {
-                let lang_def_id = self.tcx.lang_items.i8_impl();
+                let lang_def_id = lang_items.i8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyInt(ast::IntTy::I16) => {
-                let lang_def_id = self.tcx.lang_items.i16_impl();
+                let lang_def_id = lang_items.i16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyInt(ast::IntTy::I32) => {
-                let lang_def_id = self.tcx.lang_items.i32_impl();
+                let lang_def_id = lang_items.i32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyInt(ast::IntTy::I64) => {
-                let lang_def_id = self.tcx.lang_items.i64_impl();
+                let lang_def_id = lang_items.i64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyInt(ast::IntTy::I128) => {
-                let lang_def_id = self.tcx.lang_items.i128_impl();
+                let lang_def_id = lang_items.i128_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyInt(ast::IntTy::Is) => {
-                let lang_def_id = self.tcx.lang_items.isize_impl();
+                let lang_def_id = lang_items.isize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyUint(ast::UintTy::U8) => {
-                let lang_def_id = self.tcx.lang_items.u8_impl();
+                let lang_def_id = lang_items.u8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyUint(ast::UintTy::U16) => {
-                let lang_def_id = self.tcx.lang_items.u16_impl();
+                let lang_def_id = lang_items.u16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyUint(ast::UintTy::U32) => {
-                let lang_def_id = self.tcx.lang_items.u32_impl();
+                let lang_def_id = lang_items.u32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyUint(ast::UintTy::U64) => {
-                let lang_def_id = self.tcx.lang_items.u64_impl();
+                let lang_def_id = lang_items.u64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyUint(ast::UintTy::U128) => {
-                let lang_def_id = self.tcx.lang_items.u128_impl();
+                let lang_def_id = lang_items.u128_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyUint(ast::UintTy::Us) => {
-                let lang_def_id = self.tcx.lang_items.usize_impl();
+                let lang_def_id = lang_items.usize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyFloat(ast::FloatTy::F32) => {
-                let lang_def_id = self.tcx.lang_items.f32_impl();
+                let lang_def_id = lang_items.f32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             ty::TyFloat(ast::FloatTy::F64) => {
-                let lang_def_id = self.tcx.lang_items.f64_impl();
+                let lang_def_id = lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
             _ => {}
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index f2d7842e473..7fa3dd7472d 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -45,7 +45,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             ty::TyFnPtr(_) => true,
             // If it's not a simple function, look for things which implement FnOnce
             _ => {
-                let fn_once = match tcx.lang_items.require(FnOnceTraitLangItem) {
+                let fn_once = match tcx.lang_items().require(FnOnceTraitLangItem) {
                     Ok(fn_once) => fn_once,
                     Err(..) => return false,
                 };
@@ -552,14 +552,14 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a>
                     if !external_mods.insert(def_id) {
                         return;
                     }
-                    for child in tcx.sess.cstore.item_children(def_id, tcx.sess) {
+                    for child in tcx.item_children(def_id).iter() {
                         handle_external_def(tcx, traits, external_mods, child.def)
                     }
                 }
                 _ => {}
             }
         }
-        for cnum in tcx.sess.cstore.crates() {
+        for &cnum in tcx.crates().iter() {
             let def_id = DefId {
                 krate: cnum,
                 index: CRATE_DEF_INDEX,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 3f210ea1737..0a8d2129a89 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2296,13 +2296,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn resolve_lvalue_op(&self, op: LvalueOp, is_mut: bool) -> (Option<DefId>, Symbol) {
         let (tr, name) = match (op, is_mut) {
             (LvalueOp::Deref, false) =>
-                (self.tcx.lang_items.deref_trait(), "deref"),
+                (self.tcx.lang_items().deref_trait(), "deref"),
             (LvalueOp::Deref, true) =>
-                (self.tcx.lang_items.deref_mut_trait(), "deref_mut"),
+                (self.tcx.lang_items().deref_mut_trait(), "deref_mut"),
             (LvalueOp::Index, false) =>
-                (self.tcx.lang_items.index_trait(), "index"),
+                (self.tcx.lang_items().index_trait(), "index"),
             (LvalueOp::Index, true) =>
-                (self.tcx.lang_items.index_mut_trait(), "index_mut"),
+                (self.tcx.lang_items().index_mut_trait(), "index_mut"),
         };
         (tr, Symbol::intern(name))
     }
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index a4e1fdaf39e..a3dd81fddde 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -362,7 +362,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn lookup_op_method(&self, lhs_ty: Ty<'tcx>, other_tys: &[Ty<'tcx>], op: Op)
                         -> Result<MethodCallee<'tcx>, ()>
     {
-        let lang = &self.tcx.lang_items;
+        let lang = self.tcx.lang_items();
 
         let span = match op {
             Op::Binary(op, _) => op.span,
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 69f045ab4e9..9c19aef5992 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -539,7 +539,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
     {
         let mut err = error_392(self.tcx, span, param_name);
 
-        let suggested_marker_id = self.tcx.lang_items.phantom_data();
+        let suggested_marker_id = self.tcx.lang_items().phantom_data();
         match suggested_marker_id {
             Some(def_id) => {
                 err.help(
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 3da154e0689..93f15775b15 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -14,8 +14,9 @@ use rustc::ty::TyCtxt;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 
-use rustc::hir;
+use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::hir;
 use rustc::util::nodemap::DefIdSet;
 
 struct CheckVisitor<'a, 'tcx: 'a> {
@@ -25,7 +26,8 @@ struct CheckVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> CheckVisitor<'a, 'tcx> {
     fn check_import(&self, id: ast::NodeId, span: Span) {
-        if !self.tcx.maybe_unused_trait_imports.contains(&id) {
+        let hir_id = self.tcx.hir.node_to_hir_id(id);
+        if !self.tcx.maybe_unused_trait_import(hir_id) {
             return;
         }
 
@@ -73,14 +75,20 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut visitor = CheckVisitor { tcx, used_trait_imports };
     tcx.hir.krate().visit_all_item_likes(&mut visitor);
 
-    for &(id, span) in &tcx.maybe_unused_extern_crates {
-        let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id();
-        if !tcx.is_compiler_builtins(cnum)
-            && !tcx.is_panic_runtime(cnum)
-            && !tcx.has_global_allocator(cnum) {
-                let lint = lint::builtin::UNUSED_EXTERN_CRATES;
-                let msg = "unused extern crate";
-                tcx.lint_node(lint, id, span, msg);
-            }
+    for &(hir_id, span) in tcx.maybe_unused_extern_crates(LOCAL_CRATE).iter() {
+        let cnum = tcx.extern_mod_stmt_cnum(hir_id).unwrap();
+        if tcx.is_compiler_builtins(cnum) {
+            continue
+        }
+        if tcx.is_panic_runtime(cnum) {
+            continue
+        }
+        if tcx.has_global_allocator(cnum) {
+            continue
+        }
+        let id = tcx.hir.definitions().find_node_for_hir_id(hir_id);
+        let lint = lint::builtin::UNUSED_EXTERN_CRATES;
+        let msg = "unused extern crate";
+        tcx.lint_node(lint, id, span, msg);
     }
 }
diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs
index b421fdfe8d8..fedfa51d61d 100644
--- a/src/librustc_typeck/coherence/builtin.rs
+++ b/src/librustc_typeck/coherence/builtin.rs
@@ -28,9 +28,9 @@ use rustc::hir::{self, ItemImpl};
 
 pub fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId) {
     Checker { tcx, trait_def_id }
-        .check(tcx.lang_items.drop_trait(), visit_implementation_of_drop)
-        .check(tcx.lang_items.copy_trait(), visit_implementation_of_copy)
-        .check(tcx.lang_items.coerce_unsized_trait(),
+        .check(tcx.lang_items().drop_trait(), visit_implementation_of_drop)
+        .check(tcx.lang_items().copy_trait(), visit_implementation_of_copy)
+        .check(tcx.lang_items().coerce_unsized_trait(),
                visit_implementation_of_coerce_unsized);
 }
 
@@ -176,9 +176,9 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      impl_did: DefId)
                                      -> CoerceUnsizedInfo {
     debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
-    let coerce_unsized_trait = tcx.lang_items.coerce_unsized_trait().unwrap();
+    let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap();
 
-    let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) {
+    let unsize_trait = match tcx.lang_items().require(UnsizeTraitLangItem) {
         Ok(id) => id,
         Err(err) => {
             tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err));
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
index e24d7660021..15e15abfb36 100644
--- a/src/librustc_typeck/coherence/inherent_impls.rs
+++ b/src/librustc_typeck/coherence/inherent_impls.rs
@@ -112,6 +112,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
 
         let def_id = self.tcx.hir.local_def_id(item.id);
         let self_ty = self.tcx.type_of(def_id);
+        let lang_items = self.tcx.lang_items();
         match self_ty.sty {
             ty::TyAdt(def, _) => {
                 self.check_def_id(item, def.did);
@@ -121,133 +122,133 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
             }
             ty::TyChar => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.char_impl(),
+                                          lang_items.char_impl(),
                                           "char",
                                           "char",
                                           item.span);
             }
             ty::TyStr => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.str_impl(),
+                                          lang_items.str_impl(),
                                           "str",
                                           "str",
                                           item.span);
             }
             ty::TySlice(_) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.slice_impl(),
+                                          lang_items.slice_impl(),
                                           "slice",
                                           "[T]",
                                           item.span);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.const_ptr_impl(),
+                                          lang_items.const_ptr_impl(),
                                           "const_ptr",
                                           "*const T",
                                           item.span);
             }
             ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.mut_ptr_impl(),
+                                          lang_items.mut_ptr_impl(),
                                           "mut_ptr",
                                           "*mut T",
                                           item.span);
             }
             ty::TyInt(ast::IntTy::I8) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i8_impl(),
+                                          lang_items.i8_impl(),
                                           "i8",
                                           "i8",
                                           item.span);
             }
             ty::TyInt(ast::IntTy::I16) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i16_impl(),
+                                          lang_items.i16_impl(),
                                           "i16",
                                           "i16",
                                           item.span);
             }
             ty::TyInt(ast::IntTy::I32) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i32_impl(),
+                                          lang_items.i32_impl(),
                                           "i32",
                                           "i32",
                                           item.span);
             }
             ty::TyInt(ast::IntTy::I64) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i64_impl(),
+                                          lang_items.i64_impl(),
                                           "i64",
                                           "i64",
                                           item.span);
             }
             ty::TyInt(ast::IntTy::I128) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i128_impl(),
+                                          lang_items.i128_impl(),
                                           "i128",
                                           "i128",
                                           item.span);
             }
             ty::TyInt(ast::IntTy::Is) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.isize_impl(),
+                                          lang_items.isize_impl(),
                                           "isize",
                                           "isize",
                                           item.span);
             }
             ty::TyUint(ast::UintTy::U8) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u8_impl(),
+                                          lang_items.u8_impl(),
                                           "u8",
                                           "u8",
                                           item.span);
             }
             ty::TyUint(ast::UintTy::U16) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u16_impl(),
+                                          lang_items.u16_impl(),
                                           "u16",
                                           "u16",
                                           item.span);
             }
             ty::TyUint(ast::UintTy::U32) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u32_impl(),
+                                          lang_items.u32_impl(),
                                           "u32",
                                           "u32",
                                           item.span);
             }
             ty::TyUint(ast::UintTy::U64) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u64_impl(),
+                                          lang_items.u64_impl(),
                                           "u64",
                                           "u64",
                                           item.span);
             }
             ty::TyUint(ast::UintTy::U128) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u128_impl(),
+                                          lang_items.u128_impl(),
                                           "u128",
                                           "u128",
                                           item.span);
             }
             ty::TyUint(ast::UintTy::Us) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.usize_impl(),
+                                          lang_items.usize_impl(),
                                           "usize",
                                           "usize",
                                           item.span);
             }
             ty::TyFloat(ast::FloatTy::F32) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.f32_impl(),
+                                          lang_items.f32_impl(),
                                           "f32",
                                           "f32",
                                           item.span);
             }
             ty::TyFloat(ast::FloatTy::F64) => {
                 self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.f64_impl(),
+                                          lang_items.f64_impl(),
                                           "f64",
                                           "f64",
                                           item.span);
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 165be49f760..6109fc57b0d 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -51,7 +51,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
 
 fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) {
     let did = Some(trait_def_id);
-    let li = &tcx.lang_items;
+    let li = tcx.lang_items();
 
     // Disallow *all* explicit impls of `Sized` and `Unsize` for now.
     if did == li.sized_trait() {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index c177623af48..e4ca0f82ea1 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -812,7 +812,8 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
             if self.has_late_bound_regions.is_some() { return }
 
-            match self.tcx.named_region_map.defs.get(&lt.id).cloned() {
+            let hir_id = self.tcx.hir.node_to_hir_id(lt.id);
+            match self.tcx.named_region(hir_id) {
                 Some(rl::Region::Static) | Some(rl::Region::EarlyBound(..)) => {}
                 Some(rl::Region::LateBound(debruijn, _)) |
                 Some(rl::Region::LateBoundAnon(debruijn, _))
@@ -830,7 +831,8 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             tcx, binder_depth: 1, has_late_bound_regions: None
         };
         for lifetime in &generics.lifetimes {
-            if tcx.named_region_map.late_bound.contains(&lifetime.lifetime.id) {
+            let hir_id = tcx.hir.node_to_hir_id(lifetime.lifetime.id);
+            if tcx.is_late_bound(hir_id) {
                 return Some(lifetime.lifetime.span);
             }
         }
@@ -987,8 +989,8 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     }).collect::<Vec<_>>();
 
-    let object_lifetime_defaults =
-        tcx.named_region_map.object_lifetime_defaults.get(&node_id);
+    let hir_id = tcx.hir.node_to_hir_id(node_id);
+    let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
 
     // Now create the real type parameters.
     let type_start = own_start + regions.len() as u32;
@@ -1014,7 +1016,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             def_id: tcx.hir.local_def_id(p.id),
             has_default: p.default.is_some(),
             object_lifetime_default:
-                object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]),
+                object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
             pure_wrt_drop: p.pure_wrt_drop,
         }
     });
@@ -1307,7 +1309,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
         }
     }
 
-    let kind_id = tcx.lang_items.require(SizedTraitLangItem);
+    let kind_id = tcx.lang_items().require(SizedTraitLangItem);
     match unbound {
         Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
@@ -1343,7 +1345,10 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>(
     ast_generics
         .lifetimes
         .iter()
-        .filter(move |l| !tcx.named_region_map.late_bound.contains(&l.lifetime.id))
+        .filter(move |l| {
+            let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id);
+            !tcx.is_late_bound(hir_id)
+        })
 }
 
 fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index c624b11c5ec..6062ac96ada 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -94,17 +94,18 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>
 }
 
 fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
+    let lang_items = tcx.lang_items();
     let all = vec![
-        (tcx.lang_items.phantom_data(), vec![ty::Covariant]),
-        (tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]),
+        (lang_items.phantom_data(), vec![ty::Covariant]),
+        (lang_items.unsafe_cell_type(), vec![ty::Invariant]),
 
         // Deprecated:
-        (tcx.lang_items.covariant_type(), vec![ty::Covariant]),
-        (tcx.lang_items.contravariant_type(), vec![ty::Contravariant]),
-        (tcx.lang_items.invariant_type(), vec![ty::Invariant]),
-        (tcx.lang_items.covariant_lifetime(), vec![ty::Covariant]),
-        (tcx.lang_items.contravariant_lifetime(), vec![ty::Contravariant]),
-        (tcx.lang_items.invariant_lifetime(), vec![ty::Invariant]),
+        (lang_items.covariant_type(), vec![ty::Covariant]),
+        (lang_items.contravariant_type(), vec![ty::Contravariant]),
+        (lang_items.invariant_type(), vec![ty::Invariant]),
+        (lang_items.covariant_lifetime(), vec![ty::Covariant]),
+        (lang_items.contravariant_lifetime(), vec![ty::Contravariant]),
+        (lang_items.invariant_lifetime(), vec![ty::Invariant]),
 
         ];
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 5d39d1d27f4..70563b3d267 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -120,7 +120,7 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes {
 /// These names are used later on by HTML rendering to generate things like
 /// source links back to the original item.
 pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
-    let crate_name = cx.tcx.sess.cstore.crate_name(did.krate).to_string();
+    let crate_name = cx.tcx.crate_name(did.krate).to_string();
     let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
         // extern blocks have an empty name
         let s = elem.data.to_string();
@@ -236,31 +236,34 @@ pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
 
     cx.populated_all_crate_impls.set(true);
 
-    for did in tcx.sess.cstore.implementations_of_trait(None) {
-        build_impl(cx, did, &mut impls);
+    for &cnum in tcx.crates().iter() {
+        for did in tcx.all_trait_implementations(cnum).iter() {
+            build_impl(cx, *did, &mut impls);
+        }
     }
 
     // Also try to inline primitive impls from other crates.
+    let lang_items = tcx.lang_items();
     let primitive_impls = [
-        tcx.lang_items.isize_impl(),
-        tcx.lang_items.i8_impl(),
-        tcx.lang_items.i16_impl(),
-        tcx.lang_items.i32_impl(),
-        tcx.lang_items.i64_impl(),
-        tcx.lang_items.i128_impl(),
-        tcx.lang_items.usize_impl(),
-        tcx.lang_items.u8_impl(),
-        tcx.lang_items.u16_impl(),
-        tcx.lang_items.u32_impl(),
-        tcx.lang_items.u64_impl(),
-        tcx.lang_items.u128_impl(),
-        tcx.lang_items.f32_impl(),
-        tcx.lang_items.f64_impl(),
-        tcx.lang_items.char_impl(),
-        tcx.lang_items.str_impl(),
-        tcx.lang_items.slice_impl(),
-        tcx.lang_items.const_ptr_impl(),
-        tcx.lang_items.mut_ptr_impl(),
+        lang_items.isize_impl(),
+        lang_items.i8_impl(),
+        lang_items.i16_impl(),
+        lang_items.i32_impl(),
+        lang_items.i64_impl(),
+        lang_items.i128_impl(),
+        lang_items.usize_impl(),
+        lang_items.u8_impl(),
+        lang_items.u16_impl(),
+        lang_items.u32_impl(),
+        lang_items.u64_impl(),
+        lang_items.u128_impl(),
+        lang_items.f32_impl(),
+        lang_items.f64_impl(),
+        lang_items.char_impl(),
+        lang_items.str_impl(),
+        lang_items.slice_impl(),
+        lang_items.const_ptr_impl(),
+        lang_items.mut_ptr_impl(),
     ];
 
     for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
@@ -399,7 +402,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
             clean::RegionBound(..) => unreachable!(),
         }
     });
-    if trait_.def_id() == tcx.lang_items.deref_trait() {
+    if trait_.def_id() == tcx.lang_items().deref_trait() {
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
 
@@ -443,9 +446,9 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
         // two namespaces, so the target may be listed twice. Make sure we only
         // visit each node at most once.
         let mut visited = FxHashSet();
-        for item in cx.tcx.sess.cstore.item_children(did, cx.tcx.sess) {
+        for &item in cx.tcx.item_children(did).iter() {
             let def_id = item.def.def_id();
-            if cx.tcx.sess.cstore.visibility(def_id) == ty::Visibility::Public {
+            if cx.tcx.visibility(def_id) == ty::Visibility::Public {
                 if !visited.insert(def_id) { continue }
                 if let Some(i) = try_inline(cx, item.def, item.ident.name) {
                     items.extend(i)
@@ -471,7 +474,7 @@ impl hir::print::PpAnn for InlinedConst {
 }
 
 fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
-    let body = cx.tcx.sess.cstore.item_body(cx.tcx, did);
+    let body = cx.tcx.extern_const_body(did);
     let inlined = InlinedConst {
         nested_bodies: cx.tcx.item_body_nested_bodies(did)
     };
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 60651bd617f..88a0d3ad4ac 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -125,13 +125,13 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
 
         {
             let mut r = cx.renderinfo.borrow_mut();
-            r.deref_trait_did = cx.tcx.lang_items.deref_trait();
-            r.deref_mut_trait_did = cx.tcx.lang_items.deref_mut_trait();
-            r.owned_box_did = cx.tcx.lang_items.owned_box();
+            r.deref_trait_did = cx.tcx.lang_items().deref_trait();
+            r.deref_mut_trait_did = cx.tcx.lang_items().deref_mut_trait();
+            r.owned_box_did = cx.tcx.lang_items().owned_box();
         }
 
         let mut externs = Vec::new();
-        for cnum in cx.sess().cstore.crates() {
+        for &cnum in cx.tcx.crates().iter() {
             externs.push((cnum, cnum.clean(cx)));
             // Analyze doc-reachability for extern items
             LibEmbargoVisitor::new(cx).visit_lib(cnum);
@@ -244,7 +244,7 @@ impl Clean<ExternalCrate> for CrateNum {
                 }
             }).collect()
         } else {
-            cx.tcx.sess.cstore.item_children(root, cx.tcx.sess).iter().map(|item| item.def)
+            cx.tcx.item_children(root).iter().map(|item| item.def)
               .filter_map(as_primitive).collect()
         };
 
@@ -672,7 +672,7 @@ impl TyParamBound {
     fn maybe_sized(cx: &DocContext) -> TyParamBound {
         let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem);
         let empty = cx.tcx.intern_substs(&[]);
-        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
+        let path = external_path(cx, &cx.tcx.item_name(did),
             Some(did), false, vec![], empty);
         inline::record_extern_fqn(cx, did, TypeKind::Trait);
         TraitBound(PolyTrait {
@@ -689,7 +689,7 @@ impl TyParamBound {
     fn is_sized_bound(&self, cx: &DocContext) -> bool {
         use rustc::hir::TraitBoundModifier as TBM;
         if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self {
-            if trait_.def_id() == cx.tcx.lang_items.sized_trait() {
+            if trait_.def_id() == cx.tcx.lang_items().sized_trait() {
                 return true;
             }
         }
@@ -713,7 +713,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo
 
     match trait_did {
         // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
-        Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => {
+        Some(did) if cx.tcx.lang_items().fn_trait_kind(did).is_some() => {
             assert_eq!(types.len(), 1);
             let inputs = match types[0].sty {
                 ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(),
@@ -763,7 +763,7 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
 impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait);
-        let path = external_path(cx, &cx.tcx.item_name(self.def_id).as_str(),
+        let path = external_path(cx, &cx.tcx.item_name(self.def_id),
                                  Some(self.def_id), true, vec![], self.substs);
 
         debug!("ty::TraitRef\n  subst: {:?}\n", self.substs);
@@ -830,7 +830,8 @@ impl Lifetime {
 
 impl Clean<Lifetime> for hir::Lifetime {
     fn clean(&self, cx: &DocContext) -> Lifetime {
-        let def = cx.tcx.named_region_map.defs.get(&self.id).cloned();
+        let hir_id = cx.tcx.hir.node_to_hir_id(self.id);
+        let def = cx.tcx.named_region(hir_id);
         match def {
             Some(rl::Region::EarlyBound(_, node_id)) |
             Some(rl::Region::LateBound(_, node_id)) |
@@ -1924,7 +1925,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     AdtKind::Enum => TypeKind::Enum,
                 };
                 inline::record_extern_fqn(cx, did, kind);
-                let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
+                let path = external_path(cx, &cx.tcx.item_name(did),
                                          None, false, vec![], substs);
                 ResolvedPath {
                     path,
@@ -1942,7 +1943,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     reg.clean(cx).map(|b| typarams.push(RegionBound(b)));
                     for did in obj.auto_traits() {
                         let empty = cx.tcx.intern_substs(&[]);
-                        let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
+                        let path = external_path(cx, &cx.tcx.item_name(did),
                             Some(did), false, vec![], empty);
                         inline::record_extern_fqn(cx, did, TypeKind::Trait);
                         let bound = TraitBound(PolyTrait {
@@ -1965,7 +1966,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                         });
                     }
 
-                    let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
+                    let path = external_path(cx, &cx.tcx.item_name(did), Some(did),
                         false, bindings, principal.0.substs);
                     ResolvedPath {
                         path,
@@ -2535,7 +2536,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
 
         // If this impl block is an implementation of the Deref trait, then we
         // need to try inlining the target's inherent impl blocks as well.
-        if trait_.def_id() == cx.tcx.lang_items.deref_trait() {
+        if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
             build_deref_target_impls(cx, &items, &mut ret);
         }
 
@@ -2591,27 +2592,27 @@ fn build_deref_target_impls(cx: &DocContext,
             }
         };
         let did = match primitive {
-            Isize => tcx.lang_items.isize_impl(),
-            I8 => tcx.lang_items.i8_impl(),
-            I16 => tcx.lang_items.i16_impl(),
-            I32 => tcx.lang_items.i32_impl(),
-            I64 => tcx.lang_items.i64_impl(),
-            I128 => tcx.lang_items.i128_impl(),
-            Usize => tcx.lang_items.usize_impl(),
-            U8 => tcx.lang_items.u8_impl(),
-            U16 => tcx.lang_items.u16_impl(),
-            U32 => tcx.lang_items.u32_impl(),
-            U64 => tcx.lang_items.u64_impl(),
-            U128 => tcx.lang_items.u128_impl(),
-            F32 => tcx.lang_items.f32_impl(),
-            F64 => tcx.lang_items.f64_impl(),
-            Char => tcx.lang_items.char_impl(),
+            Isize => tcx.lang_items().isize_impl(),
+            I8 => tcx.lang_items().i8_impl(),
+            I16 => tcx.lang_items().i16_impl(),
+            I32 => tcx.lang_items().i32_impl(),
+            I64 => tcx.lang_items().i64_impl(),
+            I128 => tcx.lang_items().i128_impl(),
+            Usize => tcx.lang_items().usize_impl(),
+            U8 => tcx.lang_items().u8_impl(),
+            U16 => tcx.lang_items().u16_impl(),
+            U32 => tcx.lang_items().u32_impl(),
+            U64 => tcx.lang_items().u64_impl(),
+            U128 => tcx.lang_items().u128_impl(),
+            F32 => tcx.lang_items().f32_impl(),
+            F64 => tcx.lang_items().f64_impl(),
+            Char => tcx.lang_items().char_impl(),
             Bool => None,
-            Str => tcx.lang_items.str_impl(),
-            Slice => tcx.lang_items.slice_impl(),
-            Array => tcx.lang_items.slice_impl(),
+            Str => tcx.lang_items().str_impl(),
+            Slice => tcx.lang_items().slice_impl(),
+            Array => tcx.lang_items().slice_impl(),
             Tuple => None,
-            RawPointer => tcx.lang_items.const_ptr_impl(),
+            RawPointer => tcx.lang_items().const_ptr_impl(),
             Reference => None,
             Fn => None,
         };
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 1f33cd77651..d354d726ff7 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -207,8 +207,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                         continue // These are `krate.exported_macros`, handled in `self.visit()`.
                     }
 
-                    let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate);
-                    let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) {
+                    let imported_from = self.cx.tcx.original_crate_name(def_id.krate);
+                    let cstore = &self.cx.sess().cstore;
+                    let def = match cstore.load_macro_untracked(def_id, self.cx.sess()) {
                         LoadedMacro::MacroDef(macro_def) => macro_def,
                         // FIXME(jseyfried): document proc macro reexports
                         LoadedMacro::ProcMacro(..) => continue,
@@ -371,9 +372,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             _ if self.inlining && item.vis != hir::Public => {}
             hir::ItemGlobalAsm(..) => {}
             hir::ItemExternCrate(ref p) => {
-                let cstore = &self.cx.sess().cstore;
+                let hir_id = self.cx.tcx.hir.node_to_hir_id(item.id);
                 om.extern_crates.push(ExternCrate {
-                    cnum: cstore.extern_mod_stmt_cnum(item.id)
+                    cnum: self.cx.tcx.extern_mod_stmt_cnum(hir_id)
                                 .unwrap_or(LOCAL_CRATE),
                     name,
                     path: p.map(|x|x.to_string()),
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 7b5b27c5565..9f75388238f 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::{AccessLevels, AccessLevel};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
@@ -25,7 +24,6 @@ use clean::{AttributesExt, NestedAttributesExt};
 /// specific rustdoc annotations into account (i.e. `doc(hidden)`)
 pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> {
     cx: &'a ::core::DocContext<'b, 'tcx>,
-    cstore: &'a CrateStore,
     // Accessibility levels for reachable nodes
     access_levels: RefMut<'a, AccessLevels<DefId>>,
     // Previous accessibility level, None means unreachable
@@ -38,7 +36,6 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
     pub fn new(cx: &'a ::core::DocContext<'b, 'tcx>) -> LibEmbargoVisitor<'a, 'b, 'tcx> {
         LibEmbargoVisitor {
             cx,
-            cstore: &*cx.sess().cstore,
             access_levels: cx.access_levels.borrow_mut(),
             prev_level: Some(AccessLevel::Public),
             visited_mods: FxHashSet()
@@ -70,14 +67,14 @@ impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> {
             return;
         }
 
-        for item in self.cstore.item_children(def_id, self.cx.tcx.sess) {
+        for item in self.cx.tcx.item_children(def_id).iter() {
             self.visit_item(item.def);
         }
     }
 
     fn visit_item(&mut self, def: Def) {
         let def_id = def.def_id();
-        let vis = self.cstore.visibility(def_id);
+        let vis = self.cx.tcx.visibility(def_id);
         let inherited_item_level = if vis == Visibility::Public {
             self.prev_level
         } else {
diff --git a/src/test/compile-fail/empty-linkname.rs b/src/test/compile-fail/empty-linkname.rs
index cd5ee1cafec..20e0f9cd0b2 100644
--- a/src/test/compile-fail/empty-linkname.rs
+++ b/src/test/compile-fail/empty-linkname.rs
@@ -11,3 +11,5 @@
 #[link(name = "")] //~ ERROR: given with empty name
 extern {
 }
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate-static-nobundle.rs b/src/test/compile-fail/feature-gate-static-nobundle.rs
index bc0025c7c95..0d13a4937c4 100644
--- a/src/test/compile-fail/feature-gate-static-nobundle.rs
+++ b/src/test/compile-fail/feature-gate-static-nobundle.rs
@@ -11,3 +11,5 @@
 #[link(name="foo", kind="static-nobundle")]
 //~^ ERROR: kind="static-nobundle" is feature gated
 extern {}
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
index 6eec1779a2d..06b87206669 100644
--- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
+++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
@@ -99,7 +99,8 @@
 
 // For #![crate_id], see issue #43142. (I cannot bear to enshrine current behavior in a test)
 
-#![feature                    ( x0600)] //~ WARN unused or unknown feature
+// FIXME(#44232) we should warn that this isn't used.
+#![feature                    ( x0600)]
 
 // For #![no_start], see issue #43144. (I cannot bear to enshrine current behavior in a test)
 
diff --git a/src/test/compile-fail/lint-output-format-2.rs b/src/test/compile-fail/lint-output-format-2.rs
index 0e68ff752e5..ef072d4bbb3 100644
--- a/src/test/compile-fail/lint-output-format-2.rs
+++ b/src/test/compile-fail/lint-output-format-2.rs
@@ -8,21 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -F unused_features
 // aux-build:lint_output_format.rs
 
+// FIXME(#44232) we should warn that this isn't used.
 #![feature(foo)]
-//~^ ERROR unused or unknown feature
-//~| NOTE requested on the command line with `-F unused-features`
 
 #![feature(test_feature)]
+#![feature(rustc_attrs)]
 
 extern crate lint_output_format;
 use lint_output_format::{foo, bar};
 //~^ WARNING use of deprecated item: text
 //~| NOTE #[warn(deprecated)] on by default
 
-fn main() {
+#[rustc_error]
+fn main() { //~ ERROR: compilation successful
     let _x = foo();
     //~^ WARNING use of deprecated item: text
     //~| NOTE #[warn(deprecated)] on by default
diff --git a/src/test/compile-fail/lint-unknown-feature-default.rs b/src/test/compile-fail/lint-unknown-feature-default.rs
index afd1a3933bf..79ba3ea45e1 100644
--- a/src/test/compile-fail/lint-unknown-feature-default.rs
+++ b/src/test/compile-fail/lint-unknown-feature-default.rs
@@ -10,8 +10,10 @@
 
 // Tests the default for the unused_features lint
 
-#![deny(warnings)]
+// FIXME(#44232) we should warn that this isn't used.
+#![feature(this_is_not_a_feature)]
 
-#![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature
+#![feature(rustc_attrs)]
 
-fn main() { }
+#[rustc_error]
+fn main() { } //~ ERROR: compilation successful
diff --git a/src/test/compile-fail/lint-unknown-feature.rs b/src/test/compile-fail/lint-unknown-feature.rs
index ac1720b339e..d230297aaba 100644
--- a/src/test/compile-fail/lint-unknown-feature.rs
+++ b/src/test/compile-fail/lint-unknown-feature.rs
@@ -8,8 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(unused_features)]
+#![warn(unused_features)]
 
-#![feature(this_is_not_a_feature)] //~ ERROR: unused or unknown feature
+// FIXME(#44232) we should warn that this isn't used.
+#![feature(this_is_not_a_feature)]
 
-fn main() {}
+#![feature(rustc_attrs)]
+
+#[rustc_error]
+fn main() {} //~ ERROR: compilation successful
diff --git a/src/test/compile-fail/stable-features.rs b/src/test/compile-fail/stable-features.rs
index 6f8c95c3840..5993f4b5a09 100644
--- a/src/test/compile-fail/stable-features.rs
+++ b/src/test/compile-fail/stable-features.rs
@@ -12,8 +12,11 @@
 // language and lib features.
 
 #![deny(stable_features)]
+
 #![feature(test_accepted_feature)] //~ ERROR this feature has been stable since 1.0.0
-#![feature(rust1)] //~ ERROR this feature has been stable since 1.0.0
+
+// FIXME(#44232) we should error that this isn't used.
+#![feature(rust1)]
 
 fn main() {
     let _foo: Vec<()> = Vec::new();
diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs
index fdf50c27bf4..8eac959fc1e 100644
--- a/src/test/compile-fail/weak-lang-item.rs
+++ b/src/test/compile-fail/weak-lang-item.rs
@@ -16,3 +16,5 @@
 
 extern crate core;
 extern crate weak_lang_items;
+
+fn main() {}
diff --git a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
index 40067efd575..875aa329365 100644
--- a/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
+++ b/src/test/incremental/add_private_fn_at_krate_root_cc/struct_point.rs
@@ -15,6 +15,7 @@
 // revisions:rpass1 rpass2
 // compile-flags: -Z query-dep-graph
 // aux-build:point.rs
+// ignore-test FIXME(#42293) this regressed in #44142 but should get fixed with red/green
 
 #![feature(rustc_attrs)]
 #![feature(stmt_expr_attributes)]
diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs
index 701c5fec49b..58fb8bc3c88 100644
--- a/src/test/incremental/remapped_paths_cc/main.rs
+++ b/src/test/incremental/remapped_paths_cc/main.rs
@@ -11,6 +11,7 @@
 // revisions:rpass1 rpass2 rpass3
 // compile-flags: -Z query-dep-graph -g -Zincremental-cc
 // aux-build:extern_crate.rs
+// ignore-test FIXME(#42293) this regressed in #44142 but should get fixed with red/green
 
 
 // This test case makes sure that we detect if paths emitted into debuginfo
diff --git a/src/test/incremental/remove-private-item-cross-crate/main.rs b/src/test/incremental/remove-private-item-cross-crate/main.rs
index 582ee905d7c..24fa1502b92 100644
--- a/src/test/incremental/remove-private-item-cross-crate/main.rs
+++ b/src/test/incremental/remove-private-item-cross-crate/main.rs
@@ -16,7 +16,9 @@
 
 #![feature(rustc_attrs)]
 #![crate_type = "bin"]
-#![rustc_partition_reused(module="main", cfg="rpass2")]
+
+// FIXME(#42293) this regressed in #44142 but should get fixed with red/green
+// #![rustc_partition_reused(module="main", cfg="rpass2")]
 
 extern crate a;