about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2016-12-26 09:40:15 -0500
committerFelix S. Klock II <pnkfelix@pnkfx.org>2016-12-26 09:45:42 -0500
commita6fe6c9be10c79d64c988d490519f5cc07e9060d (patch)
tree4a2251e58371b6a9474451f6cb679d700b1a8bf2
parent8493dbed6c29b30844830d6e50a33493c6ea70af (diff)
downloadrust-a6fe6c9be10c79d64c988d490519f5cc07e9060d.tar.gz
rust-a6fe6c9be10c79d64c988d490519f5cc07e9060d.zip
Refactor mir::dataflow: remove Ctxt associated type from BitDenotation trait.
I no longer remember why I needed this (or thought I did). The way
that the `BitDenotation` is passed around in all existing use cases
(and planned future ones), the thing that were in the `Ctxt` can just
be part of `Self` instead.

(I think ariel had been pushing me to do this back when I first put in
this infrastructure; it took me a while to see how much of pain the
`Ctxt` was causing.)
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs35
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/impls.rs128
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/mod.rs40
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs14
-rw-r--r--src/librustc_borrowck/borrowck/mir/elaborate_drops.rs12
-rw-r--r--src/librustc_borrowck/borrowck/mir/gather_moves.rs4
-rw-r--r--src/librustc_borrowck/borrowck/mir/mod.rs46
7 files changed, 144 insertions, 135 deletions
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
index 8461f6d061a..b15c1873f9b 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs
@@ -27,16 +27,15 @@ use std::marker::PhantomData;
 use std::mem;
 use std::path::Path;
 
-use super::super::MoveDataParamEnv;
 use super::super::MirBorrowckCtxtPreDataflow;
 use super::{BitDenotation, DataflowState};
 
 impl<O: BitDenotation> DataflowState<O> {
-    fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
+    fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F)
         where F: FnMut(O::Idx) {
         //! Helper for iterating over the bits in a bitvector.
 
-        let bits_per_block = self.operator.bits_per_block(ctxt);
+        let bits_per_block = self.operator.bits_per_block();
         let usize_bits: usize = mem::size_of::<usize>() * 8;
 
         for (word_index, &word) in words.words().iter().enumerate() {
@@ -65,35 +64,33 @@ impl<O: BitDenotation> DataflowState<O> {
     }
 
     pub fn interpret_set<'c, P>(&self,
-                                ctxt: &'c O::Ctxt,
+                                o: &'c O,
                                 words: &IdxSet<O::Idx>,
                                 render_idx: &P)
                                 -> Vec<&'c Debug>
-        where P: for <'b> Fn(&'b O::Ctxt, O::Idx) -> &'b Debug
+        where P: Fn(&O, O::Idx) -> &Debug
     {
         let mut v = Vec::new();
-        self.each_bit(ctxt, words, |i| {
-            v.push(render_idx(ctxt, i));
+        self.each_bit(words, |i| {
+            v.push(render_idx(o, i));
         });
         v
     }
 }
 
 pub trait MirWithFlowState<'tcx> {
-    type BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>;
+    type BD: BitDenotation;
     fn node_id(&self) -> NodeId;
     fn mir(&self) -> &Mir<'tcx>;
-    fn analysis_ctxt(&self) -> &<Self::BD as BitDenotation>::Ctxt;
     fn flow_state(&self) -> &DataflowState<Self::BD>;
 }
 
 impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where 'tcx: 'a, BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where 'tcx: 'a, BD: BitDenotation
 {
     type BD = BD;
     fn node_id(&self) -> NodeId { self.node_id }
     fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() }
-    fn analysis_ctxt(&self) -> &BD::Ctxt { &self.flow_state.ctxt }
     fn flow_state(&self) -> &DataflowState<Self::BD> { &self.flow_state.flow_state }
 }
 
@@ -110,8 +107,8 @@ pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
     path: &Path,
     render_idx: P)
     -> io::Result<()>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>,
-          P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug
+    where BD: BitDenotation,
+          P: Fn(&BD, BD::Idx) -> &Debug
 {
     let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };
     let mut v = Vec::new();
@@ -133,9 +130,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
 
 impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
     where MWF: MirWithFlowState<'tcx>,
-          P: for <'b> Fn(&'b <MWF::BD as BitDenotation>::Ctxt,
-                         <MWF::BD as BitDenotation>::Idx)
-                         -> &'b Debug,
+          P: for <'b> Fn(&'b MWF::BD, <MWF::BD as BitDenotation>::Idx) -> &'b Debug,
 {
     type Node = Node;
     type Edge = Edge;
@@ -227,9 +222,8 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
         ::rustc_mir::graphviz::write_node_label(
             *n, self.mbcx.mir(), &mut v, 4,
             |w| {
-                let ctxt = self.mbcx.analysis_ctxt();
                 let flow = self.mbcx.flow_state();
-                let entry_interp = flow.interpret_set(ctxt,
+                let entry_interp = flow.interpret_set(&flow.operator,
                                                       flow.sets.on_entry_set_for(i),
                                                       &self.render_idx);
                 chunked_present_left(w, &entry_interp[..], chunk_size)?;
@@ -244,12 +238,11 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
                        entrybits=bits_to_string(entry.words(), bits_per_block))
             },
             |w| {
-                let ctxt = self.mbcx.analysis_ctxt();
                 let flow = self.mbcx.flow_state();
                 let gen_interp =
-                    flow.interpret_set(ctxt, flow.sets.gen_set_for(i), &self.render_idx);
+                    flow.interpret_set(&flow.operator, flow.sets.gen_set_for(i), &self.render_idx);
                 let kill_interp =
-                    flow.interpret_set(ctxt, flow.sets.kill_set_for(i), &self.render_idx);
+                    flow.interpret_set(&flow.operator, flow.sets.kill_set_for(i), &self.render_idx);
                 chunked_present_left(w, &gen_interp[..], chunk_size)?;
                 let bits_per_block = flow.sets.bits_per_block();
                 {
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
index fcb453d81aa..1fa4da94dd6 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::bitslice::{BitwiseOperator};
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
-use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
+use super::super::gather_moves::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
 use super::super::MoveDataParamEnv;
 use super::super::DropFlagState;
 use super::super::drop_flag_effects_for_function_entry;
@@ -66,14 +66,23 @@ use super::{BitDenotation, BlockSets, DataflowOperator};
 pub struct MaybeInitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'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 }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MaybeInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeInitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `MaybeUninitializedLvals` tracks all l-values that might be
 /// uninitialized upon reaching a particular point in the control flow
 /// for a function.
@@ -112,14 +121,23 @@ impl<'a, 'tcx: 'a> MaybeInitializedLvals<'a, 'tcx> {
 pub struct MaybeUninitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'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 }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        MaybeUninitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for MaybeUninitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `DefinitelyInitializedLvals` tracks all l-values that are definitely
 /// initialized upon reaching a particular point in the control flow
 /// for a function.
@@ -164,14 +182,23 @@ impl<'a, 'tcx: 'a> MaybeUninitializedLvals<'a, 'tcx> {
 pub struct DefinitelyInitializedLvals<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'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 }
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               mir: &'a Mir<'tcx>,
+               mdpe: &'a MoveDataParamEnv<'tcx>)
+               -> Self
+    {
+        DefinitelyInitializedLvals { tcx: tcx, mir: mir, mdpe: mdpe }
     }
 }
 
+impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
+}
+
 /// `MovingOutStatements` tracks the statements that perform moves out
 /// of particular l-values. More precisely, it tracks whether the
 /// *effect* of such moves (namely, the uninitialization of the
@@ -189,6 +216,11 @@ impl<'a, 'tcx: 'a> DefinitelyInitializedLvals<'a, 'tcx> {
 pub struct MovingOutStatements<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir: &'a Mir<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data }
 }
 
 impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> {
@@ -226,16 +258,15 @@ impl<'a, 'tcx> DefinitelyInitializedLvals<'a, 'tcx> {
 
 impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "maybe_init" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>)
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>)
     {
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -243,60 +274,56 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.add(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "maybe_uninit" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
     // sets on_entry bits for Arg lvalues
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>) {
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
         // set all bits to 1 (uninit) before gathering counterevidence
         for e in sets.on_entry.words_mut() { *e = !0; }
 
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.remove(&path);
@@ -304,59 +331,55 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 0 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.remove(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     type Idx = MovePathIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "definite_init" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.move_paths.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().move_paths.len()
     }
 
     // sets on_entry bits for Arg lvalues
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>) {
+    fn start_block_effect(&self, sets: &mut BlockSets<MovePathIndex>) {
         for e in sets.on_entry.words_mut() { *e = 0; }
 
         drop_flag_effects_for_function_entry(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             |path, s| {
                 assert!(s == DropFlagState::Present);
                 sets.on_entry.add(&path);
@@ -364,63 +387,58 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
     }
 
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MovePathIndex>,
                         bb: mir::BasicBlock,
                         idx: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: idx },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MovePathIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
         drop_flag_effects_for_location(
-            self.tcx, self.mir, ctxt,
+            self.tcx, self.mir, self.mdpe,
             Location { block: bb, statement_index: statements_len },
             |path, s| Self::update_bits(sets, path, s)
         )
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MovePathIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
         // when a call returns successfully, that means we need to set
         // the bits for that dest_lval to 1 (initialized).
-        on_lookup_result_bits(self.tcx, self.mir, &ctxt.move_data,
-                              ctxt.move_data.rev_lookup.find(dest_lval),
+        on_lookup_result_bits(self.tcx, self.mir, self.move_data(),
+                              self.move_data().rev_lookup.find(dest_lval),
                               |mpi| { in_out.add(&mpi); });
     }
 }
 
 impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
     type Idx = MoveOutIndex;
-    type Ctxt = MoveDataParamEnv<'tcx>;
     fn name() -> &'static str { "moving_out" }
-    fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
-        ctxt.move_data.moves.len()
+    fn bits_per_block(&self) -> usize {
+        self.move_data().moves.len()
     }
 
-    fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets<MoveOutIndex>) {
+    fn start_block_effect(&self, _sets: &mut BlockSets<MoveOutIndex>) {
         // no move-statements have been executed prior to function
         // execution, so this method has no effect on `_sets`.
     }
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<MoveOutIndex>,
                         bb: mir::BasicBlock,
                         idx: usize) {
-        let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data);
+        let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data());
         let stmt = &mir[bb].statements[idx];
         let loc_map = &move_data.loc_map;
         let path_map = &move_data.path_map;
@@ -435,7 +453,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
             // here, in dataflow vector
             zero_to_one(sets.gen_set.words_mut(), *move_index);
         }
-        let bits_per_block = self.bits_per_block(ctxt);
+        let bits_per_block = self.bits_per_block();
         match stmt.kind {
             mir::StatementKind::SetDiscriminant { .. } => {
                 span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
@@ -460,18 +478,17 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
     }
 
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<MoveOutIndex>,
                          bb: mir::BasicBlock,
                          statements_len: usize)
     {
-        let (mir, move_data) = (self.mir, &ctxt.move_data);
+        let (mir, move_data) = (self.mir, self.move_data());
         let term = mir[bb].terminator();
         let loc_map = &move_data.loc_map;
         let loc = Location { block: bb, statement_index: statements_len };
         debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}",
                term, loc, &loc_map[loc]);
-        let bits_per_block = self.bits_per_block(ctxt);
+        let bits_per_block = self.bits_per_block();
         for move_index in &loc_map[loc] {
             assert!(move_index.index() < bits_per_block);
             zero_to_one(sets.gen_set.words_mut(), *move_index);
@@ -479,13 +496,12 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
     }
 
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<MoveOutIndex>,
                              _call_bb: mir::BasicBlock,
                              _dest_bb: mir::BasicBlock,
                              dest_lval: &mir::Lvalue) {
-        let move_data = &ctxt.move_data;
-        let bits_per_block = self.bits_per_block(ctxt);
+        let move_data = self.move_data();
+        let bits_per_block = self.bits_per_block();
 
         let path_map = &move_data.path_map;
         on_lookup_result_bits(self.tcx,
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
index 51817afbfea..f11cf90834d 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/mod.rs
@@ -22,7 +22,6 @@ use std::path::PathBuf;
 use std::usize;
 
 use super::MirBorrowckCtxtPreDataflow;
-use super::MoveDataParamEnv;
 
 pub use self::sanity_check::sanity_check_via_rustc_peek;
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
@@ -33,13 +32,13 @@ mod sanity_check;
 mod impls;
 
 pub trait Dataflow<BD: BitDenotation> {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug;
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug;
 }
 
 impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
+    where BD: BitDenotation + DataflowOperator
 {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
         self.flow_state.build_sets();
         self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
         self.flow_state.propagate();
@@ -48,7 +47,7 @@ impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
 }
 
 struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O>
-    where O: 'b + BitDenotation, O::Ctxt: 'a
+    where O: 'b + BitDenotation
 {
     builder: &'b mut DataflowAnalysis<'a, 'tcx, O>,
     changed: bool,
@@ -79,7 +78,7 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD>
 
         {
             let sets = &mut self.flow_state.sets.for_block(mir::START_BLOCK.index());
-            self.flow_state.operator.start_block_effect(&self.ctxt, sets);
+            self.flow_state.operator.start_block_effect(sets);
         }
 
         for (bb, data) in self.mir.basic_blocks().iter_enumerated() {
@@ -87,12 +86,12 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD>
 
             let sets = &mut self.flow_state.sets.for_block(bb.index());
             for j_stmt in 0..statements.len() {
-                self.flow_state.operator.statement_effect(&self.ctxt, sets, bb, j_stmt);
+                self.flow_state.operator.statement_effect(sets, bb, j_stmt);
             }
 
             if terminator.is_some() {
                 let stmts_len = statements.len();
-                self.flow_state.operator.terminator_effect(&self.ctxt, sets, bb, stmts_len);
+                self.flow_state.operator.terminator_effect(sets, bb, stmts_len);
             }
         }
     }
@@ -137,10 +136,10 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
 }
 
 impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
-    where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
+    where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> &Debug
     {
         if let Some(ref path_str) = self.print_preflow_to {
             let path = dataflow_path(BD::name(), "preflow", path_str);
@@ -151,7 +150,7 @@ impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
     }
 
     fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> &Debug
     {
         if let Some(ref path_str) = self.print_postflow_to {
             let path = dataflow_path(BD::name(), "postflow", path_str);
@@ -179,11 +178,10 @@ impl<E:Idx> Bits<E> {
 }
 
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O>
-    where O: BitDenotation, O::Ctxt: 'a
+    where O: BitDenotation
 {
     flow_state: DataflowState<O>,
     mir: &'a Mir<'tcx>,
-    ctxt: &'a O::Ctxt,
 }
 
 impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
@@ -295,9 +293,6 @@ pub trait BitDenotation {
     /// Specifies what index type is used to access the bitvector.
     type Idx: Idx;
 
-    /// Specifies what, if any, separate context needs to be supplied for methods below.
-    type Ctxt;
-
     /// A name describing the dataflow analysis that this
     /// BitDenotation is supporting.  The name should be something
     /// suitable for plugging in as part of a filename e.g. avoid
@@ -308,7 +303,7 @@ pub trait BitDenotation {
     fn name() -> &'static str;
 
     /// Size of each bitvector allocated for each block in the analysis.
-    fn bits_per_block(&self, &Self::Ctxt) -> usize;
+    fn bits_per_block(&self) -> usize;
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects that have been
@@ -319,7 +314,7 @@ pub trait BitDenotation {
     /// (Typically this should only modify `sets.on_entry`, since the
     /// gen and kill sets should reflect the effects of *executing*
     /// the start block itself.)
-    fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<Self::Idx>);
+    fn start_block_effect(&self, sets: &mut BlockSets<Self::Idx>);
 
     /// Mutates the block-sets (the flow sets for the given
     /// basic block) according to the effects of evaluating statement.
@@ -332,7 +327,6 @@ pub trait BitDenotation {
     /// `bb_data` is the sequence of statements identifed by `bb` in
     /// the MIR.
     fn statement_effect(&self,
-                        ctxt: &Self::Ctxt,
                         sets: &mut BlockSets<Self::Idx>,
                         bb: mir::BasicBlock,
                         idx_stmt: usize);
@@ -348,7 +342,6 @@ pub trait BitDenotation {
     /// The effects applied here cannot depend on which branch the
     /// terminator took.
     fn terminator_effect(&self,
-                         ctxt: &Self::Ctxt,
                          sets: &mut BlockSets<Self::Idx>,
                          bb: mir::BasicBlock,
                          idx_term: usize);
@@ -373,7 +366,6 @@ pub trait BitDenotation {
     /// kill-sets associated with each edge coming out of the basic
     /// block.
     fn propagate_call_return(&self,
-                             ctxt: &Self::Ctxt,
                              in_out: &mut IdxSet<Self::Idx>,
                              call_bb: mir::BasicBlock,
                              dest_bb: mir::BasicBlock,
@@ -385,9 +377,8 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
 {
     pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>,
                mir: &'a Mir<'tcx>,
-               ctxt: &'a D::Ctxt,
                denotation: D) -> Self {
-        let bits_per_block = denotation.bits_per_block(&ctxt);
+        let bits_per_block = denotation.bits_per_block();
         let usize_bits = mem::size_of::<usize>() * 8;
         let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
 
@@ -405,7 +396,6 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
         });
 
         DataflowAnalysis {
-            ctxt: ctxt,
             mir: mir,
             flow_state: DataflowState {
                 sets: AllSets {
@@ -482,7 +472,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
                     // N.B.: This must be done *last*, after all other
                     // propagation, as documented in comment above.
                     self.flow_state.operator.propagate_call_return(
-                        &self.ctxt, in_out, bb, *dest_bb, dest_lval);
+                        in_out, bb, *dest_bb, dest_lval);
                     self.propagate_bits_into_entry_set_for(in_out, changed, dest_bb);
                 }
             }
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
index 916d17dcc91..ea6ef423c92 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow/sanity_check.rs
@@ -17,9 +17,9 @@ use rustc::mir::{self, Mir};
 use rustc_data_structures::indexed_vec::Idx;
 
 use super::super::gather_moves::{MovePathIndex, LookupResult};
-use super::super::MoveDataParamEnv;
 use super::BitDenotation;
 use super::DataflowResults;
+use super::super::gather_moves::HasMoveData;
 
 /// This function scans `mir` for all calls to the intrinsic
 /// `rustc_peek` that have the expression form `rustc_peek(&expr)`.
@@ -41,9 +41,8 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 mir: &Mir<'tcx>,
                                                 id: ast::NodeId,
                                                 _attributes: &[ast::Attribute],
-                                                flow_ctxt: &O::Ctxt,
                                                 results: &DataflowResults<O>)
-    where O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
+    where O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx>
 {
     debug!("sanity_check_via_rustc_peek id: {:?}", id);
     // FIXME: this is not DRY. Figure out way to abstract this and
@@ -51,18 +50,17 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // stuff, so such generalization may not be realistic.)
 
     for bb in mir.basic_blocks().indices() {
-        each_block(tcx, mir, flow_ctxt, results, bb);
+        each_block(tcx, mir, results, bb);
     }
 }
 
 fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            mir: &Mir<'tcx>,
-                           ctxt: &O::Ctxt,
                            results: &DataflowResults<O>,
                            bb: mir::BasicBlock) where
-    O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
+    O: BitDenotation<Idx=MovePathIndex> + HasMoveData<'tcx>
 {
-    let move_data = &ctxt.move_data;
+    let move_data = results.0.operator.move_data();
     let mir::BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = mir[bb];
 
     let (args, span) = match is_rustc_peek(tcx, terminator) {
@@ -146,7 +144,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // reset GEN and KILL sets before emulating their effect.
         for e in sets.gen_set.words_mut() { *e = 0; }
         for e in sets.kill_set.words_mut() { *e = 0; }
-        results.0.operator.statement_effect(ctxt, &mut sets, bb, j);
+        results.0.operator.statement_effect(&mut sets, bb, j);
         sets.on_entry.union(sets.gen_set);
         sets.on_entry.subtract(sets.kill_set);
     }
diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
index 4f49bfc9725..c9ce6eca865 100644
--- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
+++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::gather_moves::{MoveData, MovePathIndex, LookupResult};
+use super::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
 use super::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use super::dataflow::{DataflowResults};
 use super::{drop_flag_effects_for_location, on_all_children_bits};
@@ -51,11 +51,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
                 param_env: param_env
             };
             let flow_inits =
-                super::do_dataflow(tcx, mir, id, &[], &env,
-                                   MaybeInitializedLvals::new(tcx, mir));
+                super::do_dataflow(tcx, mir, id, &[],
+                                   MaybeInitializedLvals::new(tcx, mir, &env),
+                                   |bd, p| &bd.move_data().move_paths[p]);
             let flow_uninits =
-                super::do_dataflow(tcx, mir, id, &[], &env,
-                                   MaybeUninitializedLvals::new(tcx, mir));
+                super::do_dataflow(tcx, mir, id, &[],
+                                   MaybeUninitializedLvals::new(tcx, mir, &env),
+                                   |bd, p| &bd.move_data().move_paths[p]);
 
             ElaborateDropsCtxt {
                 tcx: tcx,
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
index 02064b52cb1..2a9acaf58b8 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
@@ -120,6 +120,10 @@ pub struct MoveData<'tcx> {
     pub rev_lookup: MovePathLookup<'tcx>,
 }
 
+pub trait HasMoveData<'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx>;
+}
+
 #[derive(Debug)]
 pub struct LocationMap<T> {
     /// Location-indexed (BasicBlock for outer index, index within BB
diff --git a/src/librustc_borrowck/borrowck/mir/mod.rs b/src/librustc_borrowck/borrowck/mir/mod.rs
index 9035c2ab3c2..68929cd4e85 100644
--- a/src/librustc_borrowck/borrowck/mir/mod.rs
+++ b/src/librustc_borrowck/borrowck/mir/mod.rs
@@ -32,7 +32,9 @@ use self::dataflow::{DataflowOperator};
 use self::dataflow::{Dataflow, DataflowAnalysis, DataflowResults};
 use self::dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals};
 use self::dataflow::{DefinitelyInitializedLvals};
-use self::gather_moves::{MoveData, MovePathIndex, LookupResult};
+use self::gather_moves::{HasMoveData, MoveData, MovePathIndex, LookupResult};
+
+use std::fmt;
 
 fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> {
     for attr in attrs {
@@ -79,20 +81,23 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     let move_data = MoveData::gather_moves(mir, tcx, &param_env);
     let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
     let flow_inits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeInitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, MaybeInitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
     let flow_uninits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeUninitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, MaybeUninitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
     let flow_def_inits =
-        do_dataflow(tcx, mir, id, attributes, &mdpe, DefinitelyInitializedLvals::new(tcx, mir));
+        do_dataflow(tcx, mir, id, attributes, DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
+                    |bd, i| &bd.move_data().move_paths[i]);
 
     if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
-        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &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, &mdpe, &flow_uninits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &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, &mdpe, &flow_def_inits);
+        dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &flow_def_inits);
     }
 
     if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
@@ -103,7 +108,7 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
         bcx: bcx,
         mir: mir,
         node_id: id,
-        move_data: mdpe.move_data,
+        move_data: &mdpe.move_data,
         flow_inits: flow_inits,
         flow_uninits: flow_uninits,
     };
@@ -115,13 +120,15 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt,
     debug!("borrowck_mir done");
 }
 
-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) -> DataflowResults<BD>
-    where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
+fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                mir: &Mir<'tcx>,
+                                node_id: ast::NodeId,
+                                attributes: &[ast::Attribute],
+                                bd: BD,
+                                p: P)
+                                -> DataflowResults<BD>
+    where BD: BitDenotation<Idx=MovePathIndex> + DataflowOperator,
+          P: Fn(&BD, BD::Idx) -> &fmt::Debug
 {
     let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
         if let Some(item) = has_rustc_mir_with(attrs, name) {
@@ -146,16 +153,15 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         node_id: node_id,
         print_preflow_to: print_preflow_to,
         print_postflow_to: print_postflow_to,
-        flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd),
+        flow_state: DataflowAnalysis::new(tcx, mir, bd),
     };
 
-    mbcx.dataflow(|ctxt, i| &ctxt.move_data.move_paths[i]);
+    mbcx.dataflow(p);
     mbcx.flow_state.results()
 }
 
 
-pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD>
-    where BD: BitDenotation, BD::Ctxt: 'a
+pub struct MirBorrowckCtxtPreDataflow<'a, 'tcx: 'a, BD> where BD: BitDenotation
 {
     node_id: ast::NodeId,
     flow_state: DataflowAnalysis<'a, 'tcx, BD>,
@@ -168,7 +174,7 @@ pub struct MirBorrowckCtxt<'b, 'a: 'b, 'tcx: 'a> {
     bcx: &'b mut BorrowckCtxt<'a, 'tcx>,
     mir: &'b Mir<'tcx>,
     node_id: ast::NodeId,
-    move_data: MoveData<'tcx>,
+    move_data: &'b MoveData<'tcx>,
     flow_inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>,
     flow_uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>
 }