diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
index c9a23e3f288..480b890da6a 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
@@ -24,23 +24,9 @@ use bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep.
 use bitslice::{BitwiseOperator};
 use indexed_set::{Idx, IdxSet};
 
-use std::marker::PhantomData;
-
 // Dataflow analyses are built upon some interpretation of the
 // bitvectors attached to each basic block, represented via a
 // zero-sized structure.
-//
-// Note on PhantomData: Each interpretation will need to instantiate
-// the `Bit` and `Ctxt` associated types, and in this case, those
-// associated types need an associated lifetime `'tcx`. The
-// interpretive structures are zero-sized, so they all need to carry a
-// `PhantomData` representing how the structures relate to the `'tcx`
-// lifetime.
-//
-// But, since all of the uses of `'tcx` are solely via instances of
-// `Ctxt` that are passed into the `BitDenotation` methods, we can
-// consistently use a `PhantomData` that is just a function over a
-// `&Ctxt` (== `&MoveData<'tcx>).
 
 /// `MaybeInitializedLvals` tracks all l-values that might be
 /// initialized upon reaching a particular point in the control flow
@@ -77,10 +63,15 @@ use std::marker::PhantomData;
 /// Similarly, at a given `drop` statement, the set-intersection
 /// between this data and `MaybeUninitializedLvals` yields the set of
 /// l-values that would require a dynamic drop-flag at that statement.
-#[derive(Debug, Default)]
 pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
-    // See "Note on PhantomData" above.
-    phantom: PhantomData<Fn(&'a MoveData<'tcx>, TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>)>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+        MaybeInitializedLvals { tcx: tcx, mir: mir }
+    }
 }
 
 /// `MaybeUninitializedLvals` tracks all l-values that might be
@@ -118,10 +109,15 @@ pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
 /// Similarly, at a given `drop` statement, the set-intersection
 /// between this data and `MaybeInitializedLvals` yields the set of
 /// l-values that would require a dynamic drop-flag at that statement.
-#[derive(Debug, Default)]
 pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
-    // See "Note on PhantomData" above.
-    phantom: PhantomData<Fn(&'a MoveData<'tcx>, TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>)>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+        MaybeUninitializedLvals { tcx: tcx, mir: mir }
+    }
 }
 
 /// `DefinitelyInitializedLvals` tracks all l-values that are definitely
@@ -165,10 +161,15 @@ pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
 /// Similarly, at a given `drop` statement, the set-difference between
 /// this data and `MaybeInitializedLvals` yields the set of l-values
 /// that would require a dynamic drop-flag at that statement.
-#[derive(Debug, Default)]
 pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
-    // See "Note on PhantomData" above.
-    phantom: PhantomData<Fn(&'a MoveData<'tcx>, TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>)>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+        DefinitelyInitializedLvals { tcx: tcx, mir: mir }
+    }
 }
 
 /// `MovingOutStatements` tracks the statements that perform moves out
@@ -184,10 +185,10 @@ pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
 /// control flow. But `MovingOutStatements` also includes the added
 /// data of *which* particular statement causing the deinitialization
 /// that the borrow checker's error meessage may need to report.
-#[derive(Debug, Default)]
+#[allow(dead_code)]
 pub struct MovingOutStatements<'a, 'tcx: 'a> {
-    // See "Note on PhantomData" above.
-    phantom: PhantomData<Fn(&'a MoveData<'tcx>, TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>)>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    mir: &'a Mir<'tcx>,
 }
 
 impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
@@ -226,18 +227,18 @@ impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> {
 impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
     type Bit = MovePath<'tcx>;
-    type Ctxt = (TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>, MoveData<'tcx>);
+    type Ctxt = MoveData<'tcx>;
     fn name() -> &'static str { "maybe_init" }
     fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.2.move_paths.len()
+        ctxt.move_paths.len()
     }
     fn interpret<'c>(&self, ctxt: &'c Self::Ctxt, idx: usize) -> &'c Self::Bit {
-        &ctxt.2.move_paths[MovePathIndex::new(idx)]
+        &ctxt.move_paths[MovePathIndex::new(idx)]
     }
     fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>)
     {
         drop_flag_effects_for_function_entry(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -251,7 +252,7 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             Location { block: bb, index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
@@ -264,7 +265,7 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             Location { block: bb, index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
@@ -278,9 +279,8 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
                              dest_lval: &repr::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        let move_data = &ctxt.2;
-        let move_path_index = move_data.rev_lookup.find(dest_lval);
-        on_all_children_bits(ctxt.0, ctxt.1, &ctxt.2,
+        let move_path_index = ctxt.rev_lookup.find(dest_lval);
+        on_all_children_bits(self.tcx, self.mir, ctxt,
                              move_path_index,
                              |mpi| { in_out.add(&mpi); });
     }
@@ -289,13 +289,13 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
 impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
     type Bit = MovePath<'tcx>;
-    type Ctxt = (TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>, MoveData<'tcx>);
+    type Ctxt = MoveData<'tcx>;
     fn name() -> &'static str { "maybe_uninit" }
     fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.2.move_paths.len()
+        ctxt.move_paths.len()
     }
     fn interpret<'c>(&self, ctxt: &'c Self::Ctxt, idx: usize) -> &'c Self::Bit {
-        &ctxt.2.move_paths[MovePathIndex::new(idx)]
+        &ctxt.move_paths[MovePathIndex::new(idx)]
     }
 
     // sets on_entry bits for Arg lvalues
@@ -304,7 +304,7 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
         for e in sets.on_entry.words_mut() { *e = !0; }
 
         drop_flag_effects_for_function_entry(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.remove(&path);
@@ -318,7 +318,7 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             Location { block: bb, index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
@@ -331,7 +331,7 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             Location { block: bb, index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
@@ -345,8 +345,8 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
                              dest_lval: &repr::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        let move_path_index = ctxt.2.rev_lookup.find(dest_lval);
-        on_all_children_bits(ctxt.0, ctxt.1, &ctxt.2,
+        let move_path_index = ctxt.rev_lookup.find(dest_lval);
+        on_all_children_bits(self.tcx, self.mir, ctxt,
                              move_path_index,
                              |mpi| { in_out.remove(&mpi); });
     }
@@ -355,13 +355,13 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
 impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
     type Bit = MovePath<'tcx>;
-    type Ctxt = (TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>, MoveData<'tcx>);
+    type Ctxt = MoveData<'tcx>;
     fn name() -> &'static str { "definite_init" }
     fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.2.move_paths.len()
+        ctxt.move_paths.len()
     }
     fn interpret<'c>(&self, ctxt: &'c Self::Ctxt, idx: usize) -> &'c Self::Bit {
-        &ctxt.2.move_paths[MovePathIndex::new(idx)]
+        &ctxt.move_paths[MovePathIndex::new(idx)]
     }
 
     // sets on_entry bits for Arg lvalues
@@ -369,7 +369,7 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
         for e in sets.on_entry.words_mut() { *e = 0; }
 
         drop_flag_effects_for_function_entry(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -383,7 +383,7 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             Location { block: bb, index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
@@ -396,7 +396,7 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            ctxt.0, ctxt.1, &ctxt.2,
+            self.tcx, self.mir, ctxt,
             Location { block: bb, index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
@@ -410,8 +410,8 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
                              dest_lval: &repr::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        let move_path_index = ctxt.2.rev_lookup.find(dest_lval);
-        on_all_children_bits(ctxt.0, ctxt.1, &ctxt.2,
+        let move_path_index = ctxt.rev_lookup.find(dest_lval);
+        on_all_children_bits(self.tcx, self.mir, ctxt,
                              move_path_index,
                              |mpi| { in_out.add(&mpi); });
     }
@@ -420,13 +420,13 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
 impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
     type Idx = MoveOutIndex;
     type Bit = MoveOut;
-    type Ctxt = (TyCtxt<'a, 'tcx, 'tcx>, &'a Mir<'tcx>, MoveData<'tcx>);
+    type Ctxt = MoveData<'tcx>;
     fn name() -> &'static str { "moving_out" }
     fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.2.moves.len()
+        ctxt.moves.len()
     }
     fn interpret<'c>(&self, ctxt: &'c Self::Ctxt, idx: usize) -> &'c Self::Bit {
-        &ctxt.2.moves[idx]
+        &ctxt.moves[idx]
     }
     fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets<MoveOutIndex>) {
         // no move-statements have been executed prior to function
@@ -437,7 +437,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
                         sets: &mut BlockSets<MoveOutIndex>,
                         bb: repr::BasicBlock,
                         idx: usize) {
-        let &(tcx, mir, ref move_data) = ctxt;
+        let (tcx, mir, move_data) = (self.tcx, self.mir, ctxt);
         let stmt = &mir.basic_block_data(bb).statements[idx];
         let loc_map = &move_data.loc_map;
         let path_map = &move_data.path_map;
@@ -477,7 +477,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
                          bb: repr::BasicBlock,
                          statements_len: usize)
     {
-        let &(_tcx, mir, ref move_data) = ctxt;
+        let (mir, move_data) = (self.mir, ctxt);
         let term = mir.basic_block_data(bb).terminator.as_ref().unwrap();
         let loc_map = &move_data.loc_map;
         let loc = Location { block: bb, index: statements_len };
@@ -496,13 +496,13 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
                              _call_bb: repr::BasicBlock,
                              _dest_bb: repr::BasicBlock,
                              dest_lval: &repr::Lvalue) {
-        let move_data = &ctxt.2;
+        let move_data = ctxt;
         let move_path_index = move_data.rev_lookup.find(dest_lval);
         let bits_per_block = self.bits_per_block(ctxt);
 
         let path_map = &move_data.path_map;
-        on_all_children_bits(ctxt.0,
-                             ctxt.1,
+        on_all_children_bits(self.tcx,
+                             self.mir,
                              move_data,
                              move_path_index,
                              |mpi| for moi in &path_map[mpi] {
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
index 97e29fe064f..e1470e62840 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
@@ -49,7 +49,7 @@ impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
 }
 
 struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O>
-    where O: 'b + BitDenotation, O::Ctxt: HasMoveData<'tcx>
+    where O: 'b + BitDenotation, O::Ctxt: 'a+HasMoveData<'tcx>
 {
     builder: &'b mut DataflowAnalysis<'a, 'tcx, O>,
     changed: bool,
@@ -191,18 +191,18 @@ impl<'tcx, A, B> HasMoveData<'tcx> for (A, B, MoveData<'tcx>) {
 }
 
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O>
-    where O: BitDenotation, O::Ctxt: HasMoveData<'tcx>
+    where O: BitDenotation, O::Ctxt: 'a+HasMoveData<'tcx>
 {
     flow_state: DataflowState<O>,
-    ctxt: O::Ctxt,
     mir: &'a Mir<'tcx>,
+    ctxt: &'a O::Ctxt,
 }
 
 impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
     where O: BitDenotation, O::Ctxt: HasMoveData<'tcx>
 {
-    pub fn results(self) -> (O::Ctxt, DataflowResults<O>) {
-        (self.ctxt, DataflowResults(self.flow_state))
+    pub fn results(self) -> DataflowResults<O> {
+        DataflowResults(self.flow_state)
     }
 
     pub fn mir(&self) -> &'a Mir<'tcx> { self.mir }
@@ -440,7 +440,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
 {
     pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               ctxt: D::Ctxt,
+               ctxt: &'a D::Ctxt,
                denotation: D) -> Self {
         let bits_per_block = denotation.bits_per_block(&ctxt);
         let usize_bits = mem::size_of::<usize>() * 8;
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs
index 37c042844e5..54132cf0258 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/mod.rs
@@ -75,24 +75,22 @@ pub fn borrowck_mir<'a, 'tcx: 'a>(
     let tcx = bcx.tcx;
 
     let move_data = MoveData::gather_moves(mir, tcx);
-    let ctxt = (tcx, mir, move_data);
-    let (ctxt, flow_inits) =
-        do_dataflow(tcx, mir, id, attributes, ctxt, MaybeInitializedLvals::default());
-    let (ctxt, flow_uninits) =
-        do_dataflow(tcx, mir, id, attributes, ctxt, MaybeUninitializedLvals::default());
-    let (ctxt, flow_def_inits) =
-        do_dataflow(tcx, mir, id, attributes, ctxt, DefinitelyInitializedLvals::default());
+    let flow_inits =
+        do_dataflow(tcx, mir, id, attributes, &move_data, MaybeInitializedLvals::new(tcx, mir));
+    let flow_uninits =
+        do_dataflow(tcx, mir, id, attributes, &move_data, MaybeUninitializedLvals::new(tcx, mir));
+    let flow_def_inits =
+        do_dataflow(tcx, mir, id, attributes, &move_data, DefinitelyInitializedLvals::new(tcx, mir));
 
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &ctxt, &flow_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &move_data, &flow_inits);
     }
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_uninit").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &ctxt, &flow_uninits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &move_data, &flow_uninits);
     }
     if has_rustc_mir_with(attributes, "rustc_peek_definite_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &ctxt, &flow_def_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &move_data, &flow_def_inits);
     }
-    let move_data = ctxt.2;
 
     if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
         bcx.tcx.sess.fatal("stop_after_dataflow ended compilation");
@@ -118,8 +116,8 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              mir: &Mir<'tcx>,
                              node_id: ast::NodeId,
                              attributes: &[ast::Attribute],
-                             ctxt: BD::Ctxt,
-                             bd: BD) -> (BD::Ctxt, DataflowResults<BD>)
+                             ctxt: &BD::Ctxt,
+                             bd: BD) -> DataflowResults<BD>
     where BD: BitDenotation + DataflowOperator, BD::Bit: Debug, BD::Ctxt: HasMoveData<'tcx>
 {
     use syntax::attr::AttrMetaMethods;
@@ -156,7 +154,7 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
 
 pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD>
-    where BD: BitDenotation, BD::Ctxt: HasMoveData<'tcx>
+    where BD: BitDenotation, BD::Ctxt: 'a+HasMoveData<'tcx>
 {
     node_id: ast::NodeId,
     flow_state: DataflowAnalysis<'a, 'tcx, BD>,