mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 22:13:27 +00:00
Auto merge of #38616 - pnkfelix:refactor-mir-dataflow-remove-ctxt, r=arielb1
Refactor mir::dataflow: remove Ctxt associated type from BitDenotation trait 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.)
This commit is contained in:
commit
469fd779ee
@ -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();
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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, ¶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<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>>
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user