threaded a ty::ParameterEnvironment for the current node id via the associated Ctxt item.

used this to address a long-standing wart/bug in how filtering-out of
values with type impl'ing `Copy` was done.
This commit is contained in:
Felix S. Klock II 2016-05-24 23:03:52 +02:00
parent fdf80bc60c
commit ad1294dbe7
5 changed files with 56 additions and 44 deletions

View File

@ -24,7 +24,7 @@
use std::mem;
use std::path::Path;
use super::super::gather_moves::{MoveData};
use super::super::MoveDataParamEnv;
use super::super::MirBorrowckCtxtPreDataflow;
use bitslice::bits_to_string;
use indexed_set::{Idx, IdxSet};
@ -79,7 +79,7 @@ pub fn interpret_set<'c, P>(&self,
}
pub trait MirWithFlowState<'tcx> {
type BD: BitDenotation<Ctxt=MoveData<'tcx>>;
type BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>;
fn node_id(&self) -> NodeId;
fn mir(&self) -> &Mir<'tcx>;
fn analysis_ctxt(&self) -> &<Self::BD as BitDenotation>::Ctxt;
@ -87,7 +87,7 @@ pub trait MirWithFlowState<'tcx> {
}
impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
where 'a, 'tcx: 'a, BD: BitDenotation<Ctxt=MoveData<'tcx>>
where 'a, 'tcx: 'a, BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
{
type BD = BD;
fn node_id(&self) -> NodeId { self.node_id }
@ -109,7 +109,7 @@ pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
path: &Path,
render_idx: P)
-> io::Result<()>
where BD: BitDenotation<Ctxt=MoveData<'tcx>>,
where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>,
P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug
{
let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };

View File

@ -12,7 +12,8 @@
use rustc::mir::repr::{self, Mir};
use super::super::gather_moves::{Location};
use super::super::gather_moves::{MoveData, MoveOutIndex, MovePathIndex};
use super::super::gather_moves::{MoveOutIndex, MovePathIndex};
use super::super::MoveDataParamEnv;
use super::super::DropFlagState;
use super::super::drop_flag_effects_for_function_entry;
use super::super::drop_flag_effects_for_location;
@ -226,10 +227,10 @@ fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex,
impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> {
type Idx = MovePathIndex;
type Ctxt = MoveData<'tcx>;
type Ctxt = MoveDataParamEnv<'tcx>;
fn name() -> &'static str { "maybe_init" }
fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
ctxt.move_paths.len()
ctxt.move_data.move_paths.len()
}
fn start_block_effect(&self, ctxt: &Self::Ctxt, sets: &mut BlockSets<MovePathIndex>)
@ -276,8 +277,8 @@ fn propagate_call_return(&self,
dest_lval: &repr::Lvalue) {
// when a call returns successfully, that means we need to set
// the bits for that dest_lval to 1 (initialized).
let move_path_index = ctxt.rev_lookup.find(dest_lval);
on_all_children_bits(self.tcx, self.mir, ctxt,
let move_path_index = ctxt.move_data.rev_lookup.find(dest_lval);
on_all_children_bits(self.tcx, self.mir, &ctxt.move_data,
move_path_index,
|mpi| { in_out.add(&mpi); });
}
@ -285,10 +286,10 @@ fn propagate_call_return(&self,
impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> {
type Idx = MovePathIndex;
type Ctxt = MoveData<'tcx>;
type Ctxt = MoveDataParamEnv<'tcx>;
fn name() -> &'static str { "maybe_uninit" }
fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
ctxt.move_paths.len()
ctxt.move_data.move_paths.len()
}
// sets on_entry bits for Arg lvalues
@ -338,8 +339,8 @@ fn propagate_call_return(&self,
dest_lval: &repr::Lvalue) {
// when a call returns successfully, that means we need to set
// the bits for that dest_lval to 1 (initialized).
let move_path_index = ctxt.rev_lookup.find(dest_lval);
on_all_children_bits(self.tcx, self.mir, ctxt,
let move_path_index = ctxt.move_data.rev_lookup.find(dest_lval);
on_all_children_bits(self.tcx, self.mir, &ctxt.move_data,
move_path_index,
|mpi| { in_out.remove(&mpi); });
}
@ -347,10 +348,10 @@ fn propagate_call_return(&self,
impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> {
type Idx = MovePathIndex;
type Ctxt = MoveData<'tcx>;
type Ctxt = MoveDataParamEnv<'tcx>;
fn name() -> &'static str { "definite_init" }
fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
ctxt.move_paths.len()
ctxt.move_data.move_paths.len()
}
// sets on_entry bits for Arg lvalues
@ -399,8 +400,8 @@ fn propagate_call_return(&self,
dest_lval: &repr::Lvalue) {
// when a call returns successfully, that means we need to set
// the bits for that dest_lval to 1 (initialized).
let move_path_index = ctxt.rev_lookup.find(dest_lval);
on_all_children_bits(self.tcx, self.mir, ctxt,
let move_path_index = ctxt.move_data.rev_lookup.find(dest_lval);
on_all_children_bits(self.tcx, self.mir, &ctxt.move_data,
move_path_index,
|mpi| { in_out.add(&mpi); });
}
@ -408,10 +409,10 @@ fn propagate_call_return(&self,
impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
type Idx = MoveOutIndex;
type Ctxt = MoveData<'tcx>;
type Ctxt = MoveDataParamEnv<'tcx>;
fn name() -> &'static str { "moving_out" }
fn bits_per_block(&self, ctxt: &Self::Ctxt) -> usize {
ctxt.moves.len()
ctxt.move_data.moves.len()
}
fn start_block_effect(&self,_move_data: &Self::Ctxt, _sets: &mut BlockSets<MoveOutIndex>) {
@ -423,7 +424,7 @@ fn statement_effect(&self,
sets: &mut BlockSets<MoveOutIndex>,
bb: repr::BasicBlock,
idx: usize) {
let (tcx, mir, move_data) = (self.tcx, self.mir, ctxt);
let (tcx, mir, move_data) = (self.tcx, self.mir, &ctxt.move_data);
let stmt = &mir.basic_block_data(bb).statements[idx];
let loc_map = &move_data.loc_map;
let path_map = &move_data.path_map;
@ -463,7 +464,7 @@ fn terminator_effect(&self,
bb: repr::BasicBlock,
statements_len: usize)
{
let (mir, move_data) = (self.mir, ctxt);
let (mir, move_data) = (self.mir, &ctxt.move_data);
let term = mir.basic_block_data(bb).terminator.as_ref().unwrap();
let loc_map = &move_data.loc_map;
let loc = Location { block: bb, index: statements_len };
@ -482,7 +483,7 @@ fn propagate_call_return(&self,
_call_bb: repr::BasicBlock,
_dest_bb: repr::BasicBlock,
dest_lval: &repr::Lvalue) {
let move_data = ctxt;
let move_data = &ctxt.move_data;
let move_path_index = move_data.rev_lookup.find(dest_lval);
let bits_per_block = self.bits_per_block(ctxt);

View File

@ -18,7 +18,7 @@
use std::usize;
use super::MirBorrowckCtxtPreDataflow;
use super::gather_moves::{MoveData};
use super::MoveDataParamEnv;
use bitslice::{bitwise, BitwiseOperator};
use indexed_set::{Idx, IdxSet, OwnIdxSet};
@ -36,7 +36,7 @@ pub trait Dataflow<BD: BitDenotation> {
}
impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
where BD: BitDenotation<Ctxt=MoveData<'tcx>> + DataflowOperator
where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
{
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
self.flow_state.build_sets();
@ -140,7 +140,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
}
impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
where BD: BitDenotation<Ctxt=MoveData<'tcx>>
where BD: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>>
{
fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug

View File

@ -15,7 +15,8 @@
use rustc::ty::{self, TyCtxt};
use rustc::mir::repr::{self, Mir};
use super::super::gather_moves::{MoveData, MovePathIndex};
use super::super::gather_moves::{MovePathIndex};
use super::super::MoveDataParamEnv;
use super::BitDenotation;
use super::DataflowResults;
@ -41,7 +42,7 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
_attributes: &[ast::Attribute],
flow_ctxt: &O::Ctxt,
results: &DataflowResults<O>)
where O: BitDenotation<Ctxt=MoveData<'tcx>, Idx=MovePathIndex>
where O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
{
debug!("sanity_check_via_rustc_peek id: {:?}", id);
// FIXME: this is not DRY. Figure out way to abstract this and
@ -56,11 +57,12 @@ pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &O::Ctxt,
ctxt: &O::Ctxt,
results: &DataflowResults<O>,
bb: repr::BasicBlock) where
O: BitDenotation<Ctxt=MoveData<'tcx>, Idx=MovePathIndex>
O: BitDenotation<Ctxt=MoveDataParamEnv<'tcx>, Idx=MovePathIndex>
{
let move_data = &ctxt.move_data;
let bb_data = mir.basic_block_data(bb);
let &repr::BasicBlockData { ref statements,
ref terminator,
@ -127,7 +129,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx.sess.span_err(span, msg);
}
}
let lhs_mpi = move_data.rev_lookup.find(lvalue);
debug!("rustc_peek: computing effect on lvalue: {:?} ({:?}) in stmt: {:?}",
@ -135,7 +137,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(move_data, &mut sets, bb, j);
results.0.operator.statement_effect(ctxt, &mut sets, bb, j);
sets.on_entry.union(sets.gen_set);
sets.on_entry.subtract(sets.kill_set);
}

View File

@ -50,6 +50,11 @@ fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<P<MetaItem
return None;
}
pub struct MoveDataParamEnv<'tcx> {
move_data: MoveData<'tcx>,
param_env: ty::ParameterEnvironment<'tcx>,
}
pub fn borrowck_mir<'a, 'tcx: 'a>(
bcx: &mut BorrowckCtxt<'a, 'tcx>,
fk: FnKind,
@ -72,21 +77,23 @@ pub fn borrowck_mir<'a, 'tcx: 'a>(
let tcx = bcx.tcx;
let move_data = MoveData::gather_moves(mir, tcx);
let param_env = ty::ParameterEnvironment::for_item(tcx, id);
let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env };
let flow_inits =
do_dataflow(tcx, mir, id, attributes, &move_data, MaybeInitializedLvals::new(tcx, mir));
do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeInitializedLvals::new(tcx, mir));
let flow_uninits =
do_dataflow(tcx, mir, id, attributes, &move_data, MaybeUninitializedLvals::new(tcx, mir));
do_dataflow(tcx, mir, id, attributes, &mdpe, MaybeUninitializedLvals::new(tcx, mir));
let flow_def_inits =
do_dataflow(tcx, mir, id, attributes, &move_data, DefinitelyInitializedLvals::new(tcx, mir));
do_dataflow(tcx, mir, id, attributes, &mdpe, DefinitelyInitializedLvals::new(tcx, mir));
if has_rustc_mir_with(attributes, "rustc_peek_maybe_init").is_some() {
dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &move_data, &flow_inits);
dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &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, &move_data, &flow_uninits);
dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &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, &move_data, &flow_def_inits);
dataflow::sanity_check_via_rustc_peek(bcx.tcx, mir, id, attributes, &mdpe, &flow_def_inits);
}
if has_rustc_mir_with(attributes, "stop_after_dataflow").is_some() {
@ -97,7 +104,7 @@ pub fn borrowck_mir<'a, 'tcx: 'a>(
bcx: bcx,
mir: mir,
node_id: id,
move_data: move_data,
move_data: mdpe.move_data,
flow_inits: flow_inits,
flow_uninits: flow_uninits,
};
@ -115,7 +122,7 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
attributes: &[ast::Attribute],
ctxt: &BD::Ctxt,
bd: BD) -> DataflowResults<BD>
where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveData<'tcx>> + DataflowOperator
where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveDataParamEnv<'tcx>> + DataflowOperator
{
use syntax::attr::AttrMetaMethods;
@ -145,7 +152,7 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd),
};
mbcx.dataflow(|move_data, i| &move_data.move_paths[i]);
mbcx.dataflow(|ctxt, i| &ctxt.move_data.move_paths[i]);
mbcx.flow_state.results()
}
@ -253,10 +260,11 @@ fn on_all_children_bits<'a, 'tcx, F>(
fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>,
ctxt: &MoveDataParamEnv<'tcx>,
mut callback: F)
where F: FnMut(MovePathIndex, DropFlagState)
{
let move_data = &ctxt.move_data;
for i in 0..(mir.arg_decls.len() as u32) {
let lvalue = repr::Lvalue::Arg(i);
let move_path_index = move_data.rev_lookup.find(&lvalue);
@ -269,11 +277,13 @@ fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
fn drop_flag_effects_for_location<'a, 'tcx, F>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mir: &Mir<'tcx>,
move_data: &MoveData<'tcx>,
ctxt: &MoveDataParamEnv<'tcx>,
loc: Location,
mut callback: F)
where F: FnMut(MovePathIndex, DropFlagState)
{
let move_data = &ctxt.move_data;
let param_env = &ctxt.param_env;
debug!("drop_flag_effects_for_location({:?})", loc);
// first, move out of the RHS
@ -284,8 +294,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
// don't move out of non-Copy things
if let MovePathContent::Lvalue(ref lvalue) = move_data.move_paths[path].content {
let ty = mir.lvalue_ty(tcx, lvalue).to_ty(tcx);
let empty_param_env = tcx.empty_parameter_environment();
if !ty.moves_by_default(tcx, &empty_param_env, DUMMY_SP) {
if !ty.moves_by_default(tcx, param_env, DUMMY_SP) {
continue;
}
}