From a6fe6c9be10c79d64c988d490519f5cc07e9060d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 26 Dec 2016 09:40:15 -0500 Subject: [PATCH] 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.) --- .../borrowck/mir/dataflow/graphviz.rs | 35 ++--- .../borrowck/mir/dataflow/impls.rs | 128 ++++++++++-------- .../borrowck/mir/dataflow/mod.rs | 40 ++---- .../borrowck/mir/dataflow/sanity_check.rs | 14 +- .../borrowck/mir/elaborate_drops.rs | 12 +- .../borrowck/mir/gather_moves.rs | 4 + src/librustc_borrowck/borrowck/mir/mod.rs | 46 ++++--- 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 8461f6d061a55..b15c1873f9bd8 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 DataflowState { - fn each_bit(&self, ctxt: &O::Ctxt, words: &IdxSet, mut f: F) + fn each_bit(&self, words: &IdxSet, 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::() * 8; for (word_index, &word) in words.words().iter().enumerate() { @@ -65,35 +64,33 @@ impl DataflowState { } pub fn interpret_set<'c, P>(&self, - ctxt: &'c O::Ctxt, + o: &'c O, words: &IdxSet, 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>; + type BD: BitDenotation; fn node_id(&self) -> NodeId; fn mir(&self) -> &Mir<'tcx>; - fn analysis_ctxt(&self) -> &::Ctxt; fn flow_state(&self) -> &DataflowState; } impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> - where 'tcx: 'a, BD: BitDenotation> + 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.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>, - 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 { impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> where MWF: MirWithFlowState<'tcx>, - P: for <'b> Fn(&'b ::Ctxt, - ::Idx) - -> &'b Debug, + P: for <'b> Fn(&'b MWF::BD, ::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 fcb453d81aa77..1fa4da94dd6bf 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) + fn start_block_effect(&self, sets: &mut BlockSets) { 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, 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, 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, _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) { + fn start_block_effect(&self, sets: &mut BlockSets) { // 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, 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, 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, _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) { + fn start_block_effect(&self, sets: &mut BlockSets) { 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, 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, 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, _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) { + fn start_block_effect(&self, _sets: &mut BlockSets) { // 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, 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, 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, _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 51817afbfeafd..f11cf90834dd9 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 { - fn dataflow

(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug; + fn dataflow

(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug; } impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD> - where BD: BitDenotation> + DataflowOperator + where BD: BitDenotation + DataflowOperator { - fn dataflow

(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug { + fn dataflow

(&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 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> + where BD: BitDenotation { fn pre_dataflow_instrumentation

(&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

(&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 Bits { } pub struct DataflowAnalysis<'a, 'tcx: 'a, O> - where O: BitDenotation, O::Ctxt: 'a + where O: BitDenotation { flow_state: DataflowState, 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); + fn start_block_effect(&self, sets: &mut BlockSets); /// 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, 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, 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, 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::() * 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 916d17dcc91de..ea6ef423c92ce 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) - where O: BitDenotation, Idx=MovePathIndex> + where O: BitDenotation + 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, bb: mir::BasicBlock) where - O: BitDenotation, Idx=MovePathIndex> + O: BitDenotation + 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 4f49bfc9725b3..c9ce6eca86517 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 02064b52cb1fb..2a9acaf58b8f2 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 { /// 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 9035c2ab3c236..68929cd4e8526 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 { for attr in attrs { @@ -79,20 +81,23 @@ pub fn borrowck_mir(bcx: &mut BorrowckCtxt, let move_data = MoveData::gather_moves(mir, tcx, ¶m_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 - where BD: BitDenotation> + 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 + where BD: BitDenotation + DataflowOperator, + P: Fn(&BD, BD::Idx) -> &fmt::Debug { let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option { 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>, flow_uninits: DataflowResults> }