about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-11-14 07:54:51 +0000
committerbors <bors@rust-lang.org>2017-11-14 07:54:51 +0000
commit24840dab0bef0047beb428e1c15e9a851f732dcc (patch)
treed7fe13d555d0954c39d2a73a0a0d545467676163
parentb5a3ab2e81c837df95a21758b00aeb4e88477b30 (diff)
parentd6aa56f44e062bfe06144318cbd88ac0b58d5814 (diff)
downloadrust-24840dab0bef0047beb428e1c15e9a851f732dcc.tar.gz
rust-24840dab0bef0047beb428e1c15e9a851f732dcc.zip
Auto merge of #45916 - eddyb:even-mirer-0, r=nikomatsakis
rustc_mir: hardcode pass list internally and remove premature pluggability.

Fixes #41712 by moving the MIR pass lists from `rustc_driver` to `rustc_mir`.
The application of the passes is done with the `rustc_mir::transform::run_passes` macro, which is public, as are all the passes AFAIK, and can be used to apply MIR passes outside of `rustc_mir`.

With the ability to override query providers through the `rustc_driver` (orthogonal to, and not included in this PR), custom drivers will be able to substitute the entire pass list if they want to.
**EDIT**: the aforementioned ability is added by #45944.

r? @nikomatsakis
-rw-r--r--src/librustc/hir/map/mod.rs22
-rw-r--r--src/librustc/hir/mod.rs12
-rw-r--r--src/librustc/middle/region.rs3
-rw-r--r--src/librustc/mir/mod.rs1
-rw-r--r--src/librustc/mir/transform.rs190
-rw-r--r--src/librustc/ty/context.rs5
-rw-r--r--src/librustc/ty/maps/keys.rs19
-rw-r--r--src/librustc_driver/driver.rs52
-rw-r--r--src/librustc_driver/test.rs2
-rw-r--r--src/librustc_mir/borrow_check.rs15
-rw-r--r--src/librustc_mir/build/mod.rs17
-rw-r--r--src/librustc_mir/build/scope.rs13
-rw-r--r--src/librustc_mir/hair/cx/mod.rs29
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/shim.rs8
-rw-r--r--src/librustc_mir/transform/add_call_guards.rs2
-rw-r--r--src/librustc_mir/transform/add_validation.rs7
-rw-r--r--src/librustc_mir/transform/clean_end_regions.rs2
-rw-r--r--src/librustc_mir/transform/copy_prop.rs28
-rw-r--r--src/librustc_mir/transform/deaggregator.rs16
-rw-r--r--src/librustc_mir/transform/dump_mir.rs46
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs15
-rw-r--r--src/librustc_mir/transform/erase_regions.rs2
-rw-r--r--src/librustc_mir/transform/generator.rs8
-rw-r--r--src/librustc_mir/transform/inline.rs14
-rw-r--r--src/librustc_mir/transform/instcombine.rs2
-rw-r--r--src/librustc_mir/transform/mod.rs157
-rw-r--r--src/librustc_mir/transform/nll/constraint_generation.rs11
-rw-r--r--src/librustc_mir/transform/nll/free_regions.rs10
-rw-r--r--src/librustc_mir/transform/nll/mod.rs14
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs22
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs6
-rw-r--r--src/librustc_mir/transform/simplify.rs2
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs2
-rw-r--r--src/librustc_mir/transform/type_check.rs8
-rw-r--r--src/librustc_mir/util/graphviz.rs14
-rw-r--r--src/librustc_mir/util/liveness.rs7
-rw-r--r--src/librustc_mir/util/pretty.rs65
-rw-r--r--src/librustc_passes/consts.rs7
40 files changed, 343 insertions, 516 deletions
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 453d30dde75..1b590c2b2c4 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -448,6 +448,28 @@ impl<'hir> Map<'hir> {
         })
     }
 
+    pub fn body_owner_kind(&self, id: NodeId) -> BodyOwnerKind {
+        // Handle constants in enum discriminants, types, and repeat expressions.
+        let def_id = self.local_def_id(id);
+        let def_key = self.def_key(def_id);
+        if def_key.disambiguated_data.data == DefPathData::Initializer {
+            return BodyOwnerKind::Const;
+        }
+
+        match self.get(id) {
+            NodeItem(&Item { node: ItemConst(..), .. }) |
+            NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
+            NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
+                BodyOwnerKind::Const
+            }
+            NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => {
+                BodyOwnerKind::Static(m)
+            }
+            // Default to function if it's not a constant or static.
+            _ => BodyOwnerKind::Fn
+        }
+    }
+
     pub fn ty_param_owner(&self, id: NodeId) -> NodeId {
         match self.get(id) {
             NodeItem(&Item { node: ItemTrait(..), .. }) => id,
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 39e222230e5..a7206f5d420 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1028,6 +1028,18 @@ impl Body {
     }
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum BodyOwnerKind {
+    /// Functions and methods.
+    Fn,
+
+    /// Constants and associated constants.
+    Const,
+
+    /// Initializer of a `static` item.
+    Static(Mutability),
+}
+
 /// An expression
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Expr {
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 89707839144..a7882992d61 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -31,7 +31,6 @@ use hir;
 use hir::def_id::DefId;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local};
-use mir::transform::MirSource;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
@@ -1298,7 +1297,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> {
 
         // The body of the every fn is a root scope.
         self.cx.parent = self.cx.var_parent;
-        if let MirSource::Fn(_) = MirSource::from_node(self.tcx, owner_id) {
+        if let hir::BodyOwnerKind::Fn = self.tcx.hir.body_owner_kind(owner_id) {
             self.visit_expr(&body.value);
         } else {
             // Only functions have an outer terminating (drop) scope, while
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index cd017650633..18c26500dbe 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -41,7 +41,6 @@ use syntax_pos::Span;
 mod cache;
 pub mod tcx;
 pub mod visit;
-pub mod transform;
 pub mod traversal;
 
 /// Types for locals
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
deleted file mode 100644
index 6c90a5f38d0..00000000000
--- a/src/librustc/mir/transform.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! See [the README](README.md) for details on writing your own pass.
-
-use hir;
-use hir::def_id::DefId;
-use hir::map::DefPathData;
-use mir::{Mir, Promoted};
-use ty::TyCtxt;
-use std::rc::Rc;
-use syntax::ast::NodeId;
-
-use std::borrow::Cow;
-
-/// Where a specific Mir comes from.
-#[derive(Debug, Copy, Clone)]
-pub enum MirSource {
-    /// Functions and methods.
-    Fn(NodeId),
-
-    /// Constants and associated constants.
-    Const(NodeId),
-
-    /// Initializer of a `static` item.
-    Static(NodeId, hir::Mutability),
-
-    /// Promoted rvalues within a function.
-    Promoted(NodeId, Promoted),
-
-    /// Drop glue for a generator.
-    GeneratorDrop(NodeId),
-}
-
-impl<'a, 'gcx, 'tcx> MirSource {
-    pub fn from_local_def_id(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> MirSource {
-        let id = tcx.hir.as_local_node_id(def_id).expect("mir source requires local def-id");
-        Self::from_node(tcx, id)
-    }
-
-    pub fn from_node(tcx: TyCtxt<'a, 'gcx, 'tcx>, id: NodeId) -> MirSource {
-        use hir::*;
-
-        // Handle constants in enum discriminants, types, and repeat expressions.
-        let def_id = tcx.hir.local_def_id(id);
-        let def_key = tcx.def_key(def_id);
-        if def_key.disambiguated_data.data == DefPathData::Initializer {
-            return MirSource::Const(id);
-        }
-
-        match tcx.hir.get(id) {
-            map::NodeItem(&Item { node: ItemConst(..), .. }) |
-            map::NodeTraitItem(&TraitItem { node: TraitItemKind::Const(..), .. }) |
-            map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
-                MirSource::Const(id)
-            }
-            map::NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => {
-                MirSource::Static(id, m)
-            }
-            // Default to function if it's not a constant or static.
-            _ => MirSource::Fn(id)
-        }
-    }
-
-    pub fn item_id(&self) -> NodeId {
-        match *self {
-            MirSource::Fn(id) |
-            MirSource::Const(id) |
-            MirSource::GeneratorDrop(id) |
-            MirSource::Static(id, _) |
-            MirSource::Promoted(id, _) => id
-        }
-    }
-}
-
-/// Generates a default name for the pass based on the name of the
-/// type `T`.
-pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
-    let name = unsafe { ::std::intrinsics::type_name::<T>() };
-    if let Some(tail) = name.rfind(":") {
-        Cow::from(&name[tail+1..])
-    } else {
-        Cow::from(name)
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct MirSuite(pub usize);
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct MirPassIndex(pub usize);
-
-/// A pass hook is invoked both before and after each pass executes.
-/// This is primarily used to dump MIR for debugging.
-///
-/// You can tell whether this is before or after by inspecting the
-/// `mir` parameter -- before the pass executes, it will be `None` (in
-/// which case you can inspect the MIR from previous pass by executing
-/// `mir_cx.read_previous_mir()`); after the pass executes, it will be
-/// `Some()` with the result of the pass (in which case the output
-/// from the previous pass is most likely stolen, so you would not
-/// want to try and access it). If the pass is interprocedural, then
-/// the hook will be invoked once per output.
-pub trait PassHook {
-    fn on_mir_pass<'a, 'tcx: 'a>(&self,
-                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 suite: MirSuite,
-                                 pass_num: MirPassIndex,
-                                 pass_name: &str,
-                                 source: MirSource,
-                                 mir: &Mir<'tcx>,
-                                 is_after: bool);
-}
-
-/// The full suite of types that identifies a particular
-/// application of a pass to a def-id.
-pub type PassId = (MirSuite, MirPassIndex, DefId);
-
-/// A streamlined trait that you can implement to create a pass; the
-/// pass will be named after the type, and it will consist of a main
-/// loop that goes over each available MIR and applies `run_pass`.
-pub trait MirPass {
-    fn name<'a>(&'a self) -> Cow<'a, str> {
-        default_name::<Self>()
-    }
-
-    fn run_pass<'a, 'tcx>(&self,
-                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          source: MirSource,
-                          mir: &mut Mir<'tcx>);
-}
-
-/// A manager for MIR passes.
-///
-/// FIXME(#41712) -- it is unclear whether we should have this struct.
-#[derive(Clone)]
-pub struct Passes {
-    pass_hooks: Vec<Rc<PassHook>>,
-    suites: Vec<Vec<Rc<MirPass>>>,
-}
-
-/// The number of "pass suites" that we have:
-///
-/// - ready for constant evaluation
-/// - unopt
-/// - optimized
-pub const MIR_SUITES: usize = 3;
-
-/// Run the passes we need to do constant qualification and evaluation.
-pub const MIR_CONST: MirSuite = MirSuite(0);
-
-/// Run the passes we need to consider the MIR validated and ready for borrowck etc.
-pub const MIR_VALIDATED: MirSuite = MirSuite(1);
-
-/// Run the passes we need to consider the MIR *optimized*.
-pub const MIR_OPTIMIZED: MirSuite = MirSuite(2);
-
-impl<'a, 'tcx> Passes {
-    pub fn new() -> Passes {
-        Passes {
-            pass_hooks: Vec::new(),
-            suites: (0..MIR_SUITES).map(|_| Vec::new()).collect(),
-        }
-    }
-
-    /// Pushes a built-in pass.
-    pub fn push_pass<T: MirPass + 'static>(&mut self, suite: MirSuite, pass: T) {
-        self.suites[suite.0].push(Rc::new(pass));
-    }
-
-    /// Pushes a pass hook.
-    pub fn push_hook<T: PassHook + 'static>(&mut self, hook: T) {
-        self.pass_hooks.push(Rc::new(hook));
-    }
-
-    pub fn passes(&self, suite: MirSuite) -> &[Rc<MirPass>] {
-        &self.suites[suite.0]
-    }
-
-    pub fn hooks(&self) -> &[Rc<PassHook>] {
-        &self.pass_hooks
-    }
-}
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 37c4346a7dc..193c3673607 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -31,7 +31,6 @@ use middle::lang_items;
 use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
 use mir::Mir;
-use mir::transform::Passes;
 use ty::subst::{Kind, Substs};
 use ty::ReprOptions;
 use traits;
@@ -882,8 +881,6 @@ pub struct GlobalCtxt<'tcx> {
 
     pub maps: maps::Maps<'tcx>,
 
-    pub mir_passes: Rc<Passes>,
-
     // Records the free variables refrenced by every closure
     // expression. Do not track deps for this, just recompute it from
     // scratch every time.
@@ -1055,7 +1052,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   cstore: &'tcx CrateStore,
                                   local_providers: ty::maps::Providers<'tcx>,
                                   extern_providers: ty::maps::Providers<'tcx>,
-                                  mir_passes: Rc<Passes>,
                                   arenas: &'tcx GlobalArenas<'tcx>,
                                   arena: &'tcx DroplessArena,
                                   resolutions: ty::Resolutions,
@@ -1172,7 +1168,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             hir,
             def_path_hash_to_def_id,
             maps: maps::Maps::new(providers),
-            mir_passes,
             rcache: RefCell::new(FxHashMap()),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs
index ee4523d6f3e..b7b64c9761a 100644
--- a/src/librustc/ty/maps/keys.rs
+++ b/src/librustc/ty/maps/keys.rs
@@ -11,7 +11,6 @@
 //! Defines the set of legal keys that can be used in queries.
 
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
-use mir::transform::{MirSuite, MirPassIndex};
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
@@ -116,24 +115,6 @@ impl<'tcx> Key for (DefId, &'tcx Substs<'tcx>) {
     }
 }
 
-impl Key for (MirSuite, DefId) {
-    fn map_crate(&self) -> CrateNum {
-        self.1.map_crate()
-    }
-    fn default_span(&self, tcx: TyCtxt) -> Span {
-        self.1.default_span(tcx)
-    }
-}
-
-impl Key for (MirSuite, MirPassIndex, DefId) {
-    fn map_crate(&self) -> CrateNum {
-        self.2.map_crate()
-    }
-    fn default_span(&self, tcx: TyCtxt) -> Span {
-        self.2.default_span(tcx)
-    }
-}
-
 impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
     fn map_crate(&self) -> CrateNum {
         self.1.def_id().krate
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 855362cf645..f7c03fde222 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -22,7 +22,6 @@ use rustc::lint;
 use rustc::middle::{self, stability, reachable};
 use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
-use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
 use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
 use rustc::traits;
 use rustc::util::common::{ErrorReported, time};
@@ -989,63 +988,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     // FIXME(eddyb) get rid of this once we replace const_eval with miri.
     rustc_const_eval::provide(&mut extern_providers);
 
-    // Setup the MIR passes that we want to run.
-    let mut passes = Passes::new();
-    passes.push_hook(mir::transform::dump_mir::DumpMir);
-
-    // Remove all `EndRegion` statements that are not involved in borrows.
-    passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions);
-
-    // What we need to do constant evaluation.
-    passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial"));
-    passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir);
-    passes.push_pass(MIR_CONST, mir::transform::rustc_peek::SanityCheck);
-
-    // We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED.
-
-    // What we need to run borrowck etc.
-
-    passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants);
-    passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts"));
-
-    // borrowck runs between MIR_VALIDATED and MIR_OPTIMIZED.
-
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
-    passes.push_pass(MIR_OPTIMIZED,
-                     mir::transform::simplify_branches::SimplifyBranches::new("initial"));
-
-    // These next passes must be executed together
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::elaborate_drops::ElaborateDrops);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::no_landing_pads::NoLandingPads);
-    // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
-    // an AllCallEdges pass right before it.
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::AllCallEdges);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_validation::AddValidation);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
-    // No lifetime analysis based on borrowing can be done from here on out.
-
-    // From here on out, regions are gone.
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::erase_regions::EraseRegions);
-
-    // Optimizations begin.
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::instcombine::InstCombine);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyLocals);
-
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::generator::StateTransform);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::add_call_guards::CriticalCallEdges);
-    passes.push_pass(MIR_OPTIMIZED, mir::transform::dump_mir::Marker("PreTrans"));
-
     let (tx, rx) = mpsc::channel();
 
     TyCtxt::create_and_enter(sess,
                              cstore,
                              local_providers,
                              extern_providers,
-                             Rc::new(passes),
                              arenas,
                              arena,
                              resolutions,
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 5ff75351b63..9e02065145d 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -28,7 +28,6 @@ use rustc::infer::{self, InferOk, InferResult};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc_metadata::cstore::CStore;
 use rustc::hir::map as hir_map;
-use rustc::mir::transform::Passes;
 use rustc::session::{self, config};
 use rustc::session::config::{OutputFilenames, OutputTypes};
 use rustc_trans_utils::trans_crate::TransCrate;
@@ -151,7 +150,6 @@ fn test_env<F>(source_string: &str,
                              &*cstore,
                              ty::maps::Providers::default(),
                              ty::maps::Providers::default(),
-                             Rc::new(Passes::new()),
                              &arenas,
                              &arena,
                              resolutions,
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
index c56631d429c..deffb85bf87 100644
--- a/src/librustc_mir/borrow_check.rs
+++ b/src/librustc_mir/borrow_check.rs
@@ -18,7 +18,6 @@ use rustc::ty::maps::Providers;
 use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local};
 use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
 use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
-use rustc::mir::transform::MirSource;
 use transform::nll;
 
 use rustc_data_structures::indexed_set::{self, IdxSetBuf};
@@ -50,8 +49,7 @@ pub fn provide(providers: &mut Providers) {
 
 fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
     let input_mir = tcx.mir_validated(def_id);
-    let src = MirSource::from_local_def_id(tcx, def_id);
-    debug!("run query mir_borrowck: {}", tcx.node_path_str(src.item_id()));
+    debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id));
 
     if {
         !tcx.has_attr(def_id, "rustc_mir_borrowck") &&
@@ -63,21 +61,20 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
 
     tcx.infer_ctxt().enter(|infcx| {
         let input_mir: &Mir = &input_mir.borrow();
-        do_mir_borrowck(&infcx, input_mir, def_id, src);
+        do_mir_borrowck(&infcx, input_mir, def_id);
     });
     debug!("mir_borrowck done");
 }
 
 fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                    input_mir: &Mir<'gcx>,
-                                   def_id: DefId,
-                                   src: MirSource)
+                                   def_id: DefId)
 {
     let tcx = infcx.tcx;
     let attributes = tcx.get_attrs(def_id);
     let param_env = tcx.param_env(def_id);
-
-    let id = src.item_id();
+    let id = tcx.hir.as_local_node_id(def_id)
+        .expect("do_mir_borrowck: non-local DefId");
 
     let move_data: MoveData<'tcx> = match MoveData::gather_moves(input_mir, tcx, param_env) {
         Ok(move_data) => move_data,
@@ -117,7 +114,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     let opt_regioncx = if !tcx.sess.opts.debugging_opts.nll {
         None
     } else {
-        Some(nll::compute_regions(infcx, src, mir))
+        Some(nll::compute_regions(infcx, def_id, mir))
     };
 
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 2073d495300..0489a03c97e 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -16,7 +16,6 @@ use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::mir::*;
-use rustc::mir::transform::MirSource;
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
@@ -30,6 +29,7 @@ use syntax::abi::Abi;
 use syntax::ast;
 use syntax::symbol::keywords;
 use syntax_pos::Span;
+use transform::MirSource;
 use util as mir_util;
 
 /// Construct the MIR for a given def-id.
@@ -83,12 +83,11 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
         _ => unsupported(),
     };
 
-    let src = MirSource::from_node(tcx, id);
     tcx.infer_ctxt().enter(|infcx| {
-        let cx = Cx::new(&infcx, src);
+        let cx = Cx::new(&infcx, id);
         let mut mir = if cx.tables().tainted_by_errors {
             build::construct_error(cx, body_id)
-        } else if let MirSource::Fn(id) = src {
+        } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind {
             // fetch the fully liberated fn signature (that is, all bound
             // types/lifetimes replaced)
             let fn_hir_id = tcx.hir.node_to_hir_id(id);
@@ -150,7 +149,8 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
             mem::transmute::<Mir, Mir<'tcx>>(mir)
         };
 
-        mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) );
+        mir_util::dump_mir(tcx, None, "mir_map", &0,
+                           MirSource::item(def_id), &mir, |_, _| Ok(()) );
 
         mir
     })
@@ -214,8 +214,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let span = tcx.hir.span(ctor_id);
     if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
         tcx.infer_ctxt().enter(|infcx| {
-            let (mut mir, src) =
-                shim::build_adt_ctor(&infcx, ctor_id, fields, span);
+            let mut mir = shim::build_adt_ctor(&infcx, ctor_id, fields, span);
 
             // Convert the Mir to global types.
             let tcx = infcx.tcx.global_tcx();
@@ -228,7 +227,9 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 mem::transmute::<Mir, Mir<'tcx>>(mir)
             };
 
-            mir_util::dump_mir(tcx, None, "mir_map", &0, src, &mir, |_, _| Ok(()) );
+            mir_util::dump_mir(tcx, None, "mir_map", &0,
+                               MirSource::item(tcx.hir.local_def_id(ctor_id)),
+                               &mir, |_, _| Ok(()) );
 
             mir
         })
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index c0d17a1590f..3c3dabdfa54 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -91,9 +91,9 @@ use build::{BlockAnd, BlockAndExtension, Builder, CFG};
 use hair::LintLevel;
 use rustc::middle::region;
 use rustc::ty::{Ty, TyCtxt};
+use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::mir::*;
-use rustc::mir::transform::MirSource;
 use syntax_pos::{Span};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::fx::FxHashMap;
@@ -596,16 +596,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, '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> {
-        match self.hir.src {
-            MirSource::Const(_) |
-            MirSource::Static(..) =>
+        match self.hir.body_owner_kind {
+            hir::BodyOwnerKind::Const |
+            hir::BodyOwnerKind::Static(_) =>
                 // No need to free storage in this context.
                 None,
-            MirSource::Fn(_) =>
+            hir::BodyOwnerKind::Fn =>
                 Some(self.topmost_scope()),
-            MirSource::Promoted(..) |
-            MirSource::GeneratorDrop(..) =>
-                bug!(),
         }
     }
 
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 4434df0ac3e..50264238aac 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -15,7 +15,6 @@
 //!
 
 use hair::*;
-use rustc::mir::transform::MirSource;
 
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
 use rustc_const_eval::ConstContext;
@@ -51,8 +50,8 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     /// `const`, or the body of a `const fn`.
     constness: hir::Constness,
 
-    /// What are we compiling?
-    pub src: MirSource,
+    /// What kind of body is being compiled.
+    pub body_owner_kind: hir::BodyOwnerKind,
 
     /// True if this constant/function needs overflow checks.
     check_overflow: bool,
@@ -60,22 +59,20 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 
 impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
     pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-               src: MirSource) -> Cx<'a, 'gcx, 'tcx> {
-        let constness = match src {
-            MirSource::Const(_) |
-            MirSource::Static(..) => hir::Constness::Const,
-            MirSource::GeneratorDrop(..) => hir::Constness::NotConst,
-            MirSource::Fn(id) => {
-                let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(id));
+               src_id: ast::NodeId) -> Cx<'a, 'gcx, 'tcx> {
+        let tcx = infcx.tcx;
+        let src_def_id = tcx.hir.local_def_id(src_id);
+        let body_owner_kind = tcx.hir.body_owner_kind(src_id);
+
+        let constness = match body_owner_kind {
+            hir::BodyOwnerKind::Const |
+            hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
+            hir::BodyOwnerKind::Fn => {
+                let fn_like = FnLikeNode::from_node(infcx.tcx.hir.get(src_id));
                 fn_like.map_or(hir::Constness::NotConst, |f| f.constness())
             }
-            MirSource::Promoted(..) => bug!(),
         };
 
-        let tcx = infcx.tcx;
-        let src_id = src.item_id();
-        let src_def_id = tcx.hir.local_def_id(src_id);
-
         let attrs = tcx.hir.attrs(src_id);
 
         // Some functions always have overflow checks enabled,
@@ -100,7 +97,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
             region_scope_tree: tcx.region_scope_tree(src_def_id),
             tables: tcx.typeck_tables_of(src_def_id),
             constness,
-            src,
+            body_owner_kind,
             check_overflow,
         }
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index b72823dff2b..5e65398e2b9 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -20,6 +20,8 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
 #![feature(const_fn)]
+#![feature(core_intrinsics)]
+#![feature(decl_macro)]
 #![feature(i128_type)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(placement_in_syntax)]
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index a3a986918a4..e1f0e01b88c 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -13,7 +13,6 @@ use rustc::hir::def_id::DefId;
 use rustc::infer;
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
-use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
@@ -826,7 +825,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
                                       ctor_id: ast::NodeId,
                                       fields: &[hir::StructField],
                                       span: Span)
-                                      -> (Mir<'tcx>, MirSource)
+                                      -> Mir<'tcx>
 {
     let tcx = infcx.tcx;
     let def_id = tcx.hir.local_def_id(ctor_id);
@@ -875,7 +874,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         is_cleanup: false
     };
 
-    let mir = Mir::new(
+    Mir::new(
         IndexVec::from_elem_n(start_block, 1),
         IndexVec::from_elem_n(
             VisibilityScopeData { span: span, parent_scope: None }, 1
@@ -888,6 +887,5 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
         sig.inputs().len(),
         vec![],
         span
-    );
-    (mir, MirSource::Fn(ctor_id))
+    )
 }
diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs
index 3f14a6be8b2..5be369f85bc 100644
--- a/src/librustc_mir/transform/add_call_guards.rs
+++ b/src/librustc_mir/transform/add_call_guards.rs
@@ -10,8 +10,8 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use transform::{MirPass, MirSource};
 
 #[derive(PartialEq)]
 pub enum AddCallGuards {
diff --git a/src/librustc_mir/transform/add_validation.rs b/src/librustc_mir/transform/add_validation.rs
index 8fad538af97..c6f2154eaa4 100644
--- a/src/librustc_mir/transform/add_validation.rs
+++ b/src/librustc_mir/transform/add_validation.rs
@@ -17,8 +17,8 @@
 use rustc::ty::{self, TyCtxt, RegionKind};
 use rustc::hir;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::middle::region;
+use transform::{MirPass, MirSource};
 
 pub struct AddValidation;
 
@@ -106,8 +106,9 @@ fn fn_contains_unsafe<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource) ->
         }
     }
 
-    let fn_like = match src {
-        MirSource::Fn(node_id) => {
+    let node_id = tcx.hir.as_local_node_id(src.def_id).unwrap();
+    let fn_like = match tcx.hir.body_owner_kind(node_id) {
+        hir::BodyOwnerKind::Fn => {
             match FnLikeNode::from_node(tcx.hir.get(node_id)) {
                 Some(fn_like) => fn_like,
                 None => return false, // e.g. struct ctor shims -- such auto-generated code cannot
diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs
index d356d3b5a85..7986313aa81 100644
--- a/src/librustc_mir/transform/clean_end_regions.rs
+++ b/src/librustc_mir/transform/clean_end_regions.rs
@@ -22,10 +22,10 @@
 use rustc_data_structures::fx::FxHashSet;
 
 use rustc::middle::region;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
 use rustc::ty::{Ty, RegionKind, TyCtxt};
+use transform::{MirPass, MirSource};
 
 pub struct CleanEndRegions;
 
diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs
index a730fc30615..2966290c296 100644
--- a/src/librustc_mir/transform/copy_prop.rs
+++ b/src/librustc_mir/transform/copy_prop.rs
@@ -29,10 +29,11 @@
 //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the
 //! future.
 
+use rustc::hir;
 use rustc::mir::{Constant, Local, LocalKind, Location, Lvalue, Mir, Operand, Rvalue, StatementKind};
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::MutVisitor;
 use rustc::ty::TyCtxt;
+use transform::{MirPass, MirSource};
 use util::def_use::DefUseAnalysis;
 
 pub struct CopyPropagation;
@@ -42,25 +43,22 @@ impl MirPass for CopyPropagation {
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           source: MirSource,
                           mir: &mut Mir<'tcx>) {
-        match source {
-            MirSource::Const(_) => {
-                // Don't run on constants, because constant qualification might reject the
-                // optimized IR.
-                return
-            }
-            MirSource::Static(..) | MirSource::Promoted(..) => {
-                // Don't run on statics and promoted statics, because trans might not be able to
-                // evaluate the optimized IR.
-                return
-            }
-            MirSource::Fn(function_node_id) => {
-                if tcx.is_const_fn(tcx.hir.local_def_id(function_node_id)) {
+        // Don't run on constant MIR, because trans might not be able to
+        // evaluate the modified MIR.
+        // FIXME(eddyb) Remove check after miri is merged.
+        let id = tcx.hir.as_local_node_id(source.def_id).unwrap();
+        match (tcx.hir.body_owner_kind(id), source.promoted) {
+            (_, Some(_)) |
+            (hir::BodyOwnerKind::Const, _) |
+            (hir::BodyOwnerKind::Static(_), _) => return,
+
+            (hir::BodyOwnerKind::Fn, _) => {
+                if tcx.is_const_fn(source.def_id) {
                     // Don't run on const functions, as, again, trans might not be able to evaluate
                     // the optimized IR.
                     return
                 }
             }
-            MirSource::GeneratorDrop(_) => (),
         }
 
         // We only run when the MIR optimization level is > 1.
diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs
index d21dbeafb5d..61b4716c564 100644
--- a/src/librustc_mir/transform/deaggregator.rs
+++ b/src/librustc_mir/transform/deaggregator.rs
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc::hir;
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_vec::Idx;
+use transform::{MirPass, MirSource};
 
 pub struct Deaggregator;
 
@@ -20,16 +21,21 @@ impl MirPass for Deaggregator {
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           source: MirSource,
                           mir: &mut Mir<'tcx>) {
-        let node_id = source.item_id();
-        let node_path = tcx.item_path_str(tcx.hir.local_def_id(node_id));
+        let node_path = tcx.item_path_str(source.def_id);
         debug!("running on: {:?}", node_path);
         // we only run when mir_opt_level > 2
         if tcx.sess.opts.debugging_opts.mir_opt_level <= 2 {
             return;
         }
 
-        // Do not trigger on constants.  Could be revised in future
-        if let MirSource::Fn(_) = source {} else { return; }
+        // Don't run on constant MIR, because trans might not be able to
+        // evaluate the modified MIR.
+        // FIXME(eddyb) Remove check after miri is merged.
+        let id = tcx.hir.as_local_node_id(source.def_id).unwrap();
+        match (tcx.hir.body_owner_kind(id), source.promoted) {
+            (hir::BodyOwnerKind::Fn, None) => {},
+            _ => return
+        }
         // In fact, we might not want to trigger in other cases.
         // Ex: when we could use SROA.  See issue #35259
 
diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs
index cea66837d9a..98753eaa5a3 100644
--- a/src/librustc_mir/transform/dump_mir.rs
+++ b/src/librustc_mir/transform/dump_mir.rs
@@ -16,9 +16,9 @@ use std::fs::File;
 use std::io;
 
 use rustc::mir::Mir;
-use rustc::mir::transform::{MirPass, MirPassIndex, MirSource, MirSuite, PassHook};
 use rustc::session::config::{OutputFilenames, OutputType};
 use rustc::ty::TyCtxt;
+use transform::{MirPass, MirSource};
 use util as mir_util;
 
 pub struct Marker(pub &'static str);
@@ -47,37 +47,21 @@ impl fmt::Display for Disambiguator {
     }
 }
 
-pub struct DumpMir;
 
-impl PassHook for DumpMir {
-    fn on_mir_pass<'a, 'tcx: 'a>(&self,
-                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 suite: MirSuite,
-                                 pass_num: MirPassIndex,
-                                 pass_name: &str,
-                                 source: MirSource,
-                                 mir: &Mir<'tcx>,
-                                 is_after: bool)
-    {
-        if mir_util::dump_enabled(tcx, pass_name, source) {
-            mir_util::dump_mir(tcx,
-                               Some((suite, pass_num)),
-                               pass_name,
-                               &Disambiguator { is_after },
-                               source,
-                               mir,
-                               |_, _| Ok(()) );
-            for (index, promoted_mir) in mir.promoted.iter_enumerated() {
-                let promoted_source = MirSource::Promoted(source.item_id(), index);
-                mir_util::dump_mir(tcx,
-                                   Some((suite, pass_num)),
-                                   pass_name,
-                                   &Disambiguator { is_after },
-                                   promoted_source,
-                                   promoted_mir,
-                                   |_, _| Ok(()) );
-            }
-        }
+pub fn on_mir_pass<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             pass_num: &fmt::Display,
+                             pass_name: &str,
+                             source: MirSource,
+                             mir: &Mir<'tcx>,
+                             is_after: bool) {
+    if mir_util::dump_enabled(tcx, pass_name, source) {
+        mir_util::dump_mir(tcx,
+                           Some(pass_num),
+                           pass_name,
+                           &Disambiguator { is_after },
+                           source,
+                           mir,
+                           |_, _| Ok(()) );
     }
 }
 
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 94da1f31a96..c24256cc92c 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -15,13 +15,14 @@ use dataflow::{on_all_children_bits, on_all_drop_children_bits};
 use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits};
 use dataflow::MoveDataParamEnv;
 use dataflow;
+use rustc::hir;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::middle::const_val::ConstVal;
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
+use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
 use util::elaborate_drops::{DropFlagState, Unwind, elaborate_drop};
 use util::elaborate_drops::{DropElaborator, DropStyle, DropFlagMode};
@@ -39,12 +40,16 @@ impl MirPass for ElaborateDrops {
                           mir: &mut Mir<'tcx>)
     {
         debug!("elaborate_drops({:?} @ {:?})", src, mir.span);
-        match src {
-            MirSource::Fn(..) => {},
+
+        // Don't run on constant MIR, because trans might not be able to
+        // evaluate the modified MIR.
+        // FIXME(eddyb) Remove check after miri is merged.
+        let id = tcx.hir.as_local_node_id(src.def_id).unwrap();
+        match (tcx.hir.body_owner_kind(id), src.promoted) {
+            (hir::BodyOwnerKind::Fn, None) => {},
             _ => return
         }
-        let id = src.item_id();
-        let param_env = tcx.param_env(tcx.hir.local_def_id(id));
+        let param_env = tcx.param_env(src.def_id);
         let move_data = MoveData::gather_moves(mir, tcx, param_env).unwrap();
         let elaborate_patch = {
             let mir = &*mir;
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 08ca20e50eb..dfa048e2e4b 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -18,7 +18,7 @@ use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::mir::*;
 use rustc::mir::visit::{MutVisitor, TyContext};
-use rustc::mir::transform::{MirPass, MirSource};
+use transform::{MirPass, MirSource};
 
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 52a50333f45..7d12d50355b 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -63,7 +63,6 @@ use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{LvalueContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
 use rustc::ty::subst::{Kind, Substs};
@@ -76,6 +75,7 @@ use std::collections::HashMap;
 use std::borrow::Cow;
 use std::iter::once;
 use std::mem;
+use transform::{MirPass, MirSource};
 use transform::simplify;
 use transform::no_landing_pads::no_landing_pads;
 use dataflow::{self, MaybeStorageLive, state_for_location};
@@ -338,7 +338,7 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                (liveness::LocalSet,
                                                 HashMap<BasicBlock, liveness::LocalSet>) {
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
-    let node_id = source.item_id();
+    let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
     let analysis = MaybeStorageLive::new(mir);
     let storage_live =
         dataflow::do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
@@ -763,8 +763,8 @@ impl MirPass for StateTransform {
 
         assert!(mir.generator_drop.is_none());
 
-        let node_id = source.item_id();
-        let def_id = tcx.hir.local_def_id(source.item_id());
+        let def_id = source.def_id;
+        let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
         let hir_id = tcx.hir.node_to_hir_id(node_id);
 
         // Get the interior types which typeck computed
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index ed809836c4f..5dec6177b36 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -10,18 +10,19 @@
 
 //! Inlining pass for MIR functions
 
+use rustc::hir;
 use rustc::hir::def_id::DefId;
 
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::*;
 use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst::{Subst,Substs};
 
 use std::collections::VecDeque;
+use transform::{MirPass, MirSource};
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
 
 use syntax::{attr};
@@ -77,12 +78,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
         let mut callsites = VecDeque::new();
 
-        let param_env;
+        let param_env = self.tcx.param_env(self.source.def_id);
 
         // Only do inlining into fn bodies.
-        if let MirSource::Fn(caller_id) = self.source {
-            let caller_def_id = self.tcx.hir.local_def_id(caller_id);
-            param_env = self.tcx.param_env(caller_def_id);
+        let id = self.tcx.hir.as_local_node_id(self.source.def_id).unwrap();
+        let body_owner_kind = self.tcx.hir.body_owner_kind(id);
+        if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) {
 
             for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
                 // Don't inline calls that are in cleanup blocks.
@@ -251,8 +252,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
 
         // FIXME: Give a bonus to functions with only a single caller
 
-        let def_id = tcx.hir.local_def_id(self.source.item_id());
-        let param_env = tcx.param_env(def_id);
+        let param_env = tcx.param_env(self.source.def_id);
 
         let mut first_block = true;
         let mut cost = 0;
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 6ccc886577a..b091f2f4b6d 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -11,12 +11,12 @@
 //! Performs various peephole optimizations.
 
 use rustc::mir::{Location, Lvalue, Mir, Operand, ProjectionElem, Rvalue, Local};
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{MutVisitor, Visitor};
 use rustc::ty::TyCtxt;
 use rustc::util::nodemap::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
+use transform::{MirPass, MirSource};
 
 pub struct InstCombine;
 
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 34cc3a289d1..441f9be9be1 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -10,19 +10,17 @@
 
 use build;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-use rustc::mir::Mir;
-use rustc::mir::transform::{MirPassIndex, MirSuite, MirSource,
-                            MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED};
+use rustc::mir::{Mir, Promoted};
 use rustc::ty::TyCtxt;
 use rustc::ty::maps::Providers;
 use rustc::ty::steal::Steal;
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::util::nodemap::DefIdSet;
+use std::borrow::Cow;
 use std::rc::Rc;
 use syntax::ast;
 use syntax_pos::Span;
-use transform;
 
 pub mod add_validation;
 pub mod clean_end_regions;
@@ -109,26 +107,112 @@ fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
     tcx.alloc_steal_mir(mir)
 }
 
+/// Where a specific Mir comes from.
+#[derive(Debug, Copy, Clone)]
+pub struct MirSource {
+    pub def_id: DefId,
+
+    /// If `Some`, this is a promoted rvalue within the parent function.
+    pub promoted: Option<Promoted>,
+}
+
+impl MirSource {
+    pub fn item(def_id: DefId) -> Self {
+        MirSource {
+            def_id,
+            promoted: None
+        }
+    }
+}
+
+/// Generates a default name for the pass based on the name of the
+/// type `T`.
+pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
+    let name = unsafe { ::std::intrinsics::type_name::<T>() };
+    if let Some(tail) = name.rfind(":") {
+        Cow::from(&name[tail+1..])
+    } else {
+        Cow::from(name)
+    }
+}
+
+/// A streamlined trait that you can implement to create a pass; the
+/// pass will be named after the type, and it will consist of a main
+/// loop that goes over each available MIR and applies `run_pass`.
+pub trait MirPass {
+    fn name<'a>(&'a self) -> Cow<'a, str> {
+        default_name::<Self>()
+    }
+
+    fn run_pass<'a, 'tcx>(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          source: MirSource,
+                          mir: &mut Mir<'tcx>);
+}
+
+pub macro run_passes($tcx:ident, $mir:ident, $def_id:ident, $suite_index:expr; $($pass:expr,)*) {{
+    let suite_index: usize = $suite_index;
+    let run_passes = |mir: &mut _, promoted| {
+        let source = MirSource {
+            def_id: $def_id,
+            promoted
+        };
+        let mut index = 0;
+        let mut run_pass = |pass: &MirPass| {
+            let run_hooks = |mir: &_, index, is_after| {
+                dump_mir::on_mir_pass($tcx, &format_args!("{:03}-{:03}", suite_index, index),
+                                      &pass.name(), source, mir, is_after);
+            };
+            run_hooks(mir, index, false);
+            pass.run_pass($tcx, source, mir);
+            run_hooks(mir, index, true);
+
+            index += 1;
+        };
+        $(run_pass(&$pass);)*
+    };
+
+    run_passes(&mut $mir, None);
+
+    for (index, promoted_mir) in $mir.promoted.iter_enumerated_mut() {
+        run_passes(promoted_mir, Some(index));
+
+        // Let's make sure we don't miss any nested instances
+        assert!(promoted_mir.promoted.is_empty());
+    }
+}}
+
 fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
     // Unsafety check uses the raw mir, so make sure it is run
     let _ = tcx.unsafety_check_result(def_id);
 
-    let source = MirSource::from_local_def_id(tcx, def_id);
     let mut mir = tcx.mir_built(def_id).steal();
-    transform::run_suite(tcx, source, MIR_CONST, &mut mir);
+    run_passes![tcx, mir, def_id, 0;
+        // Remove all `EndRegion` statements that are not involved in borrows.
+        clean_end_regions::CleanEndRegions,
+
+        // What we need to do constant evaluation.
+        simplify::SimplifyCfg::new("initial"),
+        type_check::TypeckMir,
+        rustc_peek::SanityCheck,
+    ];
     tcx.alloc_steal_mir(mir)
 }
 
 fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal<Mir<'tcx>> {
-    let source = MirSource::from_local_def_id(tcx, def_id);
-    if let MirSource::Const(_) = source {
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(node_id) {
         // Ensure that we compute the `mir_const_qualif` for constants at
         // this point, before we steal the mir-const result.
         let _ = tcx.mir_const_qualif(def_id);
     }
 
     let mut mir = tcx.mir_const(def_id).steal();
-    transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir);
+    run_passes![tcx, mir, def_id, 1;
+        // What we need to run borrowck etc.
+        qualify_consts::QualifyAndPromoteConstants,
+        simplify::SimplifyCfg::new("qualify-consts"),
+    ];
     tcx.alloc_steal_mir(mir)
 }
 
@@ -139,37 +223,34 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
     let _ = tcx.borrowck(def_id);
 
     let mut mir = tcx.mir_validated(def_id).steal();
-    let source = MirSource::from_local_def_id(tcx, def_id);
-    transform::run_suite(tcx, source, MIR_OPTIMIZED, &mut mir);
-    tcx.alloc_mir(mir)
-}
+    run_passes![tcx, mir, def_id, 2;
+        no_landing_pads::NoLandingPads,
+        simplify_branches::SimplifyBranches::new("initial"),
 
-fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                       source: MirSource,
-                       suite: MirSuite,
-                       mir: &mut Mir<'tcx>)
-{
-    let passes = tcx.mir_passes.passes(suite);
+        // These next passes must be executed together
+        add_call_guards::CriticalCallEdges,
+        elaborate_drops::ElaborateDrops,
+        no_landing_pads::NoLandingPads,
+        // AddValidation needs to run after ElaborateDrops and before EraseRegions, and it needs
+        // an AllCallEdges pass right before it.
+        add_call_guards::AllCallEdges,
+        add_validation::AddValidation,
+        simplify::SimplifyCfg::new("elaborate-drops"),
+        // No lifetime analysis based on borrowing can be done from here on out.
 
-    for (pass, index) in passes.iter().zip(0..) {
-        let pass_num = MirPassIndex(index);
+        // From here on out, regions are gone.
+        erase_regions::EraseRegions,
 
-        for hook in tcx.mir_passes.hooks() {
-            hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, false);
-        }
-
-        pass.run_pass(tcx, source, mir);
-
-        for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() {
-            let promoted_source = MirSource::Promoted(source.item_id(), index);
-            pass.run_pass(tcx, promoted_source, promoted_mir);
-
-            // Let's make sure we don't miss any nested instances
-            assert!(promoted_mir.promoted.is_empty());
-        }
+        // Optimizations begin.
+        inline::Inline,
+        instcombine::InstCombine,
+        deaggregator::Deaggregator,
+        copy_prop::CopyPropagation,
+        simplify::SimplifyLocals,
 
-        for hook in tcx.mir_passes.hooks() {
-            hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true);
-        }
-    }
+        generator::StateTransform,
+        add_call_guards::CriticalCallEdges,
+        dump_mir::Marker("PreTrans"),
+    ];
+    tcx.alloc_mir(mir)
 }
diff --git a/src/librustc_mir/transform/nll/constraint_generation.rs b/src/librustc_mir/transform/nll/constraint_generation.rs
index a2f9bbb174e..b095a198d8f 100644
--- a/src/librustc_mir/transform/nll/constraint_generation.rs
+++ b/src/librustc_mir/transform/nll/constraint_generation.rs
@@ -10,7 +10,6 @@
 
 use rustc::hir;
 use rustc::mir::{BasicBlock, BorrowKind, Location, Lvalue, Mir, Rvalue, Statement, StatementKind};
-use rustc::mir::transform::MirSource;
 use rustc::mir::visit::Visitor;
 use rustc::mir::Lvalue::Projection;
 use rustc::mir::{LvalueProjection, ProjectionElem};
@@ -31,7 +30,7 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     regioncx: &mut RegionInferenceContext<'tcx>,
     mir: &Mir<'tcx>,
-    mir_source: MirSource,
+    param_env: ty::ParamEnv<'tcx>,
     liveness: &LivenessResults,
 ) {
     ConstraintGeneration {
@@ -39,7 +38,7 @@ pub(super) fn generate_constraints<'a, 'gcx, 'tcx>(
         regioncx,
         mir,
         liveness,
-        mir_source,
+        param_env,
     }.add_constraints();
 }
 
@@ -48,7 +47,7 @@ struct ConstraintGeneration<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     regioncx: &'cx mut RegionInferenceContext<'tcx>,
     mir: &'cx Mir<'tcx>,
     liveness: &'cx LivenessResults,
-    mir_source: MirSource,
+    param_env: ty::ParamEnv<'tcx>,
 }
 
 impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
@@ -153,13 +152,11 @@ impl<'cx, 'gcx, 'tcx> ConstraintGeneration<'cx, 'gcx, 'tcx> {
             // `dtorck_constraint_for_ty` could not resolve (e.g.,
             // associated types and parameters). We need to normalize
             // associated types here and possibly recursively process.
-            let def_id = tcx.hir.local_def_id(self.mir_source.item_id());
-            let param_env = self.infcx.tcx.param_env(def_id);
             for ty in dtorck_types {
                 // FIXME -- I think that this may disregard some region obligations
                 // or something. Do we care? -nmatsakis
                 let cause = ObligationCause::dummy();
-                match traits::fully_normalize(self.infcx, cause, param_env, &ty) {
+                match traits::fully_normalize(self.infcx, cause, self.param_env, &ty) {
                     Ok(ty) => match ty.sty {
                         ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) => {
                             self.add_regular_live_constraint(ty, location);
diff --git a/src/librustc_mir/transform/nll/free_regions.rs b/src/librustc_mir/transform/nll/free_regions.rs
index 006a2f9047a..554d212880e 100644
--- a/src/librustc_mir/transform/nll/free_regions.rs
+++ b/src/librustc_mir/transform/nll/free_regions.rs
@@ -22,9 +22,9 @@
 //! The code in this file doesn't *do anything* with those results; it
 //! just returns them for other code to use.
 
+use rustc::hir::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::middle::free_region::FreeRegionMap;
-use rustc::mir::transform::MirSource;
 use rustc::ty;
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::FxHashMap;
@@ -43,12 +43,9 @@ pub struct FreeRegions<'tcx> {
 
 pub fn free_regions<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    source: MirSource,
+    item_def_id: DefId,
 ) -> FreeRegions<'tcx> {
-    debug!("free_regions(source={:?})", source);
-
-    let item_id = source.item_id();
-    let item_def_id = infcx.tcx.hir.local_def_id(item_id);
+    debug!("free_regions(item_def_id={:?})", item_def_id);
 
     let mut indices = FxHashMap();
 
@@ -63,6 +60,7 @@ pub fn free_regions<'a, 'gcx, 'tcx>(
     // Extract the late-bound regions. Use the liberated fn sigs,
     // where the late-bound regions will have been converted into free
     // regions, and add them to the map.
+    let item_id = infcx.tcx.hir.as_local_node_id(item_def_id).unwrap();
     let fn_hir_id = infcx.tcx.hir.node_to_hir_id(item_id);
     let tables = infcx.tcx.typeck_tables_of(item_def_id);
     let fn_sig = tables.liberated_fn_sigs()[fn_hir_id].clone();
diff --git a/src/librustc_mir/transform/nll/mod.rs b/src/librustc_mir/transform/nll/mod.rs
index e24def2292e..f27d0a8da16 100644
--- a/src/librustc_mir/transform/nll/mod.rs
+++ b/src/librustc_mir/transform/nll/mod.rs
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::{self, RegionKind};
+use rustc::hir::def_id::DefId;
 use rustc::mir::Mir;
-use rustc::mir::transform::MirSource;
 use rustc::infer::InferCtxt;
+use rustc::ty::{self, RegionKind};
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use std::collections::BTreeSet;
+use transform::MirSource;
 use util::liveness::{self, LivenessMode, LivenessResult, LocalSet};
 
 use util as mir_util;
@@ -34,11 +35,11 @@ mod renumber;
 /// This may result in errors being reported.
 pub fn compute_regions<'a, 'gcx, 'tcx>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-    source: MirSource,
+    def_id: DefId,
     mir: &mut Mir<'tcx>,
 ) -> RegionInferenceContext<'tcx> {
     // Compute named region information.
-    let free_regions = &free_regions::free_regions(infcx, source);
+    let free_regions = &free_regions::free_regions(infcx, def_id);
 
     // Replace all regions with fresh inference variables.
     let num_region_variables = renumber::renumber_mir(infcx, free_regions, mir);
@@ -65,12 +66,13 @@ pub fn compute_regions<'a, 'gcx, 'tcx>(
     // Create the region inference context, generate the constraints,
     // and then solve them.
     let mut regioncx = RegionInferenceContext::new(free_regions, num_region_variables, mir);
-    constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, source, liveness);
+    let param_env = infcx.tcx.param_env(def_id);
+    constraint_generation::generate_constraints(infcx, &mut regioncx, &mir, param_env, liveness);
     regioncx.solve(infcx, &mir);
 
     // Dump MIR results into a file, if that is enabled. This let us
     // write unit-tests.
-    dump_mir_results(infcx, liveness, source, &mir, &regioncx);
+    dump_mir_results(infcx, liveness, MirSource::item(def_id), &mir, &regioncx);
 
     regioncx
 }
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index 7de8de3c96b..dd5898cb561 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -14,7 +14,7 @@
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
 use rustc::mir::visit::MutVisitor;
-use rustc::mir::transform::{MirPass, MirSource};
+use transform::{MirPass, MirSource};
 
 pub struct NoLandingPads;
 
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 583dfd9b616..ab29134c325 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -26,7 +26,6 @@ use rustc::ty::cast::CastTy;
 use rustc::ty::maps::Providers;
 use rustc::mir::*;
 use rustc::mir::traversal::ReversePostorder;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{LvalueContext, Visitor};
 use rustc::middle::lang_items;
 use syntax::abi::Abi;
@@ -38,6 +37,7 @@ use std::fmt;
 use std::rc::Rc;
 use std::usize;
 
+use transform::{MirPass, MirSource};
 use super::promote_consts::{self, Candidate, TempState};
 
 bitflags! {
@@ -961,25 +961,27 @@ impl MirPass for QualifyAndPromoteConstants {
             return;
         }
 
-        let id = src.item_id();
-        let def_id = tcx.hir.local_def_id(id);
+        if src.promoted.is_some() {
+            return;
+        }
+
+        let def_id = src.def_id;
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
         let mut const_promoted_temps = None;
-        let mode = match src {
-            MirSource::Fn(_) => {
+        let mode = match tcx.hir.body_owner_kind(id) {
+            hir::BodyOwnerKind::Fn => {
                 if tcx.is_const_fn(def_id) {
                     Mode::ConstFn
                 } else {
                     Mode::Fn
                 }
             }
-            MirSource::Const(_) => {
+            hir::BodyOwnerKind::Const => {
                 const_promoted_temps = Some(tcx.mir_const_qualif(def_id).1);
                 Mode::Const
             }
-            MirSource::Static(_, hir::MutImmutable) => Mode::Static,
-            MirSource::Static(_, hir::MutMutable) => Mode::StaticMut,
-            MirSource::GeneratorDrop(_) |
-            MirSource::Promoted(..) => return
+            hir::BodyOwnerKind::Static(hir::MutImmutable) => Mode::Static,
+            hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut,
         };
 
         if mode == Mode::Fn || mode == Mode::ConstFn {
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 8d6458d7934..32d4a14c7f7 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -14,9 +14,9 @@ use syntax_pos::Span;
 
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::{self, Mir, Location};
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
+use transform::{MirPass, MirSource};
 
 use dataflow::do_dataflow;
 use dataflow::MoveDataParamEnv;
@@ -34,8 +34,8 @@ pub struct SanityCheck;
 impl MirPass for SanityCheck {
     fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           src: MirSource, mir: &mut Mir<'tcx>) {
-        let id = src.item_id();
-        let def_id = tcx.hir.local_def_id(id);
+        let def_id = src.def_id;
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
         if !tcx.has_attr(def_id, "rustc_mir_borrowck") {
             debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id));
             return;
diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs
index 89828cf375a..02ae6328461 100644
--- a/src/librustc_mir/transform/simplify.rs
+++ b/src/librustc_mir/transform/simplify.rs
@@ -41,9 +41,9 @@ use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{MutVisitor, Visitor, LvalueContext};
 use std::borrow::Cow;
+use transform::{MirPass, MirSource};
 
 pub struct SimplifyCfg { label: String }
 
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index edbbe5305e9..20c33bab1aa 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -12,8 +12,8 @@
 
 use rustc::ty::{self, TyCtxt};
 use rustc::middle::const_val::ConstVal;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::*;
+use transform::{MirPass, MirSource};
 
 use std::borrow::Cow;
 
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index b07e818ee87..dc462cd9c74 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -18,11 +18,11 @@ use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::tcx::LvalueTy;
-use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::Visitor;
 use std::fmt;
 use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
+use transform::{MirPass, MirSource};
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::Idx;
@@ -794,8 +794,8 @@ impl MirPass for TypeckMir {
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           src: MirSource,
                           mir: &mut Mir<'tcx>) {
-        let item_id = src.item_id();
-        let def_id = tcx.hir.local_def_id(item_id);
+        let def_id = src.def_id;
+        let id = tcx.hir.as_local_node_id(def_id).unwrap();
         debug!("run_pass: {:?}", def_id);
 
         if tcx.sess.err_count() > 0 {
@@ -805,7 +805,7 @@ impl MirPass for TypeckMir {
         }
         let param_env = tcx.param_env(def_id);
         tcx.infer_ctxt().enter(|infcx| {
-            let mut checker = TypeChecker::new(&infcx, item_id, param_env);
+            let mut checker = TypeChecker::new(&infcx, id, param_env);
             {
                 let mut verifier = TypeVerifier::new(&mut checker, mir);
                 verifier.visit_mir(mir);
diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs
index a38d317b823..b3c7b4bce03 100644
--- a/src/librustc_mir/util/graphviz.rs
+++ b/src/librustc_mir/util/graphviz.rs
@@ -14,7 +14,6 @@ use rustc::mir::*;
 use rustc::ty::TyCtxt;
 use std::fmt::Debug;
 use std::io::{self, Write};
-use syntax::ast::NodeId;
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -28,21 +27,20 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
     where W: Write
 {
     for def_id in dump_mir_def_ids(tcx, single) {
-        let nodeid = tcx.hir.as_local_node_id(def_id).unwrap();
         let mir = &tcx.optimized_mir(def_id);
-        write_mir_fn_graphviz(tcx, nodeid, mir, w)?;
+        write_mir_fn_graphviz(tcx, def_id, mir, w)?;
     }
     Ok(())
 }
 
 /// Write a graphviz DOT graph of the MIR.
 pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
-                                      nodeid: NodeId,
+                                      def_id: DefId,
                                       mir: &Mir,
                                       w: &mut W) -> io::Result<()>
     where W: Write
 {
-    writeln!(w, "digraph Mir_{} {{", nodeid)?;
+    writeln!(w, "digraph Mir_{} {{", tcx.hir.as_local_node_id(def_id).unwrap())?;
 
     // Global graph properties
     writeln!(w, r#"    graph [fontname="monospace"];"#)?;
@@ -50,7 +48,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>,
     writeln!(w, r#"    edge [fontname="monospace"];"#)?;
 
     // Graph label
-    write_graph_label(tcx, nodeid, mir, w)?;
+    write_graph_label(tcx, def_id, mir, w)?;
 
     // Nodes
     for (block, _) in mir.basic_blocks().iter_enumerated() {
@@ -138,11 +136,11 @@ fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result
 /// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
 /// all the variables and temporaries.
 fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                               nid: NodeId,
+                                               def_id: DefId,
                                                mir: &Mir,
                                                w: &mut W)
                                                -> io::Result<()> {
-    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
+    write!(w, "    label=<fn {}(", dot::escape_html(&tcx.item_path_str(def_id)))?;
 
     // fn argument types.
     for (i, arg) in mir.args_iter().enumerate() {
diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs
index 7658e49ea5e..4b165a71c81 100644
--- a/src/librustc_mir/util/liveness.rs
+++ b/src/librustc_mir/util/liveness.rs
@@ -38,12 +38,12 @@ use rustc::mir::visit::{LvalueContext, Visitor};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use util::pretty::{dump_enabled, write_basic_block, write_mir_intro};
-use rustc::mir::transform::MirSource;
 use rustc::ty::item_path;
 use std::path::{Path, PathBuf};
 use std::fs;
 use rustc::ty::TyCtxt;
 use std::io::{self, Write};
+use transform::MirSource;
 
 pub type LocalSet = IdxSetBuf<Local>;
 
@@ -357,7 +357,7 @@ pub fn dump_mir<'a, 'tcx>(
     }
     let node_path = item_path::with_forced_impl_filename_line(|| {
         // see notes on #41697 below
-        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
+        tcx.item_path_str(source.def_id)
     });
     dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result);
 }
@@ -375,7 +375,8 @@ fn dump_matched_mir_node<'a, 'tcx>(
         let p = Path::new(file_dir);
         file_path.push(p);
     };
-    let file_name = format!("rustc.node{}{}-liveness.mir", source.item_id(), pass_name);
+    let item_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
+    let file_name = format!("rustc.node{}{}-liveness.mir", item_id, pass_name);
     file_path.push(&file_name);
     let _ = fs::File::create(&file_path).and_then(|mut file| {
         writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?;
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 0f07f1fe550..5dc7a324c2d 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -11,7 +11,6 @@
 use rustc::hir;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::*;
-use rustc::mir::transform::{MirSuite, MirPassIndex, MirSource};
 use rustc::ty::TyCtxt;
 use rustc::ty::item_path;
 use rustc_data_structures::fx::FxHashMap;
@@ -21,6 +20,7 @@ use std::fs;
 use std::io::{self, Write};
 use std::path::{PathBuf, Path};
 use super::graphviz::write_mir_fn_graphviz;
+use transform::MirSource;
 
 const INDENT: &'static str = "    ";
 /// Alignment for lining up comments following MIR statements
@@ -57,7 +57,7 @@ pub enum PassWhere {
 ///   that can appear in the pass-name or the `item_path_str` for the given
 ///   node-id. If any one of the substrings match, the data is dumped out.
 pub fn dump_mir<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                   pass_num: Option<(MirSuite, MirPassIndex)>,
+                                   pass_num: Option<&Display>,
                                    pass_name: &str,
                                    disambiguator: &Display,
                                    source: MirSource,
@@ -71,7 +71,7 @@ where
     }
 
     let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
-        tcx.item_path_str(tcx.hir.local_def_id(source.item_id()))
+        tcx.item_path_str(source.def_id)
     });
     dump_matched_mir_node(tcx, pass_num, pass_name, &node_path,
                           disambiguator, source, mir, extra_data);
@@ -85,9 +85,8 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         None => return false,
         Some(ref filters) => filters,
     };
-    let node_id = source.item_id();
     let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below
-        tcx.item_path_str(tcx.hir.local_def_id(node_id))
+        tcx.item_path_str(source.def_id)
     });
     filters.split("&")
            .any(|filter| {
@@ -102,7 +101,7 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 // run while we are already attempting to evaluate `type_of`.
 
 fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                            pass_num: Option<(MirSuite, MirPassIndex)>,
+                                            pass_num: Option<&Display>,
                                             pass_name: &str,
                                             node_path: &str,
                                             disambiguator: &Display,
@@ -112,10 +111,9 @@ fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 where
     F: FnMut(PassWhere, &mut Write) -> io::Result<()>
 {
-    let promotion_id = match source {
-        MirSource::Promoted(_, id) => format!("-{:?}", id),
-        MirSource::GeneratorDrop(_) => format!("-drop"),
-        _ => String::new()
+    let promotion_id = match source.promoted {
+        Some(id) => format!("-{:?}", id),
+        None => String::new()
     };
 
     let pass_num = if tcx.sess.opts.debugging_opts.dump_mir_exclude_pass_number {
@@ -123,7 +121,7 @@ where
     } else {
         match pass_num {
             None => format!(".-------"),
-            Some((suite, pass_num)) => format!(".{:03}-{:03}", suite.0, pass_num.0),
+            Some(pass_num) => format!(".{}", pass_num),
         }
     };
 
@@ -134,11 +132,9 @@ where
     };
 
     let _ = fs::create_dir_all(&file_path);
-    let function_name  = tcx.hir.def_path_from_id(source.item_id())
-        .map(|d| d.to_filename_friendly_no_crate())
-        .unwrap_or(format!("node{}", source.item_id()));
+    let item_name = tcx.hir.def_path(source.def_id).to_filename_friendly_no_crate();
     let file_name = format!("rustc.{}{}{}.{}.{}.mir",
-                            function_name, promotion_id, pass_num, pass_name, disambiguator);
+                            item_name, promotion_id, pass_num, pass_name, disambiguator);
     file_path.push(&file_name);
     let _ = fs::File::create(&file_path).and_then(|mut file| {
         writeln!(file, "// MIR for `{}`", node_path)?;
@@ -158,7 +154,7 @@ where
     if tcx.sess.opts.debugging_opts.dump_mir_graphviz {
         file_path.set_extension("dot");
         let _ = fs::File::create(&file_path).and_then(|mut file| {
-            write_mir_fn_graphviz(tcx, source.item_id(), mir, &mut file)?;
+            write_mir_fn_graphviz(tcx, source.def_id, mir, &mut file)?;
             Ok(())
         });
     }
@@ -184,13 +180,15 @@ pub fn write_mir_pretty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             writeln!(w, "")?;
         }
 
-        let id = tcx.hir.as_local_node_id(def_id).unwrap();
-        let src = MirSource::from_node(tcx, id);
-        write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?;
+        write_mir_fn(tcx, MirSource::item(def_id), mir, &mut |_, _| Ok(()), w)?;
 
         for (i, mir) in mir.promoted.iter_enumerated() {
             writeln!(w, "")?;
-            write_mir_fn(tcx, MirSource::Promoted(id, i), mir, &mut |_, _| Ok(()), w)?;
+            let src = MirSource {
+                def_id,
+                promoted: Some(i)
+            };
+            write_mir_fn(tcx, src, mir, &mut |_, _| Ok(()), w)?;
         }
     }
     Ok(())
@@ -368,21 +366,22 @@ pub fn write_mir_intro<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
                  -> io::Result<()>
 {
-    match src {
-        MirSource::Fn(_) => write!(w, "fn")?,
-        MirSource::Const(_) => write!(w, "const")?,
-        MirSource::Static(_, hir::MutImmutable) => write!(w, "static")?,
-        MirSource::Static(_, hir::MutMutable) => write!(w, "static mut")?,
-        MirSource::Promoted(_, i) => write!(w, "{:?} in", i)?,
-        MirSource::GeneratorDrop(_) => write!(w, "drop_glue")?,
+    let id = tcx.hir.as_local_node_id(src.def_id).unwrap();
+    let body_owner_kind = tcx.hir.body_owner_kind(id);
+    match (body_owner_kind, src.promoted) {
+        (_, Some(i)) => write!(w, "{:?} in", i)?,
+        (hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?,
+        (hir::BodyOwnerKind::Const, _) => write!(w, "const")?,
+        (hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?,
+        (hir::BodyOwnerKind::Static(hir::MutMutable), _) => write!(w, "static mut")?,
     }
 
     item_path::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere
-        write!(w, " {}", tcx.node_path_str(src.item_id()))
+        write!(w, " {}", tcx.item_path_str(src.def_id))
     })?;
 
-    match src {
-        MirSource::Fn(_) | MirSource::GeneratorDrop(_) => {
+    match (body_owner_kind, src.promoted) {
+        (hir::BodyOwnerKind::Fn, None) => {
             write!(w, "(")?;
 
             // fn argument types.
@@ -395,9 +394,9 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
 
             write!(w, ") -> {}", mir.return_ty)
         }
-        MirSource::Const(..) |
-        MirSource::Static(..) |
-        MirSource::Promoted(..) => {
+        (hir::BodyOwnerKind::Const, _) |
+        (hir::BodyOwnerKind::Static(_), _) |
+        (_, Some(_)) => {
             assert_eq!(mir.arg_count, 0);
             write!(w, ": {} =", mir.return_ty)
         }
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index 4515d9c7837..776b5f3c984 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -37,7 +37,6 @@ use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
-use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::{queries, Providers};
 use rustc::ty::subst::Substs;
@@ -184,9 +183,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckCrateVisitor<'a, 'tcx> {
         self.in_fn = false;
         self.in_static = false;
 
-        match MirSource::from_node(self.tcx, item_id) {
-            MirSource::Fn(_) => self.in_fn = true,
-            MirSource::Static(_, _) => self.in_static = true,
+        match self.tcx.hir.body_owner_kind(item_id) {
+            hir::BodyOwnerKind::Fn => self.in_fn = true,
+            hir::BodyOwnerKind::Static(_) => self.in_static = true,
             _ => {}
         };