about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-01-12 09:44:55 +0000
committerbors <bors@rust-lang.org>2020-01-12 09:44:55 +0000
commit59c1db0339327f8b98c42ef0627a464915966d9b (patch)
tree9102e96bf3aeccaf4d58ea36632f1513734b0bca
parent0b6c116a84fb1dbb60b5870291f5d7df808c280d (diff)
parentb3589292515b811400463409b5fd5afea2aef03b (diff)
downloadrust-59c1db0339327f8b98c42ef0627a464915966d9b.tar.gz
rust-59c1db0339327f8b98c42ef0627a464915966d9b.zip
Auto merge of #67901 - matthewjasper:split-mir-build, r=nagisa
Split MIR building into its own crate

This moves `rustc_mir::{build, hair, lints}` to `rustc_mir_build`.
The new crate only has a `provide` function as it's public API.

Based on #67898

cc @Centril @rust-lang/compiler
r? @oli-obk
-rw-r--r--Cargo.lock24
-rw-r--r--src/librustc/mir/mod.rs225
-rw-r--r--src/librustc/mir/query.rs223
-rw-r--r--src/librustc/query/mod.rs9
-rw-r--r--src/librustc/ty/query/keys.rs2
-rw-r--r--src/librustc_interface/Cargo.toml1
-rw-r--r--src/librustc_interface/passes.rs2
-rw-r--r--src/librustc_mir/Cargo.toml1
-rw-r--r--src/librustc_mir/const_eval.rs29
-rw-r--r--src/librustc_mir/lib.rs8
-rw-r--r--src/librustc_mir/transform/mod.rs11
-rw-r--r--src/librustc_mir_build/Cargo.toml28
-rw-r--r--src/librustc_mir_build/build/block.rs (renamed from src/librustc_mir/build/block.rs)2
-rw-r--r--src/librustc_mir_build/build/cfg.rs (renamed from src/librustc_mir/build/cfg.rs)22
-rw-r--r--src/librustc_mir_build/build/expr/as_constant.rs (renamed from src/librustc_mir/build/expr/as_constant.rs)2
-rw-r--r--src/librustc_mir_build/build/expr/as_operand.rs (renamed from src/librustc_mir/build/expr/as_operand.rs)4
-rw-r--r--src/librustc_mir_build/build/expr/as_place.rs (renamed from src/librustc_mir/build/expr/as_place.rs)12
-rw-r--r--src/librustc_mir_build/build/expr/as_rvalue.rs (renamed from src/librustc_mir/build/expr/as_rvalue.rs)4
-rw-r--r--src/librustc_mir_build/build/expr/as_temp.rs (renamed from src/librustc_mir/build/expr/as_temp.rs)2
-rw-r--r--src/librustc_mir_build/build/expr/category.rs (renamed from src/librustc_mir/build/expr/category.rs)6
-rw-r--r--src/librustc_mir_build/build/expr/into.rs (renamed from src/librustc_mir/build/expr/into.rs)2
-rw-r--r--src/librustc_mir_build/build/expr/mod.rs (renamed from src/librustc_mir/build/expr/mod.rs)0
-rw-r--r--src/librustc_mir_build/build/expr/stmt.rs (renamed from src/librustc_mir/build/expr/stmt.rs)2
-rw-r--r--src/librustc_mir_build/build/into.rs (renamed from src/librustc_mir/build/into.rs)7
-rw-r--r--src/librustc_mir_build/build/matches/mod.rs (renamed from src/librustc_mir/build/matches/mod.rs)18
-rw-r--r--src/librustc_mir_build/build/matches/simplify.rs (renamed from src/librustc_mir/build/matches/simplify.rs)2
-rw-r--r--src/librustc_mir_build/build/matches/test.rs (renamed from src/librustc_mir/build/matches/test.rs)10
-rw-r--r--src/librustc_mir_build/build/matches/util.rs (renamed from src/librustc_mir/build/matches/util.rs)8
-rw-r--r--src/librustc_mir_build/build/misc.rs (renamed from src/librustc_mir/build/misc.rs)16
-rw-r--r--src/librustc_mir_build/build/mod.rs (renamed from src/librustc_mir/build/mod.rs)14
-rw-r--r--src/librustc_mir_build/build/scope.rs (renamed from src/librustc_mir/build/scope.rs)44
-rw-r--r--src/librustc_mir_build/hair/constant.rs (renamed from src/librustc_mir/hair/constant.rs)0
-rw-r--r--src/librustc_mir_build/hair/cx/block.rs (renamed from src/librustc_mir/hair/cx/block.rs)2
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs (renamed from src/librustc_mir/hair/cx/expr.rs)6
-rw-r--r--src/librustc_mir_build/hair/cx/mod.rs (renamed from src/librustc_mir/hair/cx/mod.rs)56
-rw-r--r--src/librustc_mir_build/hair/cx/to_ref.rs (renamed from src/librustc_mir/hair/cx/to_ref.rs)2
-rw-r--r--src/librustc_mir_build/hair/mod.rs (renamed from src/librustc_mir/hair/mod.rs)92
-rw-r--r--src/librustc_mir_build/hair/pattern/_match.rs (renamed from src/librustc_mir/hair/pattern/_match.rs)62
-rw-r--r--src/librustc_mir_build/hair/pattern/check_match.rs (renamed from src/librustc_mir/hair/pattern/check_match.rs)19
-rw-r--r--src/librustc_mir_build/hair/pattern/const_to_pat.rs (renamed from src/librustc_mir/hair/pattern/const_to_pat.rs)53
-rw-r--r--src/librustc_mir_build/hair/pattern/mod.rs (renamed from src/librustc_mir/hair/pattern/mod.rs)82
-rw-r--r--src/librustc_mir_build/hair/util.rs (renamed from src/librustc_mir/hair/util.rs)0
-rw-r--r--src/librustc_mir_build/lib.rs26
-rw-r--r--src/librustc_mir_build/lints.rs (renamed from src/librustc_mir/lints.rs)4
-rw-r--r--src/test/ui/pattern/const-pat-ice.stderr2
45 files changed, 621 insertions, 525 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0008a4a3615..4836e15cd79 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3633,6 +3633,7 @@ dependencies = [
  "rustc_lint",
  "rustc_metadata",
  "rustc_mir",
+ "rustc_mir_build",
  "rustc_parse",
  "rustc_passes",
  "rustc_plugin_impl",
@@ -3722,7 +3723,6 @@ dependencies = [
 name = "rustc_mir"
 version = "0.0.0"
 dependencies = [
- "arena",
  "either",
  "graphviz",
  "itertools 0.8.0",
@@ -3746,6 +3746,28 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_mir_build"
+version = "0.0.0"
+dependencies = [
+ "arena",
+ "itertools 0.8.0",
+ "log",
+ "rustc",
+ "rustc_apfloat",
+ "rustc_data_structures",
+ "rustc_error_codes",
+ "rustc_errors",
+ "rustc_hir",
+ "rustc_index",
+ "rustc_macros",
+ "rustc_span",
+ "rustc_target",
+ "serialize",
+ "smallvec 1.0.0",
+ "syntax",
+]
+
+[[package]]
 name = "rustc_parse"
 version = "0.0.0"
 dependencies = [
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 281cf46bdc2..ccd2a968ded 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1,5 +1,3 @@
-// ignore-tidy-filelength
-
 //! MIR datatypes and passes. See the [rustc guide] for more info.
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
@@ -23,14 +21,12 @@ use polonius_engine::Atom;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::graph::{self, GraphSuccessors};
-use rustc_data_structures::sync::Lrc;
 use rustc_index::bit_set::BitMatrix;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
-use smallvec::SmallVec;
 use std::borrow::Cow;
 use std::fmt::{self, Debug, Display, Formatter, Write};
 use std::ops::Index;
@@ -39,13 +35,15 @@ use std::{iter, mem, option, u32};
 pub use syntax::ast::Mutability;
 use syntax::ast::Name;
 
-pub use crate::mir::cache::{BodyAndCache, ReadOnlyBodyAndCache};
-pub use crate::mir::interpret::AssertMessage;
+pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache};
+pub use self::interpret::AssertMessage;
+pub use self::query::*;
 pub use crate::read_only;
 
 mod cache;
 pub mod interpret;
 pub mod mono;
+mod query;
 pub mod tcx;
 pub mod traversal;
 pub mod visit;
@@ -2581,221 +2579,6 @@ impl Location {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
-pub enum UnsafetyViolationKind {
-    General,
-    /// Permitted both in `const fn`s and regular `fn`s.
-    GeneralAndConstFn,
-    BorrowPacked(hir::HirId),
-}
-
-#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UnsafetyViolation {
-    pub source_info: SourceInfo,
-    pub description: Symbol,
-    pub details: Symbol,
-    pub kind: UnsafetyViolationKind,
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub struct UnsafetyCheckResult {
-    /// Violations that are propagated *upwards* from this function.
-    pub violations: Lrc<[UnsafetyViolation]>,
-    /// `unsafe` blocks in this function, along with whether they are used. This is
-    /// used for the "unused_unsafe" lint.
-    pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
-}
-
-rustc_index::newtype_index! {
-    pub struct GeneratorSavedLocal {
-        derive [HashStable]
-        DEBUG_FORMAT = "_{}",
-    }
-}
-
-/// The layout of generator state.
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
-pub struct GeneratorLayout<'tcx> {
-    /// The type of every local stored inside the generator.
-    pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
-
-    /// Which of the above fields are in each variant. Note that one field may
-    /// be stored in multiple variants.
-    pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
-
-    /// Which saved locals are storage-live at the same time. Locals that do not
-    /// have conflicts with each other are allowed to overlap in the computed
-    /// layout.
-    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
-}
-
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct BorrowCheckResult<'tcx> {
-    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
-    pub used_mut_upvars: SmallVec<[Field; 8]>,
-}
-
-/// The result of the `mir_const_qualif` query.
-///
-/// Each field corresponds to an implementer of the `Qualif` trait in
-/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
-/// `Qualif`.
-#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ConstQualifs {
-    pub has_mut_interior: bool,
-    pub needs_drop: bool,
-}
-
-/// After we borrow check a closure, we are left with various
-/// requirements that we have inferred between the free regions that
-/// appear in the closure's signature or on its field types. These
-/// requirements are then verified and proved by the closure's
-/// creating function. This struct encodes those requirements.
-///
-/// The requirements are listed as being between various
-/// `RegionVid`. The 0th region refers to `'static`; subsequent region
-/// vids refer to the free regions that appear in the closure (or
-/// generator's) type, in order of appearance. (This numbering is
-/// actually defined by the `UniversalRegions` struct in the NLL
-/// region checker. See for example
-/// `UniversalRegions::closure_mapping`.) Note that we treat the free
-/// regions in the closure's type "as if" they were erased, so their
-/// precise identity is not important, only their position.
-///
-/// Example: If type check produces a closure with the closure substs:
-///
-/// ```text
-/// ClosureSubsts = [
-///     i8,                                  // the "closure kind"
-///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
-///     &'a String,                          // some upvar
-/// ]
-/// ```
-///
-/// here, there is one unique free region (`'a`) but it appears
-/// twice. We would "renumber" each occurrence to a unique vid, as follows:
-///
-/// ```text
-/// ClosureSubsts = [
-///     i8,                                  // the "closure kind"
-///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
-///     &'2 String,                          // some upvar
-/// ]
-/// ```
-///
-/// Now the code might impose a requirement like `'1: '2`. When an
-/// instance of the closure is created, the corresponding free regions
-/// can be extracted from its type and constrained to have the given
-/// outlives relationship.
-///
-/// In some cases, we have to record outlives requirements between
-/// types and regions as well. In that case, if those types include
-/// any regions, those regions are recorded as `ReClosureBound`
-/// instances assigned one of these same indices. Those regions will
-/// be substituted away by the creator. We use `ReClosureBound` in
-/// that case because the regions must be allocated in the global
-/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use
-/// internally within the rest of the NLL code).
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ClosureRegionRequirements<'tcx> {
-    /// The number of external regions defined on the closure. In our
-    /// example above, it would be 3 -- one for `'static`, then `'1`
-    /// and `'2`. This is just used for a sanity check later on, to
-    /// make sure that the number of regions we see at the callsite
-    /// matches.
-    pub num_external_vids: usize,
-
-    /// Requirements between the various free regions defined in
-    /// indices.
-    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
-}
-
-/// Indicates an outlives-constraint between a type or between two
-/// free regions declared on the closure.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub struct ClosureOutlivesRequirement<'tcx> {
-    // This region or type ...
-    pub subject: ClosureOutlivesSubject<'tcx>,
-
-    // ... must outlive this one.
-    pub outlived_free_region: ty::RegionVid,
-
-    // If not, report an error here ...
-    pub blame_span: Span,
-
-    // ... due to this reason.
-    pub category: ConstraintCategory,
-}
-
-/// Outlives-constraints can be categorized to determine whether and why they
-/// are interesting (for error reporting). Order of variants indicates sort
-/// order of the category, thereby influencing diagnostic output.
-///
-/// See also [rustc_mir::borrow_check::nll::constraints].
-#[derive(
-    Copy,
-    Clone,
-    Debug,
-    Eq,
-    PartialEq,
-    PartialOrd,
-    Ord,
-    Hash,
-    RustcEncodable,
-    RustcDecodable,
-    HashStable
-)]
-pub enum ConstraintCategory {
-    Return,
-    Yield,
-    UseAsConst,
-    UseAsStatic,
-    TypeAnnotation,
-    Cast,
-
-    /// A constraint that came from checking the body of a closure.
-    ///
-    /// We try to get the category that the closure used when reporting this.
-    ClosureBounds,
-    CallArgument,
-    CopyBound,
-    SizedBound,
-    Assignment,
-    OpaqueType,
-
-    /// A "boring" constraint (caused by the given location) is one that
-    /// the user probably doesn't want to see described in diagnostics,
-    /// because it is kind of an artifact of the type system setup.
-    /// Example: `x = Foo { field: y }` technically creates
-    /// intermediate regions representing the "type of `Foo { field: y
-    /// }`", and data flows from `y` into those variables, but they
-    /// are not very interesting. The assignment into `x` on the other
-    /// hand might be.
-    Boring,
-    // Boring and applicable everywhere.
-    BoringNoLocation,
-
-    /// A constraint that doesn't correspond to anything the user sees.
-    Internal,
-}
-
-/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
-/// that must outlive some region.
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
-pub enum ClosureOutlivesSubject<'tcx> {
-    /// Subject is a type, typically a type parameter, but could also
-    /// be a projection. Indicates a requirement like `T: 'a` being
-    /// passed to the caller, where the type here is `T`.
-    ///
-    /// The type here is guaranteed not to contain any free regions at
-    /// present.
-    Ty(Ty<'tcx>),
-
-    /// Subject is a free region from the closure. Indicates a requirement
-    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
-    Region(ty::RegionVid),
-}
-
 /*
  * `TypeFoldable` implementations for MIR types
 */
diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs
new file mode 100644
index 00000000000..34f58ab89b1
--- /dev/null
+++ b/src/librustc/mir/query.rs
@@ -0,0 +1,223 @@
+//! Values computed by queries that use MIR.
+
+use crate::ty::{self, Ty};
+use rustc_data_structures::sync::Lrc;
+use rustc_hir as hir;
+use rustc_index::bit_set::BitMatrix;
+use rustc_index::vec::IndexVec;
+use rustc_span::{Span, Symbol};
+use rustc_target::abi::VariantIdx;
+use smallvec::SmallVec;
+
+use super::{Field, SourceInfo};
+
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+pub enum UnsafetyViolationKind {
+    General,
+    /// Permitted both in `const fn`s and regular `fn`s.
+    GeneralAndConstFn,
+    BorrowPacked(hir::HirId),
+}
+
+#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
+pub struct UnsafetyViolation {
+    pub source_info: SourceInfo,
+    pub description: Symbol,
+    pub details: Symbol,
+    pub kind: UnsafetyViolationKind,
+}
+
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
+pub struct UnsafetyCheckResult {
+    /// Violations that are propagated *upwards* from this function.
+    pub violations: Lrc<[UnsafetyViolation]>,
+    /// `unsafe` blocks in this function, along with whether they are used. This is
+    /// used for the "unused_unsafe" lint.
+    pub unsafe_blocks: Lrc<[(hir::HirId, bool)]>,
+}
+
+rustc_index::newtype_index! {
+    pub struct GeneratorSavedLocal {
+        derive [HashStable]
+        DEBUG_FORMAT = "_{}",
+    }
+}
+
+/// The layout of generator state.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
+pub struct GeneratorLayout<'tcx> {
+    /// The type of every local stored inside the generator.
+    pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,
+
+    /// Which of the above fields are in each variant. Note that one field may
+    /// be stored in multiple variants.
+    pub variant_fields: IndexVec<VariantIdx, IndexVec<Field, GeneratorSavedLocal>>,
+
+    /// Which saved locals are storage-live at the same time. Locals that do not
+    /// have conflicts with each other are allowed to overlap in the computed
+    /// layout.
+    pub storage_conflicts: BitMatrix<GeneratorSavedLocal, GeneratorSavedLocal>,
+}
+
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct BorrowCheckResult<'tcx> {
+    pub closure_requirements: Option<ClosureRegionRequirements<'tcx>>,
+    pub used_mut_upvars: SmallVec<[Field; 8]>,
+}
+
+/// The result of the `mir_const_qualif` query.
+///
+/// Each field corresponds to an implementer of the `Qualif` trait in
+/// `librustc_mir/transform/check_consts/qualifs.rs`. See that file for more information on each
+/// `Qualif`.
+#[derive(Clone, Copy, Debug, Default, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ConstQualifs {
+    pub has_mut_interior: bool,
+    pub needs_drop: bool,
+}
+
+/// After we borrow check a closure, we are left with various
+/// requirements that we have inferred between the free regions that
+/// appear in the closure's signature or on its field types. These
+/// requirements are then verified and proved by the closure's
+/// creating function. This struct encodes those requirements.
+///
+/// The requirements are listed as being between various
+/// `RegionVid`. The 0th region refers to `'static`; subsequent region
+/// vids refer to the free regions that appear in the closure (or
+/// generator's) type, in order of appearance. (This numbering is
+/// actually defined by the `UniversalRegions` struct in the NLL
+/// region checker. See for example
+/// `UniversalRegions::closure_mapping`.) Note that we treat the free
+/// regions in the closure's type "as if" they were erased, so their
+/// precise identity is not important, only their position.
+///
+/// Example: If type check produces a closure with the closure substs:
+///
+/// ```text
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'a &'x u32) -> &'x u32,  // the "closure signature"
+///     &'a String,                          // some upvar
+/// ]
+/// ```
+///
+/// here, there is one unique free region (`'a`) but it appears
+/// twice. We would "renumber" each occurrence to a unique vid, as follows:
+///
+/// ```text
+/// ClosureSubsts = [
+///     i8,                                  // the "closure kind"
+///     for<'x> fn(&'1 &'x u32) -> &'x u32,  // the "closure signature"
+///     &'2 String,                          // some upvar
+/// ]
+/// ```
+///
+/// Now the code might impose a requirement like `'1: '2`. When an
+/// instance of the closure is created, the corresponding free regions
+/// can be extracted from its type and constrained to have the given
+/// outlives relationship.
+///
+/// In some cases, we have to record outlives requirements between
+/// types and regions as well. In that case, if those types include
+/// any regions, those regions are recorded as `ReClosureBound`
+/// instances assigned one of these same indices. Those regions will
+/// be substituted away by the creator. We use `ReClosureBound` in
+/// that case because the regions must be allocated in the global
+/// `TyCtxt`, and hence we cannot use `ReVar` (which is what we use
+/// internally within the rest of the NLL code).
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ClosureRegionRequirements<'tcx> {
+    /// The number of external regions defined on the closure. In our
+    /// example above, it would be 3 -- one for `'static`, then `'1`
+    /// and `'2`. This is just used for a sanity check later on, to
+    /// make sure that the number of regions we see at the callsite
+    /// matches.
+    pub num_external_vids: usize,
+
+    /// Requirements between the various free regions defined in
+    /// indices.
+    pub outlives_requirements: Vec<ClosureOutlivesRequirement<'tcx>>,
+}
+
+/// Indicates an outlives-constraint between a type or between two
+/// free regions declared on the closure.
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub struct ClosureOutlivesRequirement<'tcx> {
+    // This region or type ...
+    pub subject: ClosureOutlivesSubject<'tcx>,
+
+    // ... must outlive this one.
+    pub outlived_free_region: ty::RegionVid,
+
+    // If not, report an error here ...
+    pub blame_span: Span,
+
+    // ... due to this reason.
+    pub category: ConstraintCategory,
+}
+
+/// Outlives-constraints can be categorized to determine whether and why they
+/// are interesting (for error reporting). Order of variants indicates sort
+/// order of the category, thereby influencing diagnostic output.
+///
+/// See also [rustc_mir::borrow_check::nll::constraints].
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(RustcEncodable, RustcDecodable, HashStable)]
+pub enum ConstraintCategory {
+    Return,
+    Yield,
+    UseAsConst,
+    UseAsStatic,
+    TypeAnnotation,
+    Cast,
+
+    /// A constraint that came from checking the body of a closure.
+    ///
+    /// We try to get the category that the closure used when reporting this.
+    ClosureBounds,
+    CallArgument,
+    CopyBound,
+    SizedBound,
+    Assignment,
+    OpaqueType,
+
+    /// A "boring" constraint (caused by the given location) is one that
+    /// the user probably doesn't want to see described in diagnostics,
+    /// because it is kind of an artifact of the type system setup.
+    /// Example: `x = Foo { field: y }` technically creates
+    /// intermediate regions representing the "type of `Foo { field: y
+    /// }`", and data flows from `y` into those variables, but they
+    /// are not very interesting. The assignment into `x` on the other
+    /// hand might be.
+    Boring,
+    // Boring and applicable everywhere.
+    BoringNoLocation,
+
+    /// A constraint that doesn't correspond to anything the user sees.
+    Internal,
+}
+
+/// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
+/// that must outlive some region.
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+pub enum ClosureOutlivesSubject<'tcx> {
+    /// Subject is a type, typically a type parameter, but could also
+    /// be a projection. Indicates a requirement like `T: 'a` being
+    /// passed to the caller, where the type here is `T`.
+    ///
+    /// The type here is guaranteed not to contain any free regions at
+    /// present.
+    Ty(Ty<'tcx>),
+
+    /// Subject is a free region from the closure. Indicates a requirement
+    /// like `'a: 'b` being passed to the caller; the region here is `'a`.
+    Region(ty::RegionVid),
+}
+
+/// The constituent parts of an ADT or array.
+#[derive(Copy, Clone, Debug, HashStable)]
+pub struct DestructuredConst<'tcx> {
+    pub variant: VariantIdx,
+    pub fields: &'tcx [&'tcx ty::Const<'tcx>],
+}
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs
index eca9df688c6..50ef115da2c 100644
--- a/src/librustc/query/mod.rs
+++ b/src/librustc/query/mod.rs
@@ -505,6 +505,15 @@ rustc_queries! {
             desc { "extract field of const" }
         }
 
+        /// Destructure a constant ADT or array into its variant indent and its
+        /// field values.
+        query destructure_const(
+            key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>>
+        ) -> mir::DestructuredConst<'tcx> {
+            no_force
+            desc { "destructure constant" }
+        }
+
         query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> {
             no_force
             desc { "get a &core::panic::Location referring to a span" }
diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs
index 8a713e3b6a0..d64f27d9cc2 100644
--- a/src/librustc/ty/query/keys.rs
+++ b/src/librustc/ty/query/keys.rs
@@ -142,7 +142,7 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> Key for ty::Const<'tcx> {
+impl<'tcx> Key for &'tcx ty::Const<'tcx> {
     fn query_crate(&self) -> CrateNum {
         LOCAL_CRATE
     }
diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml
index eb0551c6065..98f7def7e36 100644
--- a/src/librustc_interface/Cargo.toml
+++ b/src/librustc_interface/Cargo.toml
@@ -32,6 +32,7 @@ rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true }
 rustc_hir = { path = "../librustc_hir" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
+rustc_mir_build = { path = "../librustc_mir_build" }
 rustc_passes = { path = "../librustc_passes" }
 rustc_typeck = { path = "../librustc_typeck" }
 rustc_lint = { path = "../librustc_lint" }
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 67f9819f331..5f0d9ed5bdf 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -29,6 +29,7 @@ use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_incremental;
 use rustc_lint::LintStore;
 use rustc_mir as mir;
+use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
 use rustc_passes::{self, hir_stats, layout_test};
 use rustc_plugin_impl as plugin;
@@ -671,6 +672,7 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
     plugin::build::provide(providers);
     rustc::hir::provide(providers);
     mir::provide(providers);
+    mir_build::provide(providers);
     rustc_privacy::provide(providers);
     typeck::provide(providers);
     ty::provide(providers);
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 9b6908dbbe7..f9b61b9e2c9 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -10,7 +10,6 @@ path = "lib.rs"
 doctest = false
 
 [dependencies]
-arena = { path = "../libarena" }
 either = "1.5.0"
 dot = { path = "../libgraphviz", package = "graphviz" }
 itertools = "0.8"
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index eb89553b770..aa7be3d80e1 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -61,15 +61,32 @@ pub(crate) fn const_caller_location<'tcx>(
     tcx.mk_const(loc_const)
 }
 
-// this function uses `unwrap` copiously, because an already validated constant must have valid
-// fields and can thus never fail outside of compiler bugs
-pub(crate) fn const_variant_index<'tcx>(
+// this function uses `unwrap` copiously, because an already validated constant
+// must have valid fields and can thus never fail outside of compiler bugs
+pub(crate) fn destructure_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     val: &'tcx ty::Const<'tcx>,
-) -> VariantIdx {
-    trace!("const_variant_index: {:?}", val);
+) -> mir::DestructuredConst<'tcx> {
+    trace!("destructure_const: {:?}", val);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
     let op = ecx.eval_const_to_op(val, None).unwrap();
-    ecx.read_discriminant(op).unwrap().1
+
+    let variant = ecx.read_discriminant(op).unwrap().1;
+
+    let field_count = match val.ty.kind {
+        ty::Array(_, len) => len.eval_usize(tcx, param_env),
+        ty::Adt(def, _) => def.variants[variant].fields.len() as u64,
+        ty::Tuple(substs) => substs.len() as u64,
+        _ => bug!("cannot destructure constant {:?}", val),
+    };
+
+    let down = ecx.operand_downcast(op, variant).unwrap();
+    let fields_iter = (0..field_count).map(|i| {
+        let field_op = ecx.operand_field(down, i).unwrap();
+        op_to_const(&ecx, field_op)
+    });
+    let fields = tcx.arena.alloc_from_iter(fields_iter);
+
+    mir::DestructuredConst { variant, fields }
 }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index d2565bf9c63..1ff529181f7 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -36,12 +36,9 @@ extern crate log;
 extern crate rustc;
 
 mod borrow_check;
-mod build;
 pub mod const_eval;
 pub mod dataflow;
-mod hair;
 pub mod interpret;
-mod lints;
 pub mod monomorphize;
 mod shim;
 pub mod transform;
@@ -57,10 +54,13 @@ pub fn provide(providers: &mut Providers<'_>) {
     monomorphize::partitioning::provide(providers);
     providers.const_eval_validated = const_eval::const_eval_validated_provider;
     providers.const_eval_raw = const_eval::const_eval_raw_provider;
-    providers.check_match = hair::pattern::check_match;
     providers.const_caller_location = const_eval::const_caller_location;
     providers.const_field = |tcx, param_env_and_value| {
         let (param_env, (value, field)) = param_env_and_value.into_parts();
         const_eval::const_field(tcx, param_env, None, field, value)
     };
+    providers.destructure_const = |tcx, param_env_and_value| {
+        let (param_env, value) = param_env_and_value.into_parts();
+        const_eval::destructure_const(tcx, param_env, value)
+    }
 }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index a2f76042ea7..22aed9a9e66 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -1,4 +1,4 @@
-use crate::{build, shim};
+use crate::{shim, util};
 use rustc::hir::map::Map;
 use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted};
 use rustc::ty::query::Providers;
@@ -41,7 +41,6 @@ pub(crate) fn provide(providers: &mut Providers<'_>) {
     self::check_unsafety::provide(providers);
     *providers = Providers {
         mir_keys,
-        mir_built,
         mir_const,
         mir_const_qualif,
         mir_validated,
@@ -98,11 +97,6 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet {
     tcx.arena.alloc(set)
 }
 
-fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
-    let mir = build::mir_build(tcx, def_id);
-    tcx.alloc_steal_mir(mir)
-}
-
 /// Where a specific `mir::Body` comes from.
 #[derive(Debug, Copy, Clone)]
 pub struct MirSource<'tcx> {
@@ -222,6 +216,9 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal<BodyAndCache<'_>> {
     let _ = tcx.unsafety_check_result(def_id);
 
     let mut body = tcx.mir_built(def_id).steal();
+
+    util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
+
     run_passes(
         tcx,
         &mut body,
diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml
new file mode 100644
index 00000000000..79c73032755
--- /dev/null
+++ b/src/librustc_mir_build/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_mir_build"
+version = "0.0.0"
+edition = "2018"
+
+[lib]
+name = "rustc_mir_build"
+path = "lib.rs"
+doctest = false
+
+[dependencies]
+arena = { path = "../libarena" }
+itertools = "0.8"
+log = "0.4"
+rustc = { path = "../librustc" }
+rustc_apfloat = { path = "../librustc_apfloat" }
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_index = { path = "../librustc_index" }
+rustc_errors = { path = "../librustc_errors" }
+rustc_hir = { path = "../librustc_hir" }
+rustc_macros = { path = "../librustc_macros" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
+rustc_span = { path = "../librustc_span" }
+rustc_target = { path = "../librustc_target" }
+syntax = { path = "../libsyntax" }
+smallvec = { version = "1.0", features = ["union", "may_dangle"] }
+rustc_error_codes = { path = "../librustc_error_codes" }
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir_build/build/block.rs
index 2e133a035ee..c517d3113c6 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir_build/build/block.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
 use rustc_span::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn ast_block(
+    crate fn ast_block(
         &mut self,
         destination: &Place<'tcx>,
         block: BasicBlock,
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir_build/build/cfg.rs
index 553701c91ee..e1971102832 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir_build/build/cfg.rs
@@ -4,33 +4,33 @@ use crate::build::CFG;
 use rustc::mir::*;
 
 impl<'tcx> CFG<'tcx> {
-    pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
+    crate fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
         &self.basic_blocks[blk]
     }
 
-    pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
+    crate fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
         &mut self.basic_blocks[blk]
     }
 
     // llvm.org/PR32488 makes this function use an excess of stack space. Mark
     // it as #[inline(never)] to keep rustc's stack use in check.
     #[inline(never)]
-    pub fn start_new_block(&mut self) -> BasicBlock {
+    crate fn start_new_block(&mut self) -> BasicBlock {
         self.basic_blocks.push(BasicBlockData::new(None))
     }
 
-    pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
+    crate fn start_new_cleanup_block(&mut self) -> BasicBlock {
         let bb = self.start_new_block();
         self.block_data_mut(bb).is_cleanup = true;
         bb
     }
 
-    pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
+    crate fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
         debug!("push({:?}, {:?})", block, statement);
         self.block_data_mut(block).statements.push(statement);
     }
 
-    pub fn push_assign(
+    crate fn push_assign(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -43,7 +43,7 @@ impl<'tcx> CFG<'tcx> {
         );
     }
 
-    pub fn push_assign_constant(
+    crate fn push_assign_constant(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -53,7 +53,7 @@ impl<'tcx> CFG<'tcx> {
         self.push_assign(block, source_info, temp, Rvalue::Use(Operand::Constant(box constant)));
     }
 
-    pub fn push_assign_unit(
+    crate fn push_assign_unit(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -67,7 +67,7 @@ impl<'tcx> CFG<'tcx> {
         );
     }
 
-    pub fn push_fake_read(
+    crate fn push_fake_read(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -79,7 +79,7 @@ impl<'tcx> CFG<'tcx> {
         self.push(block, stmt);
     }
 
-    pub fn terminate(
+    crate fn terminate(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -96,7 +96,7 @@ impl<'tcx> CFG<'tcx> {
     }
 
     /// In the `origin` block, push a `goto -> target` terminator.
-    pub fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
+    crate fn goto(&mut self, origin: BasicBlock, source_info: SourceInfo, target: BasicBlock) {
         self.terminate(origin, source_info, TerminatorKind::Goto { target })
     }
 }
diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir_build/build/expr/as_constant.rs
index ceac2a0cd03..e4856262975 100644
--- a/src/librustc_mir/build/expr/as_constant.rs
+++ b/src/librustc_mir_build/build/expr/as_constant.rs
@@ -8,7 +8,7 @@ use rustc::ty::CanonicalUserTypeAnnotation;
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
     /// `expr` is a valid compile-time constant!
-    pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
+    crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir_build/build/expr/as_operand.rs
index b969932a736..efe328d2b3c 100644
--- a/src/librustc_mir/build/expr/as_operand.rs
+++ b/src/librustc_mir_build/build/expr/as_operand.rs
@@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    pub fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
+    crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -27,7 +27,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// this time.
     ///
     /// The operand is known to be live until the end of `scope`.
-    pub fn as_operand<M>(
+    crate fn as_operand<M>(
         &mut self,
         block: BasicBlock,
         scope: Option<region::Scope>,
diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs
index eb2e87f4a2d..fd6882fa19f 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir_build/build/expr/as_place.rs
@@ -24,7 +24,7 @@ struct PlaceBuilder<'tcx> {
     projection: Vec<PlaceElem<'tcx>>,
 }
 
-impl PlaceBuilder<'tcx> {
+impl<'tcx> PlaceBuilder<'tcx> {
     fn into_place(self, tcx: TyCtxt<'tcx>) -> Place<'tcx> {
         Place { local: self.local, projection: tcx.intern_place_elems(&self.projection) }
     }
@@ -47,7 +47,7 @@ impl PlaceBuilder<'tcx> {
     }
 }
 
-impl From<Local> for PlaceBuilder<'tcx> {
+impl<'tcx> From<Local> for PlaceBuilder<'tcx> {
     fn from(local: Local) -> Self {
         Self { local, projection: Vec::new() }
     }
@@ -66,7 +66,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Extra care is needed if any user code is allowed to run between calling
     /// this method and using it, as is the case for `match` and index
     /// expressions.
-    pub fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
+    crate fn as_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -89,7 +89,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// place. The place itself may or may not be mutable:
     /// * If this expr is a place expr like a.b, then we will return that place.
     /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary.
-    pub fn as_read_only_place<M>(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd<Place<'tcx>>
+    crate fn as_read_only_place<M>(
+        &mut self,
+        mut block: BasicBlock,
+        expr: M,
+    ) -> BlockAnd<Place<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs
index 6f7b7258b5a..5959b852256 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir_build/build/expr/as_rvalue.rs
@@ -18,7 +18,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// The operand returned from this function will *not be valid* after
     /// an ExprKind::Scope is passed, so please do *not* return it from
     /// functions to avoid bad miscompiles.
-    pub fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
+    crate fn as_local_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
     where
         M: Mirror<'tcx, Output = Expr<'tcx>>,
     {
@@ -276,7 +276,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn build_binary_op(
+    crate fn build_binary_op(
         &mut self,
         mut block: BasicBlock,
         op: BinOp,
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir_build/build/expr/as_temp.rs
index 3f711044b15..f47987c5617 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir_build/build/expr/as_temp.rs
@@ -11,7 +11,7 @@ use rustc_span::symbol::sym;
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
     /// up rvalues so as to freeze the value that will be consumed.
-    pub fn as_temp<M>(
+    crate fn as_temp<M>(
         &mut self,
         block: BasicBlock,
         temp_lifetime: Option<region::Scope>,
diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir_build/build/expr/category.rs
index b35616c11fb..c4d340953c9 100644
--- a/src/librustc_mir/build/expr/category.rs
+++ b/src/librustc_mir_build/build/expr/category.rs
@@ -1,7 +1,7 @@
 use crate::hair::*;
 
 #[derive(Debug, PartialEq)]
-pub enum Category {
+crate enum Category {
     // An assignable memory location like `x`, `x.f`, `foo()[3]`, that
     // sort of thing. Something that could appear on the LHS of an `=`
     // sign.
@@ -19,7 +19,7 @@ pub enum Category {
 // Rvalues fall into different "styles" that will determine which fn
 // is best suited to generate them.
 #[derive(Debug, PartialEq)]
-pub enum RvalueFunc {
+crate enum RvalueFunc {
     // Best generated by `into`. This is generally exprs that
     // cause branching, like `match`, but also includes calls.
     Into,
@@ -31,7 +31,7 @@ pub enum RvalueFunc {
 /// Determines the category for a given expression. Note that scope
 /// and paren expressions have no category.
 impl Category {
-    pub fn of(ek: &ExprKind<'_>) -> Option<Category> {
+    crate fn of(ek: &ExprKind<'_>) -> Option<Category> {
         match *ek {
             ExprKind::Scope { .. } => None,
 
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index 2cf2b21b65a..503dfb6ef5b 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -14,7 +14,7 @@ use rustc_target::spec::abi::Abi;
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
-    pub fn into_expr(
+    crate fn into_expr(
         &mut self,
         destination: &Place<'tcx>,
         mut block: BasicBlock,
diff --git a/src/librustc_mir/build/expr/mod.rs b/src/librustc_mir_build/build/expr/mod.rs
index ac8c7e725e1..ac8c7e725e1 100644
--- a/src/librustc_mir/build/expr/mod.rs
+++ b/src/librustc_mir_build/build/expr/mod.rs
diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir_build/build/expr/stmt.rs
index ff7049278ed..fd61cb833b1 100644
--- a/src/librustc_mir/build/expr/stmt.rs
+++ b/src/librustc_mir_build/build/expr/stmt.rs
@@ -10,7 +10,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// (e.g., `some().code(&here());`) then `opt_stmt_span` is the
     /// span of that statement (including its semicolon, if any).
     /// The scope is used if a statement temporary must be dropped.
-    pub fn stmt_expr(
+    crate fn stmt_expr(
         &mut self,
         mut block: BasicBlock,
         expr: Expr<'tcx>,
diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir_build/build/into.rs
index 9c3ea5f7c56..1a2a9d2bc05 100644
--- a/src/librustc_mir/build/into.rs
+++ b/src/librustc_mir_build/build/into.rs
@@ -18,7 +18,12 @@ pub(in crate::build) trait EvalInto<'tcx> {
 }
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn into<E>(&mut self, destination: &Place<'tcx>, block: BasicBlock, expr: E) -> BlockAnd<()>
+    crate fn into<E>(
+        &mut self,
+        destination: &Place<'tcx>,
+        block: BasicBlock,
+        expr: E,
+    ) -> BlockAnd<()>
     where
         E: EvalInto<'tcx>,
     {
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs
index 1dcd29d9232..f9f10b55495 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir_build/build/matches/mod.rs
@@ -81,7 +81,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// * From each prebinding block to the next prebinding block.
     /// * From each otherwise block to the next prebinding block.
-    pub fn match_expr(
+    crate fn match_expr(
         &mut self,
         destination: &Place<'tcx>,
         span: Span,
@@ -417,7 +417,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn place_into_pattern(
+    crate fn place_into_pattern(
         &mut self,
         block: BasicBlock,
         irrefutable_pat: Pat<'tcx>,
@@ -488,7 +488,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// scope for the bindings in these patterns, if such a scope had to be
     /// created. NOTE: Declaring the bindings should always be done in their
     /// drop scope.
-    pub fn declare_bindings(
+    crate fn declare_bindings(
         &mut self,
         mut visibility_scope: Option<SourceScope>,
         scope_span: Span,
@@ -525,7 +525,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         visibility_scope
     }
 
-    pub fn storage_live_binding(
+    crate fn storage_live_binding(
         &mut self,
         block: BasicBlock,
         var: HirId,
@@ -540,7 +540,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         Place::from(local_id)
     }
 
-    pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
+    crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) {
         let local_id = self.var_local_id(var, for_guard);
         let region_scope = self.hir.region_scope_tree.var_scope(var.local_id);
         self.schedule_drop(span, region_scope, local_id, DropKind::Value);
@@ -641,7 +641,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 }
 
 #[derive(Debug)]
-pub struct Candidate<'pat, 'tcx> {
+crate struct Candidate<'pat, 'tcx> {
     // span of the original pattern that gave rise to this candidate
     span: Span,
 
@@ -685,7 +685,7 @@ struct Ascription<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub struct MatchPair<'pat, 'tcx> {
+crate struct MatchPair<'pat, 'tcx> {
     // this place...
     place: Place<'tcx>,
 
@@ -739,7 +739,7 @@ enum TestKind<'tcx> {
 }
 
 #[derive(Debug)]
-pub struct Test<'tcx> {
+crate struct Test<'tcx> {
     span: Span,
     kind: TestKind<'tcx>,
 }
@@ -747,7 +747,7 @@ pub struct Test<'tcx> {
 /// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
 /// a match arm has a guard expression attached to it.
 #[derive(Copy, Clone, Debug)]
-pub(crate) struct ArmHasGuard(pub bool);
+crate struct ArmHasGuard(crate bool);
 
 ///////////////////////////////////////////////////////////////////////////
 // Main matching algorithm
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs
index 9dbf8989cc5..a5f691add65 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir_build/build/matches/simplify.rs
@@ -24,7 +24,7 @@ use syntax::attr::{SignedInt, UnsignedInt};
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
+    crate fn simplify_candidate<'pat>(&mut self, candidate: &mut Candidate<'pat, 'tcx>) {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
             let match_pairs = mem::take(&mut candidate.match_pairs);
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs
index afdb744a43a..31fc0d12105 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir_build/build/matches/test.rs
@@ -24,7 +24,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
     /// It is a bug to call this with a simplifiable pattern.
-    pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
+    crate fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
         match *match_pair.pattern.kind {
             PatKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {
                 span: match_pair.pattern.span,
@@ -85,7 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn add_cases_to_switch<'pat>(
+    crate fn add_cases_to_switch<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         candidate: &Candidate<'pat, 'tcx>,
@@ -129,7 +129,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn add_variants_to_switch<'pat>(
+    crate fn add_variants_to_switch<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         candidate: &Candidate<'pat, 'tcx>,
@@ -156,7 +156,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
-    pub fn perform_test(
+    crate fn perform_test(
         &mut self,
         block: BasicBlock,
         place: &Place<'tcx>,
@@ -507,7 +507,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// that it *doesn't* apply. For now, we return false, indicate that the
     /// test does not apply to this candidate, but it might be we can get
     /// tighter match code if we do something a bit different.
-    pub fn sort_candidate<'pat>(
+    crate fn sort_candidate<'pat>(
         &mut self,
         test_place: &Place<'tcx>,
         test: &Test<'tcx>,
diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir_build/build/matches/util.rs
index b6e643a6510..def8d1b2fd8 100644
--- a/src/librustc_mir/build/matches/util.rs
+++ b/src/librustc_mir_build/build/matches/util.rs
@@ -8,7 +8,7 @@ use std::convert::TryInto;
 use std::u32;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
-    pub fn field_match_pairs<'pat>(
+    crate fn field_match_pairs<'pat>(
         &mut self,
         place: Place<'tcx>,
         subpatterns: &'pat [FieldPat<'tcx>],
@@ -26,7 +26,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .collect()
     }
 
-    pub fn prefix_slice_suffix<'pat>(
+    crate fn prefix_slice_suffix<'pat>(
         &mut self,
         match_pairs: &mut SmallVec<[MatchPair<'pat, 'tcx>; 1]>,
         place: &Place<'tcx>,
@@ -77,7 +77,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Creates a false edge to `imaginary_target` and a real edge to
     /// real_target. If `imaginary_target` is none, or is the same as the real
     /// target, a Goto is generated instead to simplify the generated MIR.
-    pub fn false_edges(
+    crate fn false_edges(
         &mut self,
         from_block: BasicBlock,
         real_target: BasicBlock,
@@ -98,7 +98,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 }
 
 impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
-    pub fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
+    crate fn new(place: Place<'tcx>, pattern: &'pat Pat<'tcx>) -> MatchPair<'pat, 'tcx> {
         MatchPair { place, pattern }
     }
 }
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir_build/build/misc.rs
index 7c358fef7d1..3d5145b6960 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir_build/build/misc.rs
@@ -14,7 +14,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// N.B., **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
-    pub fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
+    crate fn temp(&mut self, ty: Ty<'tcx>, span: Span) -> Place<'tcx> {
         let temp = self.local_decls.push(LocalDecl::new_temp(ty, span));
         let place = Place::from(temp);
         debug!("temp: created temp {:?} with type {:?}", place, self.local_decls[temp].ty);
@@ -23,24 +23,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     /// Convenience function for creating a literal operand, one
     /// without any user type annotation.
-    pub fn literal_operand(&mut self, span: Span, literal: &'tcx ty::Const<'tcx>) -> Operand<'tcx> {
+    crate fn literal_operand(
+        &mut self,
+        span: Span,
+        literal: &'tcx ty::Const<'tcx>,
+    ) -> Operand<'tcx> {
         let constant = box Constant { span, user_ty: None, literal };
         Operand::Constant(constant)
     }
 
-    pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
+    crate fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
         Rvalue::Aggregate(box AggregateKind::Tuple, vec![])
     }
 
     // Returns a zero literal operand for the appropriate type, works for
     // bool, char and integers.
-    pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
+    crate fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty));
 
         self.literal_operand(span, literal)
     }
 
-    pub fn push_usize(
+    crate fn push_usize(
         &mut self,
         block: BasicBlock,
         source_info: SourceInfo,
@@ -61,7 +65,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         temp
     }
 
-    pub fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
+    crate fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> {
         let tcx = self.hir.tcx();
         let ty = place.ty(&self.local_decls, tcx).ty;
         if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index d4813d8ab68..6214453e64f 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -2,8 +2,6 @@ use crate::build;
 use crate::build::scope::DropKind;
 use crate::hair::cx::Cx;
 use crate::hair::{BindingMode, LintLevel, PatKind};
-use crate::transform::MirSource;
-use crate::util as mir_util;
 use rustc::middle::lang_items;
 use rustc::middle::region;
 use rustc::mir::*;
@@ -22,8 +20,12 @@ use syntax::attr::{self, UnwindAttr};
 
 use super::lints;
 
+crate fn mir_built(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::steal::Steal<BodyAndCache<'_>> {
+    tcx.alloc_steal_mir(mir_build(tcx, def_id))
+}
+
 /// Construct the MIR for a given `DefId`.
-pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
+fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
     let id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     // Figure out what primary body this item has.
@@ -172,8 +174,6 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
             build::construct_const(cx, body_id, return_ty, return_ty_span)
         };
 
-        mir_util::dump_mir(tcx, None, "mir_map", &0, MirSource::item(def_id), &body, |_, _| Ok(()));
-
         lints::check(tcx, &body, def_id);
 
         let mut body = BodyAndCache::new(body);
@@ -202,7 +202,7 @@ fn liberated_closure_env_ty(
 }
 
 #[derive(Debug, PartialEq, Eq)]
-pub enum BlockFrame {
+enum BlockFrame {
     /// Evaluation is currently within a statement.
     ///
     /// Examples include:
@@ -461,7 +461,7 @@ struct CFG<'tcx> {
 }
 
 rustc_index::newtype_index! {
-    pub struct ScopeId { .. }
+    struct ScopeId { .. }
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir_build/build/scope.rs
index 0aa9773b39a..d994b870853 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir_build/build/scope.rs
@@ -123,7 +123,7 @@ struct Scope {
 }
 
 #[derive(Debug, Default)]
-pub struct Scopes<'tcx> {
+crate struct Scopes<'tcx> {
     scopes: Vec<Scope>,
     /// The current set of breakable scopes. See module comment for more details.
     breakable_scopes: Vec<BreakableScope<'tcx>>,
@@ -183,7 +183,7 @@ struct BreakableScope<'tcx> {
 
 /// The target of an expression that breaks out of a scope
 #[derive(Clone, Copy, Debug)]
-pub enum BreakableTarget {
+crate enum BreakableTarget {
     Continue(region::Scope),
     Break(region::Scope),
     Return,
@@ -371,7 +371,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     // ==========================
     //  Start a breakable scope, which tracks where `continue`, `break` and
     //  `return` should branch to.
-    pub fn in_breakable_scope<F, R>(
+    crate fn in_breakable_scope<F, R>(
         &mut self,
         loop_block: Option<BasicBlock>,
         break_block: BasicBlock,
@@ -395,7 +395,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         res
     }
 
-    pub fn in_opt_scope<F, R>(
+    crate fn in_opt_scope<F, R>(
         &mut self,
         opt_scope: Option<(region::Scope, SourceInfo)>,
         f: F,
@@ -418,7 +418,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     /// Convenience wrapper that pushes a scope and then executes `f`
     /// to build its contents, popping the scope afterwards.
-    pub fn in_scope<F, R>(
+    crate fn in_scope<F, R>(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
         lint_level: LintLevel,
@@ -463,14 +463,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// scope and call `pop_scope` afterwards. Note that these two
     /// calls must be paired; using `in_scope` as a convenience
     /// wrapper maybe preferable.
-    pub fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
+    crate fn push_scope(&mut self, region_scope: (region::Scope, SourceInfo)) {
         self.scopes.push_scope(region_scope, self.source_scope);
     }
 
     /// Pops a scope, which should have region scope `region_scope`,
     /// adding any drops onto the end of `block` that are needed.
     /// This must match 1-to-1 with `push_scope`.
-    pub fn pop_scope(
+    crate fn pop_scope(
         &mut self,
         region_scope: (region::Scope, SourceInfo),
         mut block: BasicBlock,
@@ -500,7 +500,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         block.unit()
     }
 
-    pub fn break_scope(
+    crate fn break_scope(
         &mut self,
         mut block: BasicBlock,
         value: Option<ExprRef<'tcx>>,
@@ -535,7 +535,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Branch out of `block` to `target`, exiting all scopes up to
     /// and including `region_scope`. This will insert whatever drops are
     /// needed. See module comment for details.
-    pub fn exit_scope(
+    crate fn exit_scope(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -604,7 +604,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// This path terminates in GeneratorDrop. Returns the start of the path.
     /// None indicates there’s no cleanup to do at this point.
-    pub fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
+    crate fn generator_drop_cleanup(&mut self) -> Option<BasicBlock> {
         // Fill in the cache for unwinds
         self.diverge_cleanup_gen(true);
 
@@ -656,7 +656,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /// Creates a new source scope, nested in the current one.
-    pub fn new_source_scope(
+    crate fn new_source_scope(
         &mut self,
         span: Span,
         lint_level: LintLevel,
@@ -689,7 +689,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /// Given a span and the current source scope, make a SourceInfo.
-    pub fn source_info(&self, span: Span) -> SourceInfo {
+    crate fn source_info(&self, span: Span) -> SourceInfo {
         SourceInfo { span, scope: self.source_scope }
     }
 
@@ -717,7 +717,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// When building statics/constants, returns `None` since
     /// intermediate values do not have to be dropped in that case.
-    pub fn local_scope(&self) -> Option<region::Scope> {
+    crate fn local_scope(&self) -> Option<region::Scope> {
         match self.hir.body_owner_kind {
             hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) =>
             // No need to free storage in this context.
@@ -729,7 +729,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     // Schedule an abort block - this is used for some ABIs that cannot unwind
-    pub fn schedule_abort(&mut self) -> BasicBlock {
+    crate fn schedule_abort(&mut self) -> BasicBlock {
         let source_info = self.scopes.source_info(self.scopes.len(), self.fn_span);
         let abortblk = self.cfg.start_new_cleanup_block();
         self.cfg.terminate(abortblk, source_info, TerminatorKind::Abort);
@@ -739,7 +739,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
     // Scheduling drops
     // ================
-    pub fn schedule_drop_storage_and_value(
+    crate fn schedule_drop_storage_and_value(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -754,7 +754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// When called with `DropKind::Storage`, `place` should be a local
     /// with an index higher than the current `self.arg_count`.
-    pub fn schedule_drop(
+    crate fn schedule_drop(
         &mut self,
         span: Span,
         region_scope: region::Scope,
@@ -884,7 +884,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// spurious borrow-check errors -- the problem, ironically, is
     /// not the `DROP(_X)` itself, but the (spurious) unwind pathways
     /// that it creates. See #64391 for an example.
-    pub fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
+    crate fn record_operands_moved(&mut self, operands: &[Operand<'tcx>]) {
         let scope = match self.local_scope() {
             None => {
                 // if there is no local scope, operands won't be dropped anyway
@@ -921,7 +921,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// This is a special case because the temporary for the condition needs to
     /// be dropped on both the true and the false arm.
-    pub fn test_bool(
+    crate fn test_bool(
         &mut self,
         mut block: BasicBlock,
         condition: Expr<'tcx>,
@@ -978,7 +978,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     ///
     /// This path terminates in Resume. Returns the start of the path.
     /// See module comment for more details.
-    pub fn diverge_cleanup(&mut self) -> BasicBlock {
+    crate fn diverge_cleanup(&mut self) -> BasicBlock {
         self.diverge_cleanup_gen(false)
     }
 
@@ -1033,7 +1033,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 
     /// Utility function for *non*-scope code to build their own drops
-    pub fn build_drop_and_replace(
+    crate fn build_drop_and_replace(
         &mut self,
         block: BasicBlock,
         span: Span,
@@ -1059,7 +1059,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Creates an Assert terminator and return the success block.
     /// If the boolean condition operand is not the expected value,
     /// a runtime panic will be caused with the given message.
-    pub fn assert(
+    crate fn assert(
         &mut self,
         block: BasicBlock,
         cond: Operand<'tcx>,
@@ -1293,7 +1293,7 @@ fn build_diverge_scope<'tcx>(
     target
 }
 
-fn push_storage_deads(
+fn push_storage_deads<'tcx>(
     cfg: &mut CFG<'tcx>,
     target: BasicBlock,
     storage_deads: &mut Vec<Statement<'tcx>>,
diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir_build/hair/constant.rs
index a4bedfa6490..a4bedfa6490 100644
--- a/src/librustc_mir/hair/constant.rs
+++ b/src/librustc_mir_build/hair/constant.rs
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir_build/hair/cx/block.rs
index 674c1489b9b..a883b84f8fe 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir_build/hair/cx/block.rs
@@ -101,7 +101,7 @@ fn mirror_stmts<'a, 'tcx>(
     return result;
 }
 
-pub fn to_expr_ref<'a, 'tcx>(
+crate fn to_expr_ref<'a, 'tcx>(
     cx: &mut Cx<'a, 'tcx>,
     block: &'tcx hir::Block<'tcx>,
 ) -> ExprRef<'tcx> {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index 471e09fc03b..97e71811829 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -577,8 +577,8 @@ fn make_mirror_unadjusted<'a, 'tcx>(
     Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind }
 }
 
-fn user_substs_applied_to_res(
-    cx: &mut Cx<'a, 'tcx>,
+fn user_substs_applied_to_res<'tcx>(
+    cx: &mut Cx<'_, 'tcx>,
     hir_id: hir::HirId,
     res: Res,
 ) -> Option<ty::CanonicalUserType<'tcx>> {
@@ -775,7 +775,7 @@ fn convert_path_expr<'a, 'tcx>(
     }
 }
 
-fn convert_var(
+fn convert_var<'tcx>(
     cx: &mut Cx<'_, 'tcx>,
     expr: &'tcx hir::Expr<'tcx>,
     var_hir_id: hir::HirId,
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs
index 2e5ab334350..5fc9a1ecad5 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir_build/hair/cx/mod.rs
@@ -21,18 +21,18 @@ use syntax::ast;
 use syntax::attr;
 
 #[derive(Clone)]
-pub struct Cx<'a, 'tcx> {
+crate struct Cx<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     infcx: &'a InferCtxt<'a, 'tcx>,
 
-    pub root_lint_level: hir::HirId,
-    pub param_env: ty::ParamEnv<'tcx>,
+    crate root_lint_level: hir::HirId,
+    crate param_env: ty::ParamEnv<'tcx>,
 
     /// Identity `InternalSubsts` for use with const-evaluation.
-    pub identity_substs: &'tcx InternalSubsts<'tcx>,
+    crate identity_substs: &'tcx InternalSubsts<'tcx>,
 
-    pub region_scope_tree: &'tcx region::ScopeTree,
-    pub tables: &'a ty::TypeckTables<'tcx>,
+    crate region_scope_tree: &'tcx region::ScopeTree,
+    crate tables: &'a ty::TypeckTables<'tcx>,
 
     /// This is `Constness::Const` if we are compiling a `static`,
     /// `const`, or the body of a `const fn`.
@@ -42,7 +42,7 @@ pub struct Cx<'a, 'tcx> {
     body_owner: DefId,
 
     /// What kind of body is being compiled.
-    pub body_owner_kind: hir::BodyOwnerKind,
+    crate body_owner_kind: hir::BodyOwnerKind,
 
     /// Whether this constant/function needs overflow checks.
     check_overflow: bool,
@@ -52,7 +52,7 @@ pub struct Cx<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
+    crate fn new(infcx: &'a InferCtxt<'a, 'tcx>, src_id: hir::HirId) -> Cx<'a, 'tcx> {
         let tcx = infcx.tcx;
         let src_def_id = tcx.hir().local_def_id(src_id);
         let tables = tcx.typeck_tables_of(src_def_id);
@@ -92,42 +92,42 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
         }
     }
 
-    pub fn control_flow_destroyed(self) -> Vec<(Span, String)> {
+    crate fn control_flow_destroyed(self) -> Vec<(Span, String)> {
         self.control_flow_destroyed
     }
 }
 
 impl<'a, 'tcx> Cx<'a, 'tcx> {
     /// Normalizes `ast` into the appropriate "mirror" type.
-    pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
+    crate fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
         ast.make_mirror(self)
     }
 
-    pub fn usize_ty(&mut self) -> Ty<'tcx> {
+    crate fn usize_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.usize
     }
 
-    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
+    crate fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_usize(self.tcx, value)
     }
 
-    pub fn bool_ty(&mut self) -> Ty<'tcx> {
+    crate fn bool_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.bool
     }
 
-    pub fn unit_ty(&mut self) -> Ty<'tcx> {
+    crate fn unit_ty(&mut self) -> Ty<'tcx> {
         self.tcx.mk_unit()
     }
 
-    pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+    crate fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_bool(self.tcx, true)
     }
 
-    pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+    crate fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
         ty::Const::from_bool(self.tcx, false)
     }
 
-    pub fn const_eval_literal(
+    crate fn const_eval_literal(
         &mut self,
         lit: &'tcx ast::LitKind,
         ty: Ty<'tcx>,
@@ -151,15 +151,15 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
         }
     }
 
-    pub fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
+    crate fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
         let p = match self.tcx.hir().get(p.hir_id) {
             Node::Pat(p) | Node::Binding(p) => p,
             node => bug!("pattern became {:?}", node),
         };
-        Pat::from_hir(self.tcx, self.param_env.and(self.identity_substs), self.tables(), p)
+        Pat::from_hir(self.tcx, self.param_env, self.tables(), p)
     }
 
-    pub fn trait_method(
+    crate fn trait_method(
         &mut self,
         trait_def_id: DefId,
         method_name: Symbol,
@@ -168,6 +168,8 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
     ) -> &'tcx ty::Const<'tcx> {
         let substs = self.tcx.mk_substs_trait(self_ty, params);
         for item in self.tcx.associated_items(trait_def_id) {
+            // The unhygienic comparison here is acceptable because this is only
+            // used on known traits.
             if item.kind == ty::AssocKind::Method && item.ident.name == method_name {
                 let method_ty = self.tcx.type_of(item.def_id);
                 let method_ty = method_ty.subst(self.tcx, substs);
@@ -178,32 +180,32 @@ impl<'a, 'tcx> Cx<'a, 'tcx> {
         bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
-    pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
+    crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> {
         (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect()
     }
 
-    pub fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
+    crate fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool {
         ty.needs_drop(self.tcx, self.param_env)
     }
 
-    pub fn tcx(&self) -> TyCtxt<'tcx> {
+    crate fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
 
-    pub fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
+    crate fn tables(&self) -> &'a ty::TypeckTables<'tcx> {
         self.tables
     }
 
-    pub fn check_overflow(&self) -> bool {
+    crate fn check_overflow(&self) -> bool {
         self.check_overflow
     }
 
-    pub fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
+    crate fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool {
         self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span)
     }
 }
 
-impl UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
+impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx()
     }
diff --git a/src/librustc_mir/hair/cx/to_ref.rs b/src/librustc_mir_build/hair/cx/to_ref.rs
index d6859e356ee..6cf8122e200 100644
--- a/src/librustc_mir/hair/cx/to_ref.rs
+++ b/src/librustc_mir_build/hair/cx/to_ref.rs
@@ -2,7 +2,7 @@ use crate::hair::*;
 
 use rustc_hir as hir;
 
-pub trait ToRef {
+crate trait ToRef {
     type Output;
     fn to_ref(self) -> Self::Output;
 }
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs
index cde91cc36ca..3257f282dc1 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir_build/hair/mod.rs
@@ -17,33 +17,33 @@ use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
 mod constant;
-pub mod cx;
+crate mod cx;
 
-pub mod pattern;
-pub(crate) use self::pattern::PatTyProj;
-pub use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
+crate mod pattern;
+crate use self::pattern::PatTyProj;
+crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
 
 mod util;
 
 #[derive(Copy, Clone, Debug)]
-pub enum LintLevel {
+crate enum LintLevel {
     Inherited,
     Explicit(hir::HirId),
 }
 
 #[derive(Clone, Debug)]
-pub struct Block<'tcx> {
-    pub targeted_by_break: bool,
-    pub region_scope: region::Scope,
-    pub opt_destruction_scope: Option<region::Scope>,
-    pub span: Span,
-    pub stmts: Vec<StmtRef<'tcx>>,
-    pub expr: Option<ExprRef<'tcx>>,
-    pub safety_mode: BlockSafety,
+crate struct Block<'tcx> {
+    crate targeted_by_break: bool,
+    crate region_scope: region::Scope,
+    crate opt_destruction_scope: Option<region::Scope>,
+    crate span: Span,
+    crate stmts: Vec<StmtRef<'tcx>>,
+    crate expr: Option<ExprRef<'tcx>>,
+    crate safety_mode: BlockSafety,
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BlockSafety {
+crate enum BlockSafety {
     Safe,
     ExplicitUnsafe(hir::HirId),
     PushUnsafe,
@@ -51,18 +51,18 @@ pub enum BlockSafety {
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtRef<'tcx> {
+crate enum StmtRef<'tcx> {
     Mirror(Box<Stmt<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct Stmt<'tcx> {
-    pub kind: StmtKind<'tcx>,
-    pub opt_destruction_scope: Option<region::Scope>,
+crate struct Stmt<'tcx> {
+    crate kind: StmtKind<'tcx>,
+    crate opt_destruction_scope: Option<region::Scope>,
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtKind<'tcx> {
+crate enum StmtKind<'tcx> {
     Expr {
         /// scope for this statement; may be used as lifetime of temporaries
         scope: region::Scope,
@@ -112,23 +112,23 @@ rustc_data_structures::static_assert_size!(Expr<'_>, 168);
 /// example, method calls and overloaded operators are absent: they are
 /// expected to be converted into `Expr::Call` instances.
 #[derive(Clone, Debug)]
-pub struct Expr<'tcx> {
+crate struct Expr<'tcx> {
     /// type of this expression
-    pub ty: Ty<'tcx>,
+    crate ty: Ty<'tcx>,
 
     /// lifetime of this expression if it should be spilled into a
     /// temporary; should be None only if in a constant context
-    pub temp_lifetime: Option<region::Scope>,
+    crate temp_lifetime: Option<region::Scope>,
 
     /// span of the expression in the source
-    pub span: Span,
+    crate span: Span,
 
     /// kind of expression
-    pub kind: ExprKind<'tcx>,
+    crate kind: ExprKind<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprKind<'tcx> {
+crate enum ExprKind<'tcx> {
     Scope {
         region_scope: region::Scope,
         lint_level: LintLevel,
@@ -288,37 +288,37 @@ pub enum ExprKind<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprRef<'tcx> {
+crate enum ExprRef<'tcx> {
     Hair(&'tcx hir::Expr<'tcx>),
     Mirror(Box<Expr<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldExprRef<'tcx> {
-    pub name: Field,
-    pub expr: ExprRef<'tcx>,
+crate struct FieldExprRef<'tcx> {
+    crate name: Field,
+    crate expr: ExprRef<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct FruInfo<'tcx> {
-    pub base: ExprRef<'tcx>,
-    pub field_types: Vec<Ty<'tcx>>,
+crate struct FruInfo<'tcx> {
+    crate base: ExprRef<'tcx>,
+    crate field_types: Vec<Ty<'tcx>>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Arm<'tcx> {
-    pub pattern: Pat<'tcx>,
-    pub guard: Option<Guard<'tcx>>,
-    pub body: ExprRef<'tcx>,
-    pub lint_level: LintLevel,
-    pub scope: region::Scope,
-    pub span: Span,
+crate struct Arm<'tcx> {
+    crate pattern: Pat<'tcx>,
+    crate guard: Option<Guard<'tcx>>,
+    crate body: ExprRef<'tcx>,
+    crate lint_level: LintLevel,
+    crate scope: region::Scope,
+    crate span: Span,
 }
 
-impl Arm<'tcx> {
+impl<'tcx> Arm<'tcx> {
     // HACK(or_patterns; Centril | dlrobertson): Remove this and
     // correctly handle each case in which this method is used.
-    pub fn top_pats_hack(&self) -> &[Pat<'tcx>] {
+    crate fn top_pats_hack(&self) -> &[Pat<'tcx>] {
         match &*self.pattern.kind {
             PatKind::Or { pats } => pats,
             _ => std::slice::from_ref(&self.pattern),
@@ -327,18 +327,18 @@ impl Arm<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub enum Guard<'tcx> {
+crate enum Guard<'tcx> {
     If(ExprRef<'tcx>),
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum LogicalOp {
+crate enum LogicalOp {
     And,
     Or,
 }
 
 impl<'tcx> ExprRef<'tcx> {
-    pub fn span(&self) -> Span {
+    crate fn span(&self) -> Span {
         match self {
             ExprRef::Hair(expr) => expr.span,
             ExprRef::Mirror(expr) => expr.span,
@@ -361,7 +361,7 @@ impl<'tcx> ExprRef<'tcx> {
 /// mirrored. This allows a single AST node from the compiler to
 /// expand into one or more Hair nodes, which lets the Hair nodes be
 /// simpler.
-pub trait Mirror<'tcx> {
+crate trait Mirror<'tcx> {
     type Output;
 
     fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
@@ -378,7 +378,7 @@ impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
     type Output = Expr<'tcx>;
 
-    fn make_mirror(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
+    fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
         match self {
             ExprRef::Hair(h) => h.make_mirror(hir),
             ExprRef::Mirror(m) => *m,
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs
index 2bf1efd4441..8fcaa1e8082 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir_build/hair/pattern/_match.rs
@@ -230,7 +230,6 @@ use self::Usefulness::*;
 use self::WitnessPreference::*;
 
 use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_index::vec::Idx;
 
 use super::{compare_const_vals, PatternFoldable, PatternFolder};
@@ -260,7 +259,7 @@ use std::iter::{FromIterator, IntoIterator};
 use std::ops::RangeInclusive;
 use std::u128;
 
-pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
+crate fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pat<'tcx>) -> Pat<'tcx> {
     LiteralExpander { tcx: cx.tcx, param_env: cx.param_env }.fold_pattern(&pat)
 }
 
@@ -269,7 +268,7 @@ struct LiteralExpander<'tcx> {
     param_env: ty::ParamEnv<'tcx>,
 }
 
-impl LiteralExpander<'tcx> {
+impl<'tcx> LiteralExpander<'tcx> {
     /// Derefs `val` and potentially unsizes the value if `crty` is an array and `rty` a slice.
     ///
     /// `crty` and `rty` can differ because you can use array constants in the presence of slice
@@ -323,7 +322,7 @@ impl LiteralExpander<'tcx> {
     }
 }
 
-impl PatternFolder<'tcx> for LiteralExpander<'tcx> {
+impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> {
     fn fold_pattern(&mut self, pat: &Pat<'tcx>) -> Pat<'tcx> {
         debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind, pat.kind);
         match (&pat.ty.kind, &*pat.kind) {
@@ -381,10 +380,10 @@ impl<'tcx> Pat<'tcx> {
 /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
 /// works well.
 #[derive(Debug, Clone)]
-pub struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
+crate struct PatStack<'p, 'tcx>(SmallVec<[&'p Pat<'tcx>; 2]>);
 
 impl<'p, 'tcx> PatStack<'p, 'tcx> {
-    pub fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
+    crate fn from_pattern(pat: &'p Pat<'tcx>) -> Self {
         PatStack(smallvec![pat])
     }
 
@@ -472,15 +471,15 @@ impl<'p, 'tcx> FromIterator<&'p Pat<'tcx>> for PatStack<'p, 'tcx> {
 
 /// A 2D matrix.
 #[derive(Clone)]
-pub struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
+crate struct Matrix<'p, 'tcx>(Vec<PatStack<'p, 'tcx>>);
 
 impl<'p, 'tcx> Matrix<'p, 'tcx> {
-    pub fn empty() -> Self {
+    crate fn empty() -> Self {
         Matrix(vec![])
     }
 
     /// Pushes a new row to the matrix. If the row starts with an or-pattern, this expands it.
-    pub fn push(&mut self, row: PatStack<'p, 'tcx>) {
+    crate fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if let Some(rows) = row.expand_or_pat() {
             self.0.extend(rows);
         } else {
@@ -569,22 +568,21 @@ impl<'p, 'tcx> FromIterator<PatStack<'p, 'tcx>> for Matrix<'p, 'tcx> {
     }
 }
 
-pub struct MatchCheckCtxt<'a, 'tcx> {
-    pub tcx: TyCtxt<'tcx>,
+crate struct MatchCheckCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
     /// The module in which the match occurs. This is necessary for
     /// checking inhabited-ness of types because whether a type is (visibly)
     /// inhabited can depend on whether it was defined in the current module or
     /// not. E.g., `struct Foo { _private: ! }` cannot be seen to be empty
     /// outside it's module and should not be matchable with an empty match
     /// statement.
-    pub module: DefId,
+    crate module: DefId,
     param_env: ty::ParamEnv<'tcx>,
-    pub pattern_arena: &'a TypedArena<Pat<'tcx>>,
-    pub byte_array_map: FxHashMap<*const Pat<'tcx>, Vec<&'a Pat<'tcx>>>,
+    crate pattern_arena: &'a TypedArena<Pat<'tcx>>,
 }
 
 impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
-    pub fn create_and_enter<F, R>(
+    crate fn create_and_enter<F, R>(
         tcx: TyCtxt<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
         module: DefId,
@@ -595,13 +593,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
     {
         let pattern_arena = TypedArena::default();
 
-        f(MatchCheckCtxt {
-            tcx,
-            param_env,
-            module,
-            pattern_arena: &pattern_arena,
-            byte_array_map: FxHashMap::default(),
-        })
+        f(MatchCheckCtxt { tcx, param_env, module, pattern_arena: &pattern_arena })
     }
 
     fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool {
@@ -613,7 +605,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
     }
 
     // Returns whether the given type is an enum from another crate declared `#[non_exhaustive]`.
-    pub fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
+    crate fn is_foreign_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool {
         match ty.kind {
             ty::Adt(def, ..) => {
                 def.is_enum() && def.is_variant_list_non_exhaustive() && !def.did.is_local()
@@ -773,13 +765,13 @@ impl<'tcx> Constructor<'tcx> {
         cx: &MatchCheckCtxt<'a, 'tcx>,
         adt: &'tcx ty::AdtDef,
     ) -> VariantIdx {
-        match self {
-            Variant(id) => adt.variant_index_with_id(*id),
+        match *self {
+            Variant(id) => adt.variant_index_with_id(id),
             Single => {
                 assert!(!adt.is_enum());
                 VariantIdx::new(0)
             }
-            ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c),
+            ConstantValue(c) => cx.tcx.destructure_const(cx.param_env.and(c)).variant,
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt),
         }
     }
@@ -1058,7 +1050,7 @@ impl<'tcx> Constructor<'tcx> {
 }
 
 #[derive(Clone, Debug)]
-pub enum Usefulness<'tcx, 'p> {
+crate enum Usefulness<'tcx, 'p> {
     /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns.
     Useful(Vec<&'p Pat<'tcx>>),
     /// Carries a list of witnesses of non-exhaustiveness.
@@ -1146,7 +1138,7 @@ impl<'tcx, 'p> Usefulness<'tcx, 'p> {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum WitnessPreference {
+crate enum WitnessPreference {
     ConstructWitness,
     LeaveOutWitness,
 }
@@ -1190,10 +1182,10 @@ struct PatCtxt<'tcx> {
 ///
 /// The final `Pair(Some(_), true)` is then the resulting witness.
 #[derive(Clone, Debug)]
-pub struct Witness<'tcx>(Vec<Pat<'tcx>>);
+crate struct Witness<'tcx>(Vec<Pat<'tcx>>);
 
 impl<'tcx> Witness<'tcx> {
-    pub fn single_pattern(self) -> Pat<'tcx> {
+    crate fn single_pattern(self) -> Pat<'tcx> {
         assert_eq!(self.0.len(), 1);
         self.0.into_iter().next().unwrap()
     }
@@ -1358,9 +1350,9 @@ fn all_constructors<'a, 'tcx>(
 /// around the (offset) space: i.e., `range.lo <= range.hi`.
 #[derive(Clone, Debug)]
 struct IntRange<'tcx> {
-    pub range: RangeInclusive<u128>,
-    pub ty: Ty<'tcx>,
-    pub span: Span,
+    range: RangeInclusive<u128>,
+    ty: Ty<'tcx>,
+    span: Span,
 }
 
 impl<'tcx> IntRange<'tcx> {
@@ -1631,7 +1623,7 @@ impl<'tcx> fmt::Debug for MissingConstructors<'tcx> {
 /// relation to preceding patterns, it is not reachable) and exhaustiveness
 /// checking (if a wildcard pattern is useful in relation to a matrix, the
 /// matrix isn't exhaustive).
-pub fn is_useful<'p, 'tcx>(
+crate fn is_useful<'p, 'tcx>(
     cx: &mut MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
@@ -2238,7 +2230,7 @@ fn split_grouped_constructors<'p, 'tcx>(
     split_ctors
 }
 
-fn lint_overlapping_patterns(
+fn lint_overlapping_patterns<'tcx>(
     tcx: TyCtxt<'tcx>,
     hir_id: Option<HirId>,
     ctor_range: IntRange<'tcx>,
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs
index 0e9d16cfa56..84d57a89c98 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir_build/hair/pattern/check_match.rs
@@ -8,7 +8,6 @@ use rustc::hir::map::Map;
 use rustc::lint;
 use rustc::session::parse::feature_err;
 use rustc::session::Session;
-use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc_error_codes::*;
 use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder};
@@ -29,12 +28,8 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
         Some(id) => tcx.hir().body_owned_by(id),
     };
 
-    let mut visitor = MatchVisitor {
-        tcx,
-        tables: tcx.body_tables(body_id),
-        param_env: tcx.param_env(def_id),
-        identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
-    };
+    let mut visitor =
+        MatchVisitor { tcx, tables: tcx.body_tables(body_id), param_env: tcx.param_env(def_id) };
     visitor.visit_body(tcx.hir().body(body_id));
 }
 
@@ -46,7 +41,6 @@ struct MatchVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    identity_substs: SubstsRef<'tcx>,
 }
 
 impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> {
@@ -153,11 +147,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
             let inlined_arms: Vec<_> = arms
                 .iter()
                 .map(|arm| {
-                    let mut patcx = PatCtxt::new(
-                        self.tcx,
-                        self.param_env.and(self.identity_substs),
-                        self.tables,
-                    );
+                    let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
                     patcx.include_lint_checks();
                     let pattern = patcx.lower_pattern(&arm.pat);
                     let pattern: &_ = cx.pattern_arena.alloc(expand_pattern(cx, pattern));
@@ -189,8 +179,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
     fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>) {
         let module = self.tcx.hir().get_module_parent(pat.hir_id);
         MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| {
-            let mut patcx =
-                PatCtxt::new(self.tcx, self.param_env.and(self.identity_substs), self.tables);
+            let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.tables);
             patcx.include_lint_checks();
             let pattern = patcx.lower_pattern(pat);
             let pattern_ty = pattern.ty;
diff --git a/src/librustc_mir/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 75b25f03ca2..a21a0ee8a1b 100644
--- a/src/librustc_mir/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -1,5 +1,3 @@
-use crate::const_eval::const_variant_index;
-
 use rustc::infer::InferCtxt;
 use rustc::lint;
 use rustc::mir::Field;
@@ -167,18 +165,14 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
         let tcx = self.tcx();
         let param_env = self.param_env;
 
-        let adt_subpattern = |i, variant_opt| {
-            let field = Field::new(i);
-            let val = crate::const_eval::const_field(tcx, param_env, variant_opt, field, cv);
-            self.recur(val)
-        };
-        let adt_subpatterns = |n, variant_opt| {
-            (0..n)
-                .map(|i| {
-                    let field = Field::new(i);
-                    FieldPat { field, pattern: adt_subpattern(i, variant_opt) }
+        let field_pats = |vals: &[&'tcx ty::Const<'tcx>]| {
+            vals.iter()
+                .enumerate()
+                .map(|(idx, val)| {
+                    let field = Field::new(idx);
+                    FieldPat { field, pattern: self.recur(val) }
                 })
-                .collect::<Vec<_>>()
+                .collect()
         };
 
         let kind = match cv.ty.kind {
@@ -235,21 +229,28 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                 PatKind::Wild
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
-                let variant_index = const_variant_index(tcx, self.param_env, cv);
-                let subpatterns = adt_subpatterns(
-                    adt_def.variants[variant_index].fields.len(),
-                    Some(variant_index),
-                );
-                PatKind::Variant { adt_def, substs, variant_index, subpatterns }
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Variant {
+                    adt_def,
+                    substs,
+                    variant_index: destructured.variant,
+                    subpatterns: field_pats(destructured.fields),
+                }
+            }
+            ty::Adt(_, _) => {
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
             }
-            ty::Adt(adt_def, _) => {
-                let struct_var = adt_def.non_enum_variant();
-                PatKind::Leaf { subpatterns: adt_subpatterns(struct_var.fields.len(), None) }
+            ty::Tuple(_) => {
+                let destructured = tcx.destructure_const(param_env.and(cv));
+                PatKind::Leaf { subpatterns: field_pats(destructured.fields) }
             }
-            ty::Tuple(fields) => PatKind::Leaf { subpatterns: adt_subpatterns(fields.len(), None) },
-            ty::Array(_, n) => PatKind::Array {
-                prefix: (0..n.eval_usize(tcx, self.param_env))
-                    .map(|i| adt_subpattern(i as usize, None))
+            ty::Array(..) => PatKind::Array {
+                prefix: tcx
+                    .destructure_const(param_env.and(cv))
+                    .fields
+                    .iter()
+                    .map(|val| self.recur(val))
                     .collect(),
                 slice: None,
                 suffix: Vec::new(),
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs
index c7e26c6ea4f..9e00c4ea53a 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir_build/hair/pattern/mod.rs
@@ -31,7 +31,7 @@ use std::fmt;
 use rustc_error_codes::*;
 
 #[derive(Clone, Debug)]
-pub enum PatternError {
+crate enum PatternError {
     AssocConstInPattern(Span),
     StaticInPattern(Span),
     FloatBug,
@@ -39,22 +39,22 @@ pub enum PatternError {
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BindingMode {
+crate enum BindingMode {
     ByValue,
     ByRef(BorrowKind),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldPat<'tcx> {
-    pub field: Field,
-    pub pattern: Pat<'tcx>,
+crate struct FieldPat<'tcx> {
+    crate field: Field,
+    crate pattern: Pat<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Pat<'tcx> {
-    pub ty: Ty<'tcx>,
-    pub span: Span,
-    pub kind: Box<PatKind<'tcx>>,
+crate struct Pat<'tcx> {
+    crate ty: Ty<'tcx>,
+    crate span: Span,
+    crate kind: Box<PatKind<'tcx>>,
 }
 
 impl<'tcx> Pat<'tcx> {
@@ -64,8 +64,8 @@ impl<'tcx> Pat<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct PatTyProj<'tcx> {
-    pub user_ty: CanonicalUserType<'tcx>,
+crate struct PatTyProj<'tcx> {
+    crate user_ty: CanonicalUserType<'tcx>,
 }
 
 impl<'tcx> PatTyProj<'tcx> {
@@ -91,8 +91,8 @@ impl<'tcx> PatTyProj<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct Ascription<'tcx> {
-    pub user_ty: PatTyProj<'tcx>,
+crate struct Ascription<'tcx> {
+    crate user_ty: PatTyProj<'tcx>,
     /// Variance to use when relating the type `user_ty` to the **type of the value being
     /// matched**. Typically, this is `Variance::Covariant`, since the value being matched must
     /// have a type that is some subtype of the ascribed type.
@@ -111,12 +111,12 @@ pub struct Ascription<'tcx> {
     /// requires that `&'static str <: T_x`, where `T_x` is the type of `x`. Really, we should
     /// probably be checking for a `PartialEq` impl instead, but this preserves the behavior
     /// of the old type-check for now. See #57280 for details.
-    pub variance: ty::Variance,
-    pub user_ty_span: Span,
+    crate variance: ty::Variance,
+    crate user_ty_span: Span,
 }
 
 #[derive(Clone, Debug)]
-pub enum PatKind<'tcx> {
+crate enum PatKind<'tcx> {
     Wild,
 
     AscribeUserType {
@@ -184,10 +184,10 @@ pub enum PatKind<'tcx> {
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
-pub struct PatRange<'tcx> {
-    pub lo: &'tcx ty::Const<'tcx>,
-    pub hi: &'tcx ty::Const<'tcx>,
-    pub end: RangeEnd,
+crate struct PatRange<'tcx> {
+    crate lo: &'tcx ty::Const<'tcx>,
+    crate hi: &'tcx ty::Const<'tcx>,
+    crate end: RangeEnd,
 }
 
 impl<'tcx> fmt::Display for Pat<'tcx> {
@@ -342,23 +342,22 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
     }
 }
 
-pub struct PatCtxt<'a, 'tcx> {
-    pub tcx: TyCtxt<'tcx>,
-    pub param_env: ty::ParamEnv<'tcx>,
-    pub tables: &'a ty::TypeckTables<'tcx>,
-    pub substs: SubstsRef<'tcx>,
-    pub errors: Vec<PatternError>,
+crate struct PatCtxt<'a, 'tcx> {
+    crate tcx: TyCtxt<'tcx>,
+    crate param_env: ty::ParamEnv<'tcx>,
+    crate tables: &'a ty::TypeckTables<'tcx>,
+    crate errors: Vec<PatternError>,
     include_lint_checks: bool,
 }
 
 impl<'a, 'tcx> Pat<'tcx> {
-    pub fn from_hir(
+    crate fn from_hir(
         tcx: TyCtxt<'tcx>,
-        param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
         tables: &'a ty::TypeckTables<'tcx>,
         pat: &'tcx hir::Pat<'tcx>,
     ) -> Self {
-        let mut pcx = PatCtxt::new(tcx, param_env_and_substs, tables);
+        let mut pcx = PatCtxt::new(tcx, param_env, tables);
         let result = pcx.lower_pattern(pat);
         if !pcx.errors.is_empty() {
             let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
@@ -370,27 +369,20 @@ impl<'a, 'tcx> Pat<'tcx> {
 }
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
-    pub fn new(
+    crate fn new(
         tcx: TyCtxt<'tcx>,
-        param_env_and_substs: ty::ParamEnvAnd<'tcx, SubstsRef<'tcx>>,
+        param_env: ty::ParamEnv<'tcx>,
         tables: &'a ty::TypeckTables<'tcx>,
     ) -> Self {
-        PatCtxt {
-            tcx,
-            param_env: param_env_and_substs.param_env,
-            tables,
-            substs: param_env_and_substs.value,
-            errors: vec![],
-            include_lint_checks: false,
-        }
+        PatCtxt { tcx, param_env, tables, errors: vec![], include_lint_checks: false }
     }
 
-    pub fn include_lint_checks(&mut self) -> &mut Self {
+    crate fn include_lint_checks(&mut self) -> &mut Self {
         self.include_lint_checks = true;
         self
     }
 
-    pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
+    crate fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Pat<'tcx> {
         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
         // pattern has the type that results *after* dereferencing. For example, in this code:
         //
@@ -863,7 +855,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     }
 }
 
-impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
+impl<'tcx> UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.tcx
     }
@@ -873,7 +865,7 @@ impl UserAnnotatedTyHelpers<'tcx> for PatCtxt<'_, 'tcx> {
     }
 }
 
-pub trait PatternFoldable<'tcx>: Sized {
+crate trait PatternFoldable<'tcx>: Sized {
     fn fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         self.super_fold_with(folder)
     }
@@ -881,7 +873,7 @@ pub trait PatternFoldable<'tcx>: Sized {
     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self;
 }
 
-pub trait PatternFolder<'tcx>: Sized {
+crate trait PatternFolder<'tcx>: Sized {
     fn fold_pattern(&mut self, pattern: &Pat<'tcx>) -> Pat<'tcx> {
         pattern.super_fold_with(self)
     }
@@ -1009,7 +1001,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
     }
 }
 
-pub fn compare_const_vals<'tcx>(
+crate fn compare_const_vals<'tcx>(
     tcx: TyCtxt<'tcx>,
     a: &'tcx ty::Const<'tcx>,
     b: &'tcx ty::Const<'tcx>,
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir_build/hair/util.rs
index c27844ed0d0..c27844ed0d0 100644
--- a/src/librustc_mir/hair/util.rs
+++ b/src/librustc_mir_build/hair/util.rs
diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs
new file mode 100644
index 00000000000..96032a732ab
--- /dev/null
+++ b/src/librustc_mir_build/lib.rs
@@ -0,0 +1,26 @@
+//! Construction of MIR from HIR.
+//!
+//! This crate also contains the match exhaustiveness and usefulness checking.
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(crate_visibility_modifier)]
+#![feature(slice_patterns)]
+#![feature(bool_to_option)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate rustc;
+
+mod build;
+mod hair;
+mod lints;
+
+use rustc::ty::query::Providers;
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.check_match = hair::pattern::check_match;
+    providers.mir_built = build::mir_built;
+}
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir_build/lints.rs
index a58d17569ef..4244e1b8d80 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir_build/lints.rs
@@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::FnKind;
 use rustc_index::bit_set::BitSet;
 
-pub fn check(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
+crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
     let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
 
     if let Some(fn_like_node) = FnLikeNode::from_node(tcx.hir().get(hir_id)) {
@@ -15,7 +15,7 @@ pub fn check(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) {
     }
 }
 
-fn check_fn_for_unconditional_recursion(
+fn check_fn_for_unconditional_recursion<'tcx>(
     tcx: TyCtxt<'tcx>,
     fn_kind: FnKind<'_>,
     body: &Body<'tcx>,
diff --git a/src/test/ui/pattern/const-pat-ice.stderr b/src/test/ui/pattern/const-pat-ice.stderr
index 7a0f14425b7..7217fe1b02f 100644
--- a/src/test/ui/pattern/const-pat-ice.stderr
+++ b/src/test/ui/pattern/const-pat-ice.stderr
@@ -1,4 +1,4 @@
-thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir/hair/pattern/_match.rs:LL:CC
+thread 'rustc' panicked at 'assertion failed: rows.iter().all(|r| r.len() == v.len())', src/librustc_mir_build/hair/pattern/_match.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
 
 error: internal compiler error: unexpected panic