]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc/ty/mod.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc / ty / mod.rs
index 2c15f08e89822667ad9fd9cdab7cce33fb9ca20d..3c37c7353d683b739e76b4a4358dd911984481ec 100644 (file)
@@ -9,35 +9,35 @@
 // except according to those terms.
 
 pub use self::Variance::*;
-pub use self::DtorKind::*;
-pub use self::ImplOrTraitItemContainer::*;
+pub use self::AssociatedItemContainer::*;
 pub use self::BorrowKind::*;
-pub use self::ImplOrTraitItem::*;
 pub use self::IntVarValue::*;
 pub use self::LvaluePreference::*;
 pub use self::fold::TypeFoldable;
 
 use dep_graph::{self, DepNode};
-use hir::map as ast_map;
+use hir::{map as hir_map, FreevarMap, TraitMap};
 use middle;
-use hir::def::{Def, CtorKind, PathResolution, ExportMap};
-use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use hir::def::{Def, CtorKind, ExportMap};
+use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
+use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
 use traits;
 use ty;
 use ty::subst::{Subst, Substs};
+use ty::util::IntTypeExt;
 use ty::walk::TypeWalker;
 use util::common::MemoizationMap;
-use util::nodemap::NodeSet;
-use util::nodemap::FnvHashMap;
+use util::nodemap::{NodeSet, FxHashMap};
 
 use serialize::{self, Encodable, Encoder};
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell, Ref};
+use std::collections::BTreeMap;
 use std::hash::{Hash, Hasher};
-use std::iter;
 use std::ops::Deref;
 use std::rc::Rc;
 use std::slice;
@@ -45,18 +45,18 @@ use std::vec::IntoIter;
 use std::mem;
 use syntax::ast::{self, Name, NodeId};
 use syntax::attr;
-use syntax::parse::token::{self, InternedString};
+use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{DUMMY_SP, Span};
-
 use rustc_const_math::ConstInt;
 
+use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+
 use hir;
-use hir::intravisit::Visitor;
+use hir::itemlikevisit::ItemLikeVisitor;
 
 pub use self::sty::{Binder, DebruijnIndex};
-pub use self::sty::{BuiltinBound, BuiltinBounds};
-pub use self::sty::{BareFnTy, FnSig, PolyFnSig};
-pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject};
+pub use self::sty::{FnSig, PolyFnSig};
+pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
 pub use self::sty::{ClosureSubsts, TypeAndMut};
 pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
 pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
@@ -69,22 +69,20 @@ pub use self::sty::InferTy::*;
 pub use self::sty::Region::*;
 pub use self::sty::TypeVariants::*;
 
-pub use self::sty::BuiltinBound::Send as BoundSend;
-pub use self::sty::BuiltinBound::Sized as BoundSized;
-pub use self::sty::BuiltinBound::Copy as BoundCopy;
-pub use self::sty::BuiltinBound::Sync as BoundSync;
-
 pub use self::contents::TypeContents;
-pub use self::context::{TyCtxt, tls};
-pub use self::context::{CtxtArenas, Lift, Tables};
+pub use self::context::{TyCtxt, GlobalArenas, tls};
+pub use self::context::{Lift, TypeckTables};
 
 pub use self::trait_def::{TraitDef, TraitFlags};
 
+pub use self::maps::queries;
+
 pub mod adjustment;
 pub mod cast;
 pub mod error;
 pub mod fast_reject;
 pub mod fold;
+pub mod inhabitedness;
 pub mod item_path;
 pub mod layout;
 pub mod _match;
@@ -100,47 +98,36 @@ pub mod util;
 mod contents;
 mod context;
 mod flags;
-mod ivar;
 mod structural_impls;
 mod sty;
 
-pub type Disr = ConstInt;
-
 // Data types
 
 /// The complete set of all analyses described in this module. This is
 /// produced by the driver and fed to trans and later passes.
 #[derive(Clone)]
-pub struct CrateAnalysis<'a> {
+pub struct CrateAnalysis {
     pub export_map: ExportMap,
     pub access_levels: middle::privacy::AccessLevels,
     pub reachable: NodeSet,
-    pub name: &'a str,
+    pub name: String,
     pub glob_map: Option<hir::GlobMap>,
 }
 
-#[derive(Copy, Clone)]
-pub enum DtorKind {
-    NoDtor,
-    TraitDtor
-}
-
-impl DtorKind {
-    pub fn is_present(&self) -> bool {
-        match *self {
-            TraitDtor => true,
-            _ => false
-        }
-    }
+#[derive(Clone)]
+pub struct Resolutions {
+    pub freevars: FreevarMap,
+    pub trait_map: TraitMap,
+    pub maybe_unused_trait_imports: NodeSet,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum ImplOrTraitItemContainer {
+pub enum AssociatedItemContainer {
     TraitContainer(DefId),
     ImplContainer(DefId),
 }
 
-impl ImplOrTraitItemContainer {
+impl AssociatedItemContainer {
     pub fn id(&self) -> DefId {
         match *self {
             TraitContainer(id) => id,
@@ -170,9 +157,9 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> {
 
         let header = ImplHeader {
             impl_def_id: impl_def_id,
-            self_ty: tcx.lookup_item_type(impl_def_id).ty,
+            self_ty: tcx.item_type(impl_def_id),
             trait_ref: tcx.impl_trait_ref(impl_def_id),
-            predicates: tcx.lookup_predicates(impl_def_id).predicates
+            predicates: tcx.item_predicates(impl_def_id).predicates
         }.subst(tcx, impl_substs);
 
         let traits::Normalized { value: mut header, obligations } =
@@ -183,58 +170,44 @@ impl<'a, 'gcx, 'tcx> ImplHeader<'tcx> {
     }
 }
 
-#[derive(Clone)]
-pub enum ImplOrTraitItem<'tcx> {
-    ConstTraitItem(Rc<AssociatedConst<'tcx>>),
-    MethodTraitItem(Rc<Method<'tcx>>),
-    TypeTraitItem(Rc<AssociatedType<'tcx>>),
-}
-
-impl<'tcx> ImplOrTraitItem<'tcx> {
-    pub fn def(&self) -> Def {
-        match *self {
-            ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id),
-            MethodTraitItem(ref method) => Def::Method(method.def_id),
-            TypeTraitItem(ref ty) => Def::AssociatedTy(ty.def_id),
-        }
-    }
-
-    pub fn def_id(&self) -> DefId {
-        match *self {
-            ConstTraitItem(ref associated_const) => associated_const.def_id,
-            MethodTraitItem(ref method) => method.def_id,
-            TypeTraitItem(ref associated_type) => associated_type.def_id,
-        }
-    }
+#[derive(Copy, Clone, Debug)]
+pub struct AssociatedItem {
+    pub def_id: DefId,
+    pub name: Name,
+    pub kind: AssociatedKind,
+    pub vis: Visibility,
+    pub defaultness: hir::Defaultness,
+    pub container: AssociatedItemContainer,
 
-    pub fn name(&self) -> Name {
-        match *self {
-            ConstTraitItem(ref associated_const) => associated_const.name,
-            MethodTraitItem(ref method) => method.name,
-            TypeTraitItem(ref associated_type) => associated_type.name,
-        }
-    }
+    /// Whether this is a method with an explicit self
+    /// as its first argument, allowing method calls.
+    pub method_has_self_argument: bool,
+}
 
-    pub fn vis(&self) -> Visibility {
-        match *self {
-            ConstTraitItem(ref associated_const) => associated_const.vis,
-            MethodTraitItem(ref method) => method.vis,
-            TypeTraitItem(ref associated_type) => associated_type.vis,
-        }
-    }
+#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
+pub enum AssociatedKind {
+    Const,
+    Method,
+    Type
+}
 
-    pub fn container(&self) -> ImplOrTraitItemContainer {
-        match *self {
-            ConstTraitItem(ref associated_const) => associated_const.container,
-            MethodTraitItem(ref method) => method.container,
-            TypeTraitItem(ref associated_type) => associated_type.container,
+impl AssociatedItem {
+    pub fn def(&self) -> Def {
+        match self.kind {
+            AssociatedKind::Const => Def::AssociatedConst(self.def_id),
+            AssociatedKind::Method => Def::Method(self.def_id),
+            AssociatedKind::Type => Def::AssociatedTy(self.def_id),
         }
     }
 
-    pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
-        match *self {
-            MethodTraitItem(ref m) => Some((*m).clone()),
-            _ => None,
+    /// Tests whether the associated item admits a non-trivial implementation
+    /// for !
+    pub fn relevant_for_never<'tcx>(&self) -> bool {
+        match self.kind {
+            AssociatedKind::Const => true,
+            AssociatedKind::Type => true,
+            // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
+            AssociatedKind::Method => !self.method_has_self_argument,
         }
     }
 }
@@ -244,63 +217,72 @@ pub enum Visibility {
     /// Visible everywhere (including in other crates).
     Public,
     /// Visible only in the given crate-local module.
-    Restricted(NodeId),
+    Restricted(DefId),
     /// Not visible anywhere in the local crate. This is the visibility of private external items.
-    PrivateExternal,
+    Invisible,
 }
 
-pub trait NodeIdTree {
-    fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
-}
+pub trait DefIdTree: Copy {
+    fn parent(self, id: DefId) -> Option<DefId>;
+
+    fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
+        if descendant.krate != ancestor.krate {
+            return false;
+        }
 
-impl<'a> NodeIdTree for ast_map::Map<'a> {
-    fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
-        let mut node_ancestor = node;
-        while node_ancestor != ancestor {
-            let node_ancestor_parent = self.get_module_parent(node_ancestor);
-            if node_ancestor_parent == node_ancestor {
-                return false;
+        while descendant != ancestor {
+            match self.parent(descendant) {
+                Some(parent) => descendant = parent,
+                None => return false,
             }
-            node_ancestor = node_ancestor_parent;
         }
         true
     }
 }
 
+impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> {
+    fn parent(self, id: DefId) -> Option<DefId> {
+        self.def_key(id).parent.map(|index| DefId { index: index, ..id })
+    }
+}
+
 impl Visibility {
     pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
         match *visibility {
             hir::Public => Visibility::Public,
-            hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID),
-            hir::Visibility::Restricted { id, .. } => match tcx.expect_def(id) {
+            hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
+            hir::Visibility::Restricted { ref path, .. } => match path.def {
                 // If there is no resolution, `resolve` will have already reported an error, so
                 // assume that the visibility is public to avoid reporting more privacy errors.
                 Def::Err => Visibility::Public,
-                def => Visibility::Restricted(tcx.map.as_local_node_id(def.def_id()).unwrap()),
+                def => Visibility::Restricted(def.def_id()),
             },
-            hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
+            hir::Inherited => {
+                Visibility::Restricted(tcx.hir.local_def_id(tcx.hir.get_module_parent(id)))
+            }
         }
     }
 
     /// Returns true if an item with this visibility is accessible from the given block.
-    pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
+    pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
         let restriction = match self {
             // Public items are visible everywhere.
             Visibility::Public => return true,
             // Private items from other crates are visible nowhere.
-            Visibility::PrivateExternal => return false,
+            Visibility::Invisible => return false,
             // Restricted items are visible in an arbitrary local module.
+            Visibility::Restricted(other) if other.krate != module.krate => return false,
             Visibility::Restricted(module) => module,
         };
 
-        tree.is_descendant_of(block, restriction)
+        tree.is_descendant_of(module, restriction)
     }
 
     /// Returns true if this visibility is at least as accessible as the given visibility
-    pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
+    pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
         let vis_restriction = match vis {
             Visibility::Public => return self == Visibility::Public,
-            Visibility::PrivateExternal => return true,
+            Visibility::Invisible => return true,
             Visibility::Restricted(module) => module,
         };
 
@@ -308,64 +290,6 @@ impl Visibility {
     }
 }
 
-#[derive(Clone, Debug)]
-pub struct Method<'tcx> {
-    pub name: Name,
-    pub generics: &'tcx Generics<'tcx>,
-    pub predicates: GenericPredicates<'tcx>,
-    pub fty: &'tcx BareFnTy<'tcx>,
-    pub explicit_self: ExplicitSelfCategory<'tcx>,
-    pub vis: Visibility,
-    pub defaultness: hir::Defaultness,
-    pub has_body: bool,
-    pub def_id: DefId,
-    pub container: ImplOrTraitItemContainer,
-}
-
-impl<'tcx> Method<'tcx> {
-    pub fn container_id(&self) -> DefId {
-        match self.container {
-            TraitContainer(id) => id,
-            ImplContainer(id) => id,
-        }
-    }
-}
-
-impl<'tcx> PartialEq for Method<'tcx> {
-    #[inline]
-    fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id }
-}
-
-impl<'tcx> Eq for Method<'tcx> {}
-
-impl<'tcx> Hash for Method<'tcx> {
-    #[inline]
-    fn hash<H: Hasher>(&self, s: &mut H) {
-        self.def_id.hash(s)
-    }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct AssociatedConst<'tcx> {
-    pub name: Name,
-    pub ty: Ty<'tcx>,
-    pub vis: Visibility,
-    pub defaultness: hir::Defaultness,
-    pub def_id: DefId,
-    pub container: ImplOrTraitItemContainer,
-    pub has_value: bool
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct AssociatedType<'tcx> {
-    pub name: Name,
-    pub ty: Option<Ty<'tcx>>,
-    pub vis: Visibility,
-    pub defaultness: hir::Defaultness,
-    pub def_id: DefId,
-    pub container: ImplOrTraitItemContainer,
-}
-
 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
 pub enum Variance {
     Covariant,      // T<A> <: T<B> iff A <: B -- e.g., function return type
@@ -394,7 +318,7 @@ pub struct MethodCallee<'tcx> {
 /// needed to add to the side tables. Thus to disambiguate
 /// we also keep track of whether there's an adjustment in
 /// our key.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct MethodCall {
     pub expr_id: NodeId,
     pub autoderef: u32
@@ -418,7 +342,7 @@ impl MethodCall {
 
 // maps from an expression id that corresponds to a method call to the details
 // of the method to be invoked
-pub type MethodMap<'tcx> = FnvHashMap<MethodCall, MethodCallee<'tcx>>;
+pub type MethodMap<'tcx> = FxHashMap<MethodCall, MethodCallee<'tcx>>;
 
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
@@ -574,7 +498,7 @@ impl<T> Slice<T> {
 /// Upvars do not get their own node-id. Instead, we use the pair of
 /// the original var id (that is, the root variable that is referenced
 /// by the upvar) and the id of the closure expression.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct UpvarId {
     pub var_id: NodeId,
     pub closure_expr_id: NodeId,
@@ -587,7 +511,7 @@ pub enum BorrowKind {
 
     /// Data must be immutable but not aliasable.  This kind of borrow
     /// cannot currently be expressed by the user and is used only in
-    /// implicit closure bindings. It is needed when you the closure
+    /// implicit closure bindings. It is needed when the closure
     /// is borrowing or mutating a mutable referent, e.g.:
     ///
     ///    let x: &mut isize = ...;
@@ -650,7 +574,7 @@ pub struct UpvarBorrow<'tcx> {
     pub region: &'tcx ty::Region,
 }
 
-pub type UpvarCaptureMap<'tcx> = FnvHashMap<UpvarId, UpvarCapture<'tcx>>;
+pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
 
 #[derive(Copy, Clone)]
 pub struct ClosureUpvar<'tcx> {
@@ -665,32 +589,13 @@ pub enum IntVarValue {
     UintType(ast::UintTy),
 }
 
-/// Default region to use for the bound of objects that are
-/// supplied as the value for this type parameter. This is derived
-/// from `T:'a` annotations appearing in the type definition.  If
-/// this is `None`, then the default is inherited from the
-/// surrounding context. See RFC #599 for details.
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
-pub enum ObjectLifetimeDefault<'tcx> {
-    /// Require an explicit annotation. Occurs when multiple
-    /// `T:'a` constraints are found.
-    Ambiguous,
-
-    /// Use the base default, typically 'static, but in a fn body it is a fresh variable
-    BaseDefault,
-
-    /// Use the given region as the default.
-    Specific(&'tcx Region),
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct TypeParameterDef<'tcx> {
+pub struct TypeParameterDef {
     pub name: Name,
     pub def_id: DefId,
     pub index: u32,
-    pub default_def_id: DefId, // for use in error reporing about defaults
-    pub default: Option<Ty<'tcx>>,
-    pub object_lifetime_default: ObjectLifetimeDefault<'tcx>,
+    pub has_default: bool,
+    pub object_lifetime_default: ObjectLifetimeDefault,
 
     /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
     /// on generic parameter `T`, asserts data behind the parameter
@@ -698,12 +603,12 @@ pub struct TypeParameterDef<'tcx> {
     pub pure_wrt_drop: bool,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct RegionParameterDef<'tcx> {
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+pub struct RegionParameterDef {
     pub name: Name,
     pub def_id: DefId,
     pub index: u32,
-    pub bounds: Vec<&'tcx ty::Region>,
+    pub issue_32330: Option<ty::Issue32330>,
 
     /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
     /// on generic parameter `'a`, asserts data of lifetime `'a`
@@ -711,11 +616,7 @@ pub struct RegionParameterDef<'tcx> {
     pub pure_wrt_drop: bool,
 }
 
-impl<'tcx> RegionParameterDef<'tcx> {
-    pub fn to_early_bound_region(&self) -> ty::Region {
-        ty::ReEarlyBound(self.to_early_bound_region_data())
-    }
-
+impl RegionParameterDef {
     pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
         ty::EarlyBoundRegion {
             index: self.index,
@@ -724,24 +625,28 @@ impl<'tcx> RegionParameterDef<'tcx> {
     }
 
     pub fn to_bound_region(&self) -> ty::BoundRegion {
-        // this is an early bound region, so unaffected by #32330
-        ty::BoundRegion::BrNamed(self.def_id, self.name, Issue32330::WontChange)
+        ty::BoundRegion::BrNamed(self.def_id, self.name)
     }
 }
 
 /// Information about the formal type/lifetime parameters associated
 /// with an item or method. Analogous to hir::Generics.
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct Generics<'tcx> {
+pub struct Generics {
     pub parent: Option<DefId>,
     pub parent_regions: u32,
     pub parent_types: u32,
-    pub regions: Vec<RegionParameterDef<'tcx>>,
-    pub types: Vec<TypeParameterDef<'tcx>>,
+    pub regions: Vec<RegionParameterDef>,
+    pub types: Vec<TypeParameterDef>,
+
+    /// Reverse map to each `TypeParameterDef`'s `index` field, from
+    /// `def_id.index` (`def_id.krate` is the same as the item's).
+    pub type_param_to_index: BTreeMap<DefIndex, u32>,
+
     pub has_self: bool,
 }
 
-impl<'tcx> Generics<'tcx> {
+impl Generics {
     pub fn parent_count(&self) -> usize {
         self.parent_regions as usize + self.parent_types as usize
     }
@@ -754,17 +659,19 @@ impl<'tcx> Generics<'tcx> {
         self.parent_count() + self.own_count()
     }
 
-    pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef<'tcx> {
+    pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
+        assert_eq!(self.parent_count(), 0);
         &self.regions[param.index as usize - self.has_self as usize]
     }
 
-    pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef<'tcx> {
+    pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
+        assert_eq!(self.parent_count(), 0);
         &self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
     }
 }
 
 /// Bounds on generics.
-#[derive(Clone)]
+#[derive(Clone, Default)]
 pub struct GenericPredicates<'tcx> {
     pub parent: Option<DefId>,
     pub predicates: Vec<Predicate<'tcx>>,
@@ -791,7 +698,7 @@ impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> {
                         instantiated: &mut InstantiatedPredicates<'tcx>,
                         substs: &Substs<'tcx>) {
         if let Some(def_id) = self.parent {
-            tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs);
+            tcx.item_predicates(def_id).instantiate_into(tcx, instantiated, substs);
         }
         instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
     }
@@ -946,27 +853,22 @@ impl<'tcx> TraitPredicate<'tcx> {
 
     /// Creates the dep-node for selecting/evaluating this trait reference.
     fn dep_node(&self) -> DepNode<DefId> {
-        // Ideally, the dep-node would just have all the input types
-        // in it.  But they are limited to including def-ids. So as an
-        // approximation we include the def-ids for all nominal types
-        // found somewhere. This means that we will e.g. conflate the
-        // dep-nodes for `u32: SomeTrait` and `u64: SomeTrait`, but we
-        // would have distinct dep-nodes for `Vec<u32>: SomeTrait`,
-        // `Rc<u32>: SomeTrait`, and `(Vec<u32>, Rc<u32>): SomeTrait`.
-        // Note that it's always sound to conflate dep-nodes, it just
-        // leads to more recompilation.
-        let def_ids: Vec<_> =
+        // Extact the trait-def and first def-id from inputs.  See the
+        // docs for `DepNode::TraitSelect` for more information.
+        let trait_def_id = self.def_id();
+        let input_def_id =
             self.input_types()
                 .flat_map(|t| t.walk())
                 .filter_map(|t| match t.sty {
-                    ty::TyAdt(adt_def, _) =>
-                        Some(adt_def.did),
-                    _ =>
-                        None
+                    ty::TyAdt(adt_def, _) => Some(adt_def.did),
+                    _ => None
                 })
-                .chain(iter::once(self.def_id()))
-                .collect();
-        DepNode::TraitSelect(def_ids)
+                .next()
+                .unwrap_or(trait_def_id);
+        DepNode::TraitSelect {
+            trait_def_id: trait_def_id,
+            input_def_id: input_def_id
+        }
     }
 
     pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
@@ -1195,24 +1097,6 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
     }
 }
 
-impl<'tcx> TraitRef<'tcx> {
-    pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
-        TraitRef { def_id: def_id, substs: substs }
-    }
-
-    pub fn self_ty(&self) -> Ty<'tcx> {
-        self.substs.type_at(0)
-    }
-
-    pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
-        // Select only the "input types" from a trait-reference. For
-        // now this is all the types that appear in the
-        // trait-reference, but it should eventually exclude
-        // associated types.
-        self.substs.types()
-    }
-}
-
 /// When type checking, we use the `ParameterEnvironment` to track
 /// details about the type/lifetime parameters that are in scope.
 /// It primarily stores the bounds information.
@@ -1251,10 +1135,10 @@ pub struct ParameterEnvironment<'tcx> {
     pub free_id_outlive: CodeExtent,
 
     /// A cache for `moves_by_default`.
-    pub is_copy_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
+    pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
 
     /// A cache for `type_is_sized`
-    pub is_sized_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
+    pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
 }
 
 impl<'a, 'tcx> ParameterEnvironment<'tcx> {
@@ -1267,92 +1151,73 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
             implicit_region_bound: self.implicit_region_bound,
             caller_bounds: caller_bounds,
             free_id_outlive: self.free_id_outlive,
-            is_copy_cache: RefCell::new(FnvHashMap()),
-            is_sized_cache: RefCell::new(FnvHashMap()),
+            is_copy_cache: RefCell::new(FxHashMap()),
+            is_sized_cache: RefCell::new(FxHashMap()),
         }
     }
 
     /// Construct a parameter environment given an item, impl item, or trait item
     pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
                     -> ParameterEnvironment<'tcx> {
-        match tcx.map.find(id) {
-            Some(ast_map::NodeImplItem(ref impl_item)) => {
+        match tcx.hir.find(id) {
+            Some(hir_map::NodeImplItem(ref impl_item)) => {
                 match impl_item.node {
                     hir::ImplItemKind::Type(_) | hir::ImplItemKind::Const(..) => {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the impl
-                        let impl_id = tcx.map.get_parent(id);
-                        let impl_def_id = tcx.map.local_def_id(impl_id);
+                        let impl_id = tcx.hir.get_parent(id);
+                        let impl_def_id = tcx.hir.local_def_id(impl_id);
                         tcx.construct_parameter_environment(impl_item.span,
                                                             impl_def_id,
                                                             tcx.region_maps.item_extent(id))
                     }
                     hir::ImplItemKind::Method(_, ref body) => {
-                        let method_def_id = tcx.map.local_def_id(id);
-                        match tcx.impl_or_trait_item(method_def_id) {
-                            MethodTraitItem(ref method_ty) => {
-                                tcx.construct_parameter_environment(
-                                    impl_item.span,
-                                    method_ty.def_id,
-                                    tcx.region_maps.call_site_extent(id, body.id))
-                            }
-                            _ => {
-                                bug!("ParameterEnvironment::for_item(): \
-                                      got non-method item from impl method?!")
-                            }
-                        }
+                        tcx.construct_parameter_environment(
+                            impl_item.span,
+                            tcx.hir.local_def_id(id),
+                            tcx.region_maps.call_site_extent(id, body.node_id))
                     }
                 }
             }
-            Some(ast_map::NodeTraitItem(trait_item)) => {
+            Some(hir_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
-                    hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => {
+                    hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the trait
-                        let trait_id = tcx.map.get_parent(id);
-                        let trait_def_id = tcx.map.local_def_id(trait_id);
+                        let trait_id = tcx.hir.get_parent(id);
+                        let trait_def_id = tcx.hir.local_def_id(trait_id);
                         tcx.construct_parameter_environment(trait_item.span,
                                                             trait_def_id,
                                                             tcx.region_maps.item_extent(id))
                     }
-                    hir::MethodTraitItem(_, ref body) => {
+                    hir::TraitItemKind::Method(_, ref body) => {
                         // Use call-site for extent (unless this is a
                         // trait method with no default; then fallback
                         // to the method id).
-                        let method_def_id = tcx.map.local_def_id(id);
-                        match tcx.impl_or_trait_item(method_def_id) {
-                            MethodTraitItem(ref method_ty) => {
-                                let extent = if let Some(ref body) = *body {
-                                    // default impl: use call_site extent as free_id_outlive bound.
-                                    tcx.region_maps.call_site_extent(id, body.id)
-                                } else {
-                                    // no default impl: use item extent as free_id_outlive bound.
-                                    tcx.region_maps.item_extent(id)
-                                };
-                                tcx.construct_parameter_environment(
-                                    trait_item.span,
-                                    method_ty.def_id,
-                                    extent)
-                            }
-                            _ => {
-                                bug!("ParameterEnvironment::for_item(): \
-                                      got non-method item from provided \
-                                      method?!")
-                            }
-                        }
+                        let extent = if let hir::TraitMethod::Provided(body_id) = *body {
+                            // default impl: use call_site extent as free_id_outlive bound.
+                            tcx.region_maps.call_site_extent(id, body_id.node_id)
+                        } else {
+                            // no default impl: use item extent as free_id_outlive bound.
+                            tcx.region_maps.item_extent(id)
+                        };
+                        tcx.construct_parameter_environment(
+                            trait_item.span,
+                            tcx.hir.local_def_id(id),
+                            extent)
                     }
                 }
             }
-            Some(ast_map::NodeItem(item)) => {
+            Some(hir_map::NodeItem(item)) => {
                 match item.node {
-                    hir::ItemFn(.., ref body) => {
+                    hir::ItemFn(.., body_id) => {
                         // We assume this is a function.
-                        let fn_def_id = tcx.map.local_def_id(id);
+                        let fn_def_id = tcx.hir.local_def_id(id);
 
                         tcx.construct_parameter_environment(
                             item.span,
                             fn_def_id,
-                            tcx.region_maps.call_site_extent(id, body.id))
+                            tcx.region_maps.call_site_extent(id, body_id.node_id))
                     }
                     hir::ItemEnum(..) |
                     hir::ItemStruct(..) |
@@ -1361,13 +1226,13 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
                     hir::ItemImpl(..) |
                     hir::ItemConst(..) |
                     hir::ItemStatic(..) => {
-                        let def_id = tcx.map.local_def_id(id);
+                        let def_id = tcx.hir.local_def_id(id);
                         tcx.construct_parameter_environment(item.span,
                                                             def_id,
                                                             tcx.region_maps.item_extent(id))
                     }
                     hir::ItemTrait(..) => {
-                        let def_id = tcx.map.local_def_id(id);
+                        let def_id = tcx.hir.local_def_id(id);
                         tcx.construct_parameter_environment(item.span,
                                                             def_id,
                                                             tcx.region_maps.item_extent(id))
@@ -1380,16 +1245,21 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
                     }
                 }
             }
-            Some(ast_map::NodeExpr(expr)) => {
+            Some(hir_map::NodeExpr(expr)) => {
                 // This is a convenience to allow closures to work.
-                if let hir::ExprClosure(..) = expr.node {
-                    ParameterEnvironment::for_item(tcx, tcx.map.get_parent(id))
+                if let hir::ExprClosure(.., body, _) = expr.node {
+                    let def_id = tcx.hir.local_def_id(id);
+                    let base_def_id = tcx.closure_base_def_id(def_id);
+                    tcx.construct_parameter_environment(
+                        expr.span,
+                        base_def_id,
+                        tcx.region_maps.call_site_extent(id, body.node_id))
                 } else {
                     tcx.empty_parameter_environment()
                 }
             }
-            Some(ast_map::NodeForeignItem(item)) => {
-                let def_id = tcx.map.local_def_id(id);
+            Some(hir_map::NodeForeignItem(item)) => {
+                let def_id = tcx.hir.local_def_id(id);
                 tcx.construct_parameter_environment(item.span,
                                                     def_id,
                                                     ROOT_CODE_EXTENT)
@@ -1397,168 +1267,182 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
             _ => {
                 bug!("ParameterEnvironment::from_item(): \
                       `{}` is not an item",
-                     tcx.map.node_to_string(id))
+                     tcx.hir.node_to_string(id))
             }
         }
     }
 }
 
-/// A "type scheme", in ML terminology, is a type combined with some
-/// set of generic types that the type is, well, generic over. In Rust
-/// terms, it is the "type" of a fn item or struct -- this type will
-/// include various generic parameters that must be substituted when
-/// the item/struct is referenced. That is called converting the type
-/// scheme to a monotype.
-///
-/// - `generics`: the set of type parameters and their bounds
-/// - `ty`: the base types, which may reference the parameters defined
-///   in `generics`
-///
-/// Note that TypeSchemes are also sometimes called "polytypes" (and
-/// in fact this struct used to carry that name, so you may find some
-/// stray references in a comment or something). We try to reserve the
-/// "poly" prefix to refer to higher-ranked things, as in
-/// `PolyTraitRef`.
-///
-/// Note that each item also comes with predicates, see
-/// `lookup_predicates`.
-#[derive(Clone, Debug)]
-pub struct TypeScheme<'tcx> {
-    pub generics: &'tcx Generics<'tcx>,
-    pub ty: Ty<'tcx>,
+#[derive(Copy, Clone, Debug)]
+pub struct Destructor {
+    /// The def-id of the destructor method
+    pub did: DefId,
+    /// Invoking the destructor of a dtorck type during usual cleanup
+    /// (e.g. the glue emitted for stack unwinding) requires all
+    /// lifetimes in the type-structure of `adt` to strictly outlive
+    /// the adt value itself.
+    ///
+    /// If `adt` is not dtorck, then the adt's destructor can be
+    /// invoked even when there are lifetimes in the type-structure of
+    /// `adt` that do not strictly outlive the adt value itself.
+    /// (This allows programs to make cyclic structures without
+    /// resorting to unsafe means; see RFCs 769 and 1238).
+    pub is_dtorck: bool,
 }
 
 bitflags! {
     flags AdtFlags: u32 {
         const NO_ADT_FLAGS        = 0,
         const IS_ENUM             = 1 << 0,
-        const IS_DTORCK           = 1 << 1, // is this a dtorck type?
-        const IS_DTORCK_VALID     = 1 << 2,
-        const IS_PHANTOM_DATA     = 1 << 3,
-        const IS_SIMD             = 1 << 4,
-        const IS_FUNDAMENTAL      = 1 << 5,
-        const IS_UNION            = 1 << 6,
+        const IS_PHANTOM_DATA     = 1 << 1,
+        const IS_FUNDAMENTAL      = 1 << 2,
+        const IS_UNION            = 1 << 3,
+        const IS_BOX              = 1 << 4,
     }
 }
 
-pub type AdtDef<'tcx> = &'tcx AdtDefData<'tcx, 'static>;
-pub type VariantDef<'tcx> = &'tcx VariantDefData<'tcx, 'static>;
-pub type FieldDef<'tcx> = &'tcx FieldDefData<'tcx, 'static>;
-
-// See comment on AdtDefData for explanation
-pub type AdtDefMaster<'tcx> = &'tcx AdtDefData<'tcx, 'tcx>;
-pub type VariantDefMaster<'tcx> = &'tcx VariantDefData<'tcx, 'tcx>;
-pub type FieldDefMaster<'tcx> = &'tcx FieldDefData<'tcx, 'tcx>;
-
-pub struct VariantDefData<'tcx, 'container: 'tcx> {
+#[derive(Debug)]
+pub struct VariantDef {
     /// The variant's DefId. If this is a tuple-like struct,
     /// this is the DefId of the struct's ctor.
     pub did: DefId,
     pub name: Name, // struct's name if this is a struct
-    pub disr_val: Disr,
-    pub fields: Vec<FieldDefData<'tcx, 'container>>,
+    pub discr: VariantDiscr,
+    pub fields: Vec<FieldDef>,
     pub ctor_kind: CtorKind,
 }
 
-pub struct FieldDefData<'tcx, 'container: 'tcx> {
-    /// The field's DefId. NOTE: the fields of tuple-like enum variants
-    /// are not real items, and don't have entries in tcache etc.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+pub enum VariantDiscr {
+    /// Explicit value for this variant, i.e. `X = 123`.
+    /// The `DefId` corresponds to the embedded constant.
+    Explicit(DefId),
+
+    /// The previous variant's discriminant plus one.
+    /// For efficiency reasons, the distance from the
+    /// last `Explicit` discriminant is being stored,
+    /// or `0` for the first variant, if it has none.
+    Relative(usize),
+}
+
+#[derive(Debug)]
+pub struct FieldDef {
     pub did: DefId,
     pub name: Name,
     pub vis: Visibility,
-    /// TyIVar is used here to allow for variance (see the doc at
-    /// AdtDefData).
-    ///
-    /// Note: direct accesses to `ty` must also add dep edges.
-    ty: ivar::TyIVar<'tcx, 'container>
 }
 
 /// The definition of an abstract data type - a struct or enum.
 ///
 /// These are all interned (by intern_adt_def) into the adt_defs
 /// table.
-///
-/// Because of the possibility of nested tcx-s, this type
-/// needs 2 lifetimes: the traditional variant lifetime ('tcx)
-/// bounding the lifetime of the inner types is of course necessary.
-/// However, it is not sufficient - types from a child tcx must
-/// not be leaked into the master tcx by being stored in an AdtDefData.
-///
-/// The 'container lifetime ensures that by outliving the container
-/// tcx and preventing shorter-lived types from being inserted. When
-/// write access is not needed, the 'container lifetime can be
-/// erased to 'static, which can be done by the AdtDef wrapper.
-pub struct AdtDefData<'tcx, 'container: 'tcx> {
+pub struct AdtDef {
     pub did: DefId,
-    pub variants: Vec<VariantDefData<'tcx, 'container>>,
-    destructor: Cell<Option<DefId>>,
-    flags: Cell<AdtFlags>,
-    sized_constraint: ivar::TyIVar<'tcx, 'container>,
+    pub variants: Vec<VariantDef>,
+    flags: AdtFlags,
+    pub repr: ReprOptions,
 }
 
-impl<'tcx, 'container> PartialEq for AdtDefData<'tcx, 'container> {
-    // AdtDefData are always interned and this is part of TyS equality
+impl PartialEq for AdtDef {
+    // AdtDef are always interned and this is part of TyS equality
     #[inline]
     fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
 }
 
-impl<'tcx, 'container> Eq for AdtDefData<'tcx, 'container> {}
+impl Eq for AdtDef {}
 
-impl<'tcx, 'container> Hash for AdtDefData<'tcx, 'container> {
+impl Hash for AdtDef {
     #[inline]
     fn hash<H: Hasher>(&self, s: &mut H) {
-        (self as *const AdtDefData).hash(s)
+        (self as *const AdtDef).hash(s)
     }
 }
 
-impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> {
+impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef {
     fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         self.did.encode(s)
     }
 }
 
-impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum AdtKind { Struct, Union, Enum }
 
-impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
-    fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+/// Represents the repr options provided by the user,
+#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
+pub struct ReprOptions {
+    pub c: bool,
+    pub packed: bool,
+    pub simd: bool,
+    pub int: Option<attr::IntType>,
+}
+
+impl ReprOptions {
+    pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
+        let mut ret = ReprOptions::default();
+
+        for attr in tcx.get_attrs(did).iter() {
+            for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
+                match r {
+                    attr::ReprExtern => ret.c = true,
+                    attr::ReprPacked => ret.packed = true,
+                    attr::ReprSimd => ret.simd = true,
+                    attr::ReprInt(i) => ret.int = Some(i),
+                }
+            }
+        }
+
+        // FIXME(eddyb) This is deprecated and should be removed.
+        if tcx.has_attr(did, "simd") {
+            ret.simd = true;
+        }
+
+        ret
+    }
+
+    pub fn discr_type(&self) -> attr::IntType {
+        self.int.unwrap_or(attr::SignedInt(ast::IntTy::Is))
+    }
+
+    /// Returns true if this `#[repr()]` should inhabit "smart enum
+    /// layout" optimizations, such as representing `Foo<&T>` as a
+    /// single pointer.
+    pub fn inhibit_enum_layout_opt(&self) -> bool {
+        self.c || self.int.is_some()
+    }
+}
+
+impl<'a, 'gcx, 'tcx> AdtDef {
+    fn new(tcx: TyCtxt,
            did: DefId,
            kind: AdtKind,
-           variants: Vec<VariantDefData<'gcx, 'container>>) -> Self {
+           variants: Vec<VariantDef>,
+           repr: ReprOptions) -> Self {
         let mut flags = AdtFlags::NO_ADT_FLAGS;
         let attrs = tcx.get_attrs(did);
         if attr::contains_name(&attrs, "fundamental") {
             flags = flags | AdtFlags::IS_FUNDAMENTAL;
         }
-        if tcx.lookup_simd(did) {
-            flags = flags | AdtFlags::IS_SIMD;
-        }
         if Some(did) == tcx.lang_items.phantom_data() {
             flags = flags | AdtFlags::IS_PHANTOM_DATA;
         }
+        if Some(did) == tcx.lang_items.owned_box() {
+            flags = flags | AdtFlags::IS_BOX;
+        }
         match kind {
             AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
             AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
             AdtKind::Struct => {}
         }
-        AdtDefData {
+        AdtDef {
             did: did,
             variants: variants,
-            flags: Cell::new(flags),
-            destructor: Cell::new(None),
-            sized_constraint: ivar::TyIVar::new(),
+            flags: flags,
+            repr: repr,
         }
     }
 
-    fn calculate_dtorck(&'gcx self, tcx: TyCtxt) {
-        if tcx.is_adt_dtorck(self) {
-            self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK);
-        }
-        self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK_VALID)
-    }
-
     #[inline]
     pub fn is_struct(&self) -> bool {
         !self.is_union() && !self.is_enum()
@@ -1566,12 +1450,12 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
 
     #[inline]
     pub fn is_union(&self) -> bool {
-        self.flags.get().intersects(AdtFlags::IS_UNION)
+        self.flags.intersects(AdtFlags::IS_UNION)
     }
 
     #[inline]
     pub fn is_enum(&self) -> bool {
-        self.flags.get().intersects(AdtFlags::IS_ENUM)
+        self.flags.intersects(AdtFlags::IS_ENUM)
     }
 
     /// Returns the kind of the ADT - Struct or Enum.
@@ -1607,68 +1491,50 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
     /// alive; Otherwise, only the contents are required to be.
     #[inline]
     pub fn is_dtorck(&'gcx self, tcx: TyCtxt) -> bool {
-        if !self.flags.get().intersects(AdtFlags::IS_DTORCK_VALID) {
-            self.calculate_dtorck(tcx)
-        }
-        self.flags.get().intersects(AdtFlags::IS_DTORCK)
+        self.destructor(tcx).map_or(false, |d| d.is_dtorck)
     }
 
     /// Returns whether this type is #[fundamental] for the purposes
     /// of coherence checking.
     #[inline]
     pub fn is_fundamental(&self) -> bool {
-        self.flags.get().intersects(AdtFlags::IS_FUNDAMENTAL)
+        self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
     }
 
+    /// Returns true if this is PhantomData<T>.
     #[inline]
-    pub fn is_simd(&self) -> bool {
-        self.flags.get().intersects(AdtFlags::IS_SIMD)
+    pub fn is_phantom_data(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
     }
 
-    /// Returns true if this is PhantomData<T>.
+    /// Returns true if this is Box<T>.
     #[inline]
-    pub fn is_phantom_data(&self) -> bool {
-        self.flags.get().intersects(AdtFlags::IS_PHANTOM_DATA)
+    pub fn is_box(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_BOX)
     }
 
     /// Returns whether this type has a destructor.
-    pub fn has_dtor(&self) -> bool {
-        self.dtor_kind().is_present()
+    pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+        self.destructor(tcx).is_some()
     }
 
     /// Asserts this is a struct and returns the struct's unique
     /// variant.
-    pub fn struct_variant(&self) -> &VariantDefData<'gcx, 'container> {
+    pub fn struct_variant(&self) -> &VariantDef {
         assert!(!self.is_enum());
         &self.variants[0]
     }
 
-    #[inline]
-    pub fn type_scheme(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> TypeScheme<'gcx> {
-        tcx.lookup_item_type(self.did)
-    }
-
     #[inline]
     pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> {
-        tcx.lookup_predicates(self.did)
+        tcx.item_predicates(self.did)
     }
 
     /// Returns an iterator over all fields contained
     /// by this ADT.
     #[inline]
-    pub fn all_fields(&self) ->
-            iter::FlatMap<
-                slice::Iter<VariantDefData<'gcx, 'container>>,
-                slice::Iter<FieldDefData<'gcx, 'container>>,
-                for<'s> fn(&'s VariantDefData<'gcx, 'container>)
-                    -> slice::Iter<'s, FieldDefData<'gcx, 'container>>
-            > {
-        self.variants.iter().flat_map(VariantDefData::fields_iter)
-    }
-
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.variants.is_empty()
+    pub fn all_fields<'s>(&'s self) -> impl Iterator<Item = &'s FieldDef> {
+        self.variants.iter().flat_map(|v| v.fields.iter())
     }
 
     #[inline]
@@ -1681,7 +1547,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
             self.variants.iter().all(|v| v.fields.is_empty())
     }
 
-    pub fn variant_with_id(&self, vid: DefId) -> &VariantDefData<'gcx, 'container> {
+    pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
         self.variants
             .iter()
             .find(|v| v.did == vid)
@@ -1695,7 +1561,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
             .expect("variant_index_with_id: unknown variant")
     }
 
-    pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> {
+    pub fn variant_of_def(&self, def: Def) -> &VariantDef {
         match def {
             Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
             Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
@@ -1704,23 +1570,31 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
         }
     }
 
-    pub fn destructor(&self) -> Option<DefId> {
-        self.destructor.get()
-    }
+    pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+                         -> impl Iterator<Item=ConstInt> + 'a {
+        let repr_type = self.repr.discr_type();
+        let initial = repr_type.initial_discriminant(tcx.global_tcx());
+        let mut prev_discr = None::<ConstInt>;
+        self.variants.iter().map(move |v| {
+            let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
+            if let VariantDiscr::Explicit(expr_did) = v.discr {
+                match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] {
+                    Ok(ConstVal::Integral(v)) => {
+                        discr = v;
+                    }
+                    _ => {}
+                }
+            }
+            prev_discr = Some(discr);
 
-    pub fn set_destructor(&self, dtor: DefId) {
-        self.destructor.set(Some(dtor));
+            discr
+        })
     }
 
-    pub fn dtor_kind(&self) -> DtorKind {
-        match self.destructor.get() {
-            Some(_) => TraitDtor,
-            None => NoDtor,
-        }
+    pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
+        queries::adt_destructor::get(tcx, DUMMY_SP, self.did)
     }
-}
 
-impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     /// Returns a simpler type such that `Self: Sized` if and only
     /// if that type is Sized, or `TyErr` if this type is recursive.
     ///
@@ -1739,19 +1613,9 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        match self.sized_constraint.get(DepNode::SizedConstraint(self.did)) {
-            None => {
-                let global_tcx = tcx.global_tcx();
-                let this = global_tcx.lookup_adt_def_master(self.did);
-                this.calculate_sized_constraint_inner(global_tcx, &mut Vec::new());
-                self.sized_constraint(tcx)
-            }
-            Some(ty) => ty
-        }
+        self.calculate_sized_constraint_inner(tcx.global_tcx(), &mut Vec::new())
     }
-}
 
-impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     /// Calculates the Sized-constraint.
     ///
     /// As the Sized-constraint of enums can be a *set* of types,
@@ -1767,81 +1631,82 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     ///       such.
     ///     - a TyError, if a type contained itself. The representability
     ///       check should catch this case.
-    fn calculate_sized_constraint_inner(&'tcx self,
+    fn calculate_sized_constraint_inner(&self,
                                         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        stack: &mut Vec<AdtDefMaster<'tcx>>)
+                                        stack: &mut Vec<DefId>)
+                                        -> Ty<'tcx>
     {
-        let dep_node = || DepNode::SizedConstraint(self.did);
+        if let Some(ty) = tcx.maps.adt_sized_constraint.borrow().get(&self.did) {
+            return ty;
+        }
 
         // Follow the memoization pattern: push the computation of
         // DepNode::SizedConstraint as our current task.
-        let _task = tcx.dep_graph.in_task(dep_node());
-        if self.sized_constraint.untracked_get().is_some() {
-            //                   ---------------
-            // can skip the dep-graph read since we just pushed the task
-            return;
-        }
+        let _task = tcx.dep_graph.in_task(DepNode::SizedConstraint(self.did));
 
-        if stack.contains(&self) {
+        if stack.contains(&self.did) {
             debug!("calculate_sized_constraint: {:?} is recursive", self);
             // This should be reported as an error by `check_representable`.
             //
             // Consider the type as Sized in the meanwhile to avoid
             // further errors.
-            self.sized_constraint.fulfill(dep_node(), tcx.types.err);
-            return;
+            tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err);
+            return tcx.types.err;
         }
 
-        stack.push(self);
+        stack.push(self.did);
 
         let tys : Vec<_> =
             self.variants.iter().flat_map(|v| {
                 v.fields.last()
             }).flat_map(|f| {
-                self.sized_constraint_for_ty(tcx, stack, f.unsubst_ty())
+                let ty = tcx.item_type(f.did);
+                self.sized_constraint_for_ty(tcx, stack, ty)
             }).collect();
 
         let self_ = stack.pop().unwrap();
-        assert_eq!(self_, self);
+        assert_eq!(self_, self.did);
 
         let ty = match tys.len() {
             _ if tys.references_error() => tcx.types.err,
             0 => tcx.types.bool,
             1 => tys[0],
-            _ => tcx.intern_tup(&tys[..])
+            _ => tcx.intern_tup(&tys[..], false)
         };
 
-        match self.sized_constraint.get(dep_node()) {
+        let old = tcx.maps.adt_sized_constraint.borrow().get(&self.did).cloned();
+        match old {
             Some(old_ty) => {
                 debug!("calculate_sized_constraint: {:?} recurred", self);
-                assert_eq!(old_ty, tcx.types.err)
+                assert_eq!(old_ty, tcx.types.err);
+                old_ty
             }
             None => {
                 debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
-                self.sized_constraint.fulfill(dep_node(), ty)
+                tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, ty);
+                ty
             }
         }
     }
 
-    fn sized_constraint_for_ty(
-        &'tcx self,
-        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        stack: &mut Vec<AdtDefMaster<'tcx>>,
-        ty: Ty<'tcx>
-    ) -> Vec<Ty<'tcx>> {
+    fn sized_constraint_for_ty(&self,
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               stack: &mut Vec<DefId>,
+                               ty: Ty<'tcx>)
+                               -> Vec<Ty<'tcx>> {
         let result = match ty.sty {
             TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-            TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
+            TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
             TyArray(..) | TyClosure(..) | TyNever => {
                 vec![]
             }
 
-            TyStr | TyTrait(..) | TySlice(_) | TyError => {
+            TyStr | TyDynamic(..) | TySlice(_) | TyError => {
                 // these are never sized - return the target type
                 vec![ty]
             }
 
-            TyTuple(ref tys) => {
+            TyTuple(ref tys, _) => {
                 match tys.last() {
                     None => vec![],
                     Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty)
@@ -1850,15 +1715,12 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
 
             TyAdt(adt, substs) => {
                 // recursive case
-                let adt = tcx.lookup_adt_def_master(adt.did);
-                adt.calculate_sized_constraint_inner(tcx, stack);
                 let adt_ty =
-                    adt.sized_constraint
-                    .unwrap(DepNode::SizedConstraint(adt.did))
-                    .subst(tcx, substs);
+                    adt.calculate_sized_constraint_inner(tcx, stack)
+                       .subst(tcx, substs);
                 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
                        ty, adt_ty);
-                if let ty::TyTuple(ref tys) = adt_ty.sty {
+                if let ty::TyTuple(ref tys, _) = adt_ty.sty {
                     tys.iter().flat_map(|ty| {
                         self.sized_constraint_for_ty(tcx, stack, ty)
                     }).collect()
@@ -1886,7 +1748,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
                     def_id: sized_trait,
                     substs: tcx.mk_substs_trait(ty, &[])
                 }).to_predicate();
-                let predicates = tcx.lookup_predicates(self.did).predicates;
+                let predicates = tcx.item_predicates(self.did).predicates;
                 if predicates.into_iter().any(|p| p == sized_predicate) {
                     vec![]
                 } else {
@@ -1904,16 +1766,11 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     }
 }
 
-impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
-    #[inline]
-    fn fields_iter(&self) -> slice::Iter<FieldDefData<'tcx, 'container>> {
-        self.fields.iter()
-    }
-
+impl<'a, 'gcx, 'tcx> VariantDef {
     #[inline]
     pub fn find_field_named(&self,
                             name: ast::Name)
-                            -> Option<&FieldDefData<'tcx, 'container>> {
+                            -> Option<&FieldDef> {
         self.fields.iter().find(|f| f.name == name)
     }
 
@@ -1925,33 +1782,14 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
     }
 
     #[inline]
-    pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> {
+    pub fn field_named(&self, name: ast::Name) -> &FieldDef {
         self.find_field_named(name).unwrap()
     }
 }
 
-impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
-    pub fn new(did: DefId,
-               name: Name,
-               vis: Visibility) -> Self {
-        FieldDefData {
-            did: did,
-            name: name,
-            vis: vis,
-            ty: ivar::TyIVar::new()
-        }
-    }
-
+impl<'a, 'gcx, 'tcx> FieldDef {
     pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
-        self.unsubst_ty().subst(tcx, subst)
-    }
-
-    pub fn unsubst_ty(&self) -> Ty<'tcx> {
-        self.ty.unwrap(DepNode::FieldTy(self.did))
-    }
-
-    pub fn fulfill_ty(&self, ty: Ty<'container>) {
-        self.ty.fulfill(DepNode::FieldTy(self.did), ty);
+        tcx.item_type(self.did).subst(tcx, subst)
     }
 }
 
@@ -1974,18 +1812,14 @@ pub enum ClosureKind {
 
 impl<'a, 'tcx> ClosureKind {
     pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId {
-        let result = match *self {
-            ClosureKind::Fn => tcx.lang_items.require(FnTraitLangItem),
+        match *self {
+            ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem),
             ClosureKind::FnMut => {
-                tcx.lang_items.require(FnMutTraitLangItem)
+                tcx.require_lang_item(FnMutTraitLangItem)
             }
             ClosureKind::FnOnce => {
-                tcx.lang_items.require(FnOnceTraitLangItem)
+                tcx.require_lang_item(FnOnceTraitLangItem)
             }
-        };
-        match result {
-            Ok(trait_did) => trait_did,
-            Err(err) => tcx.sess.fatal(&err[..]),
         }
     }
 
@@ -2022,7 +1856,7 @@ impl<'tcx> TyS<'tcx> {
     /// Iterator that walks the immediate children of `self`.  Hence
     /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
     /// (but not `i32`, like `walk`).
-    pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
+    pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> {
         walk::walk_shallow(self)
     }
 
@@ -2064,28 +1898,6 @@ impl LvaluePreference {
     }
 }
 
-/// Helper for looking things up in the various maps that are populated during
-/// typeck::collect (e.g., `tcx.impl_or_trait_items`, `tcx.tcache`, etc).  All of
-/// these share the pattern that if the id is local, it should have been loaded
-/// into the map by the `typeck::collect` phase.  If the def-id is external,
-/// then we have to go consult the crate loading code (and cache the result for
-/// the future).
-fn lookup_locally_or_in_crate_store<M, F>(descr: &str,
-                                          def_id: DefId,
-                                          map: &M,
-                                          load_external: F)
-                                          -> M::Value where
-    M: MemoizationMap<Key=DefId>,
-    F: FnOnce() -> M::Value,
-{
-    map.memoize(def_id, || {
-        if def_id.is_local() {
-            bug!("No def'n found for {:?} in tcx.{}", def_id, descr);
-        }
-        load_external()
-    })
-}
-
 impl BorrowKind {
     pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
         match m {
@@ -2120,13 +1932,17 @@ impl BorrowKind {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn tables(self) -> Ref<'a, Tables<'gcx>> {
-        self.tables.borrow()
+    pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
+        self.item_tables(self.hir.body_owner_def_id(body))
+    }
+
+    pub fn item_tables(self, def_id: DefId) -> &'gcx TypeckTables<'gcx> {
+        queries::typeck_tables::get(self, DUMMY_SP, def_id)
     }
 
     pub fn expr_span(self, id: NodeId) -> Span {
-        match self.map.find(id) {
-            Some(ast_map::NodeExpr(e)) => {
+        match self.hir.find(id) {
+            Some(hir_map::NodeExpr(e)) => {
                 e.span
             }
             Some(f) => {
@@ -2139,10 +1955,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn local_var_name_str(self, id: NodeId) -> InternedString {
-        match self.map.find(id) {
-            Some(ast_map::NodeLocal(pat)) => {
+        match self.hir.find(id) {
+            Some(hir_map::NodeLocal(pat)) => {
                 match pat.node {
-                    hir::PatKind::Binding(_, ref path1, _) => path1.node.as_str(),
+                    hir::PatKind::Binding(_, _, ref path1, _) => path1.node.as_str(),
                     _ => {
                         bug!("Variable id {} maps to {:?}, not local", id, pat);
                     },
@@ -2154,11 +1970,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
          match expr.node {
-            hir::ExprPath(..) => {
-                // This function can be used during type checking when not all paths are
-                // fully resolved. Partially resolved paths in expressions can only legally
-                // refer to associated items which are always rvalues.
-                match self.expect_resolution(expr.id).base_def {
+            hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
+                match path.def {
                     Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
                     _ => false,
                 }
@@ -2175,6 +1988,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 true
             }
 
+            // Partially qualified paths in expressions can only legally
+            // refer to associated items which are always rvalues.
+            hir::ExprPath(hir::QPath::TypeRelative(..)) |
+
             hir::ExprCall(..) |
             hir::ExprMethodCall(..) |
             hir::ExprStruct(..) |
@@ -2204,18 +2021,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn provided_trait_methods(self, id: DefId) -> Vec<Rc<Method<'gcx>>> {
-        self.impl_or_trait_items(id).iter().filter_map(|&def_id| {
-            match self.impl_or_trait_item(def_id) {
-                MethodTraitItem(ref m) if m.has_body => Some(m.clone()),
-                _ => None
-            }
-        }).collect()
+    pub fn provided_trait_methods(self, id: DefId) -> Vec<AssociatedItem> {
+        self.associated_items(id)
+            .filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value())
+            .collect()
     }
 
     pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
-        if let Some(id) = self.map.as_local_node_id(id) {
-            match self.map.expect_item(id).node {
+        if let Some(id) = self.hir.as_local_node_id(id) {
+            match self.hir.expect_item(id).node {
                 hir::ItemImpl(_, polarity, ..) => polarity,
                 ref item => bug!("trait_impl_polarity: {:?} not an impl", item)
             }
@@ -2224,65 +2038,164 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    pub fn trait_relevant_for_never(self, did: DefId) -> bool {
+        self.associated_items(did).any(|item| {
+            item.relevant_for_never()
+        })
+    }
+
     pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
-        self.custom_coerce_unsized_kinds.memoize(did, || {
-            let (kind, src) = if did.krate != LOCAL_CRATE {
-                (self.sess.cstore.custom_coerce_unsized_kind(did), "external")
-            } else {
-                (None, "local")
-            };
+        queries::custom_coerce_unsized_kind::get(self, DUMMY_SP, did)
+    }
+
+    pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
+        if !def_id.is_local() {
+            return queries::associated_item::get(self, DUMMY_SP, def_id);
+        }
+
+        self.maps.associated_item.memoize(def_id, || {
+            // When the user asks for a given associated item, we
+            // always go ahead and convert all the associated items in
+            // the container. Note that we are also careful only to
+            // ever register a read on the *container* of the assoc
+            // item, not the assoc item itself. This prevents changes
+            // in the details of an item (for example, the type to
+            // which an associated type is bound) from contaminating
+            // those tasks that just need to scan the names of items
+            // and so forth.
+
+            let id = self.hir.as_local_node_id(def_id).unwrap();
+            let parent_id = self.hir.get_parent(id);
+            let parent_def_id = self.hir.local_def_id(parent_id);
+            let parent_item = self.hir.expect_item(parent_id);
+            match parent_item.node {
+                hir::ItemImpl(.., ref impl_trait_ref, _, ref impl_item_refs) => {
+                    for impl_item_ref in impl_item_refs {
+                        let assoc_item =
+                            self.associated_item_from_impl_item_ref(parent_def_id,
+                                                                    impl_trait_ref.is_some(),
+                                                                    impl_item_ref);
+                        self.maps.associated_item.borrow_mut()
+                            .insert(assoc_item.def_id, assoc_item);
+                    }
+                }
+
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    for trait_item_ref in trait_item_refs {
+                        let assoc_item =
+                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
+                        self.maps.associated_item.borrow_mut()
+                            .insert(assoc_item.def_id, assoc_item);
+                    }
+                }
 
-            match kind {
-                Some(kind) => kind,
-                None => {
-                    bug!("custom_coerce_unsized_kind: \
-                          {} impl `{}` is missing its kind",
-                          src, self.item_path_str(did));
+                ref r => {
+                    panic!("unexpected container of associated items: {:?}", r)
                 }
             }
+
+            // memoize wants us to return something, so return
+            // the one we generated for this def-id
+            *self.maps.associated_item.borrow().get(&def_id).unwrap()
         })
     }
 
-    pub fn impl_or_trait_item(self, id: DefId) -> ImplOrTraitItem<'gcx> {
-        lookup_locally_or_in_crate_store(
-            "impl_or_trait_items", id, &self.impl_or_trait_items,
-            || self.sess.cstore.impl_or_trait_item(self.global_tcx(), id)
-                   .expect("missing ImplOrTraitItem in metadata"))
-    }
+    fn associated_item_from_trait_item_ref(self,
+                                           parent_def_id: DefId,
+                                           trait_item_ref: &hir::TraitItemRef)
+                                           -> AssociatedItem {
+        let def_id = self.hir.local_def_id(trait_item_ref.id.node_id);
+        let (kind, has_self) = match trait_item_ref.kind {
+            hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+            hir::AssociatedItemKind::Method { has_self } => {
+                (ty::AssociatedKind::Method, has_self)
+            }
+            hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
+        };
 
-    pub fn impl_or_trait_items(self, id: DefId) -> Rc<Vec<DefId>> {
-        lookup_locally_or_in_crate_store(
-            "impl_or_trait_items", id, &self.impl_or_trait_item_def_ids,
-            || Rc::new(self.sess.cstore.impl_or_trait_items(id)))
-    }
+        AssociatedItem {
+            name: trait_item_ref.name,
+            kind: kind,
+            vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self),
+            defaultness: trait_item_ref.defaultness,
+            def_id: def_id,
+            container: TraitContainer(parent_def_id),
+            method_has_self_argument: has_self
+        }
+    }
+
+    fn associated_item_from_impl_item_ref(self,
+                                          parent_def_id: DefId,
+                                          from_trait_impl: bool,
+                                          impl_item_ref: &hir::ImplItemRef)
+                                          -> AssociatedItem {
+        let def_id = self.hir.local_def_id(impl_item_ref.id.node_id);
+        let (kind, has_self) = match impl_item_ref.kind {
+            hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+            hir::AssociatedItemKind::Method { has_self } => {
+                (ty::AssociatedKind::Method, has_self)
+            }
+            hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
+        };
 
-    /// Returns the trait-ref corresponding to a given impl, or None if it is
-    /// an inherent impl.
-    pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
-        lookup_locally_or_in_crate_store(
-            "impl_trait_refs", id, &self.impl_trait_refs,
-            || self.sess.cstore.impl_trait_ref(self.global_tcx(), id))
+        // Trait impl items are always public.
+        let public = hir::Public;
+        let vis = if from_trait_impl { &public } else { &impl_item_ref.vis };
+
+        ty::AssociatedItem {
+            name: impl_item_ref.name,
+            kind: kind,
+            vis: ty::Visibility::from_hir(vis, impl_item_ref.id.node_id, self),
+            defaultness: impl_item_ref.defaultness,
+            def_id: def_id,
+            container: ImplContainer(parent_def_id),
+            method_has_self_argument: has_self
+        }
     }
 
-    /// Returns a path resolution for node id if it exists, panics otherwise.
-    pub fn expect_resolution(self, id: NodeId) -> PathResolution {
-        *self.def_map.borrow().get(&id).expect("no def-map entry for node id")
+    pub fn associated_item_def_ids(self, def_id: DefId) -> Rc<Vec<DefId>> {
+        if !def_id.is_local() {
+            return queries::associated_item_def_ids::get(self, DUMMY_SP, def_id);
+        }
+
+        self.maps.associated_item_def_ids.memoize(def_id, || {
+            let id = self.hir.as_local_node_id(def_id).unwrap();
+            let item = self.hir.expect_item(id);
+            let vec: Vec<_> = match item.node {
+                hir::ItemTrait(.., ref trait_item_refs) => {
+                    trait_item_refs.iter()
+                                   .map(|trait_item_ref| trait_item_ref.id)
+                                   .map(|id| self.hir.local_def_id(id.node_id))
+                                   .collect()
+                }
+                hir::ItemImpl(.., ref impl_item_refs) => {
+                    impl_item_refs.iter()
+                                  .map(|impl_item_ref| impl_item_ref.id)
+                                  .map(|id| self.hir.local_def_id(id.node_id))
+                                  .collect()
+                }
+                _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
+            };
+            Rc::new(vec)
+        })
     }
 
-    /// Returns a fully resolved definition for node id if it exists, panics otherwise.
-    pub fn expect_def(self, id: NodeId) -> Def {
-        self.expect_resolution(id).full_def()
+    #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
+    pub fn associated_items(self, def_id: DefId)
+                            -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+        let def_ids = self.associated_item_def_ids(def_id);
+        (0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
     }
 
-    /// Returns a fully resolved definition for node id if it exists, or none if no
-    /// definition exists, panics on partial resolutions to catch errors.
-    pub fn expect_def_or_none(self, id: NodeId) -> Option<Def> {
-        self.def_map.borrow().get(&id).map(|resolution| resolution.full_def())
+    /// Returns the trait-ref corresponding to a given impl, or None if it is
+    /// an inherent impl.
+    pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
+        queries::impl_trait_ref::get(self, DUMMY_SP, id)
     }
 
     // Returns `ty::VariantDef` if `def` refers to a struct,
     // or variant or their constructors, panics otherwise.
-    pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {
+    pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
         match def {
             Def::Variant(did) | Def::VariantCtor(did, ..) => {
                 let enum_did = self.parent_def_id(did).unwrap();
@@ -2299,9 +2212,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn def_key(self, id: DefId) -> ast_map::DefKey {
+    pub fn def_key(self, id: DefId) -> hir_map::DefKey {
         if id.is_local() {
-            self.map.def_key(id)
+            self.hir.def_key(id)
         } else {
             self.sess.cstore.def_key(id)
         }
@@ -2310,52 +2223,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// Convert a `DefId` into its fully expanded `DefPath` (every
     /// `DefId` is really just an interned def-path).
     ///
-    /// Note that if `id` is not local to this crate -- or is
-    /// inlined into this crate -- the result will be a non-local
-    /// `DefPath`.
-    ///
-    /// This function is only safe to use when you are sure that the
-    /// full def-path is accessible. Examples that are known to be
-    /// safe are local def-ids or items; see `opt_def_path` for more
-    /// details.
-    pub fn def_path(self, id: DefId) -> ast_map::DefPath {
-        self.opt_def_path(id).unwrap_or_else(|| {
-            bug!("could not load def-path for {:?}", id)
-        })
+    /// Note that if `id` is not local to this crate, the result will
+    //  be a non-local `DefPath`.
+    pub fn def_path(self, id: DefId) -> hir_map::DefPath {
+        if id.is_local() {
+            self.hir.def_path(id)
+        } else {
+            self.sess.cstore.def_path(id)
+        }
     }
 
-    /// Convert a `DefId` into its fully expanded `DefPath` (every
-    /// `DefId` is really just an interned def-path).
-    ///
-    /// When going across crates, we do not save the full info for
-    /// every cross-crate def-id, and hence we may not always be able
-    /// to create a def-path. Therefore, this returns
-    /// `Option<DefPath>` to cover that possibility. It will always
-    /// return `Some` for local def-ids, however, as well as for
-    /// items. The problems arise with "minor" def-ids like those
-    /// associated with a pattern, `impl Trait`, or other internal
-    /// detail to a fn.
-    ///
-    /// Note that if `id` is not local to this crate -- or is
-    /// inlined into this crate -- the result will be a non-local
-    /// `DefPath`.
-    pub fn opt_def_path(self, id: DefId) -> Option<ast_map::DefPath> {
-        if id.is_local() {
-            Some(self.map.def_path(id))
+    pub fn def_span(self, def_id: DefId) -> Span {
+        if let Some(id) = self.hir.as_local_node_id(def_id) {
+            self.hir.span(id)
         } else {
-            self.sess.cstore.relative_def_path(id)
+            self.sess.cstore.def_span(&self.sess, def_id)
         }
     }
 
+    pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
+        vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self)
+    }
+
     pub fn item_name(self, id: DefId) -> ast::Name {
-        if let Some(id) = self.map.as_local_node_id(id) {
-            self.map.name(id)
+        if let Some(id) = self.hir.as_local_node_id(id) {
+            self.hir.name(id)
         } else if id.index == CRATE_DEF_INDEX {
-            token::intern(&self.sess.cstore.original_crate_name(id.krate))
+            self.sess.cstore.original_crate_name(id.krate)
         } else {
             let def_key = self.sess.cstore.def_key(id);
             // The name of a StructCtor is that of its struct parent.
-            if let ast_map::DefPathData::StructCtor = def_key.disambiguated_data.data {
+            if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data {
                 self.item_name(DefId {
                     krate: id.krate,
                     index: def_key.parent.unwrap()
@@ -2368,97 +2266,54 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    // Register a given item type
-    pub fn register_item_type(self, did: DefId, scheme: TypeScheme<'gcx>) {
-        self.tcache.borrow_mut().insert(did, scheme.ty);
-        self.generics.borrow_mut().insert(did, scheme.generics);
-    }
-
     // If the given item is in an external crate, looks up its type and adds it to
     // the type cache. Returns the type parameters and type.
-    pub fn lookup_item_type(self, did: DefId) -> TypeScheme<'gcx> {
-        let ty = lookup_locally_or_in_crate_store(
-            "tcache", did, &self.tcache,
-            || self.sess.cstore.item_type(self.global_tcx(), did));
-
-        TypeScheme {
-            ty: ty,
-            generics: self.lookup_generics(did)
-        }
-    }
-
-    pub fn opt_lookup_item_type(self, did: DefId) -> Option<TypeScheme<'gcx>> {
-        if did.krate != LOCAL_CRATE {
-            return Some(self.lookup_item_type(did));
-        }
-
-        if let Some(ty) = self.tcache.borrow().get(&did).cloned() {
-            Some(TypeScheme {
-                ty: ty,
-                generics: self.lookup_generics(did)
-            })
-        } else {
-            None
-        }
+    pub fn item_type(self, did: DefId) -> Ty<'gcx> {
+        queries::ty::get(self, DUMMY_SP, did)
     }
 
     /// Given the did of a trait, returns its canonical trait ref.
-    pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef<'gcx> {
-        lookup_locally_or_in_crate_store(
-            "trait_defs", did, &self.trait_defs,
-            || self.alloc_trait_def(self.sess.cstore.trait_def(self.global_tcx(), did))
-        )
-    }
-
-    /// Given the did of an ADT, return a master reference to its
-    /// definition. Unless you are planning on fulfilling the ADT's fields,
-    /// use lookup_adt_def instead.
-    pub fn lookup_adt_def_master(self, did: DefId) -> AdtDefMaster<'gcx> {
-        lookup_locally_or_in_crate_store(
-            "adt_defs", did, &self.adt_defs,
-            || self.sess.cstore.adt_def(self.global_tcx(), did)
-        )
+    pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef {
+        queries::trait_def::get(self, DUMMY_SP, did)
     }
 
     /// Given the did of an ADT, return a reference to its definition.
-    pub fn lookup_adt_def(self, did: DefId) -> AdtDef<'gcx> {
-        // when reverse-variance goes away, a transmute::<AdtDefMaster,AdtDef>
-        // would be needed here.
-        self.lookup_adt_def_master(did)
+    pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef {
+        queries::adt_def::get(self, DUMMY_SP, did)
     }
 
     /// Given the did of an item, returns its generics.
-    pub fn lookup_generics(self, did: DefId) -> &'gcx Generics<'gcx> {
-        lookup_locally_or_in_crate_store(
-            "generics", did, &self.generics,
-            || self.alloc_generics(self.sess.cstore.item_generics(self.global_tcx(), did)))
+    pub fn item_generics(self, did: DefId) -> &'gcx Generics {
+        queries::generics::get(self, DUMMY_SP, did)
     }
 
     /// Given the did of an item, returns its full set of predicates.
-    pub fn lookup_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
-        lookup_locally_or_in_crate_store(
-            "predicates", did, &self.predicates,
-            || self.sess.cstore.item_predicates(self.global_tcx(), did))
+    pub fn item_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
+        queries::predicates::get(self, DUMMY_SP, did)
     }
 
     /// Given the did of a trait, returns its superpredicates.
-    pub fn lookup_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
-        lookup_locally_or_in_crate_store(
-            "super_predicates", did, &self.super_predicates,
-            || self.sess.cstore.item_super_predicates(self.global_tcx(), did))
+    pub fn item_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
+        queries::super_predicates::get(self, DUMMY_SP, did)
     }
 
     /// Given the did of an item, returns its MIR, borrowed immutably.
     pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
-        lookup_locally_or_in_crate_store("mir_map", did, &self.mir_map, || {
-            let mir = self.sess.cstore.get_item_mir(self.global_tcx(), did);
-            let mir = self.alloc_mir(mir);
+        queries::mir::get(self, DUMMY_SP, did).borrow()
+    }
+
+    /// Given the DefId of an item, returns its MIR, borrowed immutably.
+    /// Returns None if there is no MIR for the DefId
+    pub fn maybe_item_mir(self, did: DefId) -> Option<Ref<'gcx, Mir<'gcx>>> {
+        if did.is_local() && !self.maps.mir.borrow().contains_key(&did) {
+            return None;
+        }
 
-            // Perma-borrow MIR from extern crates to prevent mutation.
-            mem::forget(mir.borrow());
+        if !did.is_local() && !self.sess.cstore.is_item_mir_available(did) {
+            return None;
+        }
 
-            mir
-        }).borrow()
+        Some(self.item_mir(did))
     }
 
     /// If `type_needs_drop` returns true, then `ty` is definitely
@@ -2497,8 +2352,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     /// Get the attributes of a definition.
     pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
-        if let Some(id) = self.map.as_local_node_id(did) {
-            Cow::Borrowed(self.map.attrs(id))
+        if let Some(id) = self.hir.as_local_node_id(did) {
+            Cow::Borrowed(self.hir.attrs(id))
         } else {
             Cow::Owned(self.sess.cstore.item_attrs(did))
         }
@@ -2509,66 +2364,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.get_attrs(did).iter().any(|item| item.check_name(attr))
     }
 
-    /// Determine whether an item is annotated with `#[repr(packed)]`
-    pub fn lookup_packed(self, did: DefId) -> bool {
-        self.lookup_repr_hints(did).contains(&attr::ReprPacked)
-    }
-
-    /// Determine whether an item is annotated with `#[simd]`
-    pub fn lookup_simd(self, did: DefId) -> bool {
-        self.has_attr(did, "simd")
-            || self.lookup_repr_hints(did).contains(&attr::ReprSimd)
-    }
-
     pub fn item_variances(self, item_id: DefId) -> Rc<Vec<ty::Variance>> {
-        lookup_locally_or_in_crate_store(
-            "item_variance_map", item_id, &self.item_variance_map,
-            || Rc::new(self.sess.cstore.item_variances(item_id)))
+        queries::variances::get(self, DUMMY_SP, item_id)
     }
 
     pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
-        self.populate_implementations_for_trait_if_necessary(trait_def_id);
-
         let def = self.lookup_trait_def(trait_def_id);
         def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
     }
 
-    /// Records a trait-to-implementation mapping.
-    pub fn record_trait_has_default_impl(self, trait_def_id: DefId) {
-        let def = self.lookup_trait_def(trait_def_id);
-        def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
-    }
-
-    /// Load primitive inherent implementations if necessary
-    pub fn populate_implementations_for_primitive_if_necessary(self,
-                                                               primitive_def_id: DefId) {
-        if primitive_def_id.is_local() {
-            return
-        }
-
-        // The primitive is not local, hence we are reading this out
-        // of metadata.
-        let _ignore = self.dep_graph.in_ignore();
-
-        if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
-            return
-        }
-
-        debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
-               primitive_def_id);
-
-        let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id);
-
-        // Store the implementation info.
-        self.impl_or_trait_item_def_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items));
-        self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
-    }
-
     /// Populates the type context with all the inherent implementations for
     /// the given type if necessary.
     pub fn populate_inherent_implementations_for_type_if_necessary(self,
+                                                                   span: Span,
                                                                    type_id: DefId) {
         if type_id.is_local() {
+            // Make sure coherence of inherent impls ran already.
+            ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
             return
         }
 
@@ -2584,13 +2396,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                type_id);
 
         let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
-        for &impl_def_id in &inherent_impls {
-            // Store the implementation info.
-            let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
-            self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
-        }
 
-        self.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
+        self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
         self.populated_external_types.borrow_mut().insert(type_id);
     }
 
@@ -2606,67 +2413,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         let _ignore = self.dep_graph.in_ignore();
 
         let def = self.lookup_trait_def(trait_id);
-        if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
+        if def.flags.get().intersects(TraitFlags::HAS_REMOTE_IMPLS) {
             return;
         }
 
         debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
 
-        if self.sess.cstore.is_defaulted_trait(trait_id) {
-            self.record_trait_has_default_impl(trait_id);
-        }
-
         for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
-            let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
             let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
 
             // Record the trait->implementation mapping.
             let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id);
             def.record_remote_impl(self, impl_def_id, trait_ref, parent);
-
-            // For any methods that use a default implementation, add them to
-            // the map. This is a bit unfortunate.
-            for &impl_item_def_id in &impl_items {
-                // load impl items eagerly for convenience
-                // FIXME: we may want to load these lazily
-                self.impl_or_trait_item(impl_item_def_id);
-            }
-
-            // Store the implementation info.
-            self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
         }
 
-        def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
+        def.flags.set(def.flags.get() | TraitFlags::HAS_REMOTE_IMPLS);
     }
 
     pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind {
-        // If this is a local def-id, it should be inserted into the
-        // tables by typeck; else, it will be retreived from
-        // the external crate metadata.
-        if let Some(&kind) = self.tables.borrow().closure_kinds.get(&def_id) {
-            return kind;
-        }
-
-        let kind = self.sess.cstore.closure_kind(def_id);
-        self.tables.borrow_mut().closure_kinds.insert(def_id, kind);
-        kind
+        queries::closure_kind::get(self, DUMMY_SP, def_id)
     }
 
-    pub fn closure_type(self,
-                        def_id: DefId,
-                        substs: ClosureSubsts<'tcx>)
-                        -> ty::ClosureTy<'tcx>
-    {
-        // If this is a local def-id, it should be inserted into the
-        // tables by typeck; else, it will be retreived from
-        // the external crate metadata.
-        if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) {
-            return ty.subst(self, substs.func_substs);
-        }
-
-        let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id);
-        self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone());
-        ty.subst(self, substs.func_substs)
+    pub fn closure_type(self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+        queries::closure_type::get(self, DUMMY_SP, def_id)
     }
 
     /// Given the def_id of an impl, return the def_id of the trait it implements.
@@ -2678,18 +2447,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// If the given def ID describes a method belonging to an impl, return the
     /// ID of the impl that the method belongs to. Otherwise, return `None`.
     pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
-        if def_id.krate != LOCAL_CRATE {
-            return self.sess.cstore.impl_or_trait_item(self.global_tcx(), def_id)
-                       .and_then(|item| {
-                match item.container() {
-                    TraitContainer(_) => None,
-                    ImplContainer(def_id) => Some(def_id),
-                }
-            });
-        }
-        match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
+        let item = if def_id.krate != LOCAL_CRATE {
+            if let Some(Def::Method(_)) = self.sess.cstore.describe_def(def_id) {
+                Some(self.associated_item(def_id))
+            } else {
+                None
+            }
+        } else {
+            self.maps.associated_item.borrow().get(&def_id).cloned()
+        };
+
+        match item {
             Some(trait_item) => {
-                match trait_item.container() {
+                match trait_item.container {
                     TraitContainer(_) => None,
                     ImplContainer(def_id) => Some(def_id),
                 }
@@ -2705,9 +2475,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         if def_id.krate != LOCAL_CRATE {
             return self.sess.cstore.trait_of_item(def_id);
         }
-        match self.impl_or_trait_items.borrow().get(&def_id) {
-            Some(impl_or_trait_item) => {
-                match impl_or_trait_item.container() {
+        match self.maps.associated_item.borrow().get(&def_id) {
+            Some(associated_item) => {
+                match associated_item.container {
                     TraitContainer(def_id) => Some(def_id),
                     ImplContainer(_) => None
                 }
@@ -2716,30 +2486,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    /// If the given def ID describes an item belonging to a trait, (either a
-    /// default method or an implementation of a trait method), return the ID of
-    /// the method inside trait definition (this means that if the given def ID
-    /// is already that of the original trait method, then the return value is
-    /// the same).
-    /// Otherwise, return `None`.
-    pub fn trait_item_of_item(self, def_id: DefId) -> Option<DefId> {
-        let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) {
-            Some(m) => m.clone(),
-            None => return None,
-        };
-        match impl_or_trait_item.container() {
-            TraitContainer(_) => Some(impl_or_trait_item.def_id()),
-            ImplContainer(def_id) => {
-                self.trait_id_of_impl(def_id).and_then(|trait_did| {
-                    let name = impl_or_trait_item.name();
-                    self.trait_items(trait_did).iter()
-                        .find(|item| item.name() == name)
-                        .map(|item| item.def_id())
-                })
-            }
-        }
-    }
-
     /// Construct a parameter environment suitable for static contexts or other contexts where there
     /// are no free type/lifetime parameters in scope.
     pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
@@ -2752,8 +2498,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             caller_bounds: Vec::new(),
             implicit_region_bound: self.mk_region(ty::ReEmpty),
             free_id_outlive: free_id_outlive,
-            is_copy_cache: RefCell::new(FnvHashMap()),
-            is_sized_cache: RefCell::new(FnvHashMap()),
+            is_copy_cache: RefCell::new(FxHashMap()),
+            is_sized_cache: RefCell::new(FxHashMap()),
         }
     }
 
@@ -2801,7 +2547,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         //
 
         let tcx = self.global_tcx();
-        let generic_predicates = tcx.lookup_predicates(def_id);
+        let generic_predicates = tcx.item_predicates(def_id);
         let bounds = generic_predicates.instantiate(tcx, free_substs);
         let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
         let predicates = bounds.predicates;
@@ -2824,8 +2570,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             implicit_region_bound: tcx.mk_region(ty::ReScope(free_id_outlive)),
             caller_bounds: predicates,
             free_id_outlive: free_id_outlive,
-            is_copy_cache: RefCell::new(FnvHashMap()),
-            is_sized_cache: RefCell::new(FnvHashMap()),
+            is_copy_cache: RefCell::new(FxHashMap()),
+            is_sized_cache: RefCell::new(FxHashMap()),
         };
 
         let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps));
@@ -2836,35 +2582,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.mk_region(ty::ReScope(self.region_maps.node_extent(id)))
     }
 
-    pub fn visit_all_items_in_krate<V,F>(self,
-                                         dep_node_fn: F,
-                                         visitor: &mut V)
-        where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'gcx>
+    pub fn visit_all_item_likes_in_krate<V,F>(self,
+                                              dep_node_fn: F,
+                                              visitor: &mut V)
+        where F: FnMut(DefId) -> DepNode<DefId>, V: ItemLikeVisitor<'gcx>
     {
-        dep_graph::visit_all_items_in_krate(self.global_tcx(), dep_node_fn, visitor);
+        dep_graph::visit_all_item_likes_in_krate(self.global_tcx(), dep_node_fn, visitor);
+    }
+
+    /// Invokes `callback` for each body in the krate. This will
+    /// create a read edge from `DepNode::Krate` to the current task;
+    /// it is meant to be run in the context of some global task like
+    /// `BorrowckCrate`. The callback would then create a task like
+    /// `BorrowckBody(DefId)` to process each individual item.
+    pub fn visit_all_bodies_in_krate<C>(self, callback: C)
+        where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId),
+    {
+        dep_graph::visit_all_bodies_in_krate(self.global_tcx(), callback)
     }
 
     /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
     /// with the name of the crate containing the impl.
-    pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, InternedString> {
+    pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
         if impl_did.is_local() {
-            let node_id = self.map.as_local_node_id(impl_did).unwrap();
-            Ok(self.map.span(node_id))
+            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))
         }
     }
 }
 
-/// The category of explicit self.
-#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
-pub enum ExplicitSelfCategory<'tcx> {
-    Static,
-    ByValue,
-    ByReference(&'tcx Region, hir::Mutability),
-    ByBox,
-}
-
 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,