From 210f76816fe54ff43ed7eca91a78096589fae953 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Mon, 4 Dec 2017 01:00:46 +0200 Subject: [PATCH] handle gen/kill sets together --- src/librustc_mir/dataflow/impls/mod.rs | 66 +++++-------------- src/librustc_mir/dataflow/mod.rs | 30 +++++++++ .../borrowck-move-moved-value-into-closure.rs | 6 +- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 50c8df3c2e3d..e7a25c212c36 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,7 +14,6 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; @@ -504,7 +503,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { let stmt = &mir[location.block].statements[location.statement_index]; let loc_map = &move_data.loc_map; let path_map = &move_data.path_map; - let bits_per_block = self.bits_per_block(); match stmt.kind { // this analysis only tries to find moves explicitly @@ -515,21 +513,15 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { _ => { debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", stmt, location, &loc_map[location]); - for move_index in &loc_map[location] { - // Every path deinitialized by a *particular move* - // has corresponding bit, "gen'ed" (i.e. set) - // here, in dataflow vector - zero_to_one(sets.gen_set.words_mut(), *move_index); - } + // Every path deinitialized by a *particular move* + // has corresponding bit, "gen'ed" (i.e. set) + // here, in dataflow vector + sets.gen_all_and_assert_dead(&loc_map[location]); } } for_location_inits(tcx, mir, move_data, location, - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - sets.kill_set.add(&moi); - } - ); + |mpi| sets.kill_all(&path_map[mpi])); } fn terminator_effect(&self, @@ -543,18 +535,10 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MovingOutStatements<'a, 'gcx, 'tcx> { debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", term, location, &loc_map[location]); - let bits_per_block = self.bits_per_block(); - for move_index in &loc_map[location] { - assert!(move_index.index() < bits_per_block); - zero_to_one(sets.gen_set.words_mut(), *move_index); - } + sets.gen_all_and_assert_dead(&loc_map[location]); for_location_inits(tcx, mir, move_data, location, - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - sets.kill_set.add(&moi); - } - ); + |mpi| sets.kill_all(&path_map[mpi])); } fn propagate_call_return(&self, @@ -585,11 +569,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { } fn start_block_effect(&self, sets: &mut BlockSets) { - let bits_per_block = self.bits_per_block(); - for init_index in (0..self.mir.arg_count).map(InitIndex::new) { - assert!(init_index.index() < bits_per_block); - sets.gen_set.add(&init_index); - } + sets.gen_all((0..self.mir.arg_count).map(InitIndex::new)); } fn statement_effect(&self, sets: &mut BlockSets, @@ -599,14 +579,10 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { let init_path_map = &move_data.init_path_map; let init_loc_map = &move_data.init_loc_map; let rev_lookup = &move_data.rev_lookup; - let bits_per_block = self.bits_per_block(); debug!("statement {:?} at loc {:?} initializes move_indexes {:?}", stmt, location, &init_loc_map[location]); - for init_index in &init_loc_map[location] { - assert!(init_index.index() < bits_per_block); - sets.gen_set.add(init_index); - } + sets.gen_all(&init_loc_map[location]); match stmt.kind { mir::StatementKind::StorageDead(local) => { @@ -614,11 +590,8 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { // be reinitialized on the next iteration of the loop. if let LookupResult::Exact(mpi) = rev_lookup.find(&mir::Place::Local(local)) { debug!("stmt {:?} at loc {:?} clears the ever initialized status of {:?}", - stmt, location, &init_path_map[mpi]); - for ii in &init_path_map[mpi] { - assert!(ii.index() < bits_per_block); - sets.kill_set.add(&ii); - } + stmt, location, &init_path_map[mpi]); + sets.kill_all(&init_path_map[mpi]); } } _ => {} @@ -634,13 +607,11 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { let init_loc_map = &move_data.init_loc_map; debug!("terminator {:?} at loc {:?} initializes move_indexes {:?}", term, location, &init_loc_map[location]); - let bits_per_block = self.bits_per_block(); - for init_index in &init_loc_map[location] { - if move_data.inits[*init_index].kind != InitKind::NonPanicPathOnly { - assert!(init_index.index() < bits_per_block); - sets.gen_set.add(init_index); - } - } + sets.gen_all( + init_loc_map[location].iter().filter(|init_index| { + move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly + }) + ); } fn propagate_call_return(&self, @@ -663,11 +634,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for EverInitializedLvals<'a, 'gcx, 'tcx> { } } -fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) { - let retval = bitvec.set_bit(move_index.index()); - assert!(retval); -} - impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'gcx, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 6be006b1ea97..12722979706f 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -18,6 +18,7 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; use rustc::session::Session; +use std::borrow::Borrow; use std::fmt::{self, Debug}; use std::io; use std::mem; @@ -492,10 +493,39 @@ impl<'a, E:Idx> BlockSets<'a, E> { self.gen_set.add(e); self.kill_set.remove(e); } + fn gen_all(&mut self, i: I) + where I: IntoIterator, + I::Item: Borrow + { + for j in i { + self.gen(j.borrow()); + } + } + + fn gen_all_and_assert_dead(&mut self, i: I) + where I: IntoIterator, + I::Item: Borrow + { + for j in i { + let j = j.borrow(); + let retval = self.gen_set.add(j); + self.kill_set.remove(j); + assert!(retval); + } + } + fn kill(&mut self, e: &E) { self.gen_set.remove(e); self.kill_set.add(e); } + fn kill_all(&mut self, i: I) + where I: IntoIterator, + I::Item: Borrow + { + for j in i { + self.kill(j.borrow()); + } + } } impl AllSets { diff --git a/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs index c46bcbb32b9c..2bd6f75df1b1 100644 --- a/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs +++ b/src/test/compile-fail/borrowck/borrowck-move-moved-value-into-closure.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: ast mir +//[mir]compile-flags: -Z borrowck=mir + #![feature(box_syntax)] fn call_f isize>(f: F) -> isize { @@ -18,5 +21,6 @@ fn main() { let t: Box<_> = box 3; call_f(move|| { *t + 1 }); - call_f(move|| { *t + 1 }); //~ ERROR capture of moved value + call_f(move|| { *t + 1 }); //[ast]~ ERROR capture of moved value + //[mir]~^ ERROR use of moved value }