about summary refs log tree commit diff
path: root/compiler/rustc_hir/src
diff options
context:
space:
mode:
authormark <markm@cs.wisc.edu>2020-08-27 22:58:48 -0500
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2020-08-30 18:45:07 +0300
commit9e5f7d5631b8f4009ac1c693e585d4b7108d4275 (patch)
tree158a05eb3f204a8e72939b58427d0c2787a4eade /compiler/rustc_hir/src
parentdb534b3ac286cf45688c3bbae6aa6e77439e52d2 (diff)
downloadrust-9e5f7d5631b8f4009ac1c693e585d4b7108d4275.tar.gz
rust-9e5f7d5631b8f4009ac1c693e585d4b7108d4275.zip
mv compiler to compiler/
Diffstat (limited to 'compiler/rustc_hir/src')
-rw-r--r--compiler/rustc_hir/src/arena.rs52
-rw-r--r--compiler/rustc_hir/src/def.rs469
-rw-r--r--compiler/rustc_hir/src/definitions.rs457
-rw-r--r--compiler/rustc_hir/src/hir.rs2773
-rw-r--r--compiler/rustc_hir/src/hir_id.rs49
-rw-r--r--compiler/rustc_hir/src/intravisit.rs1222
-rw-r--r--compiler/rustc_hir/src/itemlikevisit.rs57
-rw-r--r--compiler/rustc_hir/src/lang_items.rs334
-rw-r--r--compiler/rustc_hir/src/lib.rs36
-rw-r--r--compiler/rustc_hir/src/pat_util.rs194
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs167
-rw-r--r--compiler/rustc_hir/src/target.rs127
-rw-r--r--compiler/rustc_hir/src/weak_lang_items.rs53
13 files changed, 5990 insertions, 0 deletions
diff --git a/compiler/rustc_hir/src/arena.rs b/compiler/rustc_hir/src/arena.rs
new file mode 100644
index 00000000000..85ab7906d25
--- /dev/null
+++ b/compiler/rustc_hir/src/arena.rs
@@ -0,0 +1,52 @@
+/// This declares a list of types which can be allocated by `Arena`.
+///
+/// The `few` modifier will cause allocation to use the shared arena and recording the destructor.
+/// This is faster and more memory efficient if there's only a few allocations of the type.
+/// Leaving `few` out will cause the type to get its own dedicated `TypedArena` which is
+/// faster and more memory efficient if there is lots of allocations.
+///
+/// Specifying the `decode` modifier will add decode impls for `&T` and `&[T]`,
+/// where `T` is the type listed. These impls will appear in the implement_ty_decoder! macro.
+#[macro_export]
+macro_rules! arena_types {
+    ($macro:path, $args:tt, $tcx:lifetime) => (
+        $macro!($args, [
+            // HIR types
+            [few] hir_krate: rustc_hir::Crate<$tcx>,
+            [] arm: rustc_hir::Arm<$tcx>,
+            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
+            [] asm_template: rustc_ast::InlineAsmTemplatePiece,
+            [] attribute: rustc_ast::Attribute,
+            [] block: rustc_hir::Block<$tcx>,
+            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
+            [few] global_asm: rustc_hir::GlobalAsm,
+            [] generic_arg: rustc_hir::GenericArg<$tcx>,
+            [] generic_args: rustc_hir::GenericArgs<$tcx>,
+            [] generic_bound: rustc_hir::GenericBound<$tcx>,
+            [] generic_param: rustc_hir::GenericParam<$tcx>,
+            [] expr: rustc_hir::Expr<$tcx>,
+            [] field: rustc_hir::Field<$tcx>,
+            [] field_pat: rustc_hir::FieldPat<$tcx>,
+            [] fn_decl: rustc_hir::FnDecl<$tcx>,
+            [] foreign_item: rustc_hir::ForeignItem<$tcx>,
+            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
+            [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
+            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
+            [] local: rustc_hir::Local<$tcx>,
+            [few] macro_def: rustc_hir::MacroDef<$tcx>,
+            [] param: rustc_hir::Param<$tcx>,
+            [] pat: rustc_hir::Pat<$tcx>,
+            [] path: rustc_hir::Path<$tcx>,
+            [] path_segment: rustc_hir::PathSegment<$tcx>,
+            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
+            [] qpath: rustc_hir::QPath<$tcx>,
+            [] stmt: rustc_hir::Stmt<$tcx>,
+            [] struct_field: rustc_hir::StructField<$tcx>,
+            [] trait_item_ref: rustc_hir::TraitItemRef,
+            [] ty: rustc_hir::Ty<$tcx>,
+            [] type_binding: rustc_hir::TypeBinding<$tcx>,
+            [] variant: rustc_hir::Variant<$tcx>,
+            [] where_predicate: rustc_hir::WherePredicate<$tcx>,
+        ], $tcx);
+    )
+}
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
new file mode 100644
index 00000000000..0d61dc037c6
--- /dev/null
+++ b/compiler/rustc_hir/src/def.rs
@@ -0,0 +1,469 @@
+use crate::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::hir;
+
+use rustc_ast as ast;
+use rustc_ast::NodeId;
+use rustc_macros::HashStable_Generic;
+use rustc_span::hygiene::MacroKind;
+
+use std::fmt::Debug;
+
+/// Encodes if a `DefKind::Ctor` is the constructor of an enum variant or a struct.
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum CtorOf {
+    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit struct.
+    Struct,
+    /// This `DefKind::Ctor` is a synthesized constructor of a tuple or unit variant.
+    Variant,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum CtorKind {
+    /// Constructor function automatically created by a tuple struct/variant.
+    Fn,
+    /// Constructor constant automatically created by a unit struct/variant.
+    Const,
+    /// Unusable name in value namespace created by a struct variant.
+    Fictive,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum NonMacroAttrKind {
+    /// Single-segment attribute defined by the language (`#[inline]`)
+    Builtin,
+    /// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
+    Tool,
+    /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
+    DeriveHelper,
+    /// Single-segment custom attribute registered with `#[register_attr]`.
+    Registered,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum DefKind {
+    // Type namespace
+    Mod,
+    /// Refers to the struct itself, `DefKind::Ctor` refers to its constructor if it exists.
+    Struct,
+    Union,
+    Enum,
+    /// Refers to the variant itself, `DefKind::Ctor` refers to its constructor if it exists.
+    Variant,
+    Trait,
+    /// `type Foo = Bar;`
+    TyAlias,
+    ForeignTy,
+    TraitAlias,
+    AssocTy,
+    TyParam,
+
+    // Value namespace
+    Fn,
+    Const,
+    ConstParam,
+    Static,
+    /// Refers to the struct or enum variant's constructor.
+    Ctor(CtorOf, CtorKind),
+    AssocFn,
+    AssocConst,
+
+    // Macro namespace
+    Macro(MacroKind),
+
+    // Not namespaced (or they are, but we don't treat them so)
+    ExternCrate,
+    Use,
+    ForeignMod,
+    AnonConst,
+    OpaqueTy,
+    Field,
+    LifetimeParam,
+    GlobalAsm,
+    Impl,
+    Closure,
+    Generator,
+}
+
+impl DefKind {
+    pub fn descr(self, def_id: DefId) -> &'static str {
+        match self {
+            DefKind::Fn => "function",
+            DefKind::Mod if def_id.index == CRATE_DEF_INDEX && def_id.krate != LOCAL_CRATE => {
+                "crate"
+            }
+            DefKind::Mod => "module",
+            DefKind::Static => "static",
+            DefKind::Enum => "enum",
+            DefKind::Variant => "variant",
+            DefKind::Ctor(CtorOf::Variant, CtorKind::Fn) => "tuple variant",
+            DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => "unit variant",
+            DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive) => "struct variant",
+            DefKind::Struct => "struct",
+            DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
+            DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
+            DefKind::Ctor(CtorOf::Struct, CtorKind::Fictive) => {
+                panic!("impossible struct constructor")
+            }
+            DefKind::OpaqueTy => "opaque type",
+            DefKind::TyAlias => "type alias",
+            DefKind::TraitAlias => "trait alias",
+            DefKind::AssocTy => "associated type",
+            DefKind::Union => "union",
+            DefKind::Trait => "trait",
+            DefKind::ForeignTy => "foreign type",
+            DefKind::AssocFn => "associated function",
+            DefKind::Const => "constant",
+            DefKind::AssocConst => "associated constant",
+            DefKind::TyParam => "type parameter",
+            DefKind::ConstParam => "const parameter",
+            DefKind::Macro(macro_kind) => macro_kind.descr(),
+            DefKind::LifetimeParam => "lifetime parameter",
+            DefKind::Use => "import",
+            DefKind::ForeignMod => "foreign module",
+            DefKind::AnonConst => "constant expression",
+            DefKind::Field => "field",
+            DefKind::Impl => "implementation",
+            DefKind::Closure => "closure",
+            DefKind::Generator => "generator",
+            DefKind::ExternCrate => "extern crate",
+            DefKind::GlobalAsm => "global assembly block",
+        }
+    }
+
+    /// Gets an English article for the definition.
+    pub fn article(&self) -> &'static str {
+        match *self {
+            DefKind::AssocTy
+            | DefKind::AssocConst
+            | DefKind::AssocFn
+            | DefKind::Enum
+            | DefKind::OpaqueTy
+            | DefKind::Impl
+            | DefKind::Use
+            | DefKind::ExternCrate => "an",
+            DefKind::Macro(macro_kind) => macro_kind.article(),
+            _ => "a",
+        }
+    }
+
+    pub fn ns(&self) -> Option<Namespace> {
+        match self {
+            DefKind::Mod
+            | DefKind::Struct
+            | DefKind::Union
+            | DefKind::Enum
+            | DefKind::Variant
+            | DefKind::Trait
+            | DefKind::OpaqueTy
+            | DefKind::TyAlias
+            | DefKind::ForeignTy
+            | DefKind::TraitAlias
+            | DefKind::AssocTy
+            | DefKind::TyParam => Some(Namespace::TypeNS),
+
+            DefKind::Fn
+            | DefKind::Const
+            | DefKind::ConstParam
+            | DefKind::Static
+            | DefKind::Ctor(..)
+            | DefKind::AssocFn
+            | DefKind::AssocConst => Some(Namespace::ValueNS),
+
+            DefKind::Macro(..) => Some(Namespace::MacroNS),
+
+            // Not namespaced.
+            DefKind::AnonConst
+            | DefKind::Field
+            | DefKind::LifetimeParam
+            | DefKind::ExternCrate
+            | DefKind::Closure
+            | DefKind::Generator
+            | DefKind::Use
+            | DefKind::ForeignMod
+            | DefKind::GlobalAsm
+            | DefKind::Impl => None,
+        }
+    }
+}
+
+/// The resolution of a path or export.
+#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum Res<Id = hir::HirId> {
+    Def(DefKind, DefId),
+
+    // Type namespace
+    PrimTy(hir::PrimTy),
+    SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
+    ToolMod, // e.g., `rustfmt` in `#[rustfmt::skip]`
+
+    // Value namespace
+    SelfCtor(DefId /* impl */), // `DefId` refers to the impl
+    Local(Id),
+
+    // Macro namespace
+    NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
+
+    // All namespaces
+    Err,
+}
+
+/// The result of resolving a path before lowering to HIR,
+/// with "module" segments resolved and associated item
+/// segments deferred to type checking.
+/// `base_res` is the resolution of the resolved part of the
+/// path, `unresolved_segments` is the number of unresolved
+/// segments.
+///
+/// ```text
+/// module::Type::AssocX::AssocY::MethodOrAssocType
+/// ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/// base_res      unresolved_segments = 3
+///
+/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
+///       ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
+///       base_res        unresolved_segments = 2
+/// ```
+#[derive(Copy, Clone, Debug)]
+pub struct PartialRes {
+    base_res: Res<NodeId>,
+    unresolved_segments: usize,
+}
+
+impl PartialRes {
+    #[inline]
+    pub fn new(base_res: Res<NodeId>) -> Self {
+        PartialRes { base_res, unresolved_segments: 0 }
+    }
+
+    #[inline]
+    pub fn with_unresolved_segments(base_res: Res<NodeId>, mut unresolved_segments: usize) -> Self {
+        if base_res == Res::Err {
+            unresolved_segments = 0
+        }
+        PartialRes { base_res, unresolved_segments }
+    }
+
+    #[inline]
+    pub fn base_res(&self) -> Res<NodeId> {
+        self.base_res
+    }
+
+    #[inline]
+    pub fn unresolved_segments(&self) -> usize {
+        self.unresolved_segments
+    }
+}
+
+/// Different kinds of symbols don't influence each other.
+///
+/// Therefore, they have a separate universe (namespace).
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub enum Namespace {
+    TypeNS,
+    ValueNS,
+    MacroNS,
+}
+
+impl Namespace {
+    pub fn descr(self) -> &'static str {
+        match self {
+            Self::TypeNS => "type",
+            Self::ValueNS => "value",
+            Self::MacroNS => "macro",
+        }
+    }
+}
+
+/// Just a helper ‒ separate structure for each namespace.
+#[derive(Copy, Clone, Default, Debug)]
+pub struct PerNS<T> {
+    pub value_ns: T,
+    pub type_ns: T,
+    pub macro_ns: T,
+}
+
+impl<T> PerNS<T> {
+    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> PerNS<U> {
+        PerNS { value_ns: f(self.value_ns), type_ns: f(self.type_ns), macro_ns: f(self.macro_ns) }
+    }
+}
+
+impl<T> ::std::ops::Index<Namespace> for PerNS<T> {
+    type Output = T;
+
+    fn index(&self, ns: Namespace) -> &T {
+        match ns {
+            Namespace::ValueNS => &self.value_ns,
+            Namespace::TypeNS => &self.type_ns,
+            Namespace::MacroNS => &self.macro_ns,
+        }
+    }
+}
+
+impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> {
+    fn index_mut(&mut self, ns: Namespace) -> &mut T {
+        match ns {
+            Namespace::ValueNS => &mut self.value_ns,
+            Namespace::TypeNS => &mut self.type_ns,
+            Namespace::MacroNS => &mut self.macro_ns,
+        }
+    }
+}
+
+impl<T> PerNS<Option<T>> {
+    /// Returns `true` if all the items in this collection are `None`.
+    pub fn is_empty(&self) -> bool {
+        self.type_ns.is_none() && self.value_ns.is_none() && self.macro_ns.is_none()
+    }
+
+    /// Returns an iterator over the items which are `Some`.
+    pub fn present_items(self) -> impl Iterator<Item = T> {
+        use std::iter::once;
+
+        once(self.type_ns).chain(once(self.value_ns)).chain(once(self.macro_ns)).filter_map(|it| it)
+    }
+}
+
+impl CtorKind {
+    pub fn from_ast(vdata: &ast::VariantData) -> CtorKind {
+        match *vdata {
+            ast::VariantData::Tuple(..) => CtorKind::Fn,
+            ast::VariantData::Unit(..) => CtorKind::Const,
+            ast::VariantData::Struct(..) => CtorKind::Fictive,
+        }
+    }
+
+    pub fn from_hir(vdata: &hir::VariantData<'_>) -> CtorKind {
+        match *vdata {
+            hir::VariantData::Tuple(..) => CtorKind::Fn,
+            hir::VariantData::Unit(..) => CtorKind::Const,
+            hir::VariantData::Struct(..) => CtorKind::Fictive,
+        }
+    }
+}
+
+impl NonMacroAttrKind {
+    pub fn descr(self) -> &'static str {
+        match self {
+            NonMacroAttrKind::Builtin => "built-in attribute",
+            NonMacroAttrKind::Tool => "tool attribute",
+            NonMacroAttrKind::DeriveHelper => "derive helper attribute",
+            NonMacroAttrKind::Registered => "explicitly registered attribute",
+        }
+    }
+
+    pub fn article(self) -> &'static str {
+        match self {
+            NonMacroAttrKind::Registered => "an",
+            _ => "a",
+        }
+    }
+
+    /// Users of some attributes cannot mark them as used, so they are considered always used.
+    pub fn is_used(self) -> bool {
+        match self {
+            NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper => true,
+            NonMacroAttrKind::Builtin | NonMacroAttrKind::Registered => false,
+        }
+    }
+}
+
+impl<Id> Res<Id> {
+    /// Return the `DefId` of this `Def` if it has an ID, else panic.
+    pub fn def_id(&self) -> DefId
+    where
+        Id: Debug,
+    {
+        self.opt_def_id()
+            .unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self))
+    }
+
+    /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`.
+    pub fn opt_def_id(&self) -> Option<DefId> {
+        match *self {
+            Res::Def(_, id) => Some(id),
+
+            Res::Local(..)
+            | Res::PrimTy(..)
+            | Res::SelfTy(..)
+            | Res::SelfCtor(..)
+            | Res::ToolMod
+            | Res::NonMacroAttr(..)
+            | Res::Err => None,
+        }
+    }
+
+    /// Return the `DefId` of this `Res` if it represents a module.
+    pub fn mod_def_id(&self) -> Option<DefId> {
+        match *self {
+            Res::Def(DefKind::Mod, id) => Some(id),
+            _ => None,
+        }
+    }
+
+    /// A human readable name for the res kind ("function", "module", etc.).
+    pub fn descr(&self) -> &'static str {
+        match *self {
+            Res::Def(kind, def_id) => kind.descr(def_id),
+            Res::SelfCtor(..) => "self constructor",
+            Res::PrimTy(..) => "builtin type",
+            Res::Local(..) => "local variable",
+            Res::SelfTy(..) => "self type",
+            Res::ToolMod => "tool module",
+            Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
+            Res::Err => "unresolved item",
+        }
+    }
+
+    /// Gets an English article for the `Res`.
+    pub fn article(&self) -> &'static str {
+        match *self {
+            Res::Def(kind, _) => kind.article(),
+            Res::NonMacroAttr(kind) => kind.article(),
+            Res::Err => "an",
+            _ => "a",
+        }
+    }
+
+    pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
+        match self {
+            Res::Def(kind, id) => Res::Def(kind, id),
+            Res::SelfCtor(id) => Res::SelfCtor(id),
+            Res::PrimTy(id) => Res::PrimTy(id),
+            Res::Local(id) => Res::Local(map(id)),
+            Res::SelfTy(a, b) => Res::SelfTy(a, b),
+            Res::ToolMod => Res::ToolMod,
+            Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
+            Res::Err => Res::Err,
+        }
+    }
+
+    pub fn macro_kind(self) -> Option<MacroKind> {
+        match self {
+            Res::Def(DefKind::Macro(kind), _) => Some(kind),
+            Res::NonMacroAttr(..) => Some(MacroKind::Attr),
+            _ => None,
+        }
+    }
+
+    /// Returns `None` if this is `Res::Err`
+    pub fn ns(&self) -> Option<Namespace> {
+        match self {
+            Res::Def(kind, ..) => kind.ns(),
+            Res::PrimTy(..) | Res::SelfTy(..) | Res::ToolMod => Some(Namespace::TypeNS),
+            Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
+            Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
+            Res::Err => None,
+        }
+    }
+
+    /// Always returns `true` if `self` is `Res::Err`
+    pub fn matches_ns(&self, ns: Namespace) -> bool {
+        self.ns().map_or(true, |actual_ns| actual_ns == ns)
+    }
+}
diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs
new file mode 100644
index 00000000000..45735ead256
--- /dev/null
+++ b/compiler/rustc_hir/src/definitions.rs
@@ -0,0 +1,457 @@
+//! For each definition, we track the following data. A definition
+//! here is defined somewhat circularly as "something with a `DefId`",
+//! but it generally corresponds to things like structs, enums, etc.
+//! There are also some rather random cases (like const initializer
+//! expressions) that are mostly just leftovers.
+
+pub use crate::def_id::DefPathHash;
+use crate::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use crate::hir;
+
+use rustc_ast::crate_disambiguator::CrateDisambiguator;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::StableHasher;
+use rustc_index::vec::IndexVec;
+use rustc_span::hygiene::ExpnId;
+use rustc_span::symbol::{sym, Symbol};
+
+use std::fmt::Write;
+use std::hash::Hash;
+use tracing::debug;
+
+/// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa.
+/// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey`
+/// stores the `DefIndex` of its parent.
+/// There is one `DefPathTable` for each crate.
+#[derive(Clone, Default)]
+pub struct DefPathTable {
+    index_to_key: IndexVec<DefIndex, DefKey>,
+    def_path_hashes: IndexVec<DefIndex, DefPathHash>,
+}
+
+impl DefPathTable {
+    fn allocate(&mut self, key: DefKey, def_path_hash: DefPathHash) -> DefIndex {
+        let index = {
+            let index = DefIndex::from(self.index_to_key.len());
+            debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
+            self.index_to_key.push(key);
+            index
+        };
+        self.def_path_hashes.push(def_path_hash);
+        debug_assert!(self.def_path_hashes.len() == self.index_to_key.len());
+        index
+    }
+
+    #[inline(always)]
+    pub fn def_key(&self, index: DefIndex) -> DefKey {
+        self.index_to_key[index]
+    }
+
+    #[inline(always)]
+    pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash {
+        let hash = self.def_path_hashes[index];
+        debug!("def_path_hash({:?}) = {:?}", index, hash);
+        hash
+    }
+
+    pub fn num_def_ids(&self) -> usize {
+        self.index_to_key.len()
+    }
+
+    pub fn enumerated_keys_and_path_hashes(
+        &self,
+    ) -> impl Iterator<Item = (DefIndex, &DefKey, &DefPathHash)> + '_ {
+        self.index_to_key
+            .iter_enumerated()
+            .map(move |(index, key)| (index, key, &self.def_path_hashes[index]))
+    }
+
+    pub fn all_def_path_hashes_and_def_ids(
+        &self,
+        krate: CrateNum,
+    ) -> impl Iterator<Item = (DefPathHash, DefId)> + '_ {
+        self.def_path_hashes
+            .iter_enumerated()
+            .map(move |(index, hash)| (*hash, DefId { krate, index }))
+    }
+}
+
+/// The definition table containing node definitions.
+/// It holds the `DefPathTable` for `LocalDefId`s/`DefPath`s.
+/// It also stores mappings to convert `LocalDefId`s to/from `HirId`s.
+#[derive(Clone)]
+pub struct Definitions {
+    table: DefPathTable,
+
+    // FIXME(eddyb) ideally all `LocalDefId`s would be HIR owners.
+    pub(super) def_id_to_hir_id: IndexVec<LocalDefId, Option<hir::HirId>>,
+    /// The reverse mapping of `def_id_to_hir_id`.
+    pub(super) hir_id_to_def_id: FxHashMap<hir::HirId, LocalDefId>,
+
+    /// If `ExpnId` is an ID of some macro expansion,
+    /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined.
+    parent_modules_of_macro_defs: FxHashMap<ExpnId, DefId>,
+    /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
+    expansions_that_defined: FxHashMap<LocalDefId, ExpnId>,
+}
+
+/// A unique identifier that we can use to lookup a definition
+/// precisely. It combines the index of the definition's parent (if
+/// any) with a `DisambiguatedDefPathData`.
+#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
+pub struct DefKey {
+    /// The parent path.
+    pub parent: Option<DefIndex>,
+
+    /// The identifier of this node.
+    pub disambiguated_data: DisambiguatedDefPathData,
+}
+
+impl DefKey {
+    fn compute_stable_hash(&self, parent_hash: DefPathHash) -> DefPathHash {
+        let mut hasher = StableHasher::new();
+
+        // We hash a `0u8` here to disambiguate between regular `DefPath` hashes,
+        // and the special "root_parent" below.
+        0u8.hash(&mut hasher);
+        parent_hash.hash(&mut hasher);
+
+        let DisambiguatedDefPathData { ref data, disambiguator } = self.disambiguated_data;
+
+        ::std::mem::discriminant(data).hash(&mut hasher);
+        if let Some(name) = data.get_opt_name() {
+            // Get a stable hash by considering the symbol chars rather than
+            // the symbol index.
+            name.as_str().hash(&mut hasher);
+        }
+
+        disambiguator.hash(&mut hasher);
+
+        DefPathHash(hasher.finish())
+    }
+
+    fn root_parent_stable_hash(
+        crate_name: &str,
+        crate_disambiguator: CrateDisambiguator,
+    ) -> DefPathHash {
+        let mut hasher = StableHasher::new();
+        // Disambiguate this from a regular `DefPath` hash; see `compute_stable_hash()` above.
+        1u8.hash(&mut hasher);
+        crate_name.hash(&mut hasher);
+        crate_disambiguator.hash(&mut hasher);
+        DefPathHash(hasher.finish())
+    }
+}
+
+/// A pair of `DefPathData` and an integer disambiguator. The integer is
+/// normally `0`, but in the event that there are multiple defs with the
+/// same `parent` and `data`, we use this field to disambiguate
+/// between them. This introduces some artificial ordering dependency
+/// but means that if you have, e.g., two impls for the same type in
+/// the same module, they do get distinct `DefId`s.
+#[derive(Copy, Clone, PartialEq, Debug, Encodable, Decodable)]
+pub struct DisambiguatedDefPathData {
+    pub data: DefPathData,
+    pub disambiguator: u32,
+}
+
+#[derive(Clone, Debug, Encodable, Decodable)]
+pub struct DefPath {
+    /// The path leading from the crate root to the item.
+    pub data: Vec<DisambiguatedDefPathData>,
+
+    /// The crate root this path is relative to.
+    pub krate: CrateNum,
+}
+
+impl DefPath {
+    pub fn is_local(&self) -> bool {
+        self.krate == LOCAL_CRATE
+    }
+
+    pub fn make<FN>(krate: CrateNum, start_index: DefIndex, mut get_key: FN) -> DefPath
+    where
+        FN: FnMut(DefIndex) -> DefKey,
+    {
+        let mut data = vec![];
+        let mut index = Some(start_index);
+        loop {
+            debug!("DefPath::make: krate={:?} index={:?}", krate, index);
+            let p = index.unwrap();
+            let key = get_key(p);
+            debug!("DefPath::make: key={:?}", key);
+            match key.disambiguated_data.data {
+                DefPathData::CrateRoot => {
+                    assert!(key.parent.is_none());
+                    break;
+                }
+                _ => {
+                    data.push(key.disambiguated_data);
+                    index = key.parent;
+                }
+            }
+        }
+        data.reverse();
+        DefPath { data, krate }
+    }
+
+    /// Returns a string representation of the `DefPath` without
+    /// the crate-prefix. This method is useful if you don't have
+    /// a `TyCtxt` available.
+    pub fn to_string_no_crate(&self) -> String {
+        let mut s = String::with_capacity(self.data.len() * 16);
+
+        for component in &self.data {
+            write!(s, "::{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap();
+        }
+
+        s
+    }
+
+    /// Returns a filename-friendly string for the `DefPath`, with the
+    /// crate-prefix.
+    pub fn to_string_friendly<F>(&self, crate_imported_name: F) -> String
+    where
+        F: FnOnce(CrateNum) -> Symbol,
+    {
+        let crate_name_str = crate_imported_name(self.krate).as_str();
+        let mut s = String::with_capacity(crate_name_str.len() + self.data.len() * 16);
+
+        write!(s, "::{}", crate_name_str).unwrap();
+
+        for component in &self.data {
+            if component.disambiguator == 0 {
+                write!(s, "::{}", component.data.as_symbol()).unwrap();
+            } else {
+                write!(s, "{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap();
+            }
+        }
+
+        s
+    }
+
+    /// Returns a filename-friendly string of the `DefPath`, without
+    /// the crate-prefix. This method is useful if you don't have
+    /// a `TyCtxt` available.
+    pub fn to_filename_friendly_no_crate(&self) -> String {
+        let mut s = String::with_capacity(self.data.len() * 16);
+
+        let mut opt_delimiter = None;
+        for component in &self.data {
+            s.extend(opt_delimiter);
+            opt_delimiter = Some('-');
+            if component.disambiguator == 0 {
+                write!(s, "{}", component.data.as_symbol()).unwrap();
+            } else {
+                write!(s, "{}[{}]", component.data.as_symbol(), component.disambiguator).unwrap();
+            }
+        }
+        s
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
+pub enum DefPathData {
+    // Root: these should only be used for the root nodes, because
+    // they are treated specially by the `def_path` function.
+    /// The crate root (marker).
+    CrateRoot,
+    // Catch-all for random `DefId` things like `DUMMY_NODE_ID`.
+    Misc,
+
+    // Different kinds of items and item-like things:
+    /// An impl.
+    Impl,
+    /// Something in the type namespace.
+    TypeNs(Symbol),
+    /// Something in the value namespace.
+    ValueNs(Symbol),
+    /// Something in the macro namespace.
+    MacroNs(Symbol),
+    /// Something in the lifetime namespace.
+    LifetimeNs(Symbol),
+    /// A closure expression.
+    ClosureExpr,
+
+    // Subportions of items:
+    /// Implicit constructor for a unit or tuple-like struct or enum variant.
+    Ctor,
+    /// A constant expression (see `{ast,hir}::AnonConst`).
+    AnonConst,
+    /// An `impl Trait` type node.
+    ImplTrait,
+}
+
+impl Definitions {
+    pub fn def_path_table(&self) -> &DefPathTable {
+        &self.table
+    }
+
+    /// Gets the number of definitions.
+    pub fn def_index_count(&self) -> usize {
+        self.table.index_to_key.len()
+    }
+
+    pub fn def_key(&self, id: LocalDefId) -> DefKey {
+        self.table.def_key(id.local_def_index)
+    }
+
+    #[inline(always)]
+    pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash {
+        self.table.def_path_hash(id.local_def_index)
+    }
+
+    /// Returns the path from the crate root to `index`. The root
+    /// nodes are not included in the path (i.e., this will be an
+    /// empty vector for the crate root). For an inlined item, this
+    /// will be the path of the item in the external crate (but the
+    /// path will begin with the path to the external crate).
+    pub fn def_path(&self, id: LocalDefId) -> DefPath {
+        DefPath::make(LOCAL_CRATE, id.local_def_index, |index| {
+            self.def_key(LocalDefId { local_def_index: index })
+        })
+    }
+
+    #[inline]
+    pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId {
+        self.def_id_to_hir_id[id].unwrap()
+    }
+
+    #[inline]
+    pub fn opt_local_def_id_to_hir_id(&self, id: LocalDefId) -> Option<hir::HirId> {
+        self.def_id_to_hir_id[id]
+    }
+
+    #[inline]
+    pub fn opt_hir_id_to_local_def_id(&self, hir_id: hir::HirId) -> Option<LocalDefId> {
+        self.hir_id_to_def_id.get(&hir_id).copied()
+    }
+
+    /// Adds a root definition (no parent) and a few other reserved definitions.
+    pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions {
+        let key = DefKey {
+            parent: None,
+            disambiguated_data: DisambiguatedDefPathData {
+                data: DefPathData::CrateRoot,
+                disambiguator: 0,
+            },
+        };
+
+        let parent_hash = DefKey::root_parent_stable_hash(crate_name, crate_disambiguator);
+        let def_path_hash = key.compute_stable_hash(parent_hash);
+
+        // Create the root definition.
+        let mut table = DefPathTable::default();
+        let root = LocalDefId { local_def_index: table.allocate(key, def_path_hash) };
+        assert_eq!(root.local_def_index, CRATE_DEF_INDEX);
+
+        Definitions {
+            table,
+            def_id_to_hir_id: Default::default(),
+            hir_id_to_def_id: Default::default(),
+            expansions_that_defined: Default::default(),
+            parent_modules_of_macro_defs: Default::default(),
+        }
+    }
+
+    /// Retrieves the root definition.
+    pub fn get_root_def(&self) -> LocalDefId {
+        LocalDefId { local_def_index: CRATE_DEF_INDEX }
+    }
+
+    /// Adds a definition with a parent definition.
+    pub fn create_def(
+        &mut self,
+        parent: LocalDefId,
+        data: DefPathData,
+        expn_id: ExpnId,
+        mut next_disambiguator: impl FnMut(LocalDefId, DefPathData) -> u32,
+    ) -> LocalDefId {
+        debug!("create_def(parent={:?}, data={:?}, expn_id={:?})", parent, data, expn_id);
+
+        // The root node must be created with `create_root_def()`.
+        assert!(data != DefPathData::CrateRoot);
+
+        let disambiguator = next_disambiguator(parent, data);
+        let key = DefKey {
+            parent: Some(parent.local_def_index),
+            disambiguated_data: DisambiguatedDefPathData { data, disambiguator },
+        };
+
+        let parent_hash = self.table.def_path_hash(parent.local_def_index);
+        let def_path_hash = key.compute_stable_hash(parent_hash);
+
+        debug!("create_def: after disambiguation, key = {:?}", key);
+
+        // Create the definition.
+        let def_id = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) };
+
+        if expn_id != ExpnId::root() {
+            self.expansions_that_defined.insert(def_id, expn_id);
+        }
+
+        def_id
+    }
+
+    /// Initializes the `LocalDefId` to `HirId` mapping once it has been generated during
+    /// AST to HIR lowering.
+    pub fn init_def_id_to_hir_id_mapping(
+        &mut self,
+        mapping: IndexVec<LocalDefId, Option<hir::HirId>>,
+    ) {
+        assert!(
+            self.def_id_to_hir_id.is_empty(),
+            "trying to initialize `LocalDefId` <-> `HirId` mappings twice"
+        );
+
+        // Build the reverse mapping of `def_id_to_hir_id`.
+        self.hir_id_to_def_id = mapping
+            .iter_enumerated()
+            .filter_map(|(def_id, hir_id)| hir_id.map(|hir_id| (hir_id, def_id)))
+            .collect();
+
+        self.def_id_to_hir_id = mapping;
+    }
+
+    pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId {
+        self.expansions_that_defined.get(&id).copied().unwrap_or(ExpnId::root())
+    }
+
+    pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId {
+        self.parent_modules_of_macro_defs[&expn_id]
+    }
+
+    pub fn add_parent_module_of_macro_def(&mut self, expn_id: ExpnId, module: DefId) {
+        self.parent_modules_of_macro_defs.insert(expn_id, module);
+    }
+}
+
+impl DefPathData {
+    pub fn get_opt_name(&self) -> Option<Symbol> {
+        use self::DefPathData::*;
+        match *self {
+            TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
+
+            Impl | CrateRoot | Misc | ClosureExpr | Ctor | AnonConst | ImplTrait => None,
+        }
+    }
+
+    pub fn as_symbol(&self) -> Symbol {
+        use self::DefPathData::*;
+        match *self {
+            TypeNs(name) | ValueNs(name) | MacroNs(name) | LifetimeNs(name) => name,
+            // Note that this does not show up in user print-outs.
+            CrateRoot => sym::double_braced_crate,
+            Impl => sym::double_braced_impl,
+            Misc => sym::double_braced_misc,
+            ClosureExpr => sym::double_braced_closure,
+            Ctor => sym::double_braced_constructor,
+            AnonConst => sym::double_braced_constant,
+            ImplTrait => sym::double_braced_opaque,
+        }
+    }
+
+    pub fn to_string(&self) -> String {
+        self.as_symbol().to_string()
+    }
+}
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
new file mode 100644
index 00000000000..cd4185226dc
--- /dev/null
+++ b/compiler/rustc_hir/src/hir.rs
@@ -0,0 +1,2773 @@
+use crate::def::{DefKind, Namespace, Res};
+use crate::def_id::DefId;
+crate use crate::hir_id::HirId;
+use crate::{itemlikevisit, LangItem};
+
+use rustc_ast::node_id::NodeMap;
+use rustc_ast::util::parser::ExprPrecedence;
+use rustc_ast::{self as ast, CrateSugar, LlvmAsmDialect};
+use rustc_ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy};
+pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
+pub use rustc_ast::{CaptureBy, Movability, Mutability};
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_data_structures::sync::{par_for_each_in, Send, Sync};
+use rustc_macros::HashStable_Generic;
+use rustc_span::def_id::LocalDefId;
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_target::asm::InlineAsmRegOrRegClass;
+use rustc_target::spec::abi::Abi;
+
+use smallvec::SmallVec;
+use std::collections::{BTreeMap, BTreeSet};
+use std::fmt;
+
+#[derive(Copy, Clone, Encodable, HashStable_Generic)]
+pub struct Lifetime {
+    pub hir_id: HirId,
+    pub span: Span,
+
+    /// Either "`'a`", referring to a named lifetime definition,
+    /// or "``" (i.e., `kw::Invalid`), for elision placeholders.
+    ///
+    /// HIR lowering inserts these placeholders in type paths that
+    /// refer to type definitions needing lifetime parameters,
+    /// `&T` and `&mut T`, and trait objects without `... + 'a`.
+    pub name: LifetimeName,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
+#[derive(HashStable_Generic)]
+pub enum ParamName {
+    /// Some user-given name like `T` or `'x`.
+    Plain(Ident),
+
+    /// Synthetic name generated when user elided a lifetime in an impl header.
+    ///
+    /// E.g., the lifetimes in cases like these:
+    ///
+    ///     impl Foo for &u32
+    ///     impl Foo<'_> for u32
+    ///
+    /// in that case, we rewrite to
+    ///
+    ///     impl<'f> Foo for &'f u32
+    ///     impl<'f> Foo<'f> for u32
+    ///
+    /// where `'f` is something like `Fresh(0)`. The indices are
+    /// unique per impl, but not necessarily continuous.
+    Fresh(usize),
+
+    /// Indicates an illegal name was given and an error has been
+    /// reported (so we should squelch other derived errors). Occurs
+    /// when, e.g., `'_` is used in the wrong place.
+    Error,
+}
+
+impl ParamName {
+    pub fn ident(&self) -> Ident {
+        match *self {
+            ParamName::Plain(ident) => ident,
+            ParamName::Fresh(_) | ParamName::Error => {
+                Ident::with_dummy_span(kw::UnderscoreLifetime)
+            }
+        }
+    }
+
+    pub fn normalize_to_macros_2_0(&self) -> ParamName {
+        match *self {
+            ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()),
+            param_name => param_name,
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Encodable, Hash, Copy)]
+#[derive(HashStable_Generic)]
+pub enum LifetimeName {
+    /// User-given names or fresh (synthetic) names.
+    Param(ParamName),
+
+    /// User wrote nothing (e.g., the lifetime in `&u32`).
+    Implicit,
+
+    /// Implicit lifetime in a context like `dyn Foo`. This is
+    /// distinguished from implicit lifetimes elsewhere because the
+    /// lifetime that they default to must appear elsewhere within the
+    /// enclosing type.  This means that, in an `impl Trait` context, we
+    /// don't have to create a parameter for them. That is, `impl
+    /// Trait<Item = &u32>` expands to an opaque type like `type
+    /// Foo<'a> = impl Trait<Item = &'a u32>`, but `impl Trait<item =
+    /// dyn Bar>` expands to `type Foo = impl Trait<Item = dyn Bar +
+    /// 'static>`. The latter uses `ImplicitObjectLifetimeDefault` so
+    /// that surrounding code knows not to create a lifetime
+    /// parameter.
+    ImplicitObjectLifetimeDefault,
+
+    /// Indicates an error during lowering (usually `'_` in wrong place)
+    /// that was already reported.
+    Error,
+
+    /// User wrote specifies `'_`.
+    Underscore,
+
+    /// User wrote `'static`.
+    Static,
+}
+
+impl LifetimeName {
+    pub fn ident(&self) -> Ident {
+        match *self {
+            LifetimeName::ImplicitObjectLifetimeDefault
+            | LifetimeName::Implicit
+            | LifetimeName::Error => Ident::invalid(),
+            LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
+            LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
+            LifetimeName::Param(param_name) => param_name.ident(),
+        }
+    }
+
+    pub fn is_elided(&self) -> bool {
+        match self {
+            LifetimeName::ImplicitObjectLifetimeDefault
+            | LifetimeName::Implicit
+            | LifetimeName::Underscore => true,
+
+            // It might seem surprising that `Fresh(_)` counts as
+            // *not* elided -- but this is because, as far as the code
+            // in the compiler is concerned -- `Fresh(_)` variants act
+            // equivalently to "some fresh name". They correspond to
+            // early-bound regions on an impl, in other words.
+            LifetimeName::Error | LifetimeName::Param(_) | LifetimeName::Static => false,
+        }
+    }
+
+    fn is_static(&self) -> bool {
+        self == &LifetimeName::Static
+    }
+
+    pub fn normalize_to_macros_2_0(&self) -> LifetimeName {
+        match *self {
+            LifetimeName::Param(param_name) => {
+                LifetimeName::Param(param_name.normalize_to_macros_2_0())
+            }
+            lifetime_name => lifetime_name,
+        }
+    }
+}
+
+impl fmt::Display for Lifetime {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.name.ident().fmt(f)
+    }
+}
+
+impl fmt::Debug for Lifetime {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "lifetime({}: {})", self.hir_id, self.name.ident())
+    }
+}
+
+impl Lifetime {
+    pub fn is_elided(&self) -> bool {
+        self.name.is_elided()
+    }
+
+    pub fn is_static(&self) -> bool {
+        self.name.is_static()
+    }
+}
+
+/// A `Path` is essentially Rust's notion of a name; for instance,
+/// `std::cmp::PartialEq`. It's represented as a sequence of identifiers,
+/// along with a bunch of supporting information.
+#[derive(Debug, HashStable_Generic)]
+pub struct Path<'hir> {
+    pub span: Span,
+    /// The resolution for the path.
+    pub res: Res,
+    /// The segments in the path: the things separated by `::`.
+    pub segments: &'hir [PathSegment<'hir>],
+}
+
+impl Path<'_> {
+    pub fn is_global(&self) -> bool {
+        !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot
+    }
+}
+
+/// A segment of a path: an identifier, an optional lifetime, and a set of
+/// types.
+#[derive(Debug, HashStable_Generic)]
+pub struct PathSegment<'hir> {
+    /// The identifier portion of this path segment.
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    // `id` and `res` are optional. We currently only use these in save-analysis,
+    // any path segments without these will not have save-analysis info and
+    // therefore will not have 'jump to def' in IDEs, but otherwise will not be
+    // affected. (In general, we don't bother to get the defs for synthesized
+    // segments, only for segments which have come from the AST).
+    pub hir_id: Option<HirId>,
+    pub res: Option<Res>,
+
+    /// Type/lifetime parameters attached to this path. They come in
+    /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
+    /// this is more than just simple syntactic sugar; the use of
+    /// parens affects the region binding rules, so we preserve the
+    /// distinction.
+    pub args: Option<&'hir GenericArgs<'hir>>,
+
+    /// Whether to infer remaining type parameters, if any.
+    /// This only applies to expression and pattern paths, and
+    /// out of those only the segments with no type parameters
+    /// to begin with, e.g., `Vec::new` is `<Vec<..>>::new::<..>`.
+    pub infer_args: bool,
+}
+
+impl<'hir> PathSegment<'hir> {
+    /// Converts an identifier to the corresponding segment.
+    pub fn from_ident(ident: Ident) -> PathSegment<'hir> {
+        PathSegment { ident, hir_id: None, res: None, infer_args: true, args: None }
+    }
+
+    pub fn generic_args(&self) -> &GenericArgs<'hir> {
+        if let Some(ref args) = self.args {
+            args
+        } else {
+            const DUMMY: &GenericArgs<'_> = &GenericArgs::none();
+            DUMMY
+        }
+    }
+}
+
+#[derive(Encodable, Debug, HashStable_Generic)]
+pub struct ConstArg {
+    pub value: AnonConst,
+    pub span: Span,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum GenericArg<'hir> {
+    Lifetime(Lifetime),
+    Type(Ty<'hir>),
+    Const(ConstArg),
+}
+
+impl GenericArg<'_> {
+    pub fn span(&self) -> Span {
+        match self {
+            GenericArg::Lifetime(l) => l.span,
+            GenericArg::Type(t) => t.span,
+            GenericArg::Const(c) => c.span,
+        }
+    }
+
+    pub fn id(&self) -> HirId {
+        match self {
+            GenericArg::Lifetime(l) => l.hir_id,
+            GenericArg::Type(t) => t.hir_id,
+            GenericArg::Const(c) => c.value.hir_id,
+        }
+    }
+
+    pub fn is_const(&self) -> bool {
+        match self {
+            GenericArg::Const(_) => true,
+            _ => false,
+        }
+    }
+
+    pub fn descr(&self) -> &'static str {
+        match self {
+            GenericArg::Lifetime(_) => "lifetime",
+            GenericArg::Type(_) => "type",
+            GenericArg::Const(_) => "constant",
+        }
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct GenericArgs<'hir> {
+    /// The generic arguments for this path segment.
+    pub args: &'hir [GenericArg<'hir>],
+    /// Bindings (equality constraints) on associated types, if present.
+    /// E.g., `Foo<A = Bar>`.
+    pub bindings: &'hir [TypeBinding<'hir>],
+    /// Were arguments written in parenthesized form `Fn(T) -> U`?
+    /// This is required mostly for pretty-printing and diagnostics,
+    /// but also for changing lifetime elision rules to be "function-like".
+    pub parenthesized: bool,
+}
+
+impl GenericArgs<'_> {
+    pub const fn none() -> Self {
+        Self { args: &[], bindings: &[], parenthesized: false }
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized
+    }
+
+    pub fn inputs(&self) -> &[Ty<'_>] {
+        if self.parenthesized {
+            for arg in self.args {
+                match arg {
+                    GenericArg::Lifetime(_) => {}
+                    GenericArg::Type(ref ty) => {
+                        if let TyKind::Tup(ref tys) = ty.kind {
+                            return tys;
+                        }
+                        break;
+                    }
+                    GenericArg::Const(_) => {}
+                }
+            }
+        }
+        panic!("GenericArgs::inputs: not a `Fn(T) -> U`");
+    }
+
+    pub fn own_counts(&self) -> GenericParamCount {
+        // We could cache this as a property of `GenericParamCount`, but
+        // the aim is to refactor this away entirely eventually and the
+        // presence of this method will be a constant reminder.
+        let mut own_counts: GenericParamCount = Default::default();
+
+        for arg in self.args {
+            match arg {
+                GenericArg::Lifetime(_) => own_counts.lifetimes += 1,
+                GenericArg::Type(_) => own_counts.types += 1,
+                GenericArg::Const(_) => own_counts.consts += 1,
+            };
+        }
+
+        own_counts
+    }
+}
+
+/// A modifier on a bound, currently this is only used for `?Sized`, where the
+/// modifier is `Maybe`. Negative bounds should also be handled here.
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum TraitBoundModifier {
+    None,
+    Maybe,
+    MaybeConst,
+}
+
+/// The AST represents all type param bounds as types.
+/// `typeck::collect::compute_bounds` matches these against
+/// the "special" built-in traits (see `middle::lang_items`) and
+/// detects `Copy`, `Send` and `Sync`.
+#[derive(Debug, HashStable_Generic)]
+pub enum GenericBound<'hir> {
+    Trait(PolyTraitRef<'hir>, TraitBoundModifier),
+    // FIXME(davidtwco): Introduce `PolyTraitRef::LangItem`
+    LangItemTrait(LangItem, Span, HirId, &'hir GenericArgs<'hir>),
+    Outlives(Lifetime),
+}
+
+impl GenericBound<'_> {
+    pub fn trait_ref(&self) -> Option<&TraitRef<'_>> {
+        match self {
+            GenericBound::Trait(data, _) => Some(&data.trait_ref),
+            _ => None,
+        }
+    }
+
+    pub fn span(&self) -> Span {
+        match self {
+            &GenericBound::Trait(ref t, ..) => t.span,
+            &GenericBound::LangItemTrait(_, span, ..) => span,
+            &GenericBound::Outlives(ref l) => l.span,
+        }
+    }
+}
+
+pub type GenericBounds<'hir> = &'hir [GenericBound<'hir>];
+
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
+pub enum LifetimeParamKind {
+    // Indicates that the lifetime definition was explicitly declared (e.g., in
+    // `fn foo<'a>(x: &'a u8) -> &'a u8 { x }`).
+    Explicit,
+
+    // Indicates that the lifetime definition was synthetically added
+    // as a result of an in-band lifetime usage (e.g., in
+    // `fn foo(x: &'a u8) -> &'a u8 { x }`).
+    InBand,
+
+    // Indication that the lifetime was elided (e.g., in both cases in
+    // `fn foo(x: &u8) -> &'_ u8 { x }`).
+    Elided,
+
+    // Indication that the lifetime name was somehow in error.
+    Error,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum GenericParamKind<'hir> {
+    /// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
+    Lifetime {
+        kind: LifetimeParamKind,
+    },
+    Type {
+        default: Option<&'hir Ty<'hir>>,
+        synthetic: Option<SyntheticTyParamKind>,
+    },
+    Const {
+        ty: &'hir Ty<'hir>,
+    },
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct GenericParam<'hir> {
+    pub hir_id: HirId,
+    pub name: ParamName,
+    pub attrs: &'hir [Attribute],
+    pub bounds: GenericBounds<'hir>,
+    pub span: Span,
+    pub pure_wrt_drop: bool,
+    pub kind: GenericParamKind<'hir>,
+}
+
+impl GenericParam<'hir> {
+    pub fn bounds_span(&self) -> Option<Span> {
+        self.bounds.iter().fold(None, |span, bound| {
+            let span = span.map(|s| s.to(bound.span())).unwrap_or_else(|| bound.span());
+
+            Some(span)
+        })
+    }
+}
+
+#[derive(Default)]
+pub struct GenericParamCount {
+    pub lifetimes: usize,
+    pub types: usize,
+    pub consts: usize,
+}
+
+/// Represents lifetimes and type parameters attached to a declaration
+/// of a function, enum, trait, etc.
+#[derive(Debug, HashStable_Generic)]
+pub struct Generics<'hir> {
+    pub params: &'hir [GenericParam<'hir>],
+    pub where_clause: WhereClause<'hir>,
+    pub span: Span,
+}
+
+impl Generics<'hir> {
+    pub const fn empty() -> Generics<'hir> {
+        Generics {
+            params: &[],
+            where_clause: WhereClause { predicates: &[], span: DUMMY_SP },
+            span: DUMMY_SP,
+        }
+    }
+
+    pub fn own_counts(&self) -> GenericParamCount {
+        // We could cache this as a property of `GenericParamCount`, but
+        // the aim is to refactor this away entirely eventually and the
+        // presence of this method will be a constant reminder.
+        let mut own_counts: GenericParamCount = Default::default();
+
+        for param in self.params {
+            match param.kind {
+                GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1,
+                GenericParamKind::Type { .. } => own_counts.types += 1,
+                GenericParamKind::Const { .. } => own_counts.consts += 1,
+            };
+        }
+
+        own_counts
+    }
+
+    pub fn get_named(&self, name: Symbol) -> Option<&GenericParam<'_>> {
+        for param in self.params {
+            if name == param.name.ident().name {
+                return Some(param);
+            }
+        }
+        None
+    }
+
+    pub fn spans(&self) -> MultiSpan {
+        if self.params.is_empty() {
+            self.span.into()
+        } else {
+            self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
+        }
+    }
+}
+
+/// Synthetic type parameters are converted to another form during lowering; this allows
+/// us to track the original form they had, and is useful for error messages.
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum SyntheticTyParamKind {
+    ImplTrait,
+}
+
+/// A where-clause in a definition.
+#[derive(Debug, HashStable_Generic)]
+pub struct WhereClause<'hir> {
+    pub predicates: &'hir [WherePredicate<'hir>],
+    // Only valid if predicates aren't empty.
+    pub span: Span,
+}
+
+impl WhereClause<'_> {
+    pub fn span(&self) -> Option<Span> {
+        if self.predicates.is_empty() { None } else { Some(self.span) }
+    }
+
+    /// The `WhereClause` under normal circumstances points at either the predicates or the empty
+    /// space where the `where` clause should be. Only of use for diagnostic suggestions.
+    pub fn span_for_predicates_or_empty_place(&self) -> Span {
+        self.span
+    }
+
+    /// `Span` where further predicates would be suggested, accounting for trailing commas, like
+    ///  in `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
+    pub fn tail_span_for_suggestion(&self) -> Span {
+        let end = self.span_for_predicates_or_empty_place().shrink_to_hi();
+        self.predicates.last().map(|p| p.span()).unwrap_or(end).shrink_to_hi().to(end)
+    }
+}
+
+/// A single predicate in a where-clause.
+#[derive(Debug, HashStable_Generic)]
+pub enum WherePredicate<'hir> {
+    /// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
+    BoundPredicate(WhereBoundPredicate<'hir>),
+    /// A lifetime predicate (e.g., `'a: 'b + 'c`).
+    RegionPredicate(WhereRegionPredicate<'hir>),
+    /// An equality predicate (unsupported).
+    EqPredicate(WhereEqPredicate<'hir>),
+}
+
+impl WherePredicate<'_> {
+    pub fn span(&self) -> Span {
+        match self {
+            &WherePredicate::BoundPredicate(ref p) => p.span,
+            &WherePredicate::RegionPredicate(ref p) => p.span,
+            &WherePredicate::EqPredicate(ref p) => p.span,
+        }
+    }
+}
+
+/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
+#[derive(Debug, HashStable_Generic)]
+pub struct WhereBoundPredicate<'hir> {
+    pub span: Span,
+    /// Any generics from a `for` binding.
+    pub bound_generic_params: &'hir [GenericParam<'hir>],
+    /// The type being bounded.
+    pub bounded_ty: &'hir Ty<'hir>,
+    /// Trait and lifetime bounds (e.g., `Clone + Send + 'static`).
+    pub bounds: GenericBounds<'hir>,
+}
+
+/// A lifetime predicate (e.g., `'a: 'b + 'c`).
+#[derive(Debug, HashStable_Generic)]
+pub struct WhereRegionPredicate<'hir> {
+    pub span: Span,
+    pub lifetime: Lifetime,
+    pub bounds: GenericBounds<'hir>,
+}
+
+/// An equality predicate (e.g., `T = int`); currently unsupported.
+#[derive(Debug, HashStable_Generic)]
+pub struct WhereEqPredicate<'hir> {
+    pub hir_id: HirId,
+    pub span: Span,
+    pub lhs_ty: &'hir Ty<'hir>,
+    pub rhs_ty: &'hir Ty<'hir>,
+}
+
+#[derive(Encodable, Debug, HashStable_Generic)]
+pub struct ModuleItems {
+    // Use BTreeSets here so items are in the same order as in the
+    // list of all items in Crate
+    pub items: BTreeSet<HirId>,
+    pub trait_items: BTreeSet<TraitItemId>,
+    pub impl_items: BTreeSet<ImplItemId>,
+}
+
+/// A type representing only the top-level module.
+#[derive(Encodable, Debug, HashStable_Generic)]
+pub struct CrateItem<'hir> {
+    pub module: Mod<'hir>,
+    pub attrs: &'hir [Attribute],
+    pub span: Span,
+}
+
+/// The top-level data structure that stores the entire contents of
+/// the crate currently being compiled.
+///
+/// For more details, see the [rustc dev guide].
+///
+/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
+#[derive(Debug)]
+pub struct Crate<'hir> {
+    pub item: CrateItem<'hir>,
+    pub exported_macros: &'hir [MacroDef<'hir>],
+    // Attributes from non-exported macros, kept only for collecting the library feature list.
+    pub non_exported_macro_attrs: &'hir [Attribute],
+
+    // N.B., we use a `BTreeMap` here so that `visit_all_items` iterates
+    // over the ids in increasing order. In principle it should not
+    // matter what order we visit things in, but in *practice* it
+    // does, because it can affect the order in which errors are
+    // detected, which in turn can make compile-fail tests yield
+    // slightly different results.
+    pub items: BTreeMap<HirId, Item<'hir>>,
+
+    pub trait_items: BTreeMap<TraitItemId, TraitItem<'hir>>,
+    pub impl_items: BTreeMap<ImplItemId, ImplItem<'hir>>,
+    pub bodies: BTreeMap<BodyId, Body<'hir>>,
+    pub trait_impls: BTreeMap<DefId, Vec<HirId>>,
+
+    /// A list of the body ids written out in the order in which they
+    /// appear in the crate. If you're going to process all the bodies
+    /// in the crate, you should iterate over this list rather than the keys
+    /// of bodies.
+    pub body_ids: Vec<BodyId>,
+
+    /// A list of modules written out in the order in which they
+    /// appear in the crate. This includes the main crate module.
+    pub modules: BTreeMap<HirId, ModuleItems>,
+    /// A list of proc macro HirIds, written out in the order in which
+    /// they are declared in the static array generated by proc_macro_harness.
+    pub proc_macros: Vec<HirId>,
+
+    pub trait_map: BTreeMap<HirId, Vec<TraitCandidate>>,
+}
+
+impl Crate<'hir> {
+    pub fn item(&self, id: HirId) -> &Item<'hir> {
+        &self.items[&id]
+    }
+
+    pub fn trait_item(&self, id: TraitItemId) -> &TraitItem<'hir> {
+        &self.trait_items[&id]
+    }
+
+    pub fn impl_item(&self, id: ImplItemId) -> &ImplItem<'hir> {
+        &self.impl_items[&id]
+    }
+
+    pub fn body(&self, id: BodyId) -> &Body<'hir> {
+        &self.bodies[&id]
+    }
+}
+
+impl Crate<'_> {
+    /// Visits all items in the crate in some deterministic (but
+    /// unspecified) order. If you just need to process every item,
+    /// but don't care about nesting, this method is the best choice.
+    ///
+    /// If you do care about nesting -- usually because your algorithm
+    /// follows lexical scoping rules -- then you want a different
+    /// approach. You should override `visit_nested_item` in your
+    /// visitor and then call `intravisit::walk_crate` instead.
+    pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
+    where
+        V: itemlikevisit::ItemLikeVisitor<'hir>,
+    {
+        for item in self.items.values() {
+            visitor.visit_item(item);
+        }
+
+        for trait_item in self.trait_items.values() {
+            visitor.visit_trait_item(trait_item);
+        }
+
+        for impl_item in self.impl_items.values() {
+            visitor.visit_impl_item(impl_item);
+        }
+    }
+
+    /// A parallel version of `visit_all_item_likes`.
+    pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
+    where
+        V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send,
+    {
+        parallel!(
+            {
+                par_for_each_in(&self.items, |(_, item)| {
+                    visitor.visit_item(item);
+                });
+            },
+            {
+                par_for_each_in(&self.trait_items, |(_, trait_item)| {
+                    visitor.visit_trait_item(trait_item);
+                });
+            },
+            {
+                par_for_each_in(&self.impl_items, |(_, impl_item)| {
+                    visitor.visit_impl_item(impl_item);
+                });
+            }
+        );
+    }
+}
+
+/// A macro definition, in this crate or imported from another.
+///
+/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
+#[derive(Debug, HashStable_Generic)]
+pub struct MacroDef<'hir> {
+    pub ident: Ident,
+    pub vis: Visibility<'hir>,
+    pub attrs: &'hir [Attribute],
+    pub hir_id: HirId,
+    pub span: Span,
+    pub ast: ast::MacroDef,
+}
+
+/// A block of statements `{ .. }`, which may have a label (in this case the
+/// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
+/// the `rules` being anything but `DefaultBlock`.
+#[derive(Debug, HashStable_Generic)]
+pub struct Block<'hir> {
+    /// Statements in a block.
+    pub stmts: &'hir [Stmt<'hir>],
+    /// An expression at the end of the block
+    /// without a semicolon, if any.
+    pub expr: Option<&'hir Expr<'hir>>,
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    /// Distinguishes between `unsafe { ... }` and `{ ... }`.
+    pub rules: BlockCheckMode,
+    pub span: Span,
+    /// If true, then there may exist `break 'a` values that aim to
+    /// break out of this block early.
+    /// Used by `'label: {}` blocks and by `try {}` blocks.
+    pub targeted_by_break: bool,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct Pat<'hir> {
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    pub kind: PatKind<'hir>,
+    pub span: Span,
+}
+
+impl Pat<'_> {
+    // FIXME(#19596) this is a workaround, but there should be a better way
+    fn walk_short_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) -> bool {
+        if !it(self) {
+            return false;
+        }
+
+        use PatKind::*;
+        match &self.kind {
+            Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true,
+            Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it),
+            Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
+            TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
+            Slice(before, slice, after) => {
+                before.iter().chain(slice.iter()).chain(after.iter()).all(|p| p.walk_short_(it))
+            }
+        }
+    }
+
+    /// Walk the pattern in left-to-right order,
+    /// short circuiting (with `.all(..)`) if `false` is returned.
+    ///
+    /// Note that when visiting e.g. `Tuple(ps)`,
+    /// if visiting `ps[0]` returns `false`,
+    /// then `ps[1]` will not be visited.
+    pub fn walk_short(&self, mut it: impl FnMut(&Pat<'_>) -> bool) -> bool {
+        self.walk_short_(&mut it)
+    }
+
+    // FIXME(#19596) this is a workaround, but there should be a better way
+    fn walk_(&self, it: &mut impl FnMut(&Pat<'_>) -> bool) {
+        if !it(self) {
+            return;
+        }
+
+        use PatKind::*;
+        match &self.kind {
+            Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}
+            Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it),
+            Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
+            TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
+            Slice(before, slice, after) => {
+                before.iter().chain(slice.iter()).chain(after.iter()).for_each(|p| p.walk_(it))
+            }
+        }
+    }
+
+    /// Walk the pattern in left-to-right order.
+    ///
+    /// If `it(pat)` returns `false`, the children are not visited.
+    pub fn walk(&self, mut it: impl FnMut(&Pat<'_>) -> bool) {
+        self.walk_(&mut it)
+    }
+
+    /// Walk the pattern in left-to-right order.
+    ///
+    /// If you always want to recurse, prefer this method over `walk`.
+    pub fn walk_always(&self, mut it: impl FnMut(&Pat<'_>)) {
+        self.walk(|p| {
+            it(p);
+            true
+        })
+    }
+}
+
+/// A single field in a struct pattern.
+///
+/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
+/// are treated the same as` x: x, y: ref y, z: ref mut z`,
+/// except `is_shorthand` is true.
+#[derive(Debug, HashStable_Generic)]
+pub struct FieldPat<'hir> {
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    /// The identifier for the field.
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    /// The pattern the field is destructured to.
+    pub pat: &'hir Pat<'hir>,
+    pub is_shorthand: bool,
+    pub span: Span,
+}
+
+/// Explicit binding annotations given in the HIR for a binding. Note
+/// that this is not the final binding *mode* that we infer after type
+/// inference.
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum BindingAnnotation {
+    /// No binding annotation given: this means that the final binding mode
+    /// will depend on whether we have skipped through a `&` reference
+    /// when matching. For example, the `x` in `Some(x)` will have binding
+    /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
+    /// ultimately be inferred to be by-reference.
+    ///
+    /// Note that implicit reference skipping is not implemented yet (#42640).
+    Unannotated,
+
+    /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
+    Mutable,
+
+    /// Annotated as `ref`, like `ref x`
+    Ref,
+
+    /// Annotated as `ref mut x`.
+    RefMut,
+}
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum RangeEnd {
+    Included,
+    Excluded,
+}
+
+impl fmt::Display for RangeEnd {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match self {
+            RangeEnd::Included => "..=",
+            RangeEnd::Excluded => "..",
+        })
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum PatKind<'hir> {
+    /// Represents a wildcard pattern (i.e., `_`).
+    Wild,
+
+    /// A fresh binding `ref mut binding @ OPT_SUBPATTERN`.
+    /// The `HirId` is the canonical ID for the variable being bound,
+    /// (e.g., in `Ok(x) | Err(x)`, both `x` use the same canonical ID),
+    /// which is the pattern ID of the first `x`.
+    Binding(BindingAnnotation, HirId, Ident, Option<&'hir Pat<'hir>>),
+
+    /// A struct or struct variant pattern (e.g., `Variant {x, y, ..}`).
+    /// The `bool` is `true` in the presence of a `..`.
+    Struct(QPath<'hir>, &'hir [FieldPat<'hir>], bool),
+
+    /// A tuple struct/variant pattern `Variant(x, y, .., z)`.
+    /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
+    /// `0 <= position <= subpats.len()`
+    TupleStruct(QPath<'hir>, &'hir [&'hir Pat<'hir>], Option<usize>),
+
+    /// An or-pattern `A | B | C`.
+    /// Invariant: `pats.len() >= 2`.
+    Or(&'hir [&'hir Pat<'hir>]),
+
+    /// A path pattern for an unit struct/variant or a (maybe-associated) constant.
+    Path(QPath<'hir>),
+
+    /// A tuple pattern (e.g., `(a, b)`).
+    /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
+    /// `0 <= position <= subpats.len()`
+    Tuple(&'hir [&'hir Pat<'hir>], Option<usize>),
+
+    /// A `box` pattern.
+    Box(&'hir Pat<'hir>),
+
+    /// A reference pattern (e.g., `&mut (a, b)`).
+    Ref(&'hir Pat<'hir>, Mutability),
+
+    /// A literal.
+    Lit(&'hir Expr<'hir>),
+
+    /// A range pattern (e.g., `1..=2` or `1..2`).
+    Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
+
+    /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
+    ///
+    /// Here, `slice` is lowered from the syntax `($binding_mode $ident @)? ..`.
+    /// If `slice` exists, then `after` can be non-empty.
+    ///
+    /// The representation for e.g., `[a, b, .., c, d]` is:
+    /// ```
+    /// PatKind::Slice([Binding(a), Binding(b)], Some(Wild), [Binding(c), Binding(d)])
+    /// ```
+    Slice(&'hir [&'hir Pat<'hir>], Option<&'hir Pat<'hir>>, &'hir [&'hir Pat<'hir>]),
+}
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum BinOpKind {
+    /// The `+` operator (addition).
+    Add,
+    /// The `-` operator (subtraction).
+    Sub,
+    /// The `*` operator (multiplication).
+    Mul,
+    /// The `/` operator (division).
+    Div,
+    /// The `%` operator (modulus).
+    Rem,
+    /// The `&&` operator (logical and).
+    And,
+    /// The `||` operator (logical or).
+    Or,
+    /// The `^` operator (bitwise xor).
+    BitXor,
+    /// The `&` operator (bitwise and).
+    BitAnd,
+    /// The `|` operator (bitwise or).
+    BitOr,
+    /// The `<<` operator (shift left).
+    Shl,
+    /// The `>>` operator (shift right).
+    Shr,
+    /// The `==` operator (equality).
+    Eq,
+    /// The `<` operator (less than).
+    Lt,
+    /// The `<=` operator (less than or equal to).
+    Le,
+    /// The `!=` operator (not equal to).
+    Ne,
+    /// The `>=` operator (greater than or equal to).
+    Ge,
+    /// The `>` operator (greater than).
+    Gt,
+}
+
+impl BinOpKind {
+    pub fn as_str(self) -> &'static str {
+        match self {
+            BinOpKind::Add => "+",
+            BinOpKind::Sub => "-",
+            BinOpKind::Mul => "*",
+            BinOpKind::Div => "/",
+            BinOpKind::Rem => "%",
+            BinOpKind::And => "&&",
+            BinOpKind::Or => "||",
+            BinOpKind::BitXor => "^",
+            BinOpKind::BitAnd => "&",
+            BinOpKind::BitOr => "|",
+            BinOpKind::Shl => "<<",
+            BinOpKind::Shr => ">>",
+            BinOpKind::Eq => "==",
+            BinOpKind::Lt => "<",
+            BinOpKind::Le => "<=",
+            BinOpKind::Ne => "!=",
+            BinOpKind::Ge => ">=",
+            BinOpKind::Gt => ">",
+        }
+    }
+
+    pub fn is_lazy(self) -> bool {
+        match self {
+            BinOpKind::And | BinOpKind::Or => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_shift(self) -> bool {
+        match self {
+            BinOpKind::Shl | BinOpKind::Shr => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_comparison(self) -> bool {
+        match self {
+            BinOpKind::Eq
+            | BinOpKind::Lt
+            | BinOpKind::Le
+            | BinOpKind::Ne
+            | BinOpKind::Gt
+            | BinOpKind::Ge => true,
+            BinOpKind::And
+            | BinOpKind::Or
+            | BinOpKind::Add
+            | BinOpKind::Sub
+            | BinOpKind::Mul
+            | BinOpKind::Div
+            | BinOpKind::Rem
+            | BinOpKind::BitXor
+            | BinOpKind::BitAnd
+            | BinOpKind::BitOr
+            | BinOpKind::Shl
+            | BinOpKind::Shr => false,
+        }
+    }
+
+    /// Returns `true` if the binary operator takes its arguments by value.
+    pub fn is_by_value(self) -> bool {
+        !self.is_comparison()
+    }
+}
+
+impl Into<ast::BinOpKind> for BinOpKind {
+    fn into(self) -> ast::BinOpKind {
+        match self {
+            BinOpKind::Add => ast::BinOpKind::Add,
+            BinOpKind::Sub => ast::BinOpKind::Sub,
+            BinOpKind::Mul => ast::BinOpKind::Mul,
+            BinOpKind::Div => ast::BinOpKind::Div,
+            BinOpKind::Rem => ast::BinOpKind::Rem,
+            BinOpKind::And => ast::BinOpKind::And,
+            BinOpKind::Or => ast::BinOpKind::Or,
+            BinOpKind::BitXor => ast::BinOpKind::BitXor,
+            BinOpKind::BitAnd => ast::BinOpKind::BitAnd,
+            BinOpKind::BitOr => ast::BinOpKind::BitOr,
+            BinOpKind::Shl => ast::BinOpKind::Shl,
+            BinOpKind::Shr => ast::BinOpKind::Shr,
+            BinOpKind::Eq => ast::BinOpKind::Eq,
+            BinOpKind::Lt => ast::BinOpKind::Lt,
+            BinOpKind::Le => ast::BinOpKind::Le,
+            BinOpKind::Ne => ast::BinOpKind::Ne,
+            BinOpKind::Ge => ast::BinOpKind::Ge,
+            BinOpKind::Gt => ast::BinOpKind::Gt,
+        }
+    }
+}
+
+pub type BinOp = Spanned<BinOpKind>;
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum UnOp {
+    /// The `*` operator (deferencing).
+    UnDeref,
+    /// The `!` operator (logical negation).
+    UnNot,
+    /// The `-` operator (negation).
+    UnNeg,
+}
+
+impl UnOp {
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Self::UnDeref => "*",
+            Self::UnNot => "!",
+            Self::UnNeg => "-",
+        }
+    }
+
+    /// Returns `true` if the unary operator takes its argument by value.
+    pub fn is_by_value(self) -> bool {
+        match self {
+            Self::UnNeg | Self::UnNot => true,
+            _ => false,
+        }
+    }
+}
+
+/// A statement.
+#[derive(Debug, HashStable_Generic)]
+pub struct Stmt<'hir> {
+    pub hir_id: HirId,
+    pub kind: StmtKind<'hir>,
+    pub span: Span,
+}
+
+/// The contents of a statement.
+#[derive(Debug, HashStable_Generic)]
+pub enum StmtKind<'hir> {
+    /// A local (`let`) binding.
+    Local(&'hir Local<'hir>),
+
+    /// An item binding.
+    Item(ItemId),
+
+    /// An expression without a trailing semi-colon (must have unit type).
+    Expr(&'hir Expr<'hir>),
+
+    /// An expression with a trailing semi-colon (may have any type).
+    Semi(&'hir Expr<'hir>),
+}
+
+impl StmtKind<'hir> {
+    pub fn attrs(&self) -> &'hir [Attribute] {
+        match *self {
+            StmtKind::Local(ref l) => &l.attrs,
+            StmtKind::Item(_) => &[],
+            StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => &e.attrs,
+        }
+    }
+}
+
+/// Represents a `let` statement (i.e., `let <pat>:<ty> = <expr>;`).
+#[derive(Debug, HashStable_Generic)]
+pub struct Local<'hir> {
+    pub pat: &'hir Pat<'hir>,
+    /// Type annotation, if any (otherwise the type will be inferred).
+    pub ty: Option<&'hir Ty<'hir>>,
+    /// Initializer expression to set the value, if any.
+    pub init: Option<&'hir Expr<'hir>>,
+    pub hir_id: HirId,
+    pub span: Span,
+    pub attrs: AttrVec,
+    /// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop
+    /// desugaring. Otherwise will be `Normal`.
+    pub source: LocalSource,
+}
+
+/// Represents a single arm of a `match` expression, e.g.
+/// `<pat> (if <guard>) => <body>`.
+#[derive(Debug, HashStable_Generic)]
+pub struct Arm<'hir> {
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    pub span: Span,
+    pub attrs: &'hir [Attribute],
+    /// If this pattern and the optional guard matches, then `body` is evaluated.
+    pub pat: &'hir Pat<'hir>,
+    /// Optional guard clause.
+    pub guard: Option<Guard<'hir>>,
+    /// The expression the arm evaluates to if this arm matches.
+    pub body: &'hir Expr<'hir>,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum Guard<'hir> {
+    If(&'hir Expr<'hir>),
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct Field<'hir> {
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    pub ident: Ident,
+    pub expr: &'hir Expr<'hir>,
+    pub span: Span,
+    pub is_shorthand: bool,
+}
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum BlockCheckMode {
+    DefaultBlock,
+    UnsafeBlock(UnsafeSource),
+    PushUnsafeBlock(UnsafeSource),
+    PopUnsafeBlock(UnsafeSource),
+}
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum UnsafeSource {
+    CompilerGenerated,
+    UserProvided,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Hash, Debug)]
+pub struct BodyId {
+    pub hir_id: HirId,
+}
+
+/// The body of a function, closure, or constant value. In the case of
+/// a function, the body contains not only the function body itself
+/// (which is an expression), but also the argument patterns, since
+/// those are something that the caller doesn't really care about.
+///
+/// # Examples
+///
+/// ```
+/// fn foo((x, y): (u32, u32)) -> u32 {
+///     x + y
+/// }
+/// ```
+///
+/// Here, the `Body` associated with `foo()` would contain:
+///
+/// - an `params` array containing the `(x, y)` pattern
+/// - a `value` containing the `x + y` expression (maybe wrapped in a block)
+/// - `generator_kind` would be `None`
+///
+/// All bodies have an **owner**, which can be accessed via the HIR
+/// map using `body_owner_def_id()`.
+#[derive(Debug)]
+pub struct Body<'hir> {
+    pub params: &'hir [Param<'hir>],
+    pub value: Expr<'hir>,
+    pub generator_kind: Option<GeneratorKind>,
+}
+
+impl Body<'hir> {
+    pub fn id(&self) -> BodyId {
+        BodyId { hir_id: self.value.hir_id }
+    }
+
+    pub fn generator_kind(&self) -> Option<GeneratorKind> {
+        self.generator_kind
+    }
+}
+
+/// The type of source expression that caused this generator to be created.
+#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
+pub enum GeneratorKind {
+    /// An explicit `async` block or the body of an async function.
+    Async(AsyncGeneratorKind),
+
+    /// A generator literal created via a `yield` inside a closure.
+    Gen,
+}
+
+impl fmt::Display for GeneratorKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            GeneratorKind::Async(k) => fmt::Display::fmt(k, f),
+            GeneratorKind::Gen => f.write_str("generator"),
+        }
+    }
+}
+
+/// In the case of a generator created as part of an async construct,
+/// which kind of async construct caused it to be created?
+///
+/// This helps error messages but is also used to drive coercions in
+/// type-checking (see #60424).
+#[derive(Clone, PartialEq, Eq, HashStable_Generic, Encodable, Decodable, Debug, Copy)]
+pub enum AsyncGeneratorKind {
+    /// An explicit `async` block written by the user.
+    Block,
+
+    /// An explicit `async` block written by the user.
+    Closure,
+
+    /// The `async` block generated as the body of an async function.
+    Fn,
+}
+
+impl fmt::Display for AsyncGeneratorKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match self {
+            AsyncGeneratorKind::Block => "`async` block",
+            AsyncGeneratorKind::Closure => "`async` closure body",
+            AsyncGeneratorKind::Fn => "`async fn` body",
+        })
+    }
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum BodyOwnerKind {
+    /// Functions and methods.
+    Fn,
+
+    /// Closures
+    Closure,
+
+    /// Constants and associated constants.
+    Const,
+
+    /// Initializer of a `static` item.
+    Static(Mutability),
+}
+
+impl BodyOwnerKind {
+    pub fn is_fn_or_closure(self) -> bool {
+        match self {
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
+            BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
+        }
+    }
+}
+
+/// The kind of an item that requires const-checking.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum ConstContext {
+    /// A `const fn`.
+    ConstFn,
+
+    /// A `static` or `static mut`.
+    Static(Mutability),
+
+    /// A `const`, associated `const`, or other const context.
+    ///
+    /// Other contexts include:
+    /// - Array length expressions
+    /// - Enum discriminants
+    /// - Const generics
+    ///
+    /// For the most part, other contexts are treated just like a regular `const`, so they are
+    /// lumped into the same category.
+    Const,
+}
+
+impl ConstContext {
+    /// A description of this const context that can appear between backticks in an error message.
+    ///
+    /// E.g. `const` or `static mut`.
+    pub fn keyword_name(self) -> &'static str {
+        match self {
+            Self::Const => "const",
+            Self::Static(Mutability::Not) => "static",
+            Self::Static(Mutability::Mut) => "static mut",
+            Self::ConstFn => "const fn",
+        }
+    }
+}
+
+/// A colloquial, trivially pluralizable description of this const context for use in error
+/// messages.
+impl fmt::Display for ConstContext {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Self::Const => write!(f, "constant"),
+            Self::Static(_) => write!(f, "static"),
+            Self::ConstFn => write!(f, "constant function"),
+        }
+    }
+}
+
+/// A literal.
+pub type Lit = Spanned<LitKind>;
+
+/// A constant (expression) that's not an item or associated item,
+/// but needs its own `DefId` for type-checking, const-eval, etc.
+/// These are usually found nested inside types (e.g., array lengths)
+/// or expressions (e.g., repeat counts), and also used to define
+/// explicit discriminant values for enum variants.
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Debug, HashStable_Generic)]
+pub struct AnonConst {
+    pub hir_id: HirId,
+    pub body: BodyId,
+}
+
+/// An expression.
+#[derive(Debug)]
+pub struct Expr<'hir> {
+    pub hir_id: HirId,
+    pub kind: ExprKind<'hir>,
+    pub attrs: AttrVec,
+    pub span: Span,
+}
+
+// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+rustc_data_structures::static_assert_size!(Expr<'static>, 72);
+
+impl Expr<'_> {
+    pub fn precedence(&self) -> ExprPrecedence {
+        match self.kind {
+            ExprKind::Box(_) => ExprPrecedence::Box,
+            ExprKind::Array(_) => ExprPrecedence::Array,
+            ExprKind::Call(..) => ExprPrecedence::Call,
+            ExprKind::MethodCall(..) => ExprPrecedence::MethodCall,
+            ExprKind::Tup(_) => ExprPrecedence::Tup,
+            ExprKind::Binary(op, ..) => ExprPrecedence::Binary(op.node.into()),
+            ExprKind::Unary(..) => ExprPrecedence::Unary,
+            ExprKind::Lit(_) => ExprPrecedence::Lit,
+            ExprKind::Type(..) | ExprKind::Cast(..) => ExprPrecedence::Cast,
+            ExprKind::DropTemps(ref expr, ..) => expr.precedence(),
+            ExprKind::Loop(..) => ExprPrecedence::Loop,
+            ExprKind::Match(..) => ExprPrecedence::Match,
+            ExprKind::Closure(..) => ExprPrecedence::Closure,
+            ExprKind::Block(..) => ExprPrecedence::Block,
+            ExprKind::Assign(..) => ExprPrecedence::Assign,
+            ExprKind::AssignOp(..) => ExprPrecedence::AssignOp,
+            ExprKind::Field(..) => ExprPrecedence::Field,
+            ExprKind::Index(..) => ExprPrecedence::Index,
+            ExprKind::Path(..) => ExprPrecedence::Path,
+            ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
+            ExprKind::Break(..) => ExprPrecedence::Break,
+            ExprKind::Continue(..) => ExprPrecedence::Continue,
+            ExprKind::Ret(..) => ExprPrecedence::Ret,
+            ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
+            ExprKind::Struct(..) => ExprPrecedence::Struct,
+            ExprKind::Repeat(..) => ExprPrecedence::Repeat,
+            ExprKind::Yield(..) => ExprPrecedence::Yield,
+            ExprKind::Err => ExprPrecedence::Err,
+        }
+    }
+
+    // Whether this looks like a place expr, without checking for deref
+    // adjustments.
+    // This will return `true` in some potentially surprising cases such as
+    // `CONSTANT.field`.
+    pub fn is_syntactic_place_expr(&self) -> bool {
+        self.is_place_expr(|_| true)
+    }
+
+    /// Whether this is a place expression.
+    ///
+    /// `allow_projections_from` should return `true` if indexing a field or index expression based
+    /// on the given expression should be considered a place expression.
+    pub fn is_place_expr(&self, mut allow_projections_from: impl FnMut(&Self) -> bool) -> bool {
+        match self.kind {
+            ExprKind::Path(QPath::Resolved(_, ref path)) => match path.res {
+                Res::Local(..) | Res::Def(DefKind::Static, _) | Res::Err => true,
+                _ => false,
+            },
+
+            // Type ascription inherits its place expression kind from its
+            // operand. See:
+            // https://github.com/rust-lang/rfcs/blob/master/text/0803-type-ascription.md#type-ascription-and-temporaries
+            ExprKind::Type(ref e, _) => e.is_place_expr(allow_projections_from),
+
+            ExprKind::Unary(UnOp::UnDeref, _) => true,
+
+            ExprKind::Field(ref base, _) | ExprKind::Index(ref base, _) => {
+                allow_projections_from(base) || base.is_place_expr(allow_projections_from)
+            }
+
+            // Lang item paths cannot currently be local variables or statics.
+            ExprKind::Path(QPath::LangItem(..)) => false,
+
+            // Partially qualified paths in expressions can only legally
+            // refer to associated items which are always rvalues.
+            ExprKind::Path(QPath::TypeRelative(..))
+            | ExprKind::Call(..)
+            | ExprKind::MethodCall(..)
+            | ExprKind::Struct(..)
+            | ExprKind::Tup(..)
+            | ExprKind::Match(..)
+            | ExprKind::Closure(..)
+            | ExprKind::Block(..)
+            | ExprKind::Repeat(..)
+            | ExprKind::Array(..)
+            | ExprKind::Break(..)
+            | ExprKind::Continue(..)
+            | ExprKind::Ret(..)
+            | ExprKind::Loop(..)
+            | ExprKind::Assign(..)
+            | ExprKind::InlineAsm(..)
+            | ExprKind::LlvmInlineAsm(..)
+            | ExprKind::AssignOp(..)
+            | ExprKind::Lit(_)
+            | ExprKind::Unary(..)
+            | ExprKind::Box(..)
+            | ExprKind::AddrOf(..)
+            | ExprKind::Binary(..)
+            | ExprKind::Yield(..)
+            | ExprKind::Cast(..)
+            | ExprKind::DropTemps(..)
+            | ExprKind::Err => false,
+        }
+    }
+
+    /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps`
+    /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically
+    /// silent, only signaling the ownership system. By doing this, suggestions that check the
+    /// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps`
+    /// beyond remembering to call this function before doing analysis on it.
+    pub fn peel_drop_temps(&self) -> &Self {
+        let mut expr = self;
+        while let ExprKind::DropTemps(inner) = &expr.kind {
+            expr = inner;
+        }
+        expr
+    }
+}
+
+/// Checks if the specified expression is a built-in range literal.
+/// (See: `LoweringContext::lower_expr()`).
+pub fn is_range_literal(expr: &Expr<'_>) -> bool {
+    match expr.kind {
+        // All built-in range literals but `..=` and `..` desugar to `Struct`s.
+        ExprKind::Struct(ref qpath, _, _) => matches!(
+            **qpath,
+            QPath::LangItem(
+                LangItem::Range
+                | LangItem::RangeTo
+                | LangItem::RangeFrom
+                | LangItem::RangeFull
+                | LangItem::RangeToInclusive,
+                _,
+            )
+        ),
+
+        // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
+        ExprKind::Call(ref func, _) => {
+            matches!(func.kind, ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, _)))
+        }
+
+        _ => false,
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum ExprKind<'hir> {
+    /// A `box x` expression.
+    Box(&'hir Expr<'hir>),
+    /// An array (e.g., `[a, b, c, d]`).
+    Array(&'hir [Expr<'hir>]),
+    /// A function call.
+    ///
+    /// The first field resolves to the function itself (usually an `ExprKind::Path`),
+    /// and the second field is the list of arguments.
+    /// This also represents calling the constructor of
+    /// tuple-like ADTs such as tuple structs and enum variants.
+    Call(&'hir Expr<'hir>, &'hir [Expr<'hir>]),
+    /// A method call (e.g., `x.foo::<'static, Bar, Baz>(a, b, c, d)`).
+    ///
+    /// The `PathSegment`/`Span` represent the method name and its generic arguments
+    /// (within the angle brackets).
+    /// The first element of the vector of `Expr`s is the expression that evaluates
+    /// to the object on which the method is being called on (the receiver),
+    /// and the remaining elements are the rest of the arguments.
+    /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
+    /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
+    /// The final `Span` represents the span of the function and arguments
+    /// (e.g. `foo::<Bar, Baz>(a, b, c, d)` in `x.foo::<Bar, Baz>(a, b, c, d)`
+    ///
+    /// To resolve the called method to a `DefId`, call [`type_dependent_def_id`] with
+    /// the `hir_id` of the `MethodCall` node itself.
+    ///
+    /// [`type_dependent_def_id`]: ../ty/struct.TypeckResults.html#method.type_dependent_def_id
+    MethodCall(&'hir PathSegment<'hir>, Span, &'hir [Expr<'hir>], Span),
+    /// A tuple (e.g., `(a, b, c, d)`).
+    Tup(&'hir [Expr<'hir>]),
+    /// A binary operation (e.g., `a + b`, `a * b`).
+    Binary(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
+    /// A unary operation (e.g., `!x`, `*x`).
+    Unary(UnOp, &'hir Expr<'hir>),
+    /// A literal (e.g., `1`, `"foo"`).
+    Lit(Lit),
+    /// A cast (e.g., `foo as f64`).
+    Cast(&'hir Expr<'hir>, &'hir Ty<'hir>),
+    /// A type reference (e.g., `Foo`).
+    Type(&'hir Expr<'hir>, &'hir Ty<'hir>),
+    /// Wraps the expression in a terminating scope.
+    /// This makes it semantically equivalent to `{ let _t = expr; _t }`.
+    ///
+    /// This construct only exists to tweak the drop order in HIR lowering.
+    /// An example of that is the desugaring of `for` loops.
+    DropTemps(&'hir Expr<'hir>),
+    /// A conditionless loop (can be exited with `break`, `continue`, or `return`).
+    ///
+    /// I.e., `'label: loop { <block> }`.
+    Loop(&'hir Block<'hir>, Option<Label>, LoopSource),
+    /// A `match` block, with a source that indicates whether or not it is
+    /// the result of a desugaring, and if so, which kind.
+    Match(&'hir Expr<'hir>, &'hir [Arm<'hir>], MatchSource),
+    /// A closure (e.g., `move |a, b, c| {a + b + c}`).
+    ///
+    /// The `Span` is the argument block `|...|`.
+    ///
+    /// This may also be a generator literal or an `async block` as indicated by the
+    /// `Option<Movability>`.
+    Closure(CaptureBy, &'hir FnDecl<'hir>, BodyId, Span, Option<Movability>),
+    /// A block (e.g., `'label: { ... }`).
+    Block(&'hir Block<'hir>, Option<Label>),
+
+    /// An assignment (e.g., `a = foo()`).
+    Assign(&'hir Expr<'hir>, &'hir Expr<'hir>, Span),
+    /// An assignment with an operator.
+    ///
+    /// E.g., `a += 1`.
+    AssignOp(BinOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
+    /// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct or tuple field.
+    Field(&'hir Expr<'hir>, Ident),
+    /// An indexing operation (`foo[2]`).
+    Index(&'hir Expr<'hir>, &'hir Expr<'hir>),
+
+    /// Path to a definition, possibly containing lifetime or type parameters.
+    Path(QPath<'hir>),
+
+    /// A referencing operation (i.e., `&a` or `&mut a`).
+    AddrOf(BorrowKind, Mutability, &'hir Expr<'hir>),
+    /// A `break`, with an optional label to break.
+    Break(Destination, Option<&'hir Expr<'hir>>),
+    /// A `continue`, with an optional label.
+    Continue(Destination),
+    /// A `return`, with an optional value to be returned.
+    Ret(Option<&'hir Expr<'hir>>),
+
+    /// Inline assembly (from `asm!`), with its outputs and inputs.
+    InlineAsm(&'hir InlineAsm<'hir>),
+    /// Inline assembly (from `llvm_asm!`), with its outputs and inputs.
+    LlvmInlineAsm(&'hir LlvmInlineAsm<'hir>),
+
+    /// A struct or struct-like variant literal expression.
+    ///
+    /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`,
+    /// where `base` is the `Option<Expr>`.
+    Struct(&'hir QPath<'hir>, &'hir [Field<'hir>], Option<&'hir Expr<'hir>>),
+
+    /// An array literal constructed from one repeated element.
+    ///
+    /// E.g., `[1; 5]`. The first expression is the element
+    /// to be repeated; the second is the number of times to repeat it.
+    Repeat(&'hir Expr<'hir>, AnonConst),
+
+    /// A suspension point for generators (i.e., `yield <expr>`).
+    Yield(&'hir Expr<'hir>, YieldSource),
+
+    /// A placeholder for an expression that wasn't syntactically well formed in some way.
+    Err,
+}
+
+/// Represents an optionally `Self`-qualified value/type path or associated extension.
+///
+/// To resolve the path to a `DefId`, call [`qpath_res`].
+///
+/// [`qpath_res`]: ../rustc_middle/ty/struct.TypeckResults.html#method.qpath_res
+#[derive(Debug, HashStable_Generic)]
+pub enum QPath<'hir> {
+    /// Path to a definition, optionally "fully-qualified" with a `Self`
+    /// type, if the path points to an associated item in a trait.
+    ///
+    /// E.g., an unqualified path like `Clone::clone` has `None` for `Self`,
+    /// while `<Vec<T> as Clone>::clone` has `Some(Vec<T>)` for `Self`,
+    /// even though they both have the same two-segment `Clone::clone` `Path`.
+    Resolved(Option<&'hir Ty<'hir>>, &'hir Path<'hir>),
+
+    /// Type-related paths (e.g., `<T>::default` or `<T>::Output`).
+    /// Will be resolved by type-checking to an associated item.
+    ///
+    /// UFCS source paths can desugar into this, with `Vec::new` turning into
+    /// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
+    /// the `X` and `Y` nodes each being a `TyKind::Path(QPath::TypeRelative(..))`.
+    TypeRelative(&'hir Ty<'hir>, &'hir PathSegment<'hir>),
+
+    /// Reference to a `#[lang = "foo"]` item.
+    LangItem(LangItem, Span),
+}
+
+impl<'hir> QPath<'hir> {
+    /// Returns the span of this `QPath`.
+    pub fn span(&self) -> Span {
+        match *self {
+            QPath::Resolved(_, path) => path.span,
+            QPath::TypeRelative(_, ps) => ps.ident.span,
+            QPath::LangItem(_, span) => span,
+        }
+    }
+
+    /// Returns the span of the qself of this `QPath`. For example, `()` in
+    /// `<() as Trait>::method`.
+    pub fn qself_span(&self) -> Span {
+        match *self {
+            QPath::Resolved(_, path) => path.span,
+            QPath::TypeRelative(qself, _) => qself.span,
+            QPath::LangItem(_, span) => span,
+        }
+    }
+
+    /// Returns the span of the last segment of this `QPath`. For example, `method` in
+    /// `<() as Trait>::method`.
+    pub fn last_segment_span(&self) -> Span {
+        match *self {
+            QPath::Resolved(_, path) => path.segments.last().unwrap().ident.span,
+            QPath::TypeRelative(_, segment) => segment.ident.span,
+            QPath::LangItem(_, span) => span,
+        }
+    }
+}
+
+/// Hints at the original code for a let statement.
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+pub enum LocalSource {
+    /// A `match _ { .. }`.
+    Normal,
+    /// A desugared `for _ in _ { .. }` loop.
+    ForLoopDesugar,
+    /// When lowering async functions, we create locals within the `async move` so that
+    /// all parameters are dropped after the future is polled.
+    ///
+    /// ```ignore (pseudo-Rust)
+    /// async fn foo(<pattern> @ x: Type) {
+    ///     async move {
+    ///         let <pattern> = x;
+    ///     }
+    /// }
+    /// ```
+    AsyncFn,
+    /// A desugared `<expr>.await`.
+    AwaitDesugar,
+}
+
+/// Hints at the original code for a `match _ { .. }`.
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum MatchSource {
+    /// A `match _ { .. }`.
+    Normal,
+    /// An `if _ { .. }` (optionally with `else { .. }`).
+    IfDesugar { contains_else_clause: bool },
+    /// An `if let _ = _ { .. }` (optionally with `else { .. }`).
+    IfLetDesugar { contains_else_clause: bool },
+    /// A `while _ { .. }` (which was desugared to a `loop { match _ { .. } }`).
+    WhileDesugar,
+    /// A `while let _ = _ { .. }` (which was desugared to a
+    /// `loop { match _ { .. } }`).
+    WhileLetDesugar,
+    /// A desugared `for _ in _ { .. }` loop.
+    ForLoopDesugar,
+    /// A desugared `?` operator.
+    TryDesugar,
+    /// A desugared `<expr>.await`.
+    AwaitDesugar,
+}
+
+impl MatchSource {
+    pub fn name(self) -> &'static str {
+        use MatchSource::*;
+        match self {
+            Normal => "match",
+            IfDesugar { .. } | IfLetDesugar { .. } => "if",
+            WhileDesugar | WhileLetDesugar => "while",
+            ForLoopDesugar => "for",
+            TryDesugar => "?",
+            AwaitDesugar => ".await",
+        }
+    }
+}
+
+/// The loop type that yielded an `ExprKind::Loop`.
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum LoopSource {
+    /// A `loop { .. }` loop.
+    Loop,
+    /// A `while _ { .. }` loop.
+    While,
+    /// A `while let _ = _ { .. }` loop.
+    WhileLet,
+    /// A `for _ in _ { .. }` loop.
+    ForLoop,
+}
+
+impl LoopSource {
+    pub fn name(self) -> &'static str {
+        match self {
+            LoopSource::Loop => "loop",
+            LoopSource::While | LoopSource::WhileLet => "while",
+            LoopSource::ForLoop => "for",
+        }
+    }
+}
+
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+pub enum LoopIdError {
+    OutsideLoopScope,
+    UnlabeledCfInWhileCondition,
+    UnresolvedLabel,
+}
+
+impl fmt::Display for LoopIdError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match self {
+            LoopIdError::OutsideLoopScope => "not inside loop scope",
+            LoopIdError::UnlabeledCfInWhileCondition => {
+                "unlabeled control flow (break or continue) in while condition"
+            }
+            LoopIdError::UnresolvedLabel => "label not found",
+        })
+    }
+}
+
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+pub struct Destination {
+    // This is `Some(_)` iff there is an explicit user-specified `label
+    pub label: Option<Label>,
+
+    // These errors are caught and then reported during the diagnostics pass in
+    // librustc_passes/loops.rs
+    pub target_id: Result<HirId, LoopIdError>,
+}
+
+/// The yield kind that caused an `ExprKind::Yield`.
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Encodable, Decodable, HashStable_Generic)]
+pub enum YieldSource {
+    /// An `<expr>.await`.
+    Await { expr: Option<HirId> },
+    /// A plain `yield`.
+    Yield,
+}
+
+impl YieldSource {
+    pub fn is_await(&self) -> bool {
+        match self {
+            YieldSource::Await { .. } => true,
+            YieldSource::Yield => false,
+        }
+    }
+}
+
+impl fmt::Display for YieldSource {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match self {
+            YieldSource::Await { .. } => "`await`",
+            YieldSource::Yield => "`yield`",
+        })
+    }
+}
+
+impl From<GeneratorKind> for YieldSource {
+    fn from(kind: GeneratorKind) -> Self {
+        match kind {
+            // Guess based on the kind of the current generator.
+            GeneratorKind::Gen => Self::Yield,
+            GeneratorKind::Async(_) => Self::Await { expr: None },
+        }
+    }
+}
+
+// N.B., if you change this, you'll probably want to change the corresponding
+// type structure in middle/ty.rs as well.
+#[derive(Debug, HashStable_Generic)]
+pub struct MutTy<'hir> {
+    pub ty: &'hir Ty<'hir>,
+    pub mutbl: Mutability,
+}
+
+/// Represents a function's signature in a trait declaration,
+/// trait implementation, or a free function.
+#[derive(Debug, HashStable_Generic)]
+pub struct FnSig<'hir> {
+    pub header: FnHeader,
+    pub decl: &'hir FnDecl<'hir>,
+    pub span: Span,
+}
+
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
+pub struct TraitItemId {
+    pub hir_id: HirId,
+}
+
+/// Represents an item declaration within a trait declaration,
+/// possibly including a default implementation. A trait item is
+/// either required (meaning it doesn't have an implementation, just a
+/// signature) or provided (meaning it has a default implementation).
+#[derive(Debug)]
+pub struct TraitItem<'hir> {
+    pub ident: Ident,
+    pub hir_id: HirId,
+    pub attrs: &'hir [Attribute],
+    pub generics: Generics<'hir>,
+    pub kind: TraitItemKind<'hir>,
+    pub span: Span,
+}
+
+/// Represents a trait method's body (or just argument names).
+#[derive(Encodable, Debug, HashStable_Generic)]
+pub enum TraitFn<'hir> {
+    /// No default body in the trait, just a signature.
+    Required(&'hir [Ident]),
+
+    /// Both signature and body are provided in the trait.
+    Provided(BodyId),
+}
+
+/// Represents a trait method or associated constant or type
+#[derive(Debug, HashStable_Generic)]
+pub enum TraitItemKind<'hir> {
+    /// An associated constant with an optional value (otherwise `impl`s must contain a value).
+    Const(&'hir Ty<'hir>, Option<BodyId>),
+    /// An associated function with an optional body.
+    Fn(FnSig<'hir>, TraitFn<'hir>),
+    /// An associated type with (possibly empty) bounds and optional concrete
+    /// type.
+    Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
+}
+
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Debug)]
+pub struct ImplItemId {
+    pub hir_id: HirId,
+}
+
+/// Represents anything within an `impl` block.
+#[derive(Debug)]
+pub struct ImplItem<'hir> {
+    pub ident: Ident,
+    pub hir_id: HirId,
+    pub vis: Visibility<'hir>,
+    pub defaultness: Defaultness,
+    pub attrs: &'hir [Attribute],
+    pub generics: Generics<'hir>,
+    pub kind: ImplItemKind<'hir>,
+    pub span: Span,
+}
+
+/// Represents various kinds of content within an `impl`.
+#[derive(Debug, HashStable_Generic)]
+pub enum ImplItemKind<'hir> {
+    /// An associated constant of the given type, set to the constant result
+    /// of the expression.
+    Const(&'hir Ty<'hir>, BodyId),
+    /// An associated function implementation with the given signature and body.
+    Fn(FnSig<'hir>, BodyId),
+    /// An associated type.
+    TyAlias(&'hir Ty<'hir>),
+}
+
+impl ImplItemKind<'_> {
+    pub fn namespace(&self) -> Namespace {
+        match self {
+            ImplItemKind::TyAlias(..) => Namespace::TypeNS,
+            ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS,
+        }
+    }
+}
+
+// The name of the associated type for `Fn` return types.
+pub const FN_OUTPUT_NAME: Symbol = sym::Output;
+
+/// Bind a type to an associated type (i.e., `A = Foo`).
+///
+/// Bindings like `A: Debug` are represented as a special type `A =
+/// $::Debug` that is understood by the astconv code.
+///
+/// FIXME(alexreg): why have a separate type for the binding case,
+/// wouldn't it be better to make the `ty` field an enum like the
+/// following?
+///
+/// ```
+/// enum TypeBindingKind {
+///    Equals(...),
+///    Binding(...),
+/// }
+/// ```
+#[derive(Debug, HashStable_Generic)]
+pub struct TypeBinding<'hir> {
+    pub hir_id: HirId,
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub kind: TypeBindingKind<'hir>,
+    pub span: Span,
+}
+
+// Represents the two kinds of type bindings.
+#[derive(Debug, HashStable_Generic)]
+pub enum TypeBindingKind<'hir> {
+    /// E.g., `Foo<Bar: Send>`.
+    Constraint { bounds: &'hir [GenericBound<'hir>] },
+    /// E.g., `Foo<Bar = ()>`.
+    Equality { ty: &'hir Ty<'hir> },
+}
+
+impl TypeBinding<'_> {
+    pub fn ty(&self) -> &Ty<'_> {
+        match self.kind {
+            TypeBindingKind::Equality { ref ty } => ty,
+            _ => panic!("expected equality type binding for parenthesized generic args"),
+        }
+    }
+}
+
+#[derive(Debug)]
+pub struct Ty<'hir> {
+    pub hir_id: HirId,
+    pub kind: TyKind<'hir>,
+    pub span: Span,
+}
+
+/// Not represented directly in the AST; referred to by name through a `ty_path`.
+#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug)]
+#[derive(HashStable_Generic)]
+pub enum PrimTy {
+    Int(IntTy),
+    Uint(UintTy),
+    Float(FloatTy),
+    Str,
+    Bool,
+    Char,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct BareFnTy<'hir> {
+    pub unsafety: Unsafety,
+    pub abi: Abi,
+    pub generic_params: &'hir [GenericParam<'hir>],
+    pub decl: &'hir FnDecl<'hir>,
+    pub param_names: &'hir [Ident],
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct OpaqueTy<'hir> {
+    pub generics: Generics<'hir>,
+    pub bounds: GenericBounds<'hir>,
+    pub impl_trait_fn: Option<DefId>,
+    pub origin: OpaqueTyOrigin,
+}
+
+/// From whence the opaque type came.
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
+pub enum OpaqueTyOrigin {
+    /// `-> impl Trait`
+    FnReturn,
+    /// `async fn`
+    AsyncFn,
+    /// `let _: impl Trait = ...`
+    Binding,
+    /// Impl trait in type aliases, consts, statics, bounds.
+    Misc,
+}
+
+/// The various kinds of types recognized by the compiler.
+#[derive(Debug, HashStable_Generic)]
+pub enum TyKind<'hir> {
+    /// A variable length slice (i.e., `[T]`).
+    Slice(&'hir Ty<'hir>),
+    /// A fixed length array (i.e., `[T; n]`).
+    Array(&'hir Ty<'hir>, AnonConst),
+    /// A raw pointer (i.e., `*const T` or `*mut T`).
+    Ptr(MutTy<'hir>),
+    /// A reference (i.e., `&'a T` or `&'a mut T`).
+    Rptr(Lifetime, MutTy<'hir>),
+    /// A bare function (e.g., `fn(usize) -> bool`).
+    BareFn(&'hir BareFnTy<'hir>),
+    /// The never type (`!`).
+    Never,
+    /// A tuple (`(A, B, C, D, ...)`).
+    Tup(&'hir [Ty<'hir>]),
+    /// A path to a type definition (`module::module::...::Type`), or an
+    /// associated type (e.g., `<Vec<T> as Trait>::Type` or `<T>::Target`).
+    ///
+    /// Type parameters may be stored in each `PathSegment`.
+    Path(QPath<'hir>),
+    /// A opaque type definition itself. This is currently only used for the
+    /// `opaque type Foo: Trait` item that `impl Trait` in desugars to.
+    ///
+    /// The generic argument list contains the lifetimes (and in the future
+    /// possibly parameters) that are actually bound on the `impl Trait`.
+    OpaqueDef(ItemId, &'hir [GenericArg<'hir>]),
+    /// A trait object type `Bound1 + Bound2 + Bound3`
+    /// where `Bound` is a trait or a lifetime.
+    TraitObject(&'hir [PolyTraitRef<'hir>], Lifetime),
+    /// Unused for now.
+    Typeof(AnonConst),
+    /// `TyKind::Infer` means the type should be inferred instead of it having been
+    /// specified. This can appear anywhere in a type.
+    Infer,
+    /// Placeholder for a type that has failed to be defined.
+    Err,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum InlineAsmOperand<'hir> {
+    In {
+        reg: InlineAsmRegOrRegClass,
+        expr: Expr<'hir>,
+    },
+    Out {
+        reg: InlineAsmRegOrRegClass,
+        late: bool,
+        expr: Option<Expr<'hir>>,
+    },
+    InOut {
+        reg: InlineAsmRegOrRegClass,
+        late: bool,
+        expr: Expr<'hir>,
+    },
+    SplitInOut {
+        reg: InlineAsmRegOrRegClass,
+        late: bool,
+        in_expr: Expr<'hir>,
+        out_expr: Option<Expr<'hir>>,
+    },
+    Const {
+        expr: Expr<'hir>,
+    },
+    Sym {
+        expr: Expr<'hir>,
+    },
+}
+
+impl<'hir> InlineAsmOperand<'hir> {
+    pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
+        match *self {
+            Self::In { reg, .. }
+            | Self::Out { reg, .. }
+            | Self::InOut { reg, .. }
+            | Self::SplitInOut { reg, .. } => Some(reg),
+            Self::Const { .. } | Self::Sym { .. } => None,
+        }
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct InlineAsm<'hir> {
+    pub template: &'hir [InlineAsmTemplatePiece],
+    pub operands: &'hir [InlineAsmOperand<'hir>],
+    pub options: InlineAsmOptions,
+    pub line_spans: &'hir [Span],
+}
+
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
+pub struct LlvmInlineAsmOutput {
+    pub constraint: Symbol,
+    pub is_rw: bool,
+    pub is_indirect: bool,
+    pub span: Span,
+}
+
+// NOTE(eddyb) This is used within MIR as well, so unlike the rest of the HIR,
+// it needs to be `Clone` and `Decodable` and use plain `Vec<T>` instead of
+// arena-allocated slice.
+#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, PartialEq)]
+pub struct LlvmInlineAsmInner {
+    pub asm: Symbol,
+    pub asm_str_style: StrStyle,
+    pub outputs: Vec<LlvmInlineAsmOutput>,
+    pub inputs: Vec<Symbol>,
+    pub clobbers: Vec<Symbol>,
+    pub volatile: bool,
+    pub alignstack: bool,
+    pub dialect: LlvmAsmDialect,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct LlvmInlineAsm<'hir> {
+    pub inner: LlvmInlineAsmInner,
+    pub outputs_exprs: &'hir [Expr<'hir>],
+    pub inputs_exprs: &'hir [Expr<'hir>],
+}
+
+/// Represents a parameter in a function header.
+#[derive(Debug, HashStable_Generic)]
+pub struct Param<'hir> {
+    pub attrs: &'hir [Attribute],
+    pub hir_id: HirId,
+    pub pat: &'hir Pat<'hir>,
+    pub ty_span: Span,
+    pub span: Span,
+}
+
+/// Represents the header (not the body) of a function declaration.
+#[derive(Debug, HashStable_Generic)]
+pub struct FnDecl<'hir> {
+    /// The types of the function's parameters.
+    ///
+    /// Additional argument data is stored in the function's [body](Body::params).
+    pub inputs: &'hir [Ty<'hir>],
+    pub output: FnRetTy<'hir>,
+    pub c_variadic: bool,
+    /// Does the function have an implicit self?
+    pub implicit_self: ImplicitSelfKind,
+}
+
+/// Represents what type of implicit self a function has, if any.
+#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
+pub enum ImplicitSelfKind {
+    /// Represents a `fn x(self);`.
+    Imm,
+    /// Represents a `fn x(mut self);`.
+    Mut,
+    /// Represents a `fn x(&self);`.
+    ImmRef,
+    /// Represents a `fn x(&mut self);`.
+    MutRef,
+    /// Represents when a function does not have a self argument or
+    /// when a function has a `self: X` argument.
+    None,
+}
+
+impl ImplicitSelfKind {
+    /// Does this represent an implicit self?
+    pub fn has_implicit_self(&self) -> bool {
+        match *self {
+            ImplicitSelfKind::None => false,
+            _ => true,
+        }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Encodable, Decodable, Debug)]
+#[derive(HashStable_Generic)]
+pub enum IsAsync {
+    Async,
+    NotAsync,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)]
+pub enum Defaultness {
+    Default { has_value: bool },
+    Final,
+}
+
+impl Defaultness {
+    pub fn has_value(&self) -> bool {
+        match *self {
+            Defaultness::Default { has_value } => has_value,
+            Defaultness::Final => true,
+        }
+    }
+
+    pub fn is_final(&self) -> bool {
+        *self == Defaultness::Final
+    }
+
+    pub fn is_default(&self) -> bool {
+        match *self {
+            Defaultness::Default { .. } => true,
+            _ => false,
+        }
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum FnRetTy<'hir> {
+    /// Return type is not specified.
+    ///
+    /// Functions default to `()` and
+    /// closures default to inference. Span points to where return
+    /// type would be inserted.
+    DefaultReturn(Span),
+    /// Everything else.
+    Return(&'hir Ty<'hir>),
+}
+
+impl FnRetTy<'_> {
+    pub fn span(&self) -> Span {
+        match *self {
+            Self::DefaultReturn(span) => span,
+            Self::Return(ref ty) => ty.span,
+        }
+    }
+}
+
+#[derive(Encodable, Debug)]
+pub struct Mod<'hir> {
+    /// A span from the first token past `{` to the last token until `}`.
+    /// For `mod foo;`, the inner span ranges from the first token
+    /// to the last token in the external file.
+    pub inner: Span,
+    pub item_ids: &'hir [ItemId],
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct ForeignMod<'hir> {
+    pub abi: Abi,
+    pub items: &'hir [ForeignItem<'hir>],
+}
+
+#[derive(Encodable, Debug, HashStable_Generic)]
+pub struct GlobalAsm {
+    pub asm: Symbol,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct EnumDef<'hir> {
+    pub variants: &'hir [Variant<'hir>],
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct Variant<'hir> {
+    /// Name of the variant.
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    /// Attributes of the variant.
+    pub attrs: &'hir [Attribute],
+    /// Id of the variant (not the constructor, see `VariantData::ctor_hir_id()`).
+    pub id: HirId,
+    /// Fields and constructor id of the variant.
+    pub data: VariantData<'hir>,
+    /// Explicit discriminant (e.g., `Foo = 1`).
+    pub disr_expr: Option<AnonConst>,
+    /// Span
+    pub span: Span,
+}
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum UseKind {
+    /// One import, e.g., `use foo::bar` or `use foo::bar as baz`.
+    /// Also produced for each element of a list `use`, e.g.
+    /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`.
+    Single,
+
+    /// Glob import, e.g., `use foo::*`.
+    Glob,
+
+    /// Degenerate list import, e.g., `use foo::{a, b}` produces
+    /// an additional `use foo::{}` for performing checks such as
+    /// unstable feature gating. May be removed in the future.
+    ListStem,
+}
+
+/// References to traits in impls.
+///
+/// `resolve` maps each `TraitRef`'s `ref_id` to its defining trait; that's all
+/// that the `ref_id` is for. Note that `ref_id`'s value is not the `HirId` of the
+/// trait being referred to but just a unique `HirId` that serves as a key
+/// within the resolution map.
+#[derive(Debug, HashStable_Generic)]
+pub struct TraitRef<'hir> {
+    pub path: &'hir Path<'hir>,
+    // Don't hash the `ref_id`. It is tracked via the thing it is used to access.
+    #[stable_hasher(ignore)]
+    pub hir_ref_id: HirId,
+}
+
+impl TraitRef<'_> {
+    /// Gets the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
+    pub fn trait_def_id(&self) -> Option<DefId> {
+        match self.path.res {
+            Res::Def(DefKind::Trait | DefKind::TraitAlias, did) => Some(did),
+            Res::Err => None,
+            _ => unreachable!(),
+        }
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct PolyTraitRef<'hir> {
+    /// The `'a` in `for<'a> Foo<&'a T>`.
+    pub bound_generic_params: &'hir [GenericParam<'hir>],
+
+    /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`.
+    pub trait_ref: TraitRef<'hir>,
+
+    pub span: Span,
+}
+
+pub type Visibility<'hir> = Spanned<VisibilityKind<'hir>>;
+
+#[derive(Debug)]
+pub enum VisibilityKind<'hir> {
+    Public,
+    Crate(CrateSugar),
+    Restricted { path: &'hir Path<'hir>, hir_id: HirId },
+    Inherited,
+}
+
+impl VisibilityKind<'_> {
+    pub fn is_pub(&self) -> bool {
+        match *self {
+            VisibilityKind::Public => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_pub_restricted(&self) -> bool {
+        match *self {
+            VisibilityKind::Public | VisibilityKind::Inherited => false,
+            VisibilityKind::Crate(..) | VisibilityKind::Restricted { .. } => true,
+        }
+    }
+
+    pub fn descr(&self) -> &'static str {
+        match *self {
+            VisibilityKind::Public => "public",
+            VisibilityKind::Inherited => "private",
+            VisibilityKind::Crate(..) => "crate-visible",
+            VisibilityKind::Restricted { .. } => "restricted",
+        }
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct StructField<'hir> {
+    pub span: Span,
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub vis: Visibility<'hir>,
+    pub hir_id: HirId,
+    pub ty: &'hir Ty<'hir>,
+    pub attrs: &'hir [Attribute],
+}
+
+impl StructField<'_> {
+    // Still necessary in couple of places
+    pub fn is_positional(&self) -> bool {
+        let first = self.ident.as_str().as_bytes()[0];
+        first >= b'0' && first <= b'9'
+    }
+}
+
+/// Fields and constructor IDs of enum variants and structs.
+#[derive(Debug, HashStable_Generic)]
+pub enum VariantData<'hir> {
+    /// A struct variant.
+    ///
+    /// E.g., `Bar { .. }` as in `enum Foo { Bar { .. } }`.
+    Struct(&'hir [StructField<'hir>], /* recovered */ bool),
+    /// A tuple variant.
+    ///
+    /// E.g., `Bar(..)` as in `enum Foo { Bar(..) }`.
+    Tuple(&'hir [StructField<'hir>], HirId),
+    /// A unit variant.
+    ///
+    /// E.g., `Bar = ..` as in `enum Foo { Bar = .. }`.
+    Unit(HirId),
+}
+
+impl VariantData<'hir> {
+    /// Return the fields of this variant.
+    pub fn fields(&self) -> &'hir [StructField<'hir>] {
+        match *self {
+            VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => fields,
+            _ => &[],
+        }
+    }
+
+    /// Return the `HirId` of this variant's constructor, if it has one.
+    pub fn ctor_hir_id(&self) -> Option<HirId> {
+        match *self {
+            VariantData::Struct(_, _) => None,
+            VariantData::Tuple(_, hir_id) | VariantData::Unit(hir_id) => Some(hir_id),
+        }
+    }
+}
+
+// The bodies for items are stored "out of line", in a separate
+// hashmap in the `Crate`. Here we just record the node-id of the item
+// so it can fetched later.
+#[derive(Copy, Clone, Encodable, Debug)]
+pub struct ItemId {
+    pub id: HirId,
+}
+
+/// An item
+///
+/// The name might be a dummy name in case of anonymous items
+#[derive(Debug)]
+pub struct Item<'hir> {
+    pub ident: Ident,
+    pub hir_id: HirId,
+    pub attrs: &'hir [Attribute],
+    pub kind: ItemKind<'hir>,
+    pub vis: Visibility<'hir>,
+    pub span: Span,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum Unsafety {
+    Unsafe,
+    Normal,
+}
+
+impl Unsafety {
+    pub fn prefix_str(&self) -> &'static str {
+        match self {
+            Self::Unsafe => "unsafe ",
+            Self::Normal => "",
+        }
+    }
+}
+
+impl fmt::Display for Unsafety {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match *self {
+            Self::Unsafe => "unsafe",
+            Self::Normal => "normal",
+        })
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable_Generic)]
+pub enum Constness {
+    Const,
+    NotConst,
+}
+
+#[derive(Copy, Clone, Encodable, Debug, HashStable_Generic)]
+pub struct FnHeader {
+    pub unsafety: Unsafety,
+    pub constness: Constness,
+    pub asyncness: IsAsync,
+    pub abi: Abi,
+}
+
+impl FnHeader {
+    pub fn is_const(&self) -> bool {
+        match &self.constness {
+            Constness::Const => true,
+            _ => false,
+        }
+    }
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub enum ItemKind<'hir> {
+    /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
+    ///
+    /// E.g., `extern crate foo` or `extern crate foo_bar as foo`.
+    ExternCrate(Option<Symbol>),
+
+    /// `use foo::bar::*;` or `use foo::bar::baz as quux;`
+    ///
+    /// or just
+    ///
+    /// `use foo::bar::baz;` (with `as baz` implicitly on the right).
+    Use(&'hir Path<'hir>, UseKind),
+
+    /// A `static` item.
+    Static(&'hir Ty<'hir>, Mutability, BodyId),
+    /// A `const` item.
+    Const(&'hir Ty<'hir>, BodyId),
+    /// A function declaration.
+    Fn(FnSig<'hir>, Generics<'hir>, BodyId),
+    /// A module.
+    Mod(Mod<'hir>),
+    /// An external module, e.g. `extern { .. }`.
+    ForeignMod(ForeignMod<'hir>),
+    /// Module-level inline assembly (from `global_asm!`).
+    GlobalAsm(&'hir GlobalAsm),
+    /// A type alias, e.g., `type Foo = Bar<u8>`.
+    TyAlias(&'hir Ty<'hir>, Generics<'hir>),
+    /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
+    OpaqueTy(OpaqueTy<'hir>),
+    /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
+    Enum(EnumDef<'hir>, Generics<'hir>),
+    /// A struct definition, e.g., `struct Foo<A> {x: A}`.
+    Struct(VariantData<'hir>, Generics<'hir>),
+    /// A union definition, e.g., `union Foo<A, B> {x: A, y: B}`.
+    Union(VariantData<'hir>, Generics<'hir>),
+    /// A trait definition.
+    Trait(IsAuto, Unsafety, Generics<'hir>, GenericBounds<'hir>, &'hir [TraitItemRef]),
+    /// A trait alias.
+    TraitAlias(Generics<'hir>, GenericBounds<'hir>),
+
+    /// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
+    Impl {
+        unsafety: Unsafety,
+        polarity: ImplPolarity,
+        defaultness: Defaultness,
+        // We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
+        // decoding as `Span`s cannot be decoded when a `Session` is not available.
+        defaultness_span: Option<Span>,
+        constness: Constness,
+        generics: Generics<'hir>,
+
+        /// The trait being implemented, if any.
+        of_trait: Option<TraitRef<'hir>>,
+
+        self_ty: &'hir Ty<'hir>,
+        items: &'hir [ImplItemRef<'hir>],
+    },
+}
+
+impl ItemKind<'_> {
+    pub fn generics(&self) -> Option<&Generics<'_>> {
+        Some(match *self {
+            ItemKind::Fn(_, ref generics, _)
+            | ItemKind::TyAlias(_, ref generics)
+            | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. })
+            | ItemKind::Enum(_, ref generics)
+            | ItemKind::Struct(_, ref generics)
+            | ItemKind::Union(_, ref generics)
+            | ItemKind::Trait(_, _, ref generics, _, _)
+            | ItemKind::Impl { ref generics, .. } => generics,
+            _ => return None,
+        })
+    }
+}
+
+/// A reference from an trait to one of its associated items. This
+/// contains the item's id, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the ID (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Encodable, Debug, HashStable_Generic)]
+pub struct TraitItemRef {
+    pub id: TraitItemId,
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub kind: AssocItemKind,
+    pub span: Span,
+    pub defaultness: Defaultness,
+}
+
+/// A reference from an impl to one of its associated items. This
+/// contains the item's ID, naturally, but also the item's name and
+/// some other high-level details (like whether it is an associated
+/// type or method, and whether it is public). This allows other
+/// passes to find the impl they want without loading the ID (which
+/// means fewer edges in the incremental compilation graph).
+#[derive(Debug, HashStable_Generic)]
+pub struct ImplItemRef<'hir> {
+    pub id: ImplItemId,
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub kind: AssocItemKind,
+    pub span: Span,
+    pub vis: Visibility<'hir>,
+    pub defaultness: Defaultness,
+}
+
+#[derive(Copy, Clone, PartialEq, Encodable, Debug, HashStable_Generic)]
+pub enum AssocItemKind {
+    Const,
+    Fn { has_self: bool },
+    Type,
+}
+
+#[derive(Debug, HashStable_Generic)]
+pub struct ForeignItem<'hir> {
+    #[stable_hasher(project(name))]
+    pub ident: Ident,
+    pub attrs: &'hir [Attribute],
+    pub kind: ForeignItemKind<'hir>,
+    pub hir_id: HirId,
+    pub span: Span,
+    pub vis: Visibility<'hir>,
+}
+
+/// An item within an `extern` block.
+#[derive(Debug, HashStable_Generic)]
+pub enum ForeignItemKind<'hir> {
+    /// A foreign function.
+    Fn(&'hir FnDecl<'hir>, &'hir [Ident], Generics<'hir>),
+    /// A foreign static item (`static ext: u8`).
+    Static(&'hir Ty<'hir>, Mutability),
+    /// A foreign type.
+    Type,
+}
+
+/// A variable captured by a closure.
+#[derive(Debug, Copy, Clone, Encodable, HashStable_Generic)]
+pub struct Upvar {
+    // First span where it is accessed (there can be multiple).
+    pub span: Span,
+}
+
+pub type CaptureModeMap = NodeMap<CaptureBy>;
+
+// The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
+// has length > 0 if the trait is found through an chain of imports, starting with the
+// import/use statement in the scope where the trait is used.
+#[derive(Encodable, Decodable, Clone, Debug)]
+pub struct TraitCandidate {
+    pub def_id: DefId,
+    pub import_ids: SmallVec<[LocalDefId; 1]>,
+}
+
+#[derive(Copy, Clone, Debug, HashStable_Generic)]
+pub enum Node<'hir> {
+    Param(&'hir Param<'hir>),
+    Item(&'hir Item<'hir>),
+    ForeignItem(&'hir ForeignItem<'hir>),
+    TraitItem(&'hir TraitItem<'hir>),
+    ImplItem(&'hir ImplItem<'hir>),
+    Variant(&'hir Variant<'hir>),
+    Field(&'hir StructField<'hir>),
+    AnonConst(&'hir AnonConst),
+    Expr(&'hir Expr<'hir>),
+    Stmt(&'hir Stmt<'hir>),
+    PathSegment(&'hir PathSegment<'hir>),
+    Ty(&'hir Ty<'hir>),
+    TraitRef(&'hir TraitRef<'hir>),
+    Binding(&'hir Pat<'hir>),
+    Pat(&'hir Pat<'hir>),
+    Arm(&'hir Arm<'hir>),
+    Block(&'hir Block<'hir>),
+    Local(&'hir Local<'hir>),
+    MacroDef(&'hir MacroDef<'hir>),
+
+    /// `Ctor` refers to the constructor of an enum variant or struct. Only tuple or unit variants
+    /// with synthesized constructors.
+    Ctor(&'hir VariantData<'hir>),
+
+    Lifetime(&'hir Lifetime),
+    GenericParam(&'hir GenericParam<'hir>),
+    Visibility(&'hir Visibility<'hir>),
+
+    Crate(&'hir CrateItem<'hir>),
+}
+
+impl<'hir> Node<'hir> {
+    pub fn ident(&self) -> Option<Ident> {
+        match self {
+            Node::TraitItem(TraitItem { ident, .. })
+            | Node::ImplItem(ImplItem { ident, .. })
+            | Node::ForeignItem(ForeignItem { ident, .. })
+            | Node::Item(Item { ident, .. }) => Some(*ident),
+            _ => None,
+        }
+    }
+
+    pub fn fn_decl(&self) -> Option<&FnDecl<'hir>> {
+        match self {
+            Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
+            Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
+                Some(fn_decl)
+            }
+            _ => None,
+        }
+    }
+
+    pub fn body_id(&self) -> Option<BodyId> {
+        match self {
+            Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
+                ..
+            })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
+            _ => None,
+        }
+    }
+
+    pub fn generics(&self) -> Option<&'hir Generics<'hir>> {
+        match self {
+            Node::TraitItem(TraitItem { generics, .. })
+            | Node::ImplItem(ImplItem { generics, .. }) => Some(generics),
+            Node::Item(item) => item.kind.generics(),
+            _ => None,
+        }
+    }
+
+    pub fn hir_id(&self) -> Option<HirId> {
+        match self {
+            Node::Item(Item { hir_id, .. })
+            | Node::ForeignItem(ForeignItem { hir_id, .. })
+            | Node::TraitItem(TraitItem { hir_id, .. })
+            | Node::ImplItem(ImplItem { hir_id, .. })
+            | Node::Field(StructField { hir_id, .. })
+            | Node::AnonConst(AnonConst { hir_id, .. })
+            | Node::Expr(Expr { hir_id, .. })
+            | Node::Stmt(Stmt { hir_id, .. })
+            | Node::Ty(Ty { hir_id, .. })
+            | Node::Binding(Pat { hir_id, .. })
+            | Node::Pat(Pat { hir_id, .. })
+            | Node::Arm(Arm { hir_id, .. })
+            | Node::Block(Block { hir_id, .. })
+            | Node::Local(Local { hir_id, .. })
+            | Node::MacroDef(MacroDef { hir_id, .. })
+            | Node::Lifetime(Lifetime { hir_id, .. })
+            | Node::Param(Param { hir_id, .. })
+            | Node::GenericParam(GenericParam { hir_id, .. }) => Some(*hir_id),
+            Node::TraitRef(TraitRef { hir_ref_id, .. }) => Some(*hir_ref_id),
+            Node::PathSegment(PathSegment { hir_id, .. }) => *hir_id,
+            Node::Variant(Variant { id, .. }) => Some(*id),
+            Node::Ctor(variant) => variant.ctor_hir_id(),
+            Node::Crate(_) | Node::Visibility(_) => None,
+        }
+    }
+}
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
new file mode 100644
index 00000000000..fea850c12d9
--- /dev/null
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -0,0 +1,49 @@
+use crate::def_id::{LocalDefId, CRATE_DEF_INDEX};
+use std::fmt;
+
+/// Uniquely identifies a node in the HIR of the current crate. It is
+/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
+/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
+/// and the `local_id` which is unique within the given owner.
+///
+/// This two-level structure makes for more stable values: One can move an item
+/// around within the source code, or add or remove stuff before it, without
+/// the `local_id` part of the `HirId` changing, which is a very useful property in
+/// incremental compilation where we have to persist things through changes to
+/// the code base.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
+#[derive(Encodable, Decodable)]
+pub struct HirId {
+    pub owner: LocalDefId,
+    pub local_id: ItemLocalId,
+}
+
+impl fmt::Display for HirId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+rustc_data_structures::define_id_collections!(HirIdMap, HirIdSet, HirId);
+rustc_data_structures::define_id_collections!(ItemLocalMap, ItemLocalSet, ItemLocalId);
+
+rustc_index::newtype_index! {
+    /// An `ItemLocalId` uniquely identifies something within a given "item-like";
+    /// that is, within a `hir::Item`, `hir::TraitItem`, or `hir::ImplItem`. There is no
+    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
+    /// the node's position within the owning item in any way, but there is a
+    /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
+    /// integers starting at zero, so a mapping that maps all or most nodes within
+    /// an "item-like" to something else can be implemented by a `Vec` instead of a
+    /// tree or hash map.
+    pub struct ItemLocalId { .. }
+}
+rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId);
+
+/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`.
+pub const CRATE_HIR_ID: HirId = HirId {
+    owner: LocalDefId { local_def_index: CRATE_DEF_INDEX },
+    local_id: ItemLocalId::from_u32(0),
+};
+
+pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
new file mode 100644
index 00000000000..76cf6bd4776
--- /dev/null
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -0,0 +1,1222 @@
+//! HIR walker for walking the contents of nodes.
+//!
+//! **For an overview of the visitor strategy, see the docs on the
+//! `super::itemlikevisit::ItemLikeVisitor` trait.**
+//!
+//! If you have decided to use this visitor, here are some general
+//! notes on how to do so:
+//!
+//! Each overridden visit method has full control over what
+//! happens with its node, it can do its own traversal of the node's children,
+//! call `intravisit::walk_*` to apply the default traversal algorithm, or prevent
+//! deeper traversal by doing nothing.
+//!
+//! When visiting the HIR, the contents of nested items are NOT visited
+//! by default. This is different from the AST visitor, which does a deep walk.
+//! Hence this module is called `intravisit`; see the method `visit_nested_item`
+//! for more details.
+//!
+//! Note: it is an important invariant that the default visitor walks
+//! the body of a function in "execution order" - more concretely, if
+//! we consider the reverse post-order (RPO) of the CFG implied by the HIR,
+//! then a pre-order traversal of the HIR is consistent with the CFG RPO
+//! on the *initial CFG point* of each HIR node, while a post-order traversal
+//! of the HIR is consistent with the CFG RPO on each *final CFG point* of
+//! each CFG node.
+//!
+//! One thing that follows is that if HIR node A always starts/ends executing
+//! before HIR node B, then A appears in traversal pre/postorder before B,
+//! respectively. (This follows from RPO respecting CFG domination).
+//!
+//! This order consistency is required in a few places in rustc, for
+//! example generator inference, and possibly also HIR borrowck.
+
+use crate::hir::*;
+use crate::hir_id::CRATE_HIR_ID;
+use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor};
+use rustc_ast::walk_list;
+use rustc_ast::{Attribute, Label};
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::Span;
+
+pub struct DeepVisitor<'v, V> {
+    visitor: &'v mut V,
+}
+
+impl<'v, V> DeepVisitor<'v, V> {
+    pub fn new(base: &'v mut V) -> Self {
+        DeepVisitor { visitor: base }
+    }
+}
+
+impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
+where
+    V: Visitor<'hir>,
+{
+    fn visit_item(&mut self, item: &'hir Item<'hir>) {
+        self.visitor.visit_item(item);
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>) {
+        self.visitor.visit_trait_item(trait_item);
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>) {
+        self.visitor.visit_impl_item(impl_item);
+    }
+}
+
+pub trait IntoVisitor<'hir> {
+    type Visitor: Visitor<'hir>;
+    fn into_visitor(&self) -> Self::Visitor;
+}
+
+pub struct ParDeepVisitor<V>(pub V);
+
+impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
+where
+    V: IntoVisitor<'hir>,
+{
+    fn visit_item(&self, item: &'hir Item<'hir>) {
+        self.0.into_visitor().visit_item(item);
+    }
+
+    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>) {
+        self.0.into_visitor().visit_trait_item(trait_item);
+    }
+
+    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>) {
+        self.0.into_visitor().visit_impl_item(impl_item);
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum FnKind<'a> {
+    /// `#[xxx] pub async/const/extern "Abi" fn foo()`
+    ItemFn(Ident, &'a Generics<'a>, FnHeader, &'a Visibility<'a>, &'a [Attribute]),
+
+    /// `fn foo(&self)`
+    Method(Ident, &'a FnSig<'a>, Option<&'a Visibility<'a>>, &'a [Attribute]),
+
+    /// `|x, y| {}`
+    Closure(&'a [Attribute]),
+}
+
+impl<'a> FnKind<'a> {
+    pub fn attrs(&self) -> &'a [Attribute] {
+        match *self {
+            FnKind::ItemFn(.., attrs) => attrs,
+            FnKind::Method(.., attrs) => attrs,
+            FnKind::Closure(attrs) => attrs,
+        }
+    }
+
+    pub fn header(&self) -> Option<&FnHeader> {
+        match *self {
+            FnKind::ItemFn(_, _, ref header, _, _) => Some(header),
+            FnKind::Method(_, ref sig, _, _) => Some(&sig.header),
+            FnKind::Closure(_) => None,
+        }
+    }
+}
+
+/// An abstract representation of the HIR `rustc_middle::hir::map::Map`.
+pub trait Map<'hir> {
+    /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
+    fn find(&self, hir_id: HirId) -> Option<Node<'hir>>;
+    fn body(&self, id: BodyId) -> &'hir Body<'hir>;
+    fn item(&self, id: HirId) -> &'hir Item<'hir>;
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir>;
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>;
+}
+
+/// An erased version of `Map<'hir>`, using dynamic dispatch.
+/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`.
+pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>);
+
+impl<'hir> Map<'hir> for ErasedMap<'hir> {
+    fn find(&self, _: HirId) -> Option<Node<'hir>> {
+        None
+    }
+    fn body(&self, id: BodyId) -> &'hir Body<'hir> {
+        self.0.body(id)
+    }
+    fn item(&self, id: HirId) -> &'hir Item<'hir> {
+        self.0.item(id)
+    }
+    fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
+        self.0.trait_item(id)
+    }
+    fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
+        self.0.impl_item(id)
+    }
+}
+
+/// Specifies what nested things a visitor wants to visit. The most
+/// common choice is `OnlyBodies`, which will cause the visitor to
+/// visit fn bodies for fns that it encounters, but skip over nested
+/// item-like things.
+///
+/// See the comments on `ItemLikeVisitor` for more details on the overall
+/// visit strategy.
+pub enum NestedVisitorMap<M> {
+    /// Do not visit any nested things. When you add a new
+    /// "non-nested" thing, you will want to audit such uses to see if
+    /// they remain valid.
+    ///
+    /// Use this if you are only walking some particular kind of tree
+    /// (i.e., a type, or fn signature) and you don't want to thread a
+    /// HIR map around.
+    None,
+
+    /// Do not visit nested item-like things, but visit nested things
+    /// that are inside of an item-like.
+    ///
+    /// **This is the most common choice.** A very common pattern is
+    /// to use `visit_all_item_likes()` as an outer loop,
+    /// and to have the visitor that visits the contents of each item
+    /// using this setting.
+    OnlyBodies(M),
+
+    /// Visits all nested things, including item-likes.
+    ///
+    /// **This is an unusual choice.** It is used when you want to
+    /// process everything within their lexical context. Typically you
+    /// kick off the visit by doing `walk_krate()`.
+    All(M),
+}
+
+impl<M> NestedVisitorMap<M> {
+    /// Returns the map to use for an "intra item-like" thing (if any).
+    /// E.g., function body.
+    fn intra(self) -> Option<M> {
+        match self {
+            NestedVisitorMap::None => None,
+            NestedVisitorMap::OnlyBodies(map) => Some(map),
+            NestedVisitorMap::All(map) => Some(map),
+        }
+    }
+
+    /// Returns the map to use for an "item-like" thing (if any).
+    /// E.g., item, impl-item.
+    fn inter(self) -> Option<M> {
+        match self {
+            NestedVisitorMap::None => None,
+            NestedVisitorMap::OnlyBodies(_) => None,
+            NestedVisitorMap::All(map) => Some(map),
+        }
+    }
+}
+
+/// Each method of the Visitor trait is a hook to be potentially
+/// overridden. Each method's default implementation recursively visits
+/// the substructure of the input via the corresponding `walk` method;
+/// e.g., the `visit_mod` method by default calls `intravisit::walk_mod`.
+///
+/// Note that this visitor does NOT visit nested items by default
+/// (this is why the module is called `intravisit`, to distinguish it
+/// from the AST's `visit` module, which acts differently). If you
+/// simply want to visit all items in the crate in some order, you
+/// should call `Crate::visit_all_items`. Otherwise, see the comment
+/// on `visit_nested_item` for details on how to visit nested items.
+///
+/// If you want to ensure that your code handles every variant
+/// explicitly, you need to override each method. (And you also need
+/// to monitor future changes to `Visitor` in case a new method with a
+/// new default implementation gets introduced.)
+pub trait Visitor<'v>: Sized {
+    type Map: Map<'v>;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Nested items.
+
+    /// The default versions of the `visit_nested_XXX` routines invoke
+    /// this method to get a map to use. By selecting an enum variant,
+    /// you control which kinds of nested HIR are visited; see
+    /// `NestedVisitorMap` for details. By "nested HIR", we are
+    /// referring to bits of HIR that are not directly embedded within
+    /// one another but rather indirectly, through a table in the
+    /// crate. This is done to control dependencies during incremental
+    /// compilation: the non-inline bits of HIR can be tracked and
+    /// hashed separately.
+    ///
+    /// **If for some reason you want the nested behavior, but don't
+    /// have a `Map` at your disposal:** then you should override the
+    /// `visit_nested_XXX` methods, and override this method to
+    /// `panic!()`. This way, if a new `visit_nested_XXX` variant is
+    /// added in the future, we will see the panic in your code and
+    /// fix it appropriately.
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map>;
+
+    /// Invoked when a nested item is encountered. By default does
+    /// nothing unless you override `nested_visit_map` to return other than
+    /// `None`, in which case it will walk the item. **You probably
+    /// don't want to override this method** -- instead, override
+    /// `nested_visit_map` or use the "shallow" or "deep" visit
+    /// patterns described on `itemlikevisit::ItemLikeVisitor`. The only
+    /// reason to override this method is if you want a nested pattern
+    /// but cannot supply a `Map`; see `nested_visit_map` for advice.
+    #[allow(unused_variables)]
+    fn visit_nested_item(&mut self, id: ItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.item(id.id));
+        walk_list!(self, visit_item, opt_item);
+    }
+
+    /// Like `visit_nested_item()`, but for trait items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    #[allow(unused_variables)]
+    fn visit_nested_trait_item(&mut self, id: TraitItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.trait_item(id));
+        walk_list!(self, visit_trait_item, opt_item);
+    }
+
+    /// Like `visit_nested_item()`, but for impl items. See
+    /// `visit_nested_item()` for advice on when to override this
+    /// method.
+    #[allow(unused_variables)]
+    fn visit_nested_impl_item(&mut self, id: ImplItemId) {
+        let opt_item = self.nested_visit_map().inter().map(|map| map.impl_item(id));
+        walk_list!(self, visit_impl_item, opt_item);
+    }
+
+    /// Invoked to visit the body of a function, method or closure. Like
+    /// visit_nested_item, does nothing by default unless you override
+    /// `nested_visit_map` to return other than `None`, in which case it will walk
+    /// the body.
+    fn visit_nested_body(&mut self, id: BodyId) {
+        let opt_body = self.nested_visit_map().intra().map(|map| map.body(id));
+        walk_list!(self, visit_body, opt_body);
+    }
+
+    fn visit_param(&mut self, param: &'v Param<'v>) {
+        walk_param(self, param)
+    }
+
+    /// Visits the top-level item and (optionally) nested items / impl items. See
+    /// `visit_nested_item` for details.
+    fn visit_item(&mut self, i: &'v Item<'v>) {
+        walk_item(self, i)
+    }
+
+    fn visit_body(&mut self, b: &'v Body<'v>) {
+        walk_body(self, b);
+    }
+
+    /// When invoking `visit_all_item_likes()`, you need to supply an
+    /// item-like visitor. This method converts a "intra-visit"
+    /// visitor into an item-like visitor that walks the entire tree.
+    /// If you use this, you probably don't want to process the
+    /// contents of nested item-like things, since the outer loop will
+    /// visit them as well.
+    fn as_deep_visitor(&mut self) -> DeepVisitor<'_, Self> {
+        DeepVisitor::new(self)
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    fn visit_id(&mut self, _hir_id: HirId) {
+        // Nothing to do.
+    }
+    fn visit_name(&mut self, _span: Span, _name: Symbol) {
+        // Nothing to do.
+    }
+    fn visit_ident(&mut self, ident: Ident) {
+        walk_ident(self, ident)
+    }
+    fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, n: HirId) {
+        walk_mod(self, m, n)
+    }
+    fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) {
+        walk_foreign_item(self, i)
+    }
+    fn visit_local(&mut self, l: &'v Local<'v>) {
+        walk_local(self, l)
+    }
+    fn visit_block(&mut self, b: &'v Block<'v>) {
+        walk_block(self, b)
+    }
+    fn visit_stmt(&mut self, s: &'v Stmt<'v>) {
+        walk_stmt(self, s)
+    }
+    fn visit_arm(&mut self, a: &'v Arm<'v>) {
+        walk_arm(self, a)
+    }
+    fn visit_pat(&mut self, p: &'v Pat<'v>) {
+        walk_pat(self, p)
+    }
+    fn visit_anon_const(&mut self, c: &'v AnonConst) {
+        walk_anon_const(self, c)
+    }
+    fn visit_expr(&mut self, ex: &'v Expr<'v>) {
+        walk_expr(self, ex)
+    }
+    fn visit_ty(&mut self, t: &'v Ty<'v>) {
+        walk_ty(self, t)
+    }
+    fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) {
+        walk_generic_param(self, p)
+    }
+    fn visit_generics(&mut self, g: &'v Generics<'v>) {
+        walk_generics(self, g)
+    }
+    fn visit_where_predicate(&mut self, predicate: &'v WherePredicate<'v>) {
+        walk_where_predicate(self, predicate)
+    }
+    fn visit_fn_decl(&mut self, fd: &'v FnDecl<'v>) {
+        walk_fn_decl(self, fd)
+    }
+    fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl<'v>, b: BodyId, s: Span, id: HirId) {
+        walk_fn(self, fk, fd, b, s, id)
+    }
+    fn visit_use(&mut self, path: &'v Path<'v>, hir_id: HirId) {
+        walk_use(self, path, hir_id)
+    }
+    fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) {
+        walk_trait_item(self, ti)
+    }
+    fn visit_trait_item_ref(&mut self, ii: &'v TraitItemRef) {
+        walk_trait_item_ref(self, ii)
+    }
+    fn visit_impl_item(&mut self, ii: &'v ImplItem<'v>) {
+        walk_impl_item(self, ii)
+    }
+    fn visit_impl_item_ref(&mut self, ii: &'v ImplItemRef<'v>) {
+        walk_impl_item_ref(self, ii)
+    }
+    fn visit_trait_ref(&mut self, t: &'v TraitRef<'v>) {
+        walk_trait_ref(self, t)
+    }
+    fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) {
+        walk_param_bound(self, bounds)
+    }
+    fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>, m: TraitBoundModifier) {
+        walk_poly_trait_ref(self, t, m)
+    }
+    fn visit_variant_data(
+        &mut self,
+        s: &'v VariantData<'v>,
+        _: Symbol,
+        _: &'v Generics<'v>,
+        _parent_id: HirId,
+        _: Span,
+    ) {
+        walk_struct_def(self, s)
+    }
+    fn visit_struct_field(&mut self, s: &'v StructField<'v>) {
+        walk_struct_field(self, s)
+    }
+    fn visit_enum_def(
+        &mut self,
+        enum_definition: &'v EnumDef<'v>,
+        generics: &'v Generics<'v>,
+        item_id: HirId,
+        _: Span,
+    ) {
+        walk_enum_def(self, enum_definition, generics, item_id)
+    }
+    fn visit_variant(&mut self, v: &'v Variant<'v>, g: &'v Generics<'v>, item_id: HirId) {
+        walk_variant(self, v, g, item_id)
+    }
+    fn visit_label(&mut self, label: &'v Label) {
+        walk_label(self, label)
+    }
+    fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) {
+        match generic_arg {
+            GenericArg::Lifetime(lt) => self.visit_lifetime(lt),
+            GenericArg::Type(ty) => self.visit_ty(ty),
+            GenericArg::Const(ct) => self.visit_anon_const(&ct.value),
+        }
+    }
+    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
+        walk_lifetime(self, lifetime)
+    }
+    fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, span: Span) {
+        walk_qpath(self, qpath, id, span)
+    }
+    fn visit_path(&mut self, path: &'v Path<'v>, _id: HirId) {
+        walk_path(self, path)
+    }
+    fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment<'v>) {
+        walk_path_segment(self, path_span, path_segment)
+    }
+    fn visit_generic_args(&mut self, path_span: Span, generic_args: &'v GenericArgs<'v>) {
+        walk_generic_args(self, path_span, generic_args)
+    }
+    fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding<'v>) {
+        walk_assoc_type_binding(self, type_binding)
+    }
+    fn visit_attribute(&mut self, _attr: &'v Attribute) {}
+    fn visit_macro_def(&mut self, macro_def: &'v MacroDef<'v>) {
+        walk_macro_def(self, macro_def)
+    }
+    fn visit_vis(&mut self, vis: &'v Visibility<'v>) {
+        walk_vis(self, vis)
+    }
+    fn visit_associated_item_kind(&mut self, kind: &'v AssocItemKind) {
+        walk_associated_item_kind(self, kind);
+    }
+    fn visit_defaultness(&mut self, defaultness: &'v Defaultness) {
+        walk_defaultness(self, defaultness);
+    }
+}
+
+/// Walks the contents of a crate. See also `Crate::visit_all_items`.
+pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) {
+    visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID);
+    walk_list!(visitor, visit_attribute, krate.item.attrs);
+    walk_list!(visitor, visit_macro_def, krate.exported_macros);
+}
+
+pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef<'v>) {
+    visitor.visit_id(macro_def.hir_id);
+    visitor.visit_ident(macro_def.ident);
+    walk_list!(visitor, visit_attribute, macro_def.attrs);
+}
+
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod<'v>, mod_hir_id: HirId) {
+    visitor.visit_id(mod_hir_id);
+    for &item_id in module.item_ids {
+        visitor.visit_nested_item(item_id);
+    }
+}
+
+pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body<'v>) {
+    walk_list!(visitor, visit_param, body.params);
+    visitor.visit_expr(&body.value);
+}
+
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local<'v>) {
+    // Intentionally visiting the expr first - the initialization expr
+    // dominates the local's definition.
+    walk_list!(visitor, visit_expr, &local.init);
+    walk_list!(visitor, visit_attribute, local.attrs.iter());
+    visitor.visit_id(local.hir_id);
+    visitor.visit_pat(&local.pat);
+    walk_list!(visitor, visit_ty, &local.ty);
+}
+
+pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, ident: Ident) {
+    visitor.visit_name(ident.span, ident.name);
+}
+
+pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) {
+    visitor.visit_ident(label.ident);
+}
+
+pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+    visitor.visit_id(lifetime.hir_id);
+    match lifetime.name {
+        LifetimeName::Param(ParamName::Plain(ident)) => {
+            visitor.visit_ident(ident);
+        }
+        LifetimeName::Param(ParamName::Fresh(_))
+        | LifetimeName::Param(ParamName::Error)
+        | LifetimeName::Static
+        | LifetimeName::Error
+        | LifetimeName::Implicit
+        | LifetimeName::ImplicitObjectLifetimeDefault
+        | LifetimeName::Underscore => {}
+    }
+}
+
+pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    trait_ref: &'v PolyTraitRef<'v>,
+    _modifier: TraitBoundModifier,
+) {
+    walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params);
+    visitor.visit_trait_ref(&trait_ref.trait_ref);
+}
+
+pub fn walk_trait_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_ref: &'v TraitRef<'v>) {
+    visitor.visit_id(trait_ref.hir_ref_id);
+    visitor.visit_path(&trait_ref.path, trait_ref.hir_ref_id)
+}
+
+pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) {
+    visitor.visit_id(param.hir_id);
+    visitor.visit_pat(&param.pat);
+    walk_list!(visitor, visit_attribute, param.attrs);
+}
+
+pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
+    visitor.visit_vis(&item.vis);
+    visitor.visit_ident(item.ident);
+    match item.kind {
+        ItemKind::ExternCrate(orig_name) => {
+            visitor.visit_id(item.hir_id);
+            if let Some(orig_name) = orig_name {
+                visitor.visit_name(item.span, orig_name);
+            }
+        }
+        ItemKind::Use(ref path, _) => {
+            visitor.visit_use(path, item.hir_id);
+        }
+        ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => {
+            visitor.visit_id(item.hir_id);
+            visitor.visit_ty(typ);
+            visitor.visit_nested_body(body);
+        }
+        ItemKind::Fn(ref sig, ref generics, body_id) => visitor.visit_fn(
+            FnKind::ItemFn(item.ident, generics, sig.header, &item.vis, &item.attrs),
+            &sig.decl,
+            body_id,
+            item.span,
+            item.hir_id,
+        ),
+        ItemKind::Mod(ref module) => {
+            // `visit_mod()` takes care of visiting the `Item`'s `HirId`.
+            visitor.visit_mod(module, item.span, item.hir_id)
+        }
+        ItemKind::ForeignMod(ref foreign_module) => {
+            visitor.visit_id(item.hir_id);
+            walk_list!(visitor, visit_foreign_item, foreign_module.items);
+        }
+        ItemKind::GlobalAsm(_) => {
+            visitor.visit_id(item.hir_id);
+        }
+        ItemKind::TyAlias(ref ty, ref generics) => {
+            visitor.visit_id(item.hir_id);
+            visitor.visit_ty(ty);
+            visitor.visit_generics(generics)
+        }
+        ItemKind::OpaqueTy(OpaqueTy { ref generics, bounds, .. }) => {
+            visitor.visit_id(item.hir_id);
+            walk_generics(visitor, generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
+        ItemKind::Enum(ref enum_definition, ref generics) => {
+            visitor.visit_generics(generics);
+            // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
+            visitor.visit_enum_def(enum_definition, generics, item.hir_id, item.span)
+        }
+        ItemKind::Impl {
+            unsafety: _,
+            defaultness: _,
+            polarity: _,
+            constness: _,
+            defaultness_span: _,
+            ref generics,
+            ref of_trait,
+            ref self_ty,
+            items,
+        } => {
+            visitor.visit_id(item.hir_id);
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_trait_ref, of_trait);
+            visitor.visit_ty(self_ty);
+            walk_list!(visitor, visit_impl_item_ref, items);
+        }
+        ItemKind::Struct(ref struct_definition, ref generics)
+        | ItemKind::Union(ref struct_definition, ref generics) => {
+            visitor.visit_generics(generics);
+            visitor.visit_id(item.hir_id);
+            visitor.visit_variant_data(
+                struct_definition,
+                item.ident.name,
+                generics,
+                item.hir_id,
+                item.span,
+            );
+        }
+        ItemKind::Trait(.., ref generics, bounds, trait_item_refs) => {
+            visitor.visit_id(item.hir_id);
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_trait_item_ref, trait_item_refs);
+        }
+        ItemKind::TraitAlias(ref generics, bounds) => {
+            visitor.visit_id(item.hir_id);
+            visitor.visit_generics(generics);
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
+    }
+    walk_list!(visitor, visit_attribute, item.attrs);
+}
+
+pub fn walk_use<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>, hir_id: HirId) {
+    visitor.visit_id(hir_id);
+    visitor.visit_path(path, hir_id);
+}
+
+pub fn walk_enum_def<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    enum_definition: &'v EnumDef<'v>,
+    generics: &'v Generics<'v>,
+    item_id: HirId,
+) {
+    visitor.visit_id(item_id);
+    walk_list!(visitor, visit_variant, enum_definition.variants, generics, item_id);
+}
+
+pub fn walk_variant<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    variant: &'v Variant<'v>,
+    generics: &'v Generics<'v>,
+    parent_item_id: HirId,
+) {
+    visitor.visit_ident(variant.ident);
+    visitor.visit_id(variant.id);
+    visitor.visit_variant_data(
+        &variant.data,
+        variant.ident.name,
+        generics,
+        parent_item_id,
+        variant.span,
+    );
+    walk_list!(visitor, visit_anon_const, &variant.disr_expr);
+    walk_list!(visitor, visit_attribute, variant.attrs);
+}
+
+pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) {
+    visitor.visit_id(typ.hir_id);
+
+    match typ.kind {
+        TyKind::Slice(ref ty) => visitor.visit_ty(ty),
+        TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty),
+        TyKind::Rptr(ref lifetime, ref mutable_type) => {
+            visitor.visit_lifetime(lifetime);
+            visitor.visit_ty(&mutable_type.ty)
+        }
+        TyKind::Never => {}
+        TyKind::Tup(tuple_element_types) => {
+            walk_list!(visitor, visit_ty, tuple_element_types);
+        }
+        TyKind::BareFn(ref function_declaration) => {
+            walk_list!(visitor, visit_generic_param, function_declaration.generic_params);
+            visitor.visit_fn_decl(&function_declaration.decl);
+        }
+        TyKind::Path(ref qpath) => {
+            visitor.visit_qpath(qpath, typ.hir_id, typ.span);
+        }
+        TyKind::OpaqueDef(item_id, lifetimes) => {
+            visitor.visit_nested_item(item_id);
+            walk_list!(visitor, visit_generic_arg, lifetimes);
+        }
+        TyKind::Array(ref ty, ref length) => {
+            visitor.visit_ty(ty);
+            visitor.visit_anon_const(length)
+        }
+        TyKind::TraitObject(bounds, ref lifetime) => {
+            for bound in bounds {
+                visitor.visit_poly_trait_ref(bound, TraitBoundModifier::None);
+            }
+            visitor.visit_lifetime(lifetime);
+        }
+        TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression),
+        TyKind::Infer | TyKind::Err => {}
+    }
+}
+
+pub fn walk_qpath<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    qpath: &'v QPath<'v>,
+    id: HirId,
+    span: Span,
+) {
+    match *qpath {
+        QPath::Resolved(ref maybe_qself, ref path) => {
+            walk_list!(visitor, visit_ty, maybe_qself);
+            visitor.visit_path(path, id)
+        }
+        QPath::TypeRelative(ref qself, ref segment) => {
+            visitor.visit_ty(qself);
+            visitor.visit_path_segment(span, segment);
+        }
+        QPath::LangItem(..) => {}
+    }
+}
+
+pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path<'v>) {
+    for segment in path.segments {
+        visitor.visit_path_segment(path.span, segment);
+    }
+}
+
+pub fn walk_path_segment<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    path_span: Span,
+    segment: &'v PathSegment<'v>,
+) {
+    visitor.visit_ident(segment.ident);
+    walk_list!(visitor, visit_id, segment.hir_id);
+    if let Some(ref args) = segment.args {
+        visitor.visit_generic_args(path_span, args);
+    }
+}
+
+pub fn walk_generic_args<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    _path_span: Span,
+    generic_args: &'v GenericArgs<'v>,
+) {
+    walk_list!(visitor, visit_generic_arg, generic_args.args);
+    walk_list!(visitor, visit_assoc_type_binding, generic_args.bindings);
+}
+
+pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    type_binding: &'v TypeBinding<'v>,
+) {
+    visitor.visit_id(type_binding.hir_id);
+    visitor.visit_ident(type_binding.ident);
+    match type_binding.kind {
+        TypeBindingKind::Equality { ref ty } => {
+            visitor.visit_ty(ty);
+        }
+        TypeBindingKind::Constraint { bounds } => {
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
+    }
+}
+
+pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) {
+    visitor.visit_id(pattern.hir_id);
+    match pattern.kind {
+        PatKind::TupleStruct(ref qpath, children, _) => {
+            visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
+            walk_list!(visitor, visit_pat, children);
+        }
+        PatKind::Path(ref qpath) => {
+            visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
+        }
+        PatKind::Struct(ref qpath, fields, _) => {
+            visitor.visit_qpath(qpath, pattern.hir_id, pattern.span);
+            for field in fields {
+                visitor.visit_id(field.hir_id);
+                visitor.visit_ident(field.ident);
+                visitor.visit_pat(&field.pat)
+            }
+        }
+        PatKind::Or(pats) => walk_list!(visitor, visit_pat, pats),
+        PatKind::Tuple(tuple_elements, _) => {
+            walk_list!(visitor, visit_pat, tuple_elements);
+        }
+        PatKind::Box(ref subpattern) | PatKind::Ref(ref subpattern, _) => {
+            visitor.visit_pat(subpattern)
+        }
+        PatKind::Binding(_, _hir_id, ident, ref optional_subpattern) => {
+            visitor.visit_ident(ident);
+            walk_list!(visitor, visit_pat, optional_subpattern);
+        }
+        PatKind::Lit(ref expression) => visitor.visit_expr(expression),
+        PatKind::Range(ref lower_bound, ref upper_bound, _) => {
+            walk_list!(visitor, visit_expr, lower_bound);
+            walk_list!(visitor, visit_expr, upper_bound);
+        }
+        PatKind::Wild => (),
+        PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
+            walk_list!(visitor, visit_pat, prepatterns);
+            walk_list!(visitor, visit_pat, slice_pattern);
+            walk_list!(visitor, visit_pat, postpatterns);
+        }
+    }
+}
+
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem<'v>) {
+    visitor.visit_id(foreign_item.hir_id);
+    visitor.visit_vis(&foreign_item.vis);
+    visitor.visit_ident(foreign_item.ident);
+
+    match foreign_item.kind {
+        ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => {
+            visitor.visit_generics(generics);
+            visitor.visit_fn_decl(function_declaration);
+            for &param_name in param_names {
+                visitor.visit_ident(param_name);
+            }
+        }
+        ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
+        ForeignItemKind::Type => (),
+    }
+
+    walk_list!(visitor, visit_attribute, foreign_item.attrs);
+}
+
+pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound<'v>) {
+    match *bound {
+        GenericBound::Trait(ref typ, modifier) => {
+            visitor.visit_poly_trait_ref(typ, modifier);
+        }
+        GenericBound::LangItemTrait(_, span, hir_id, args) => {
+            visitor.visit_id(hir_id);
+            visitor.visit_generic_args(span, args);
+        }
+        GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime),
+    }
+}
+
+pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam<'v>) {
+    visitor.visit_id(param.hir_id);
+    walk_list!(visitor, visit_attribute, param.attrs);
+    match param.name {
+        ParamName::Plain(ident) => visitor.visit_ident(ident),
+        ParamName::Error | ParamName::Fresh(_) => {}
+    }
+    match param.kind {
+        GenericParamKind::Lifetime { .. } => {}
+        GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
+        GenericParamKind::Const { ref ty } => visitor.visit_ty(ty),
+    }
+    walk_list!(visitor, visit_param_bound, param.bounds);
+}
+
+pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) {
+    walk_list!(visitor, visit_generic_param, generics.params);
+    walk_list!(visitor, visit_where_predicate, generics.where_clause.predicates);
+}
+
+pub fn walk_where_predicate<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    predicate: &'v WherePredicate<'v>,
+) {
+    match predicate {
+        &WherePredicate::BoundPredicate(WhereBoundPredicate {
+            ref bounded_ty,
+            bounds,
+            bound_generic_params,
+            ..
+        }) => {
+            visitor.visit_ty(bounded_ty);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_generic_param, bound_generic_params);
+        }
+        &WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
+            visitor.visit_lifetime(lifetime);
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
+        &WherePredicate::EqPredicate(WhereEqPredicate {
+            hir_id, ref lhs_ty, ref rhs_ty, ..
+        }) => {
+            visitor.visit_id(hir_id);
+            visitor.visit_ty(lhs_ty);
+            visitor.visit_ty(rhs_ty);
+        }
+    }
+}
+
+pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) {
+    if let FnRetTy::Return(ref output_ty) = *ret_ty {
+        visitor.visit_ty(output_ty)
+    }
+}
+
+pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl<'v>) {
+    for ty in function_declaration.inputs {
+        visitor.visit_ty(ty)
+    }
+    walk_fn_ret_ty(visitor, &function_declaration.output)
+}
+
+pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
+    match function_kind {
+        FnKind::ItemFn(_, generics, ..) => {
+            visitor.visit_generics(generics);
+        }
+        FnKind::Method(..) | FnKind::Closure(_) => {}
+    }
+}
+
+pub fn walk_fn<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    function_kind: FnKind<'v>,
+    function_declaration: &'v FnDecl<'v>,
+    body_id: BodyId,
+    _span: Span,
+    id: HirId,
+) {
+    visitor.visit_id(id);
+    visitor.visit_fn_decl(function_declaration);
+    walk_fn_kind(visitor, function_kind);
+    visitor.visit_nested_body(body_id)
+}
+
+pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
+    visitor.visit_ident(trait_item.ident);
+    walk_list!(visitor, visit_attribute, trait_item.attrs);
+    visitor.visit_generics(&trait_item.generics);
+    match trait_item.kind {
+        TraitItemKind::Const(ref ty, default) => {
+            visitor.visit_id(trait_item.hir_id);
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_nested_body, default);
+        }
+        TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => {
+            visitor.visit_id(trait_item.hir_id);
+            visitor.visit_fn_decl(&sig.decl);
+            for &param_name in param_names {
+                visitor.visit_ident(param_name);
+            }
+        }
+        TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => {
+            visitor.visit_fn(
+                FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs),
+                &sig.decl,
+                body_id,
+                trait_item.span,
+                trait_item.hir_id,
+            );
+        }
+        TraitItemKind::Type(bounds, ref default) => {
+            visitor.visit_id(trait_item.hir_id);
+            walk_list!(visitor, visit_param_bound, bounds);
+            walk_list!(visitor, visit_ty, default);
+        }
+    }
+}
+
+pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: &'v TraitItemRef) {
+    // N.B., deliberately force a compilation error if/when new fields are added.
+    let TraitItemRef { id, ident, ref kind, span: _, ref defaultness } = *trait_item_ref;
+    visitor.visit_nested_trait_item(id);
+    visitor.visit_ident(ident);
+    visitor.visit_associated_item_kind(kind);
+    visitor.visit_defaultness(defaultness);
+}
+
+pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
+    // N.B., deliberately force a compilation error if/when new fields are added.
+    let ImplItem {
+        hir_id: _,
+        ident,
+        ref vis,
+        ref defaultness,
+        attrs,
+        ref generics,
+        ref kind,
+        span: _,
+    } = *impl_item;
+
+    visitor.visit_ident(ident);
+    visitor.visit_vis(vis);
+    visitor.visit_defaultness(defaultness);
+    walk_list!(visitor, visit_attribute, attrs);
+    visitor.visit_generics(generics);
+    match *kind {
+        ImplItemKind::Const(ref ty, body) => {
+            visitor.visit_id(impl_item.hir_id);
+            visitor.visit_ty(ty);
+            visitor.visit_nested_body(body);
+        }
+        ImplItemKind::Fn(ref sig, body_id) => {
+            visitor.visit_fn(
+                FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs),
+                &sig.decl,
+                body_id,
+                impl_item.span,
+                impl_item.hir_id,
+            );
+        }
+        ImplItemKind::TyAlias(ref ty) => {
+            visitor.visit_id(impl_item.hir_id);
+            visitor.visit_ty(ty);
+        }
+    }
+}
+
+pub fn walk_impl_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, impl_item_ref: &'v ImplItemRef<'v>) {
+    // N.B., deliberately force a compilation error if/when new fields are added.
+    let ImplItemRef { id, ident, ref kind, span: _, ref vis, ref defaultness } = *impl_item_ref;
+    visitor.visit_nested_impl_item(id);
+    visitor.visit_ident(ident);
+    visitor.visit_associated_item_kind(kind);
+    visitor.visit_vis(vis);
+    visitor.visit_defaultness(defaultness);
+}
+
+pub fn walk_struct_def<'v, V: Visitor<'v>>(
+    visitor: &mut V,
+    struct_definition: &'v VariantData<'v>,
+) {
+    walk_list!(visitor, visit_id, struct_definition.ctor_hir_id());
+    walk_list!(visitor, visit_struct_field, struct_definition.fields());
+}
+
+pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField<'v>) {
+    visitor.visit_id(struct_field.hir_id);
+    visitor.visit_vis(&struct_field.vis);
+    visitor.visit_ident(struct_field.ident);
+    visitor.visit_ty(&struct_field.ty);
+    walk_list!(visitor, visit_attribute, struct_field.attrs);
+}
+
+pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) {
+    visitor.visit_id(block.hir_id);
+    walk_list!(visitor, visit_stmt, block.stmts);
+    walk_list!(visitor, visit_expr, &block.expr);
+}
+
+pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
+    visitor.visit_id(statement.hir_id);
+    match statement.kind {
+        StmtKind::Local(ref local) => visitor.visit_local(local),
+        StmtKind::Item(item) => visitor.visit_nested_item(item),
+        StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => {
+            visitor.visit_expr(expression)
+        }
+    }
+}
+
+pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
+    visitor.visit_id(constant.hir_id);
+    visitor.visit_nested_body(constant.body);
+}
+
+pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) {
+    visitor.visit_id(expression.hir_id);
+    walk_list!(visitor, visit_attribute, expression.attrs.iter());
+    match expression.kind {
+        ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression),
+        ExprKind::Array(subexpressions) => {
+            walk_list!(visitor, visit_expr, subexpressions);
+        }
+        ExprKind::Repeat(ref element, ref count) => {
+            visitor.visit_expr(element);
+            visitor.visit_anon_const(count)
+        }
+        ExprKind::Struct(ref qpath, fields, ref optional_base) => {
+            visitor.visit_qpath(qpath, expression.hir_id, expression.span);
+            for field in fields {
+                visitor.visit_id(field.hir_id);
+                visitor.visit_ident(field.ident);
+                visitor.visit_expr(&field.expr)
+            }
+            walk_list!(visitor, visit_expr, optional_base);
+        }
+        ExprKind::Tup(subexpressions) => {
+            walk_list!(visitor, visit_expr, subexpressions);
+        }
+        ExprKind::Call(ref callee_expression, arguments) => {
+            visitor.visit_expr(callee_expression);
+            walk_list!(visitor, visit_expr, arguments);
+        }
+        ExprKind::MethodCall(ref segment, _, arguments, _) => {
+            visitor.visit_path_segment(expression.span, segment);
+            walk_list!(visitor, visit_expr, arguments);
+        }
+        ExprKind::Binary(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(left_expression);
+            visitor.visit_expr(right_expression)
+        }
+        ExprKind::AddrOf(_, _, ref subexpression) | ExprKind::Unary(_, ref subexpression) => {
+            visitor.visit_expr(subexpression)
+        }
+        ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_ty(typ)
+        }
+        ExprKind::DropTemps(ref subexpression) => {
+            visitor.visit_expr(subexpression);
+        }
+        ExprKind::Loop(ref block, ref opt_label, _) => {
+            walk_list!(visitor, visit_label, opt_label);
+            visitor.visit_block(block);
+        }
+        ExprKind::Match(ref subexpression, arms, _) => {
+            visitor.visit_expr(subexpression);
+            walk_list!(visitor, visit_arm, arms);
+        }
+        ExprKind::Closure(_, ref function_declaration, body, _fn_decl_span, _gen) => visitor
+            .visit_fn(
+                FnKind::Closure(&expression.attrs),
+                function_declaration,
+                body,
+                expression.span,
+                expression.hir_id,
+            ),
+        ExprKind::Block(ref block, ref opt_label) => {
+            walk_list!(visitor, visit_label, opt_label);
+            visitor.visit_block(block);
+        }
+        ExprKind::Assign(ref lhs, ref rhs, _) => {
+            visitor.visit_expr(rhs);
+            visitor.visit_expr(lhs)
+        }
+        ExprKind::AssignOp(_, ref left_expression, ref right_expression) => {
+            visitor.visit_expr(right_expression);
+            visitor.visit_expr(left_expression);
+        }
+        ExprKind::Field(ref subexpression, ident) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_ident(ident);
+        }
+        ExprKind::Index(ref main_expression, ref index_expression) => {
+            visitor.visit_expr(main_expression);
+            visitor.visit_expr(index_expression)
+        }
+        ExprKind::Path(ref qpath) => {
+            visitor.visit_qpath(qpath, expression.hir_id, expression.span);
+        }
+        ExprKind::Break(ref destination, ref opt_expr) => {
+            walk_list!(visitor, visit_label, &destination.label);
+            walk_list!(visitor, visit_expr, opt_expr);
+        }
+        ExprKind::Continue(ref destination) => {
+            walk_list!(visitor, visit_label, &destination.label);
+        }
+        ExprKind::Ret(ref optional_expression) => {
+            walk_list!(visitor, visit_expr, optional_expression);
+        }
+        ExprKind::InlineAsm(ref asm) => {
+            for op in asm.operands {
+                match op {
+                    InlineAsmOperand::In { expr, .. }
+                    | InlineAsmOperand::InOut { expr, .. }
+                    | InlineAsmOperand::Const { expr, .. }
+                    | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
+                    InlineAsmOperand::Out { expr, .. } => {
+                        if let Some(expr) = expr {
+                            visitor.visit_expr(expr);
+                        }
+                    }
+                    InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
+                        visitor.visit_expr(in_expr);
+                        if let Some(out_expr) = out_expr {
+                            visitor.visit_expr(out_expr);
+                        }
+                    }
+                }
+            }
+        }
+        ExprKind::LlvmInlineAsm(ref asm) => {
+            walk_list!(visitor, visit_expr, asm.outputs_exprs);
+            walk_list!(visitor, visit_expr, asm.inputs_exprs);
+        }
+        ExprKind::Yield(ref subexpression, _) => {
+            visitor.visit_expr(subexpression);
+        }
+        ExprKind::Lit(_) | ExprKind::Err => {}
+    }
+}
+
+pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
+    visitor.visit_id(arm.hir_id);
+    visitor.visit_pat(&arm.pat);
+    if let Some(ref g) = arm.guard {
+        match g {
+            Guard::If(ref e) => visitor.visit_expr(e),
+        }
+    }
+    visitor.visit_expr(&arm.body);
+    walk_list!(visitor, visit_attribute, arm.attrs);
+}
+
+pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility<'v>) {
+    if let VisibilityKind::Restricted { ref path, hir_id } = vis.node {
+        visitor.visit_id(hir_id);
+        visitor.visit_path(path, hir_id)
+    }
+}
+
+pub fn walk_associated_item_kind<'v, V: Visitor<'v>>(_: &mut V, _: &'v AssocItemKind) {
+    // No visitable content here: this fn exists so you can call it if
+    // the right thing to do, should content be added in the future,
+    // would be to walk it.
+}
+
+pub fn walk_defaultness<'v, V: Visitor<'v>>(_: &mut V, _: &'v Defaultness) {
+    // No visitable content here: this fn exists so you can call it if
+    // the right thing to do, should content be added in the future,
+    // would be to walk it.
+}
diff --git a/compiler/rustc_hir/src/itemlikevisit.rs b/compiler/rustc_hir/src/itemlikevisit.rs
new file mode 100644
index 00000000000..369cd49621b
--- /dev/null
+++ b/compiler/rustc_hir/src/itemlikevisit.rs
@@ -0,0 +1,57 @@
+use super::{ImplItem, Item, TraitItem};
+
+/// The "item-like visitor" defines only the top-level methods
+/// that can be invoked by `Crate::visit_all_item_likes()`. Whether
+/// this trait is the right one to implement will depend on the
+/// overall pattern you need. Here are the three available patterns,
+/// in roughly the order of desirability:
+///
+/// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR.
+///    - Example: find all items with a `#[foo]` attribute on them.
+///    - How: Implement `ItemLikeVisitor` and call `tcx.hir().krate().visit_all_item_likes()`.
+///    - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves.
+///    - Con: Don't get information about nesting
+///    - Con: Don't have methods for specific bits of HIR, like "on
+///      every expr, do this".
+/// 2. **Deep visit**: Want to scan for specific kinds of HIR nodes within
+///    an item, but don't care about how item-like things are nested
+///    within one another.
+///    - Example: Examine each expression to look for its type and do some check or other.
+///    - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method
+///      to return `NestedVisitorMap::OnlyBodies` and use
+///      `tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor())`. Within
+///      your `intravisit::Visitor` impl, implement methods like `visit_expr()` (don't forget
+///      to invoke `intravisit::walk_expr()` to keep walking the subparts).
+///    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
+///    - Pro: Integrates well into dependency tracking.
+///    - Con: Don't get information about nesting between items
+/// 3. **Nested visit**: Want to visit the whole HIR and you care about the nesting between
+///    item-like things.
+///    - Example: Lifetime resolution, which wants to bring lifetimes declared on the
+///      impl into scope while visiting the impl-items, and then back out again.
+///    - How: Implement `intravisit::Visitor` and override the `nested_visit_map()` method
+///      to return `NestedVisitorMap::All`. Walk your crate with `intravisit::walk_crate()`
+///      invoked on `tcx.hir().krate()`.
+///    - Pro: Visitor methods for any kind of HIR node, not just item-like things.
+///    - Pro: Preserves nesting information
+///    - Con: Does not integrate well into dependency tracking.
+///
+/// Note: the methods of `ItemLikeVisitor` intentionally have no
+/// defaults, so that as we expand the list of item-like things, we
+/// revisit the various visitors to see if they need to change. This
+/// is harder to do with `intravisit::Visitor`, so when you add a new
+/// `visit_nested_foo()` method, it is recommended that you search for
+/// existing `fn visit_nested` methods to see where changes are
+/// needed.
+pub trait ItemLikeVisitor<'hir> {
+    fn visit_item(&mut self, item: &'hir Item<'hir>);
+    fn visit_trait_item(&mut self, trait_item: &'hir TraitItem<'hir>);
+    fn visit_impl_item(&mut self, impl_item: &'hir ImplItem<'hir>);
+}
+
+/// A parallel variant of `ItemLikeVisitor`.
+pub trait ParItemLikeVisitor<'hir> {
+    fn visit_item(&self, item: &'hir Item<'hir>);
+    fn visit_trait_item(&self, trait_item: &'hir TraitItem<'hir>);
+    fn visit_impl_item(&self, impl_item: &'hir ImplItem<'hir>);
+}
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
new file mode 100644
index 00000000000..acf6847c014
--- /dev/null
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -0,0 +1,334 @@
+//! Defines language items.
+//!
+//! Language items are items that represent concepts intrinsic to the language
+//! itself. Examples are:
+//!
+//! * Traits that specify "kinds"; e.g., `Sync`, `Send`.
+//! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`.
+//! * Functions called by the compiler itself.
+
+use crate::def_id::DefId;
+use crate::{MethodKind, Target};
+
+use rustc_ast as ast;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_macros::HashStable_Generic;
+use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::Span;
+
+use lazy_static::lazy_static;
+
+pub enum LangItemGroup {
+    Op,
+}
+
+const NUM_GROUPS: usize = 1;
+
+macro_rules! expand_group {
+    () => {
+        None
+    };
+    ($group:expr) => {
+        Some($group)
+    };
+}
+
+// The actual lang items defined come at the end of this file in one handy table.
+// So you probably just want to nip down to the end.
+macro_rules! language_item_table {
+    (
+        $( $variant:ident $($group:expr)?, $name:expr, $method:ident, $target:expr; )*
+    ) => {
+
+        enum_from_u32! {
+            /// A representation of all the valid language items in Rust.
+            #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)]
+            pub enum LangItem {
+                $($variant,)*
+            }
+        }
+
+        impl LangItem {
+            /// Returns the `name` symbol in `#[lang = "$name"]`.
+            /// For example, `LangItem::EqTraitLangItem`,
+            /// that is `#[lang = "eq"]` would result in `sym::eq`.
+            pub fn name(self) -> Symbol {
+                match self {
+                    $( LangItem::$variant => $name, )*
+                }
+            }
+
+            pub fn group(self) -> Option<LangItemGroup> {
+                use LangItemGroup::*;
+                match self {
+                    $( LangItem::$variant => expand_group!($($group)*), )*
+                }
+            }
+        }
+
+        #[derive(HashStable_Generic)]
+        pub struct LanguageItems {
+            /// Mappings from lang items to their possibly found `DefId`s.
+            /// The index corresponds to the order in `LangItem`.
+            pub items: Vec<Option<DefId>>,
+            /// Lang items that were not found during collection.
+            pub missing: Vec<LangItem>,
+            /// Mapping from `LangItemGroup` discriminants to all
+            /// `DefId`s of lang items in that group.
+            pub groups: [Vec<DefId>; NUM_GROUPS],
+        }
+
+        impl LanguageItems {
+            /// Construct an empty collection of lang items and no missing ones.
+            pub fn new() -> Self {
+                fn init_none(_: LangItem) -> Option<DefId> { None }
+
+                Self {
+                    items: vec![$(init_none(LangItem::$variant)),*],
+                    missing: Vec::new(),
+                    groups: [vec![]; NUM_GROUPS],
+                }
+            }
+
+            /// Returns the mappings to the possibly found `DefId`s for each lang item.
+            pub fn items(&self) -> &[Option<DefId>] {
+                &*self.items
+            }
+
+            /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
+            /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
+            /// returns an error message as a string.
+            pub fn require(&self, it: LangItem) -> Result<DefId, String> {
+                self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
+            }
+
+            pub fn group(&self, group: LangItemGroup) -> &[DefId] {
+                self.groups[group as usize].as_ref()
+            }
+
+            $(
+                /// Returns the corresponding `DefId` for the lang item if it
+                /// exists.
+                #[allow(dead_code)]
+                pub fn $method(&self) -> Option<DefId> {
+                    self.items[LangItem::$variant as usize]
+                }
+            )*
+        }
+
+        lazy_static! {
+            /// A mapping from the name of the lang item to its order and the form it must be of.
+            pub static ref ITEM_REFS: FxHashMap<Symbol, (usize, Target)> = {
+                let mut item_refs = FxHashMap::default();
+                $( item_refs.insert($name, (LangItem::$variant as usize, $target)); )*
+                item_refs
+            };
+        }
+
+// End of the macro
+    }
+}
+
+impl<CTX> HashStable<CTX> for LangItem {
+    fn hash_stable(&self, _: &mut CTX, hasher: &mut StableHasher) {
+        ::std::hash::Hash::hash(self, hasher);
+    }
+}
+
+/// Extracts the first `lang = "$name"` out of a list of attributes.
+/// The attributes `#[panic_handler]` and `#[alloc_error_handler]`
+/// are also extracted out when found.
+///
+/// About the `check_name` argument: passing in a `Session` would be simpler,
+/// because then we could call `Session::check_name` directly. But we want to
+/// avoid the need for `librustc_hir` to depend on `librustc_session`, so we
+/// use a closure instead.
+pub fn extract<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<(Symbol, Span)>
+where
+    F: Fn(&'a ast::Attribute, Symbol) -> bool,
+{
+    attrs.iter().find_map(|attr| {
+        Some(match attr {
+            _ if check_name(attr, sym::lang) => (attr.value_str()?, attr.span),
+            _ if check_name(attr, sym::panic_handler) => (sym::panic_impl, attr.span),
+            _ if check_name(attr, sym::alloc_error_handler) => (sym::oom, attr.span),
+            _ => return None,
+        })
+    })
+}
+
+language_item_table! {
+//  Variant name,            Name,                    Method name,             Target;
+    Bool,                    sym::bool,                bool_impl,                  Target::Impl;
+    Char,                    sym::char,                char_impl,                  Target::Impl;
+    Str,                     sym::str,                 str_impl,                   Target::Impl;
+    Array,                   sym::array,               array_impl,                 Target::Impl;
+    Slice,                   sym::slice,               slice_impl,                 Target::Impl;
+    SliceU8,                 sym::slice_u8,            slice_u8_impl,              Target::Impl;
+    StrAlloc,                sym::str_alloc,           str_alloc_impl,             Target::Impl;
+    SliceAlloc,              sym::slice_alloc,         slice_alloc_impl,           Target::Impl;
+    SliceU8Alloc,            sym::slice_u8_alloc,      slice_u8_alloc_impl,        Target::Impl;
+    ConstPtr,                sym::const_ptr,           const_ptr_impl,             Target::Impl;
+    MutPtr,                  sym::mut_ptr,             mut_ptr_impl,               Target::Impl;
+    ConstSlicePtr,           sym::const_slice_ptr,     const_slice_ptr_impl,       Target::Impl;
+    MutSlicePtr,             sym::mut_slice_ptr,       mut_slice_ptr_impl,         Target::Impl;
+    I8,                      sym::i8,                  i8_impl,                    Target::Impl;
+    I16,                     sym::i16,                 i16_impl,                   Target::Impl;
+    I32,                     sym::i32,                 i32_impl,                   Target::Impl;
+    I64,                     sym::i64,                 i64_impl,                   Target::Impl;
+    I128,                    sym::i128,                i128_impl,                  Target::Impl;
+    Isize,                   sym::isize,               isize_impl,                 Target::Impl;
+    U8,                      sym::u8,                  u8_impl,                    Target::Impl;
+    U16,                     sym::u16,                 u16_impl,                   Target::Impl;
+    U32,                     sym::u32,                 u32_impl,                   Target::Impl;
+    U64,                     sym::u64,                 u64_impl,                   Target::Impl;
+    U128,                    sym::u128,                u128_impl,                  Target::Impl;
+    Usize,                   sym::usize,               usize_impl,                 Target::Impl;
+    F32,                     sym::f32,                 f32_impl,                   Target::Impl;
+    F64,                     sym::f64,                 f64_impl,                   Target::Impl;
+    F32Runtime,              sym::f32_runtime,         f32_runtime_impl,           Target::Impl;
+    F64Runtime,              sym::f64_runtime,         f64_runtime_impl,           Target::Impl;
+
+    Sized,                   sym::sized,               sized_trait,                Target::Trait;
+    Unsize,                  sym::unsize,              unsize_trait,               Target::Trait;
+    // Trait injected by #[derive(PartialEq)], (i.e. "Partial EQ").
+    StructuralPeq,           sym::structural_peq,      structural_peq_trait,       Target::Trait;
+    // Trait injected by #[derive(Eq)], (i.e. "Total EQ"; no, I will not apologize).
+    StructuralTeq,           sym::structural_teq,      structural_teq_trait,       Target::Trait;
+    Copy,                    sym::copy,                copy_trait,                 Target::Trait;
+    Clone,                   sym::clone,               clone_trait,                Target::Trait;
+    Sync,                    sym::sync,                sync_trait,                 Target::Trait;
+    DiscriminantKind,        sym::discriminant_kind,   discriminant_kind_trait,    Target::Trait;
+    // The associated item of `trait DiscriminantKind`.
+    Discriminant,            sym::discriminant_type,   discriminant_type,          Target::AssocTy;
+
+    Freeze,                  sym::freeze,              freeze_trait,               Target::Trait;
+
+    Drop,                    sym::drop,                drop_trait,                 Target::Trait;
+
+    CoerceUnsized,           sym::coerce_unsized,      coerce_unsized_trait,       Target::Trait;
+    DispatchFromDyn,         sym::dispatch_from_dyn,   dispatch_from_dyn_trait,    Target::Trait;
+
+    Add(Op),                 sym::add,                 add_trait,                  Target::Trait;
+    Sub(Op),                 sym::sub,                 sub_trait,                  Target::Trait;
+    Mul(Op),                 sym::mul,                 mul_trait,                  Target::Trait;
+    Div(Op),                 sym::div,                 div_trait,                  Target::Trait;
+    Rem(Op),                 sym::rem,                 rem_trait,                  Target::Trait;
+    Neg(Op),                 sym::neg,                 neg_trait,                  Target::Trait;
+    Not(Op),                 sym::not,                 not_trait,                  Target::Trait;
+    BitXor(Op),              sym::bitxor,              bitxor_trait,               Target::Trait;
+    BitAnd(Op),              sym::bitand,              bitand_trait,               Target::Trait;
+    BitOr(Op),               sym::bitor,               bitor_trait,                Target::Trait;
+    Shl(Op),                 sym::shl,                 shl_trait,                  Target::Trait;
+    Shr(Op),                 sym::shr,                 shr_trait,                  Target::Trait;
+    AddAssign(Op),           sym::add_assign,          add_assign_trait,           Target::Trait;
+    SubAssign(Op),           sym::sub_assign,          sub_assign_trait,           Target::Trait;
+    MulAssign(Op),           sym::mul_assign,          mul_assign_trait,           Target::Trait;
+    DivAssign(Op),           sym::div_assign,          div_assign_trait,           Target::Trait;
+    RemAssign(Op),           sym::rem_assign,          rem_assign_trait,           Target::Trait;
+    BitXorAssign(Op),        sym::bitxor_assign,       bitxor_assign_trait,        Target::Trait;
+    BitAndAssign(Op),        sym::bitand_assign,       bitand_assign_trait,        Target::Trait;
+    BitOrAssign(Op),         sym::bitor_assign,        bitor_assign_trait,         Target::Trait;
+    ShlAssign(Op),           sym::shl_assign,          shl_assign_trait,           Target::Trait;
+    ShrAssign(Op),           sym::shr_assign,          shr_assign_trait,           Target::Trait;
+    Index(Op),               sym::index,               index_trait,                Target::Trait;
+    IndexMut(Op),            sym::index_mut,           index_mut_trait,            Target::Trait;
+
+    UnsafeCell,              sym::unsafe_cell,         unsafe_cell_type,           Target::Struct;
+    VaList,                  sym::va_list,             va_list,                    Target::Struct;
+
+    Deref,                   sym::deref,               deref_trait,                Target::Trait;
+    DerefMut,                sym::deref_mut,           deref_mut_trait,            Target::Trait;
+    Receiver,                sym::receiver,            receiver_trait,             Target::Trait;
+
+    Fn,                      kw::Fn,                   fn_trait,                   Target::Trait;
+    FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait;
+    FnOnce,                  sym::fn_once,             fn_once_trait,              Target::Trait;
+
+    FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy;
+
+    Future,                  sym::future_trait,        future_trait,               Target::Trait;
+    GeneratorState,          sym::generator_state,     gen_state,                  Target::Enum;
+    Generator,               sym::generator,           gen_trait,                  Target::Trait;
+    Unpin,                   sym::unpin,               unpin_trait,                Target::Trait;
+    Pin,                     sym::pin,                 pin_type,                   Target::Struct;
+
+    PartialEq,               sym::eq,                  eq_trait,                   Target::Trait;
+    PartialOrd,              sym::partial_ord,         partial_ord_trait,          Target::Trait;
+
+    // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
+    // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
+    //
+    // The `begin_unwind` lang item has a predefined symbol name and is sort of a "weak lang item"
+    // in the sense that a crate is not required to have it defined to use it, but a final product
+    // is required to define it somewhere. Additionally, there are restrictions on crates that use
+    // a weak lang item, but do not have it defined.
+    Panic,                   sym::panic,               panic_fn,                   Target::Fn;
+    PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn;
+    PanicInfo,               sym::panic_info,          panic_info,                 Target::Struct;
+    PanicLocation,           sym::panic_location,      panic_location,             Target::Struct;
+    PanicImpl,               sym::panic_impl,          panic_impl,                 Target::Fn;
+    // libstd panic entry point. Necessary for const eval to be able to catch it
+    BeginPanic,              sym::begin_panic,         begin_panic_fn,             Target::Fn;
+
+    ExchangeMalloc,          sym::exchange_malloc,     exchange_malloc_fn,         Target::Fn;
+    BoxFree,                 sym::box_free,            box_free_fn,                Target::Fn;
+    DropInPlace,             sym::drop_in_place,       drop_in_place_fn,           Target::Fn;
+    Oom,                     sym::oom,                 oom,                        Target::Fn;
+    AllocLayout,             sym::alloc_layout,        alloc_layout,               Target::Struct;
+
+    Start,                   sym::start,               start_fn,                   Target::Fn;
+
+    EhPersonality,           sym::eh_personality,      eh_personality,             Target::Fn;
+    EhCatchTypeinfo,         sym::eh_catch_typeinfo,   eh_catch_typeinfo,          Target::Static;
+
+    OwnedBox,                sym::owned_box,           owned_box,                  Target::Struct;
+
+    PhantomData,             sym::phantom_data,        phantom_data,               Target::Struct;
+
+    ManuallyDrop,            sym::manually_drop,       manually_drop,              Target::Struct;
+
+    MaybeUninit,             sym::maybe_uninit,        maybe_uninit,               Target::Union;
+
+    // Align offset for stride != 1; must not panic.
+    AlignOffset,             sym::align_offset,        align_offset_fn,            Target::Fn;
+
+    Termination,             sym::termination,         termination,                Target::Trait;
+
+    Try,                     kw::Try,                  try_trait,                  Target::Trait;
+
+    // Language items from AST lowering
+    TryFromError,            sym::from_error,          from_error_fn,              Target::Method(MethodKind::Trait { body: false });
+    TryFromOk,               sym::from_ok,             from_ok_fn,                 Target::Method(MethodKind::Trait { body: false });
+    TryIntoResult,           sym::into_result,         into_result_fn,             Target::Method(MethodKind::Trait { body: false });
+
+    PollReady,               sym::Ready,               poll_ready_variant,         Target::Variant;
+    PollPending,             sym::Pending,             poll_pending_variant,       Target::Variant;
+
+    FromGenerator,           sym::from_generator,      from_generator_fn,          Target::Fn;
+    GetContext,              sym::get_context,         get_context_fn,             Target::Fn;
+
+    FuturePoll,              sym::poll,                future_poll_fn,             Target::Method(MethodKind::Trait { body: false });
+
+    FromFrom,                sym::from,                from_fn,                    Target::Method(MethodKind::Trait { body: false });
+
+    OptionSome,              sym::Some,                option_some_variant,        Target::Variant;
+    OptionNone,              sym::None,                option_none_variant,        Target::Variant;
+
+    ResultOk,                sym::Ok,                  result_ok_variant,          Target::Variant;
+    ResultErr,               sym::Err,                 result_err_variant,         Target::Variant;
+
+    IntoIterIntoIter,        sym::into_iter,           into_iter_fn,               Target::Method(MethodKind::Trait { body: false });
+    IteratorNext,            sym::next,                next_fn,                    Target::Method(MethodKind::Trait { body: false});
+
+    PinNewUnchecked,         sym::new_unchecked,       new_unchecked_fn,           Target::Method(MethodKind::Inherent);
+
+    RangeFrom,               sym::RangeFrom,           range_from_struct,          Target::Struct;
+    RangeFull,               sym::RangeFull,           range_full_struct,          Target::Struct;
+    RangeInclusiveStruct,    sym::RangeInclusive,      range_inclusive_struct,     Target::Struct;
+    RangeInclusiveNew,       sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent);
+    Range,                   sym::Range,               range_struct,               Target::Struct;
+    RangeToInclusive,        sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct;
+    RangeTo,                 sym::RangeTo,             range_to_struct,            Target::Struct;
+}
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
new file mode 100644
index 00000000000..19ea1de5683
--- /dev/null
+++ b/compiler/rustc_hir/src/lib.rs
@@ -0,0 +1,36 @@
+//! HIR datatypes. See the [rustc dev guide] for more info.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
+
+#![feature(crate_visibility_modifier)]
+#![feature(const_fn)] // For the unsizing cast on `&[]`
+#![feature(const_panic)]
+#![feature(in_band_lifetimes)]
+#![feature(or_patterns)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate rustc_macros;
+
+#[macro_use]
+extern crate rustc_data_structures;
+
+mod arena;
+pub mod def;
+pub mod definitions;
+pub use rustc_span::def_id;
+mod hir;
+pub mod hir_id;
+pub mod intravisit;
+pub mod itemlikevisit;
+pub mod lang_items;
+pub mod pat_util;
+mod stable_hash_impls;
+mod target;
+pub mod weak_lang_items;
+
+pub use hir::*;
+pub use hir_id::*;
+pub use lang_items::{LangItem, LanguageItems};
+pub use stable_hash_impls::HashStableContext;
+pub use target::{MethodKind, Target};
diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs
new file mode 100644
index 00000000000..2f1b5da8e13
--- /dev/null
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -0,0 +1,194 @@
+use crate::def::{CtorOf, DefKind, Res};
+use crate::def_id::DefId;
+use crate::hir::{self, HirId, PatKind};
+use rustc_span::symbol::Ident;
+use rustc_span::Span;
+
+use std::iter::{Enumerate, ExactSizeIterator};
+
+pub struct EnumerateAndAdjust<I> {
+    enumerate: Enumerate<I>,
+    gap_pos: usize,
+    gap_len: usize,
+}
+
+impl<I> Iterator for EnumerateAndAdjust<I>
+where
+    I: Iterator,
+{
+    type Item = (usize, <I as Iterator>::Item);
+
+    fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
+        self.enumerate
+            .next()
+            .map(|(i, elem)| (if i < self.gap_pos { i } else { i + self.gap_len }, elem))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.enumerate.size_hint()
+    }
+}
+
+pub trait EnumerateAndAdjustIterator {
+    fn enumerate_and_adjust(
+        self,
+        expected_len: usize,
+        gap_pos: Option<usize>,
+    ) -> EnumerateAndAdjust<Self>
+    where
+        Self: Sized;
+}
+
+impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
+    fn enumerate_and_adjust(
+        self,
+        expected_len: usize,
+        gap_pos: Option<usize>,
+    ) -> EnumerateAndAdjust<Self>
+    where
+        Self: Sized,
+    {
+        let actual_len = self.len();
+        EnumerateAndAdjust {
+            enumerate: self.enumerate(),
+            gap_pos: gap_pos.unwrap_or(expected_len),
+            gap_len: expected_len - actual_len,
+        }
+    }
+}
+
+impl hir::Pat<'_> {
+    pub fn is_refutable(&self) -> bool {
+        match self.kind {
+            PatKind::Lit(_)
+            | PatKind::Range(..)
+            | PatKind::Path(hir::QPath::Resolved(Some(..), _) | hir::QPath::TypeRelative(..)) => {
+                true
+            }
+
+            PatKind::Path(hir::QPath::Resolved(_, ref path))
+            | PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..)
+            | PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => match path.res {
+                Res::Def(DefKind::Variant, _) => true,
+                _ => false,
+            },
+            PatKind::Slice(..) => true,
+            _ => false,
+        }
+    }
+
+    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
+    /// `match foo() { Some(a) => (), None => () }`
+    pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, Ident)) {
+        self.walk_always(|p| {
+            if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
+                f(binding_mode, p.hir_id, p.span, ident);
+            }
+        });
+    }
+
+    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
+    /// `match foo() { Some(a) => (), None => () }`.
+    ///
+    /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
+    pub fn each_binding_or_first(
+        &self,
+        f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, Ident),
+    ) {
+        self.walk(|p| match &p.kind {
+            PatKind::Or(ps) => {
+                ps[0].each_binding_or_first(f);
+                false
+            }
+            PatKind::Binding(bm, _, ident, _) => {
+                f(*bm, p.hir_id, p.span, *ident);
+                true
+            }
+            _ => true,
+        })
+    }
+
+    /// Checks if the pattern contains any patterns that bind something to
+    /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
+    pub fn contains_bindings(&self) -> bool {
+        self.satisfies(|p| match p.kind {
+            PatKind::Binding(..) => true,
+            _ => false,
+        })
+    }
+
+    /// Checks if the pattern contains any patterns that bind something to
+    /// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`,
+    pub fn contains_bindings_or_wild(&self) -> bool {
+        self.satisfies(|p| match p.kind {
+            PatKind::Binding(..) | PatKind::Wild => true,
+            _ => false,
+        })
+    }
+
+    /// Checks if the pattern satisfies the given predicate on some sub-pattern.
+    fn satisfies(&self, pred: impl Fn(&hir::Pat<'_>) -> bool) -> bool {
+        let mut satisfies = false;
+        self.walk_short(|p| {
+            if pred(p) {
+                satisfies = true;
+                false // Found one, can short circuit now.
+            } else {
+                true
+            }
+        });
+        satisfies
+    }
+
+    pub fn simple_ident(&self) -> Option<Ident> {
+        match self.kind {
+            PatKind::Binding(
+                hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
+                _,
+                ident,
+                None,
+            ) => Some(ident),
+            _ => None,
+        }
+    }
+
+    /// Returns variants that are necessary to exist for the pattern to match.
+    pub fn necessary_variants(&self) -> Vec<DefId> {
+        let mut variants = vec![];
+        self.walk(|p| match &p.kind {
+            PatKind::Or(_) => false,
+            PatKind::Path(hir::QPath::Resolved(_, path))
+            | PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..)
+            | PatKind::Struct(hir::QPath::Resolved(_, path), ..) => {
+                if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) =
+                    path.res
+                {
+                    variants.push(id);
+                }
+                true
+            }
+            _ => true,
+        });
+        variants.sort();
+        variants.dedup();
+        variants
+    }
+
+    /// Checks if the pattern contains any `ref` or `ref mut` bindings, and if
+    /// yes whether it contains mutable or just immutables ones.
+    //
+    // FIXME(tschottdorf): this is problematic as the HIR is being scraped, but
+    // ref bindings are be implicit after #42640 (default match binding modes). See issue #44848.
+    pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
+        let mut result = None;
+        self.each_binding(|annotation, _, _, _| match annotation {
+            hir::BindingAnnotation::Ref => match result {
+                None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
+                _ => {}
+            },
+            hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut),
+            _ => {}
+        });
+        result
+    }
+}
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
new file mode 100644
index 00000000000..1d3f44a0899
--- /dev/null
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -0,0 +1,167 @@
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+
+use crate::hir::{
+    BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty,
+    VisibilityKind,
+};
+use crate::hir_id::{HirId, ItemLocalId};
+use rustc_span::def_id::{DefPathHash, LocalDefId};
+
+/// Requirements for a `StableHashingContext` to be used in this crate.
+/// This is a hack to allow using the `HashStable_Generic` derive macro
+/// instead of implementing everything in librustc_middle.
+pub trait HashStableContext:
+    rustc_ast::HashStableContext + rustc_target::HashStableContext
+{
+    fn hash_hir_id(&mut self, _: HirId, hasher: &mut StableHasher);
+    fn hash_body_id(&mut self, _: BodyId, hasher: &mut StableHasher);
+    fn hash_reference_to_item(&mut self, _: HirId, hasher: &mut StableHasher);
+    fn hash_hir_mod(&mut self, _: &Mod<'_>, hasher: &mut StableHasher);
+    fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher);
+    fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher);
+    fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher);
+    fn hash_hir_item_like<F: FnOnce(&mut Self)>(&mut self, f: F);
+    fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash;
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        let def_path_hash = hcx.local_def_path_hash(self.owner);
+        (def_path_hash, self.local_id)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
+    type KeyType = (DefPathHash, ItemLocalId);
+
+    #[inline]
+    fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
+        self.hir_id.to_stable_hash_key(hcx)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for HirId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_hir_id(*self, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for BodyId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_body_id(*self, hasher)
+    }
+}
+
+// The following implementations of HashStable for `ItemId`, `TraitItemId`, and
+// `ImplItemId` deserve special attention. Normally we do not hash `NodeId`s within
+// the HIR, since they just signify a HIR nodes own path. But `ItemId` et al
+// are used when another item in the HIR is *referenced* and we certainly
+// want to pick up on a reference changing its target, so we hash the NodeIds
+// in "DefPath Mode".
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ItemId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_reference_to_item(self.id, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItemId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_reference_to_item(self.hir_id, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItemId {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_reference_to_item(self.hir_id, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Mod<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_hir_mod(self, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Expr<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_hir_expr(self, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Ty<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_hir_ty(self, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for VisibilityKind<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        hcx.hash_hir_visibility_kind(self, hasher)
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for TraitItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            generics.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for ImplItem<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let ImplItem {
+            hir_id: _,
+            ident,
+            ref vis,
+            defaultness,
+            ref attrs,
+            ref generics,
+            ref kind,
+            span,
+        } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            defaultness.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            generics.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
+
+impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
+    fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
+        let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self;
+
+        hcx.hash_hir_item_like(|hcx| {
+            ident.name.hash_stable(hcx, hasher);
+            attrs.hash_stable(hcx, hasher);
+            kind.hash_stable(hcx, hasher);
+            vis.hash_stable(hcx, hasher);
+            span.hash_stable(hcx, hasher);
+        });
+    }
+}
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
new file mode 100644
index 00000000000..1efc8bc3124
--- /dev/null
+++ b/compiler/rustc_hir/src/target.rs
@@ -0,0 +1,127 @@
+//! This module implements some validity checks for attributes.
+//! In particular it verifies that `#[inline]` and `#[repr]` attributes are
+//! attached to items that actually support them and if there are
+//! conflicts between multiple such attributes attached to the same
+//! item.
+
+use crate::hir;
+use crate::{Item, ItemKind, TraitItem, TraitItemKind};
+
+use std::fmt::{self, Display};
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum MethodKind {
+    Trait { body: bool },
+    Inherent,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum Target {
+    ExternCrate,
+    Use,
+    Static,
+    Const,
+    Fn,
+    Closure,
+    Mod,
+    ForeignMod,
+    GlobalAsm,
+    TyAlias,
+    OpaqueTy,
+    Enum,
+    Variant,
+    Struct,
+    Union,
+    Trait,
+    TraitAlias,
+    Impl,
+    Expression,
+    Statement,
+    AssocConst,
+    Method(MethodKind),
+    AssocTy,
+    ForeignFn,
+    ForeignStatic,
+    ForeignTy,
+}
+
+impl Display for Target {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(
+            f,
+            "{}",
+            match *self {
+                Target::ExternCrate => "extern crate",
+                Target::Use => "use",
+                Target::Static => "static item",
+                Target::Const => "constant item",
+                Target::Fn => "function",
+                Target::Closure => "closure",
+                Target::Mod => "module",
+                Target::ForeignMod => "foreign module",
+                Target::GlobalAsm => "global asm",
+                Target::TyAlias => "type alias",
+                Target::OpaqueTy => "opaque type",
+                Target::Enum => "enum",
+                Target::Variant => "enum variant",
+                Target::Struct => "struct",
+                Target::Union => "union",
+                Target::Trait => "trait",
+                Target::TraitAlias => "trait alias",
+                Target::Impl => "item",
+                Target::Expression => "expression",
+                Target::Statement => "statement",
+                Target::AssocConst => "associated const",
+                Target::Method(_) => "method",
+                Target::AssocTy => "associated type",
+                Target::ForeignFn => "foreign function",
+                Target::ForeignStatic => "foreign static item",
+                Target::ForeignTy => "foreign type",
+            }
+        )
+    }
+}
+
+impl Target {
+    pub fn from_item(item: &Item<'_>) -> Target {
+        match item.kind {
+            ItemKind::ExternCrate(..) => Target::ExternCrate,
+            ItemKind::Use(..) => Target::Use,
+            ItemKind::Static(..) => Target::Static,
+            ItemKind::Const(..) => Target::Const,
+            ItemKind::Fn(..) => Target::Fn,
+            ItemKind::Mod(..) => Target::Mod,
+            ItemKind::ForeignMod(..) => Target::ForeignMod,
+            ItemKind::GlobalAsm(..) => Target::GlobalAsm,
+            ItemKind::TyAlias(..) => Target::TyAlias,
+            ItemKind::OpaqueTy(..) => Target::OpaqueTy,
+            ItemKind::Enum(..) => Target::Enum,
+            ItemKind::Struct(..) => Target::Struct,
+            ItemKind::Union(..) => Target::Union,
+            ItemKind::Trait(..) => Target::Trait,
+            ItemKind::TraitAlias(..) => Target::TraitAlias,
+            ItemKind::Impl { .. } => Target::Impl,
+        }
+    }
+
+    pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target {
+        match trait_item.kind {
+            TraitItemKind::Const(..) => Target::AssocConst,
+            TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => {
+                Target::Method(MethodKind::Trait { body: false })
+            }
+            TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => {
+                Target::Method(MethodKind::Trait { body: true })
+            }
+            TraitItemKind::Type(..) => Target::AssocTy,
+        }
+    }
+
+    pub fn from_foreign_item(foreign_item: &hir::ForeignItem<'_>) -> Target {
+        match foreign_item.kind {
+            hir::ForeignItemKind::Fn(..) => Target::ForeignFn,
+            hir::ForeignItemKind::Static(..) => Target::ForeignStatic,
+            hir::ForeignItemKind::Type => Target::ForeignTy,
+        }
+    }
+}
diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs
new file mode 100644
index 00000000000..129eec7d29e
--- /dev/null
+++ b/compiler/rustc_hir/src/weak_lang_items.rs
@@ -0,0 +1,53 @@
+//! Validity checking for weak lang items
+
+use crate::def_id::DefId;
+use crate::{lang_items, LangItem, LanguageItems};
+
+use rustc_ast as ast;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::symbol::{sym, Symbol};
+
+use lazy_static::lazy_static;
+
+macro_rules! weak_lang_items {
+    ($($name:ident, $item:ident, $sym:ident;)*) => (
+
+lazy_static! {
+    pub static ref WEAK_ITEMS_REFS: FxHashMap<Symbol, LangItem> = {
+        let mut map = FxHashMap::default();
+        $(map.insert(sym::$name, LangItem::$item);)*
+        map
+    };
+}
+
+/// The `check_name` argument avoids the need for `librustc_hir` to depend on
+/// `librustc_session`.
+pub fn link_name<'a, F>(check_name: F, attrs: &'a [ast::Attribute]) -> Option<Symbol>
+where
+    F: Fn(&'a ast::Attribute, Symbol) -> bool
+{
+    lang_items::extract(check_name, attrs).and_then(|(name, _)| {
+        $(if name == sym::$name {
+            Some(sym::$sym)
+        } else)* {
+            None
+        }
+    })
+}
+
+impl LanguageItems {
+    pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
+        let did = Some(item_def_id);
+
+        $(self.$name() == did)||*
+    }
+}
+
+) }
+
+weak_lang_items! {
+    panic_impl,         PanicImpl,          rust_begin_unwind;
+    eh_personality,     EhPersonality,      rust_eh_personality;
+    eh_catch_typeinfo,  EhCatchTypeinfo,    rust_eh_catch_typeinfo;
+    oom,                Oom,                rust_oom;
+}