From 38c7d1ab7cf49370f4c261f705ee3cd19a12b10c Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Fri, 6 Jul 2018 20:57:01 +0530 Subject: [PATCH 01/16] add generic parameter --- src/librustc_mir/borrow_check/nll/mod.rs | 7 ++- .../borrow_check/nll/type_check/liveness.rs | 12 ++-- src/librustc_mir/transform/generator.rs | 52 +++++++-------- src/librustc_mir/util/liveness.rs | 63 ++++++++++--------- 4 files changed, 71 insertions(+), 63 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 5fcf46f690379..ba96e7c3b30be 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -22,6 +22,7 @@ use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; +use rustc_data_structures::indexed_vec::Idx; use std::collections::BTreeSet; use std::fmt::Debug; use std::env; @@ -207,9 +208,9 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( (regioncx, polonius_output, closure_region_requirements) } -fn dump_mir_results<'a, 'gcx, 'tcx>( +fn dump_mir_results<'a, 'gcx, 'tcx, V: Idx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, source: MirSource, mir: &Mir<'tcx>, regioncx: &RegionInferenceContext, @@ -405,7 +406,7 @@ impl ToRegionVid for RegionVid { } } -fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { +fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { // sort and deduplicate: let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index cd468eabd5f8b..7c0e7941a4413 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -20,6 +20,7 @@ use rustc::traits::query::type_op::outlives::DropckOutlives; use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; use util::liveness::LivenessResults; @@ -33,10 +34,10 @@ use super::TypeChecker; /// /// NB. This computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'gcx, 'tcx>( +pub(super) fn generate<'gcx, 'tcx, V: Idx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { @@ -54,16 +55,17 @@ pub(super) fn generate<'gcx, 'tcx>( } } -struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> +struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> where 'typeck: 'gen, 'flow: 'gen, 'tcx: 'typeck + 'flow, 'gcx: 'tcx, + V: Idx + 'gen, { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults, + liveness: &'gen LivenessResults, flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, @@ -74,7 +76,7 @@ struct DropData<'tcx> { region_constraint_data: Option>>>, } -impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> { +impl<'gen, 'typeck, 'flow, 'gcx, 'tcx, V: Idx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> { /// Liveness constraints: /// /// > If a variable V is live at point P, then all regions R in the type of V diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a6017fafcc8d4..0b8c7e512fbd8 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -126,14 +126,14 @@ fn self_arg() -> Local { Local::new(1) } -struct SuspensionPoint { +struct SuspensionPoint { state: u32, resume: BasicBlock, drop: Option, - storage_liveness: liveness::LocalSet, + storage_liveness: liveness::LocalSet, } -struct TransformVisitor<'a, 'tcx: 'a> { +struct TransformVisitor<'a, 'tcx: 'a, V: Idx> { tcx: TyCtxt<'a, 'tcx, 'tcx>, state_adt_ref: &'tcx AdtDef, state_substs: &'tcx Substs<'tcx>, @@ -145,16 +145,16 @@ struct TransformVisitor<'a, 'tcx: 'a> { remap: HashMap, usize)>, // A map from a suspension point in a block to the locals which have live storage at that point - storage_liveness: HashMap, + storage_liveness: HashMap>, // A list of suspension points, generated during the transform - suspension_points: Vec, + suspension_points: Vec>, // The original RETURN_PLACE local new_ret_local: Local, } -impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { +impl<'a, 'tcx, V: Idx> TransformVisitor<'a, 'tcx, V> { // Make a GeneratorState rvalue fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> { let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None); @@ -191,7 +191,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> { +impl<'a, 'tcx, V: Idx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx, V> { fn visit_local(&mut self, local: &mut Local, _: PlaceContext<'tcx>, @@ -317,9 +317,9 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>, new_ret_local } -struct StorageIgnored(liveness::LocalSet); +struct StorageIgnored(liveness::LocalSet); -impl<'tcx> Visitor<'tcx> for StorageIgnored { +impl<'tcx, V: Idx> Visitor<'tcx> for StorageIgnored { fn visit_statement(&mut self, _block: BasicBlock, statement: &Statement<'tcx>, @@ -332,9 +332,9 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored { } } -struct BorrowedLocals(liveness::LocalSet); +struct BorrowedLocals(liveness::LocalSet); -fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { +fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { Place::Local(l) => { locals.0.add(&l); }, Place::Static(..) => (), @@ -349,7 +349,7 @@ fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { } } -impl<'tcx> Visitor<'tcx> for BorrowedLocals { +impl<'tcx, V: Idx> Visitor<'tcx> for BorrowedLocals { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { @@ -361,12 +361,12 @@ impl<'tcx> Visitor<'tcx> for BorrowedLocals { } } -fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn locals_live_across_suspend_points<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, source: MirSource, movable: bool) -> - (liveness::LocalSet, - HashMap) { + (liveness::LocalSet, + HashMap>) { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); @@ -460,7 +460,7 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (set, storage_liveness_map) } -fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, upvars: Vec>, interior: Ty<'tcx>, @@ -468,7 +468,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) -> (HashMap, usize)>, GeneratorLayout<'tcx>, - HashMap) + HashMap>) { // Use a liveness analysis to compute locals which are live across a suspension point let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, @@ -524,10 +524,10 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (remap, layout, storage_liveness) } -fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn insert_switch<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>, cases: Vec<(u32, BasicBlock)>, - transform: &TransformVisitor<'a, 'tcx>, + transform: &TransformVisitor<'a, 'tcx, V>, default: TerminatorKind<'tcx>) { let default_block = insert_term_block(mir, default); @@ -608,9 +608,9 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn create_generator_drop_shim<'a, 'tcx>( +fn create_generator_drop_shim<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - transform: &TransformVisitor<'a, 'tcx>, + transform: &TransformVisitor<'a, 'tcx, V>, def_id: DefId, source: MirSource, gen_ty: Ty<'tcx>, @@ -719,9 +719,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert_block } -fn create_generator_resume_function<'a, 'tcx>( +fn create_generator_resume_function<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - transform: TransformVisitor<'a, 'tcx>, + transform: TransformVisitor<'a, 'tcx, V>, def_id: DefId, source: MirSource, mir: &mut Mir<'tcx>) { @@ -790,10 +790,10 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock { drop_clean } -fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>, - transform: &TransformVisitor<'a, 'tcx>, +fn create_cases<'a, 'tcx, F, V: Idx>(mir: &mut Mir<'tcx>, + transform: &TransformVisitor<'a, 'tcx, V>, target: F) -> Vec<(u32, BasicBlock)> - where F: Fn(&SuspensionPoint) -> Option { + where F: Fn(&SuspensionPoint) -> Option { let source_info = source_info(mir); transform.suspension_points.iter().filter_map(|point| { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index e1d5e302c3a06..5c1b92b672f31 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -47,18 +47,18 @@ use rustc::ty::TyCtxt; use std::io::{self, Write}; use transform::MirSource; -pub type LocalSet = IdxSetBuf; +pub type LocalSet = IdxSetBuf; /// This gives the result of the liveness analysis at the boundary of /// basic blocks. You can use `simulate_block` to obtain the /// intra-block results. -pub struct LivenessResult { +pub struct LivenessResult { /// Liveness mode in use when these results were computed. pub mode: LivenessMode, /// Live variables on exit to each basic block. This is equal to /// the union of the `ins` for each successor. - pub outs: IndexVec, + pub outs: IndexVec>, } #[derive(Copy, Clone, Debug)] @@ -80,18 +80,18 @@ pub struct LivenessMode { } /// A combination of liveness results, used in NLL. -pub struct LivenessResults { +pub struct LivenessResults { /// Liveness results where a regular use makes a variable X live, /// but not a drop. - pub regular: LivenessResult, + pub regular: LivenessResult, /// Liveness results where a drop makes a variable X live, /// but not a regular use. - pub drop: LivenessResult, + pub drop: LivenessResult, } -impl LivenessResults { - pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults { +impl LivenessResults { + pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults { LivenessResults { regular: liveness_of_locals( &mir, @@ -115,7 +115,7 @@ impl LivenessResults { /// Compute which local variables are live within the given function /// `mir`. The liveness mode `mode` determines what sorts of uses are /// considered to make a variable live (e.g., do drops count?). -pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { +pub fn liveness_of_locals<'tcx, V: Idx>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { let locals = mir.local_decls.len(); let def_use: IndexVec<_, _> = mir.basic_blocks() .iter() @@ -156,14 +156,16 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness LivenessResult { mode, outs } } -impl LivenessResult { +impl LivenessResult +where V:Idx +{ /// Walks backwards through the statements/terminator in the given /// basic block `block`. At each point within `block`, invokes /// the callback `op` with the current location and the set of /// variables that are live on entry to that location. pub fn simulate_block<'tcx, OP>(&self, mir: &Mir<'tcx>, block: BasicBlock, mut callback: OP) where - OP: FnMut(Location, &LocalSet), + OP: FnMut(Location, &LocalSet), { let data = &mir[block]; @@ -281,24 +283,25 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti } } -struct DefsUsesVisitor { +struct DefsUsesVisitor { mode: LivenessMode, - defs_uses: DefsUses, + defs_uses: DefsUses, } #[derive(Eq, PartialEq, Clone)] -struct DefsUses { - defs: LocalSet, - uses: LocalSet, +struct DefsUses +{ + defs: LocalSet, + uses: LocalSet, } -impl DefsUses { +impl DefsUses { fn clear(&mut self) { self.uses.clear(); self.defs.clear(); } - fn apply(&self, bits: &mut LocalSet) -> bool { + fn apply(&self, bits: &mut LocalSet) -> bool { bits.subtract(&self.defs) | bits.union(&self.uses) } @@ -332,15 +335,17 @@ impl DefsUses { } } -impl DefsUsesVisitor { +impl DefsUsesVisitor +where V: Idx +{ /// Update `bits` with the effects of `value` and call `callback`. We /// should always visit in reverse order. This method assumes that we have /// not visited anything before; if you have, clear `bits` first. fn update_bits_and_do_callback<'tcx, OP>(&mut self, location: Location, - value: &impl MirVisitable<'tcx>, bits: &mut LocalSet, + value: &impl MirVisitable<'tcx>, bits: &mut LocalSet, callback: &mut OP) where - OP: FnMut(Location, &LocalSet), + OP: FnMut(Location, &LocalSet), { value.apply(location, self); self.defs_uses.apply(bits); @@ -348,7 +353,7 @@ impl DefsUsesVisitor { } } -impl<'tcx> Visitor<'tcx> for DefsUsesVisitor { +impl<'tcx, V: Idx> Visitor<'tcx> for DefsUsesVisitor { fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) { match categorize(context, self.mode) { Some(DefUse::Def) => { @@ -364,7 +369,7 @@ impl<'tcx> Visitor<'tcx> for DefsUsesVisitor { } } -fn block<'tcx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses { +fn block<'tcx, V: Idx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses { let mut visitor = DefsUsesVisitor { mode, defs_uses: DefsUses { @@ -388,12 +393,12 @@ fn block<'tcx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> D visitor.defs_uses } -pub fn dump_mir<'a, 'tcx>( +pub fn dump_mir<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_name: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult, + result: &LivenessResult, ) { if !dump_enabled(tcx, pass_name, source) { return; @@ -405,13 +410,13 @@ pub fn dump_mir<'a, 'tcx>( dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result); } -fn dump_matched_mir_node<'a, 'tcx>( +fn dump_matched_mir_node<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_name: &str, node_path: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult, + result: &LivenessResult, ) { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir)); @@ -428,12 +433,12 @@ fn dump_matched_mir_node<'a, 'tcx>( }); } -pub fn write_mir_fn<'a, 'tcx>( +pub fn write_mir_fn<'a, 'tcx, V :Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &Mir<'tcx>, w: &mut dyn Write, - result: &LivenessResult, + result: &LivenessResult, ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { From f2b5583f6084c68cf1f46a1554db7ee3f0252ec1 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Sun, 8 Jul 2018 02:14:57 +0530 Subject: [PATCH 02/16] add trait structs and other changes from V to local --- src/librustc_mir/borrow_check/nll/mod.rs | 8 +-- .../borrow_check/nll/type_check/liveness.rs | 11 ++- src/librustc_mir/transform/generator.rs | 52 +++++++------- src/librustc_mir/util/liveness.rs | 69 +++++++++++++------ 4 files changed, 84 insertions(+), 56 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index ba96e7c3b30be..72d7b473204f8 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -19,7 +19,7 @@ use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, Local}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -208,9 +208,9 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( (regioncx, polonius_output, closure_region_requirements) } -fn dump_mir_results<'a, 'gcx, 'tcx, V: Idx>( +fn dump_mir_results<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, source: MirSource, mir: &Mir<'tcx>, regioncx: &RegionInferenceContext, @@ -406,7 +406,7 @@ impl ToRegionVid for RegionVid { } } -fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { +fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { // sort and deduplicate: let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 7c0e7941a4413..e70c87e8401c9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -34,10 +34,10 @@ use super::TypeChecker; /// /// NB. This computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'gcx, 'tcx, V: Idx>( +pub(super) fn generate<'gcx, 'tcx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { @@ -55,17 +55,16 @@ pub(super) fn generate<'gcx, 'tcx, V: Idx>( } } -struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> +struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> where 'typeck: 'gen, 'flow: 'gen, 'tcx: 'typeck + 'flow, 'gcx: 'tcx, - V: Idx + 'gen, { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults, + liveness: &'gen LivenessResults, flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, @@ -76,7 +75,7 @@ struct DropData<'tcx> { region_constraint_data: Option>>>, } -impl<'gen, 'typeck, 'flow, 'gcx, 'tcx, V: Idx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> { +impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> { /// Liveness constraints: /// /// > If a variable V is live at point P, then all regions R in the type of V diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0b8c7e512fbd8..f1091e40c77a5 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -126,14 +126,14 @@ fn self_arg() -> Local { Local::new(1) } -struct SuspensionPoint { +struct SuspensionPoint { state: u32, resume: BasicBlock, drop: Option, - storage_liveness: liveness::LocalSet, + storage_liveness: liveness::LocalSet, } -struct TransformVisitor<'a, 'tcx: 'a, V: Idx> { +struct TransformVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, state_adt_ref: &'tcx AdtDef, state_substs: &'tcx Substs<'tcx>, @@ -145,16 +145,16 @@ struct TransformVisitor<'a, 'tcx: 'a, V: Idx> { remap: HashMap, usize)>, // A map from a suspension point in a block to the locals which have live storage at that point - storage_liveness: HashMap>, + storage_liveness: HashMap>, // A list of suspension points, generated during the transform - suspension_points: Vec>, + suspension_points: Vec, // The original RETURN_PLACE local new_ret_local: Local, } -impl<'a, 'tcx, V: Idx> TransformVisitor<'a, 'tcx, V> { +impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { // Make a GeneratorState rvalue fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> { let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None); @@ -191,7 +191,7 @@ impl<'a, 'tcx, V: Idx> TransformVisitor<'a, 'tcx, V> { } } -impl<'a, 'tcx, V: Idx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx, V> { +impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> { fn visit_local(&mut self, local: &mut Local, _: PlaceContext<'tcx>, @@ -317,9 +317,9 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>, new_ret_local } -struct StorageIgnored(liveness::LocalSet); +struct StorageIgnored(liveness::LocalSet); -impl<'tcx, V: Idx> Visitor<'tcx> for StorageIgnored { +impl<'tcx> Visitor<'tcx> for StorageIgnored { fn visit_statement(&mut self, _block: BasicBlock, statement: &Statement<'tcx>, @@ -332,9 +332,9 @@ impl<'tcx, V: Idx> Visitor<'tcx> for StorageIgnored { } } -struct BorrowedLocals(liveness::LocalSet); +struct BorrowedLocals(liveness::LocalSet); -fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { +fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { Place::Local(l) => { locals.0.add(&l); }, Place::Static(..) => (), @@ -349,7 +349,7 @@ fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLoca } } -impl<'tcx, V: Idx> Visitor<'tcx> for BorrowedLocals { +impl<'tcx> Visitor<'tcx> for BorrowedLocals { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { @@ -361,12 +361,12 @@ impl<'tcx, V: Idx> Visitor<'tcx> for BorrowedLocals { } } -fn locals_live_across_suspend_points<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, source: MirSource, movable: bool) -> - (liveness::LocalSet, - HashMap>) { + (liveness::LocalSet, + HashMap>) { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); @@ -460,7 +460,7 @@ fn locals_live_across_suspend_points<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tc (set, storage_liveness_map) } -fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, source: MirSource, upvars: Vec>, interior: Ty<'tcx>, @@ -468,7 +468,7 @@ fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) -> (HashMap, usize)>, GeneratorLayout<'tcx>, - HashMap>) + HashMap>) { // Use a liveness analysis to compute locals which are live across a suspension point let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, @@ -524,10 +524,10 @@ fn compute_layout<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (remap, layout, storage_liveness) } -fn insert_switch<'a, 'tcx, V: Idx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, +fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>, cases: Vec<(u32, BasicBlock)>, - transform: &TransformVisitor<'a, 'tcx, V>, + transform: &TransformVisitor<'a, 'tcx>, default: TerminatorKind<'tcx>) { let default_block = insert_term_block(mir, default); @@ -608,9 +608,9 @@ fn elaborate_generator_drops<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } -fn create_generator_drop_shim<'a, 'tcx, V: Idx>( +fn create_generator_drop_shim<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - transform: &TransformVisitor<'a, 'tcx, V>, + transform: &TransformVisitor<'a, 'tcx>, def_id: DefId, source: MirSource, gen_ty: Ty<'tcx>, @@ -719,9 +719,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, assert_block } -fn create_generator_resume_function<'a, 'tcx, V: Idx>( +fn create_generator_resume_function<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - transform: TransformVisitor<'a, 'tcx, V>, + transform: TransformVisitor<'a, 'tcx>, def_id: DefId, source: MirSource, mir: &mut Mir<'tcx>) { @@ -790,10 +790,10 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock { drop_clean } -fn create_cases<'a, 'tcx, F, V: Idx>(mir: &mut Mir<'tcx>, - transform: &TransformVisitor<'a, 'tcx, V>, +fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>, + transform: &TransformVisitor<'a, 'tcx>, target: F) -> Vec<(u32, BasicBlock)> - where F: Fn(&SuspensionPoint) -> Option { + where F: Fn(&SuspensionPoint) -> Option { let source_info = source_info(mir); transform.suspension_points.iter().filter_map(|point| { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 5c1b92b672f31..811e0e5590937 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -40,6 +40,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::work_queue::WorkQueue; use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; use rustc::ty::item_path; +use rustc::mir::Local; use rustc::mir::visit::MirVisitable; use std::path::{Path, PathBuf}; use std::fs; @@ -61,6 +62,28 @@ pub struct LivenessResult { pub outs: IndexVec>, } +trait LiveVariableMap { + type LiveVar; + + fn from_local(&self, local: Local) -> Option; + fn from_live_var(&self, local: Self::LiveVar) -> Local; +} + +#[derive(Eq, PartialEq, Clone)] +struct IdentityMap; + +impl LiveVariableMap for IdentityMap { + type LiveVar = Local; + + fn from_local(&self, local: Local) -> Option { + Some(local) + } + + fn from_live_var(&self, local: Self::LiveVar) -> Local { + local + } +} + #[derive(Copy, Clone, Debug)] pub struct LivenessMode { /// If true, then we will consider "regular uses" of a variable to be live. @@ -91,7 +114,7 @@ pub struct LivenessResults { } impl LivenessResults { - pub fn compute<'tcx>(mir: &Mir<'tcx>) -> LivenessResults { + pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap) -> LivenessResults { LivenessResults { regular: liveness_of_locals( &mir, @@ -187,6 +210,7 @@ where V:Idx defs_uses: DefsUses { defs: LocalSet::new_empty(locals), uses: LocalSet::new_empty(locals), + map: &IdentityMap {}, }, }; // Visit the various parts of the basic block in reverse. If we go @@ -283,25 +307,26 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti } } -struct DefsUsesVisitor { +struct DefsUsesVisitor<'lv> { mode: LivenessMode, - defs_uses: DefsUses, + defs_uses: DefsUses<'lv>, } #[derive(Eq, PartialEq, Clone)] -struct DefsUses +struct DefsUses<'lv> { - defs: LocalSet, - uses: LocalSet, + defs: LocalSet, + uses: LocalSet, + map: &'lv dyn LiveVariableMap, } -impl DefsUses { +impl<'lv> DefsUses<'lv> { fn clear(&mut self) { self.uses.clear(); self.defs.clear(); } - fn apply(&self, bits: &mut LocalSet) -> bool { + fn apply(&self, bits: &mut LocalSet) -> bool { bits.subtract(&self.defs) | bits.union(&self.uses) } @@ -315,8 +340,10 @@ impl DefsUses { // X = 5 // // Defs = {}, Uses = {X} // use(X) - self.uses.remove(&index); - self.defs.add(&index); + if let Some(v_index) = self.map.from_local(index) { + self.uses.remove(&v_index); + self.defs.add(&v_index); + } } fn add_use(&mut self, index: Local) { @@ -330,22 +357,23 @@ impl DefsUses { // X = 5 // // Defs = {}, Uses = {X} // use(X) - self.defs.remove(&index); - self.uses.add(&index); + if let Some(v_index) = self.map.from_local(index) { + self.defs.remove(&v_index); + self.uses.add(&v_index); + } } } -impl DefsUsesVisitor -where V: Idx +impl<'lv> DefsUsesVisitor<'lv> { /// Update `bits` with the effects of `value` and call `callback`. We /// should always visit in reverse order. This method assumes that we have /// not visited anything before; if you have, clear `bits` first. fn update_bits_and_do_callback<'tcx, OP>(&mut self, location: Location, - value: &impl MirVisitable<'tcx>, bits: &mut LocalSet, + value: &impl MirVisitable<'tcx>, bits: &mut LocalSet, callback: &mut OP) where - OP: FnMut(Location, &LocalSet), + OP: FnMut(Location, &LocalSet), { value.apply(location, self); self.defs_uses.apply(bits); @@ -353,7 +381,7 @@ where V: Idx } } -impl<'tcx, V: Idx> Visitor<'tcx> for DefsUsesVisitor { +impl<'tcx, 'lv> Visitor<'tcx> for DefsUsesVisitor<'lv> { fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) { match categorize(context, self.mode) { Some(DefUse::Def) => { @@ -369,12 +397,13 @@ impl<'tcx, V: Idx> Visitor<'tcx> for DefsUsesVisitor { } } -fn block<'tcx, V: Idx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses { +fn block<'tcx, 'lv>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses<'lv> { let mut visitor = DefsUsesVisitor { mode, defs_uses: DefsUses { defs: LocalSet::new_empty(locals), uses: LocalSet::new_empty(locals), + map: &IdentityMap {}, }, }; @@ -398,7 +427,7 @@ pub fn dump_mir<'a, 'tcx, V: Idx>( pass_name: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult, + result: &LivenessResult, ) { if !dump_enabled(tcx, pass_name, source) { return; @@ -442,7 +471,7 @@ pub fn write_mir_fn<'a, 'tcx, V :Idx>( ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - let print = |w: &mut dyn Write, prefix, result: &IndexVec| { + let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { let live: Vec = mir.local_decls .indices() .filter(|i| result[block].contains(i)) From d25231f84ad3d95d70d86a71739f309f299ec1e3 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Sun, 8 Jul 2018 19:14:36 +0530 Subject: [PATCH 03/16] use LiveVariableMap as trait bound --- .../borrow_check/nll/type_check/liveness.rs | 15 ++++---- src/librustc_mir/util/liveness.rs | 36 +++++++++---------- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index e70c87e8401c9..972e92de77e52 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -22,7 +22,7 @@ use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; -use util::liveness::LivenessResults; +use util::liveness::{LivenessResults, LiveVariableMap}; use super::TypeChecker; @@ -34,10 +34,10 @@ use super::TypeChecker; /// /// NB. This computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'gcx, 'tcx>( +pub(super) fn generate<'gcx, 'tcx, V: LiveVariableMap>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { @@ -55,16 +55,17 @@ pub(super) fn generate<'gcx, 'tcx>( } } -struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> +struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V: LiveVariableMap> where 'typeck: 'gen, 'flow: 'gen, 'tcx: 'typeck + 'flow, 'gcx: 'tcx, + V: 'gen, { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults, + liveness: &'gen LivenessResults, flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, @@ -75,7 +76,7 @@ struct DropData<'tcx> { region_constraint_data: Option>>>, } -impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> { +impl<'gen, 'typeck, 'flow, 'gcx, 'tcx, V:LiveVariableMap> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> { /// Liveness constraints: /// /// > If a variable V is live at point P, then all regions R in the type of V @@ -92,7 +93,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo } }); - let mut all_live_locals: Vec<(Location, Vec)> = vec![]; + let mut all_live_locals: Vec<(Location, Vec)> = vec![]; self.liveness .drop .simulate_block(self.mir, bb, |location, live_locals| { diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 811e0e5590937..5bd81f332e6b2 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -48,21 +48,21 @@ use rustc::ty::TyCtxt; use std::io::{self, Write}; use transform::MirSource; -pub type LocalSet = IdxSetBuf; +pub type LocalSet = IdxSetBuf; /// This gives the result of the liveness analysis at the boundary of /// basic blocks. You can use `simulate_block` to obtain the /// intra-block results. -pub struct LivenessResult { +pub struct LivenessResult { /// Liveness mode in use when these results were computed. pub mode: LivenessMode, /// Live variables on exit to each basic block. This is equal to /// the union of the `ins` for each successor. - pub outs: IndexVec>, + pub outs: IndexVec>, } -trait LiveVariableMap { +pub(crate) trait LiveVariableMap { type LiveVar; fn from_local(&self, local: Local) -> Option; @@ -103,18 +103,18 @@ pub struct LivenessMode { } /// A combination of liveness results, used in NLL. -pub struct LivenessResults { +pub struct LivenessResults { /// Liveness results where a regular use makes a variable X live, /// but not a drop. - pub regular: LivenessResult, + pub regular: LivenessResult, /// Liveness results where a drop makes a variable X live, /// but not a regular use. - pub drop: LivenessResult, + pub drop: LivenessResult, } -impl LivenessResults { - pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap) -> LivenessResults { +impl LivenessResults { + pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap) -> LivenessResults { LivenessResults { regular: liveness_of_locals( &mir, @@ -138,7 +138,7 @@ impl LivenessResults { /// Compute which local variables are live within the given function /// `mir`. The liveness mode `mode` determines what sorts of uses are /// considered to make a variable live (e.g., do drops count?). -pub fn liveness_of_locals<'tcx, V: Idx>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { +pub fn liveness_of_locals<'tcx, V: LiveVariableMap>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { let locals = mir.local_decls.len(); let def_use: IndexVec<_, _> = mir.basic_blocks() .iter() @@ -179,8 +179,7 @@ pub fn liveness_of_locals<'tcx, V: Idx>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { mode, outs } } -impl LivenessResult -where V:Idx +impl LivenessResult { /// Walks backwards through the statements/terminator in the given /// basic block `block`. At each point within `block`, invokes @@ -422,12 +421,13 @@ fn block<'tcx, 'lv>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) visitor.defs_uses } -pub fn dump_mir<'a, 'tcx, V: Idx>( +pub fn dump_mir<'a, 'tcx, V: LiveVariableMap>( tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_name: &str, source: MirSource, mir: &Mir<'tcx>, result: &LivenessResult, + map: &impl LiveVariableMap ) { if !dump_enabled(tcx, pass_name, source) { return; @@ -439,13 +439,13 @@ pub fn dump_mir<'a, 'tcx, V: Idx>( dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result); } -fn dump_matched_mir_node<'a, 'tcx, V: Idx>( +fn dump_matched_mir_node<'a, 'tcx, V: LiveVariableMap>( tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_name: &str, node_path: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult, + result: &LivenessResult, ) { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir)); @@ -462,16 +462,16 @@ fn dump_matched_mir_node<'a, 'tcx, V: Idx>( }); } -pub fn write_mir_fn<'a, 'tcx, V :Idx>( +pub fn write_mir_fn<'a, 'tcx, V: LiveVariableMap>( tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &Mir<'tcx>, w: &mut dyn Write, - result: &LivenessResult, + result: &LivenessResult, ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { + let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { let live: Vec = mir.local_decls .indices() .filter(|i| result[block].contains(i)) From 4b5f0ba8c260d7c2e40c152bee11e8f329867c80 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Fri, 13 Jul 2018 16:40:24 +0530 Subject: [PATCH 04/16] generic shuffle continues --- .../borrow_check/nll/type_check/liveness.rs | 8 ++++---- src/librustc_mir/util/liveness.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 972e92de77e52..97f3b1a1c966c 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -34,10 +34,10 @@ use super::TypeChecker; /// /// NB. This computation requires normalization; therefore, it must be /// performed before -pub(super) fn generate<'gcx, 'tcx, V: LiveVariableMap>( +pub(super) fn generate<'gcx, 'tcx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { @@ -55,7 +55,7 @@ pub(super) fn generate<'gcx, 'tcx, V: LiveVariableMap>( } } -struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V: LiveVariableMap> +struct TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> where 'typeck: 'gen, 'flow: 'gen, @@ -65,7 +65,7 @@ where { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults, + liveness: &'gen LivenessResults, flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 5bd81f332e6b2..4e78be76b6137 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -103,18 +103,18 @@ pub struct LivenessMode { } /// A combination of liveness results, used in NLL. -pub struct LivenessResults { +pub struct LivenessResults { /// Liveness results where a regular use makes a variable X live, /// but not a drop. - pub regular: LivenessResult, + pub regular: LivenessResult, /// Liveness results where a drop makes a variable X live, /// but not a regular use. - pub drop: LivenessResult, + pub drop: LivenessResult, } -impl LivenessResults { - pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &dyn LiveVariableMap) -> LivenessResults { +impl> LivenessResults { + pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &M) -> LivenessResults { LivenessResults { regular: liveness_of_locals( &mir, @@ -138,7 +138,7 @@ impl LivenessResults { /// Compute which local variables are live within the given function /// `mir`. The liveness mode `mode` determines what sorts of uses are /// considered to make a variable live (e.g., do drops count?). -pub fn liveness_of_locals<'tcx, V: LiveVariableMap>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { +pub fn liveness_of_locals<'tcx, V>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { let locals = mir.local_decls.len(); let def_use: IndexVec<_, _> = mir.basic_blocks() .iter() From 43b69c27771929e6dfa7bf1771bc8ee5ce7a99c5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 15 Jul 2018 00:28:26 -0400 Subject: [PATCH 05/16] make liveness generic over set of local variables We used to hardcode that we wanted the liveness of *all* variables. This can now be configured by selecting an alternative index type V and providing a (partial) map from locals to that new type V. --- src/librustc_mir/borrow_check/nll/mod.rs | 11 +- .../borrow_check/nll/type_check/liveness.rs | 14 +- src/librustc_mir/transform/generator.rs | 25 +- src/librustc_mir/util/liveness.rs | 222 +++++++++++------- 4 files changed, 170 insertions(+), 102 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 72d7b473204f8..15ebb7a7a29f1 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -22,7 +22,6 @@ use rustc::infer::InferCtxt; use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, Local}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::indexed_vec::Idx; use std::collections::BTreeSet; use std::fmt::Debug; use std::env; @@ -31,7 +30,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; use transform::MirSource; -use util::liveness::{LivenessResults, LocalSet}; +use util::liveness::{IdentityMap, LivenessResults, LocalSet}; use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; @@ -104,7 +103,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len())); // Run the MIR type-checker. - let liveness = &LivenessResults::compute(mir); + let liveness = &LivenessResults::compute(mir, &IdentityMap::new(mir)); let constraint_sets = type_check::type_check( infcx, param_env, @@ -220,6 +219,8 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( return; } + let map = &IdentityMap::new(mir); + let regular_liveness_per_location: FxHashMap<_, _> = mir .basic_blocks() .indices() @@ -227,7 +228,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( let mut results = vec![]; liveness .regular - .simulate_block(&mir, bb, |location, local_set| { + .simulate_block(&mir, bb, map, |location, local_set| { results.push((location, local_set.clone())); }); results @@ -241,7 +242,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( let mut results = vec![]; liveness .drop - .simulate_block(&mir, bb, |location, local_set| { + .simulate_block(&mir, bb, map, |location, local_set| { results.push((location, local_set.clone())); }); results diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 97f3b1a1c966c..0eb88b7bcbfd3 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -20,9 +20,8 @@ use rustc::traits::query::type_op::outlives::DropckOutlives; use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; -use util::liveness::{LivenessResults, LiveVariableMap}; +use util::liveness::{IdentityMap, LivenessResults}; use super::TypeChecker; @@ -48,6 +47,7 @@ pub(super) fn generate<'gcx, 'tcx>( flow_inits, move_data, drop_data: FxHashMap(), + map: &IdentityMap::new(mir), }; for bb in mir.basic_blocks().indices() { @@ -61,7 +61,6 @@ where 'flow: 'gen, 'tcx: 'typeck + 'flow, 'gcx: 'tcx, - V: 'gen, { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, @@ -69,6 +68,7 @@ where flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, + map: &'gen IdentityMap<'gen, 'tcx>, } struct DropData<'tcx> { @@ -76,7 +76,7 @@ struct DropData<'tcx> { region_constraint_data: Option>>>, } -impl<'gen, 'typeck, 'flow, 'gcx, 'tcx, V:LiveVariableMap> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx, V> { +impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> { /// Liveness constraints: /// /// > If a variable V is live at point P, then all regions R in the type of V @@ -86,17 +86,17 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx, V:LiveVariableMap> TypeLivenessGenerator< self.liveness .regular - .simulate_block(self.mir, bb, |location, live_locals| { + .simulate_block(self.mir, bb, self.map, |location, live_locals| { for live_local in live_locals.iter() { let live_local_ty = self.mir.local_decls[live_local].ty; Self::push_type_live_constraint(&mut self.cx, live_local_ty, location); } }); - let mut all_live_locals: Vec<(Location, Vec)> = vec![]; + let mut all_live_locals: Vec<(Location, Vec)> = vec![]; self.liveness .drop - .simulate_block(self.mir, bb, |location, live_locals| { + .simulate_block(self.mir, bb, self.map, |location, live_locals| { all_live_locals.push((location, live_locals.iter().collect())); }); debug!( diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index f1091e40c77a5..7d4d561072e7a 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -66,7 +66,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor}; use rustc::ty::{self, TyCtxt, AdtDef, Ty}; use rustc::ty::subst::Substs; use util::dump_mir; -use util::liveness::{self, LivenessMode}; +use util::liveness::{self, IdentityMap, LivenessMode}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_set::IdxSetBuf; use std::collections::HashMap; @@ -334,7 +334,7 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored { struct BorrowedLocals(liveness::LocalSet); -fn mark_as_borrowed<'tcx, V: Idx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { +fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { Place::Local(l) => { locals.0.add(&l); }, Place::Static(..) => (), @@ -397,11 +397,22 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Calculate the liveness of MIR locals ignoring borrows. let mut set = liveness::LocalSet::new_empty(mir.local_decls.len()); - let mut liveness = liveness::liveness_of_locals(mir, LivenessMode { - include_regular_use: true, - include_drops: true, - }); - liveness::dump_mir(tcx, "generator_liveness", source, mir, &liveness); + let mut liveness = liveness::liveness_of_locals( + mir, + LivenessMode { + include_regular_use: true, + include_drops: true, + }, + &IdentityMap::new(mir), + ); + liveness::dump_mir( + tcx, + "generator_liveness", + source, + mir, + &IdentityMap::new(mir), + &liveness, + ); let mut storage_liveness_map = HashMap::new(); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 4e78be76b6137..ea8a180e3b618 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -33,46 +33,63 @@ //! generator yield points, all pre-existing references are invalidated, so this //! doesn't matter). -use rustc::mir::*; +use rustc::mir::visit::MirVisitable; use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc::mir::Local; +use rustc::mir::*; +use rustc::ty::item_path; +use rustc::ty::TyCtxt; use rustc_data_structures::indexed_set::IdxSetBuf; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; -use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; -use rustc::ty::item_path; -use rustc::mir::Local; -use rustc::mir::visit::MirVisitable; -use std::path::{Path, PathBuf}; use std::fs; -use rustc::ty::TyCtxt; use std::io::{self, Write}; +use std::path::{Path, PathBuf}; use transform::MirSource; +use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; -pub type LocalSet = IdxSetBuf; +pub type LocalSet = IdxSetBuf; /// This gives the result of the liveness analysis at the boundary of /// basic blocks. You can use `simulate_block` to obtain the /// intra-block results. -pub struct LivenessResult { +/// +/// The `V` type defines the set of variables that we computed +/// liveness for. This is often `Local`, in which case we computed +/// liveness for all variables -- but it can also be some other type, +/// which indicates a subset of the variables within the graph. +pub struct LivenessResult { /// Liveness mode in use when these results were computed. pub mode: LivenessMode, /// Live variables on exit to each basic block. This is equal to /// the union of the `ins` for each successor. - pub outs: IndexVec>, + pub outs: IndexVec>, } -pub(crate) trait LiveVariableMap { +/// Defines the mapping to/from the MIR local variables (`Local`) to +/// the "live variable indices" we are using in a particular +/// computation. +pub trait LiveVariableMap { type LiveVar; fn from_local(&self, local: Local) -> Option; fn from_live_var(&self, local: Self::LiveVar) -> Local; + fn num_variables(&self) -> usize; } -#[derive(Eq, PartialEq, Clone)] -struct IdentityMap; +#[derive(Debug)] +pub struct IdentityMap<'a, 'tcx: 'a> { + mir: &'a Mir<'tcx>, +} -impl LiveVariableMap for IdentityMap { +impl<'a, 'tcx> IdentityMap<'a, 'tcx> { + pub fn new(mir: &'a Mir<'tcx>) -> Self { + Self { mir } + } +} + +impl<'a, 'tcx> LiveVariableMap for IdentityMap<'a, 'tcx> { type LiveVar = Local; fn from_local(&self, local: Local) -> Option { @@ -82,6 +99,10 @@ impl LiveVariableMap for IdentityMap { fn from_live_var(&self, local: Self::LiveVar) -> Local { local } + + fn num_variables(&self) -> usize { + self.mir.local_decls.len() + } } #[derive(Copy, Clone, Debug)] @@ -103,7 +124,7 @@ pub struct LivenessMode { } /// A combination of liveness results, used in NLL. -pub struct LivenessResults { +pub struct LivenessResults { /// Liveness results where a regular use makes a variable X live, /// but not a drop. pub regular: LivenessResult, @@ -113,8 +134,11 @@ pub struct LivenessResults { pub drop: LivenessResult, } -impl> LivenessResults { - pub fn compute<'tcx>(mir: &Mir<'tcx>, map: &M) -> LivenessResults { +impl LivenessResults { + pub fn compute<'tcx>( + mir: &Mir<'tcx>, + map: &impl LiveVariableMap, + ) -> LivenessResults { LivenessResults { regular: liveness_of_locals( &mir, @@ -122,6 +146,7 @@ impl> LivenessResults { include_regular_use: true, include_drops: false, }, + map, ), drop: liveness_of_locals( @@ -130,6 +155,7 @@ impl> LivenessResults { include_regular_use: false, include_drops: true, }, + map, ), } } @@ -138,14 +164,21 @@ impl> LivenessResults { /// Compute which local variables are live within the given function /// `mir`. The liveness mode `mode` determines what sorts of uses are /// considered to make a variable live (e.g., do drops count?). -pub fn liveness_of_locals<'tcx, V>(mir: &Mir<'tcx>, mode: LivenessMode) -> LivenessResult { - let locals = mir.local_decls.len(); - let def_use: IndexVec<_, _> = mir.basic_blocks() +pub fn liveness_of_locals<'tcx, V: Idx>( + mir: &Mir<'tcx>, + mode: LivenessMode, + map: &impl LiveVariableMap, +) -> LivenessResult { + let locals = map.num_variables(); + + let def_use: IndexVec<_, DefsUses> = mir + .basic_blocks() .iter() - .map(|b| block(mode, b, locals)) + .map(|b| block(mode, map, b, locals)) .collect(); - let mut outs: IndexVec<_, _> = mir.basic_blocks() + let mut outs: IndexVec<_, LocalSet> = mir + .basic_blocks() .indices() .map(|_| LocalSet::new_empty(locals)) .collect(); @@ -179,14 +212,18 @@ pub fn liveness_of_locals<'tcx, V>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liven LivenessResult { mode, outs } } -impl LivenessResult -{ +impl LivenessResult { /// Walks backwards through the statements/terminator in the given /// basic block `block`. At each point within `block`, invokes /// the callback `op` with the current location and the set of /// variables that are live on entry to that location. - pub fn simulate_block<'tcx, OP>(&self, mir: &Mir<'tcx>, block: BasicBlock, mut callback: OP) - where + pub fn simulate_block<'tcx, OP>( + &self, + mir: &Mir<'tcx>, + block: BasicBlock, + map: &impl LiveVariableMap, + mut callback: OP, + ) where OP: FnMut(Location, &LocalSet), { let data = &mir[block]; @@ -206,16 +243,20 @@ impl LivenessResult let locals = mir.local_decls.len(); let mut visitor = DefsUsesVisitor { mode: self.mode, + map, defs_uses: DefsUses { defs: LocalSet::new_empty(locals), uses: LocalSet::new_empty(locals), - map: &IdentityMap {}, }, }; // Visit the various parts of the basic block in reverse. If we go // forward, the logic in `add_def` and `add_use` would be wrong. - visitor.update_bits_and_do_callback(terminator_location, &data.terminator, &mut bits, - &mut callback); + visitor.update_bits_and_do_callback( + terminator_location, + &data.terminator, + &mut bits, + &mut callback, + ); // Compute liveness before each statement (in rev order) and invoke callback. for statement in data.statements.iter().rev() { @@ -225,8 +266,12 @@ impl LivenessResult statement_index, }; visitor.defs_uses.clear(); - visitor.update_bits_and_do_callback(statement_location, statement, &mut bits, - &mut callback); + visitor.update_bits_and_do_callback( + statement_location, + statement, + &mut bits, + &mut callback, + ); } } } @@ -306,30 +351,33 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti } } -struct DefsUsesVisitor<'lv> { +struct DefsUsesVisitor<'lv, V, M> +where + V: Idx, + M: LiveVariableMap + 'lv, +{ mode: LivenessMode, - defs_uses: DefsUses<'lv>, + map: &'lv M, + defs_uses: DefsUses, } #[derive(Eq, PartialEq, Clone)] -struct DefsUses<'lv> -{ - defs: LocalSet, - uses: LocalSet, - map: &'lv dyn LiveVariableMap, +struct DefsUses { + defs: LocalSet, + uses: LocalSet, } -impl<'lv> DefsUses<'lv> { +impl DefsUses { fn clear(&mut self) { self.uses.clear(); self.defs.clear(); } - fn apply(&self, bits: &mut LocalSet) -> bool { + fn apply(&self, bits: &mut LocalSet) -> bool { bits.subtract(&self.defs) | bits.union(&self.uses) } - fn add_def(&mut self, index: Local) { + fn add_def(&mut self, index: V) { // If it was used already in the block, remove that use // now that we found a definition. // @@ -339,13 +387,11 @@ impl<'lv> DefsUses<'lv> { // X = 5 // // Defs = {}, Uses = {X} // use(X) - if let Some(v_index) = self.map.from_local(index) { - self.uses.remove(&v_index); - self.defs.add(&v_index); - } + self.uses.remove(&index); + self.defs.add(&index); } - fn add_use(&mut self, index: Local) { + fn add_use(&mut self, index: V) { // Inverse of above. // // Example: @@ -356,23 +402,27 @@ impl<'lv> DefsUses<'lv> { // X = 5 // // Defs = {}, Uses = {X} // use(X) - if let Some(v_index) = self.map.from_local(index) { - self.defs.remove(&v_index); - self.uses.add(&v_index); - } + self.defs.remove(&index); + self.uses.add(&index); } } -impl<'lv> DefsUsesVisitor<'lv> +impl<'lv, V, M> DefsUsesVisitor<'lv, V, M> +where + V: Idx, + M: LiveVariableMap, { /// Update `bits` with the effects of `value` and call `callback`. We /// should always visit in reverse order. This method assumes that we have /// not visited anything before; if you have, clear `bits` first. - fn update_bits_and_do_callback<'tcx, OP>(&mut self, location: Location, - value: &impl MirVisitable<'tcx>, bits: &mut LocalSet, - callback: &mut OP) - where - OP: FnMut(Location, &LocalSet), + fn update_bits_and_do_callback<'tcx, OP>( + &mut self, + location: Location, + value: &impl MirVisitable<'tcx>, + bits: &mut LocalSet, + callback: &mut OP, + ) where + OP: FnMut(Location, &LocalSet), { value.apply(location, self); self.defs_uses.apply(bits); @@ -380,29 +430,34 @@ impl<'lv> DefsUsesVisitor<'lv> } } -impl<'tcx, 'lv> Visitor<'tcx> for DefsUsesVisitor<'lv> { +impl<'tcx, 'lv, V, M> Visitor<'tcx> for DefsUsesVisitor<'lv, V, M> +where + V: Idx, + M: LiveVariableMap, +{ fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) { - match categorize(context, self.mode) { - Some(DefUse::Def) => { - self.defs_uses.add_def(local); + if let Some(v_index) = self.map.from_local(local) { + match categorize(context, self.mode) { + Some(DefUse::Def) => self.defs_uses.add_def(v_index), + Some(DefUse::Use) => self.defs_uses.add_use(v_index), + None => (), } - - Some(DefUse::Use) => { - self.defs_uses.add_use(local); - } - - None => {} } } } -fn block<'tcx, 'lv>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses<'lv> { +fn block<'tcx, V: Idx>( + mode: LivenessMode, + map: &impl LiveVariableMap, + b: &BasicBlockData<'tcx>, + locals: usize, +) -> DefsUses { let mut visitor = DefsUsesVisitor { mode, + map, defs_uses: DefsUses { defs: LocalSet::new_empty(locals), uses: LocalSet::new_empty(locals), - map: &IdentityMap {}, }, }; @@ -421,13 +476,13 @@ fn block<'tcx, 'lv>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) visitor.defs_uses } -pub fn dump_mir<'a, 'tcx, V: LiveVariableMap>( +pub fn dump_mir<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_name: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult, - map: &impl LiveVariableMap + map: &impl LiveVariableMap, + result: &LivenessResult, ) { if !dump_enabled(tcx, pass_name, source) { return; @@ -436,16 +491,17 @@ pub fn dump_mir<'a, 'tcx, V: LiveVariableMap>( // see notes on #41697 below tcx.item_path_str(source.def_id) }); - dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, result); + dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, map, result); } -fn dump_matched_mir_node<'a, 'tcx, V: LiveVariableMap>( +fn dump_matched_mir_node<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, pass_name: &str, node_path: &str, source: MirSource, mir: &Mir<'tcx>, - result: &LivenessResult, + map: &dyn LiveVariableMap, + result: &LivenessResult, ) { let mut file_path = PathBuf::new(); file_path.push(Path::new(&tcx.sess.opts.debugging_opts.dump_mir_dir)); @@ -457,25 +513,25 @@ fn dump_matched_mir_node<'a, 'tcx, V: LiveVariableMap>( writeln!(file, "// source = {:?}", source)?; writeln!(file, "// pass_name = {}", pass_name)?; writeln!(file, "")?; - write_mir_fn(tcx, source, mir, &mut file, result)?; + write_mir_fn(tcx, source, mir, map, &mut file, result)?; Ok(()) }); } -pub fn write_mir_fn<'a, 'tcx, V: LiveVariableMap>( +pub fn write_mir_fn<'a, 'tcx, V: Idx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &Mir<'tcx>, + map: &dyn LiveVariableMap, w: &mut dyn Write, - result: &LivenessResult, + result: &LivenessResult, ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { - let live: Vec = mir.local_decls - .indices() - .filter(|i| result[block].contains(i)) - .map(|i| format!("{:?}", i)) + let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { + let live: Vec = result[block].iter() + .map(|v| map.from_live_var(v)) + .map(|local| format!("{:?}", local)) .collect(); writeln!(w, "{} {{{}}}", prefix, live.join(", ")) }; From 0d847ec1ab70e94deece40bd3b1c51787cca0126 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Wed, 18 Jul 2018 22:31:04 +0530 Subject: [PATCH 06/16] add LocalWithRegion NllLivenessMap --- src/librustc/mir/mod.rs | 20 +++++---- src/librustc/mir/visit.rs | 10 ++--- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/nll/mod.rs | 13 +++--- .../borrow_check/nll/type_check/liveness.rs | 8 ++-- .../borrow_check/nll/type_check/mod.rs | 3 +- .../dataflow/impls/borrowed_locals.rs | 14 +++---- src/librustc_mir/util/liveness.rs | 42 ++++++++++++++++++- 8 files changed, 76 insertions(+), 36 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f6076896385a6..18b3cf991d8b3 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -52,7 +52,7 @@ pub mod traversal; pub mod visit; /// Types for locals -type LocalDecls<'tcx> = IndexVec>; +type LocalDecls<'tcx> = IndexVec>; pub trait HasLocalDecls<'tcx> { fn local_decls(&self) -> &LocalDecls<'tcx>; @@ -141,7 +141,7 @@ impl<'tcx> Mir<'tcx> { source_scope_local_data: ClearCrossCrate>, promoted: IndexVec>, yield_ty: Option>, - local_decls: IndexVec>, + local_decls: IndexVec>, arg_count: usize, upvar_decls: Vec, span: Span, @@ -209,7 +209,7 @@ impl<'tcx> Mir<'tcx> { } #[inline] - pub fn local_kind(&self, local: Local) -> LocalKind { + pub fn local_kind(&self, local: LocalWithRegion) -> LocalKind { let index = local.0 as usize; if index == 0 { debug_assert!( @@ -234,9 +234,9 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all temporaries. #[inline] - pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); + let local = LocalWithRegion::new(index); if self.local_decls[local].is_user_variable.is_some() { None } else { @@ -247,9 +247,9 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all user-declared locals. #[inline] - pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); + let local = LocalWithRegion::new(index); if self.local_decls[local].is_user_variable.is_some() { Some(local) } else { @@ -260,9 +260,9 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all user-declared mutable arguments and locals. #[inline] - pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { (1..self.local_decls.len()).filter_map(move |index| { - let local = Local::new(index); + let local = LocalWithRegion::new(index); let decl = &self.local_decls[local]; if (decl.is_user_variable.is_some() || index < self.arg_count + 1) && decl.mutability == Mutability::Mut @@ -2932,3 +2932,5 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { } } } + +newtype_index!(LocalWithRegion); \ No newline at end of file diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 758d887cd7b3e..ced185d132a73 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -146,7 +146,7 @@ macro_rules! make_mir_visitor { fn visit_user_assert_ty(&mut self, c_ty: & $($mutability)* CanonicalTy<'tcx>, - local: & $($mutability)* Local, + local: & $($mutability)* LocalWithRegion, location: Location) { self.super_user_assert_ty(c_ty, local, location); } @@ -250,13 +250,13 @@ macro_rules! make_mir_visitor { } fn visit_local_decl(&mut self, - local: Local, + local: LocalWithRegion, local_decl: & $($mutability)* LocalDecl<'tcx>) { self.super_local_decl(local, local_decl); } fn visit_local(&mut self, - _local: & $($mutability)* Local, + _local: & $($mutability)* LocalWithRegion, _context: PlaceContext<'tcx>, _location: Location) { } @@ -632,7 +632,7 @@ macro_rules! make_mir_visitor { fn super_user_assert_ty(&mut self, _c_ty: & $($mutability)* CanonicalTy<'tcx>, - local: & $($mutability)* Local, + local: & $($mutability)* LocalWithRegion, location: Location) { self.visit_local(local, PlaceContext::Validate, location); } @@ -708,7 +708,7 @@ macro_rules! make_mir_visitor { } fn super_local_decl(&mut self, - local: Local, + local: LocalWithRegion, local_decl: & $($mutability)* LocalDecl<'tcx>) { let LocalDecl { mutability: _, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index e7f00b577b39f..ae539f43957c5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -278,7 +278,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // Note that this set is expected to be small - only upvars from closures // would have a chance of erroneously adding non-user-defined mutable vars // to the set. - let temporary_used_locals: FxHashSet = mbcx + let temporary_used_locals: FxHashSet = mbcx .used_mut .iter() .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some()) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 15ebb7a7a29f1..2fcf2d80d2a90 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -19,7 +19,7 @@ use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, Local}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, LocalWithRegion}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; use std::collections::BTreeSet; @@ -30,7 +30,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; use transform::MirSource; -use util::liveness::{IdentityMap, LivenessResults, LocalSet}; +use util::liveness::{IdentityMap, LivenessResults, LocalSet, NllLivenessMap}; use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; @@ -103,7 +103,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len())); // Run the MIR type-checker. - let liveness = &LivenessResults::compute(mir, &IdentityMap::new(mir)); + let liveness_map = NllLivenessMap::compute(&mir); + let liveness = LivenessResults::compute(mir, &liveness_map); let constraint_sets = type_check::type_check( infcx, param_env, @@ -193,7 +194,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( // write unit-tests, as well as helping with debugging. dump_mir_results( infcx, - liveness, + &liveness, MirSource::item(def_id), &mir, ®ioncx, @@ -209,7 +210,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( fn dump_mir_results<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, source: MirSource, mir: &Mir<'tcx>, regioncx: &RegionInferenceContext, @@ -407,7 +408,7 @@ impl ToRegionVid for RegionVid { } } -fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { +fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { // sort and deduplicate: let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 0eb88b7bcbfd3..17cc99c552268 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -13,7 +13,7 @@ use dataflow::move_paths::{HasMoveData, MoveData}; use dataflow::MaybeInitializedPlaces; use dataflow::{FlowAtLocation, FlowsAtLocation}; use rustc::infer::canonical::QueryRegionConstraint; -use rustc::mir::Local; +use rustc::mir::{Local, LocalWithRegion}; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::traits::query::dropck_outlives::DropckOutlivesResult; use rustc::traits::query::type_op::outlives::DropckOutlives; @@ -36,7 +36,7 @@ use super::TypeChecker; pub(super) fn generate<'gcx, 'tcx>( cx: &mut TypeChecker<'_, 'gcx, 'tcx>, mir: &Mir<'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, ) { @@ -64,7 +64,7 @@ where { cx: &'gen mut TypeChecker<'typeck, 'gcx, 'tcx>, mir: &'gen Mir<'tcx>, - liveness: &'gen LivenessResults, + liveness: &'gen LivenessResults, flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, @@ -93,7 +93,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo } }); - let mut all_live_locals: Vec<(Location, Vec)> = vec![]; + let mut all_live_locals: Vec<(Location, Vec)> = vec![]; self.liveness .drop .simulate_block(self.mir, bb, self.map, |location, live_locals| { diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index e188c9d7559c9..6cf5ea576e2d6 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -108,8 +108,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( mir_def_id: DefId, universal_regions: &UniversalRegions<'tcx>, location_table: &LocationTable, - borrow_set: &BorrowSet<'tcx>, - liveness: &LivenessResults, + liveness: &LivenessResults, all_facts: &mut Option, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index c7513ac88163a..9cfddb5b32048 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -37,18 +37,18 @@ impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> { } impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { - type Idx = Local; + type Idx = LocalWithRegion; fn name() -> &'static str { "has_been_borrowed_locals" } fn bits_per_block(&self) -> usize { self.mir.local_decls.len() } - fn start_block_effect(&self, _sets: &mut IdxSet) { + fn start_block_effect(&self, _sets: &mut IdxSet) { // Nothing is borrowed on function entry } fn statement_effect(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, loc: Location) { BorrowedLocalsVisitor { sets, @@ -56,7 +56,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { } fn terminator_effect(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, loc: Location) { BorrowedLocalsVisitor { sets, @@ -64,7 +64,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { } fn propagate_call_return(&self, - _in_out: &mut IdxSet, + _in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { @@ -87,10 +87,10 @@ impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> { } struct BorrowedLocalsVisitor<'b, 'c: 'b> { - sets: &'b mut BlockSets<'c, Local>, + sets: &'b mut BlockSets<'c, LocalWithRegion>, } -fn find_local<'tcx>(place: &Place<'tcx>) -> Option { +fn find_local<'tcx>(place: &Place<'tcx>) -> Option { match *place { Place::Local(l) => Some(l), Place::Static(..) => None, diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index ea8a180e3b618..2d36e6105fe72 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -37,8 +37,7 @@ use rustc::mir::visit::MirVisitable; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::mir::Local; use rustc::mir::*; -use rustc::ty::item_path; -use rustc::ty::TyCtxt; +use rustc::ty::{item_path, TyCtxt, TypeFoldable}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; @@ -545,3 +544,42 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>( writeln!(w, "}}")?; Ok(()) } + +crate struct NllLivenessMap { + pub from_local: IndexVec>, + pub to_local: IndexVec, + +} + +impl LiveVariableMap for NllLivenessMap { + type LiveVar = LocalWithRegion; + + fn from_local(&self, local: Local) -> Option { + self.from_local[local] + } + + fn from_live_var(&self, local: Self::LiveVar) -> Local { + self.to_local[local] + } + + fn num_variables(&self) -> usize { + self.to_local.len() + } +} + +impl NllLivenessMap { + pub fn compute(mir: &Mir) -> Self { + let mut to_local = IndexVec::default(); + let from_local: IndexVec<_,_> = mir.local.decls.iter_enumerated.map(|local, local_decl| { + if local_decl.ty.has_free_regions() { + Some(to_local.push(local)) + } + else { + None + } + }).collect(); + + Self { from_local, to_local } + } +} + From 0819ba9bea742dcc484a939710952a9840c8fae8 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Thu, 19 Jul 2018 00:14:32 +0530 Subject: [PATCH 07/16] mir/mod.rs / visit.rs reverted back to using Local --- src/librustc/mir/mod.rs | 18 +++++++++--------- src/librustc/mir/visit.rs | 10 +++++----- src/librustc_mir/borrow_check/mod.rs | 2 +- .../borrow_check/nll/type_check/liveness.rs | 2 +- .../dataflow/impls/borrowed_locals.rs | 14 +++++++------- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 18b3cf991d8b3..e19d2b9f18126 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -52,7 +52,7 @@ pub mod traversal; pub mod visit; /// Types for locals -type LocalDecls<'tcx> = IndexVec>; +type LocalDecls<'tcx> = IndexVec>; pub trait HasLocalDecls<'tcx> { fn local_decls(&self) -> &LocalDecls<'tcx>; @@ -141,7 +141,7 @@ impl<'tcx> Mir<'tcx> { source_scope_local_data: ClearCrossCrate>, promoted: IndexVec>, yield_ty: Option>, - local_decls: IndexVec>, + local_decls: IndexVec>, arg_count: usize, upvar_decls: Vec, span: Span, @@ -209,7 +209,7 @@ impl<'tcx> Mir<'tcx> { } #[inline] - pub fn local_kind(&self, local: LocalWithRegion) -> LocalKind { + pub fn local_kind(&self, local: Local) -> LocalKind { let index = local.0 as usize; if index == 0 { debug_assert!( @@ -234,9 +234,9 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all temporaries. #[inline] - pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn temps_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = LocalWithRegion::new(index); + let local = Local::new(index); if self.local_decls[local].is_user_variable.is_some() { None } else { @@ -247,9 +247,9 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all user-declared locals. #[inline] - pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn vars_iter<'a>(&'a self) -> impl Iterator + 'a { (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| { - let local = LocalWithRegion::new(index); + let local = Local::new(index); if self.local_decls[local].is_user_variable.is_some() { Some(local) } else { @@ -260,9 +260,9 @@ impl<'tcx> Mir<'tcx> { /// Returns an iterator over all user-declared mutable arguments and locals. #[inline] - pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { + pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { (1..self.local_decls.len()).filter_map(move |index| { - let local = LocalWithRegion::new(index); + let local = Local::new(index); let decl = &self.local_decls[local]; if (decl.is_user_variable.is_some() || index < self.arg_count + 1) && decl.mutability == Mutability::Mut diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ced185d132a73..758d887cd7b3e 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -146,7 +146,7 @@ macro_rules! make_mir_visitor { fn visit_user_assert_ty(&mut self, c_ty: & $($mutability)* CanonicalTy<'tcx>, - local: & $($mutability)* LocalWithRegion, + local: & $($mutability)* Local, location: Location) { self.super_user_assert_ty(c_ty, local, location); } @@ -250,13 +250,13 @@ macro_rules! make_mir_visitor { } fn visit_local_decl(&mut self, - local: LocalWithRegion, + local: Local, local_decl: & $($mutability)* LocalDecl<'tcx>) { self.super_local_decl(local, local_decl); } fn visit_local(&mut self, - _local: & $($mutability)* LocalWithRegion, + _local: & $($mutability)* Local, _context: PlaceContext<'tcx>, _location: Location) { } @@ -632,7 +632,7 @@ macro_rules! make_mir_visitor { fn super_user_assert_ty(&mut self, _c_ty: & $($mutability)* CanonicalTy<'tcx>, - local: & $($mutability)* LocalWithRegion, + local: & $($mutability)* Local, location: Location) { self.visit_local(local, PlaceContext::Validate, location); } @@ -708,7 +708,7 @@ macro_rules! make_mir_visitor { } fn super_local_decl(&mut self, - local: LocalWithRegion, + local: Local, local_decl: & $($mutability)* LocalDecl<'tcx>) { let LocalDecl { mutability: _, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index ae539f43957c5..e7f00b577b39f 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -278,7 +278,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // Note that this set is expected to be small - only upvars from closures // would have a chance of erroneously adding non-user-defined mutable vars // to the set. - let temporary_used_locals: FxHashSet = mbcx + let temporary_used_locals: FxHashSet = mbcx .used_mut .iter() .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable.is_some()) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 17cc99c552268..675c7f24e6532 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -192,7 +192,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo /// particular this takes `#[may_dangle]` into account. fn add_drop_live_constraint( &mut self, - dropped_local: Local, + dropped_local: LocalWithRegion, dropped_ty: Ty<'tcx>, location: Location, ) { diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 9cfddb5b32048..c7513ac88163a 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -37,18 +37,18 @@ impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> { } impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { - type Idx = LocalWithRegion; + type Idx = Local; fn name() -> &'static str { "has_been_borrowed_locals" } fn bits_per_block(&self) -> usize { self.mir.local_decls.len() } - fn start_block_effect(&self, _sets: &mut IdxSet) { + fn start_block_effect(&self, _sets: &mut IdxSet) { // Nothing is borrowed on function entry } fn statement_effect(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, loc: Location) { BorrowedLocalsVisitor { sets, @@ -56,7 +56,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { } fn terminator_effect(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, loc: Location) { BorrowedLocalsVisitor { sets, @@ -64,7 +64,7 @@ impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> { } fn propagate_call_return(&self, - _in_out: &mut IdxSet, + _in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { @@ -87,10 +87,10 @@ impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> { } struct BorrowedLocalsVisitor<'b, 'c: 'b> { - sets: &'b mut BlockSets<'c, LocalWithRegion>, + sets: &'b mut BlockSets<'c, Local>, } -fn find_local<'tcx>(place: &Place<'tcx>) -> Option { +fn find_local<'tcx>(place: &Place<'tcx>) -> Option { match *place { Place::Local(l) => Some(l), Place::Static(..) => None, From 1951a3070258ac548519369871c1c2326f7c268d Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Thu, 19 Jul 2018 22:48:06 +0530 Subject: [PATCH 08/16] convert LocalWithRegion to Local --- src/librustc_mir/borrow_check/nll/mod.rs | 4 ++-- .../borrow_check/nll/type_check/liveness.rs | 17 ++++++++++------- src/librustc_mir/util/liveness.rs | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 2fcf2d80d2a90..95eac46afbb34 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -30,7 +30,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; use transform::MirSource; -use util::liveness::{IdentityMap, LivenessResults, LocalSet, NllLivenessMap}; +use util::liveness::{LivenessResults, LocalSet, NllLivenessMap}; use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; @@ -220,7 +220,7 @@ fn dump_mir_results<'a, 'gcx, 'tcx>( return; } - let map = &IdentityMap::new(mir); + let map = &NllLivenessMap::compute(mir); let regular_liveness_per_location: FxHashMap<_, _> = mir .basic_blocks() diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 675c7f24e6532..6fa1ce44fab8f 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -13,7 +13,7 @@ use dataflow::move_paths::{HasMoveData, MoveData}; use dataflow::MaybeInitializedPlaces; use dataflow::{FlowAtLocation, FlowsAtLocation}; use rustc::infer::canonical::QueryRegionConstraint; -use rustc::mir::{Local, LocalWithRegion}; +use rustc::mir::LocalWithRegion; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::traits::query::dropck_outlives::DropckOutlivesResult; use rustc::traits::query::type_op::outlives::DropckOutlives; @@ -21,7 +21,7 @@ use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use std::rc::Rc; -use util::liveness::{IdentityMap, LivenessResults}; +use util::liveness::{NllLivenessMap, LivenessResults, LiveVariableMap }; use super::TypeChecker; @@ -47,7 +47,7 @@ pub(super) fn generate<'gcx, 'tcx>( flow_inits, move_data, drop_data: FxHashMap(), - map: &IdentityMap::new(mir), + map: &NllLivenessMap::compute(mir), }; for bb in mir.basic_blocks().indices() { @@ -68,7 +68,7 @@ where flow_inits: &'gen mut FlowAtLocation>, move_data: &'gen MoveData<'tcx>, drop_data: FxHashMap, DropData<'tcx>>, - map: &'gen IdentityMap<'gen, 'tcx>, + map: &'gen NllLivenessMap, } struct DropData<'tcx> { @@ -88,7 +88,8 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo .regular .simulate_block(self.mir, bb, self.map, |location, live_locals| { for live_local in live_locals.iter() { - let live_local_ty = self.mir.local_decls[live_local].ty; + let local = self.map.from_live_var(live_local); + let live_local_ty = self.mir.local_decls[local].ty; Self::push_type_live_constraint(&mut self.cx, live_local_ty, location); } }); @@ -123,7 +124,8 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo }); } - let mpi = self.move_data.rev_lookup.find_local(live_local); + let local = self.map.from_live_var(live_local); + let mpi = self.move_data.rev_lookup.find_local(local); if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) { debug!( "add_liveness_constraints: mpi={:?} has initialized child {:?}", @@ -131,7 +133,8 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo self.move_data.move_paths[initialized_child] ); - let live_local_ty = self.mir.local_decls[live_local].ty; + let local = self.map.from_live_var(live_local); + let live_local_ty = self.mir.local_decls[local].ty; self.add_drop_live_constraint(live_local, live_local_ty, location); } } diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 2d36e6105fe72..6f73868ff9f2e 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -570,7 +570,7 @@ impl LiveVariableMap for NllLivenessMap { impl NllLivenessMap { pub fn compute(mir: &Mir) -> Self { let mut to_local = IndexVec::default(); - let from_local: IndexVec<_,_> = mir.local.decls.iter_enumerated.map(|local, local_decl| { + let from_local: IndexVec> = mir.local_decls.iter_enumerated().map(|(local, local_decl)| { if local_decl.ty.has_free_regions() { Some(to_local.push(local)) } From 225578621288b5c67c2174a6f4b1576f16155324 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Thu, 19 Jul 2018 23:36:26 +0530 Subject: [PATCH 09/16] left out one field during merge --- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6cf5ea576e2d6..ebfad6d37dc22 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -108,6 +108,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( mir_def_id: DefId, universal_regions: &UniversalRegions<'tcx>, location_table: &LocationTable, + borrow_set: &BorrowSet<'tcx>, liveness: &LivenessResults, all_facts: &mut Option, flow_inits: &mut FlowAtLocation>, From 9910dee6776e967993b5a95b74390da179a479a6 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Fri, 20 Jul 2018 00:22:57 +0530 Subject: [PATCH 10/16] tidy fixes --- src/librustc/mir/mod.rs | 2 +- src/librustc_mir/borrow_check/nll/mod.rs | 5 ++++- src/librustc_mir/util/liveness.rs | 6 ++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e19d2b9f18126..bfac03debab46 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2933,4 +2933,4 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { } } -newtype_index!(LocalWithRegion); \ No newline at end of file +newtype_index!(LocalWithRegion); diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 95eac46afbb34..f2f8ffa6a8b89 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -408,7 +408,10 @@ impl ToRegionVid for RegionVid { } } -fn live_variable_set(regular: &LocalSet, drops: &LocalSet) -> String { +fn live_variable_set( + regular: &LocalSet, + drops: &LocalSet +) -> String { // sort and deduplicate: let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 6f73868ff9f2e..c19fdb9503413 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -570,7 +570,10 @@ impl LiveVariableMap for NllLivenessMap { impl NllLivenessMap { pub fn compute(mir: &Mir) -> Self { let mut to_local = IndexVec::default(); - let from_local: IndexVec> = mir.local_decls.iter_enumerated().map(|(local, local_decl)| { + let from_local: IndexVec> = mir + .local_decls + .iter_enumerated() + .map(|(local, local_decl)| { if local_decl.ty.has_free_regions() { Some(to_local.push(local)) } @@ -582,4 +585,3 @@ impl NllLivenessMap { Self { from_local, to_local } } } - From 67685dee3fab4982695473b34e0435c2bd7935b9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 20 Jul 2018 00:46:06 -0400 Subject: [PATCH 11/16] always get number of live variables from the map --- src/librustc_mir/util/liveness.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index c19fdb9503413..5ef4a9e235788 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -168,21 +168,21 @@ pub fn liveness_of_locals<'tcx, V: Idx>( mode: LivenessMode, map: &impl LiveVariableMap, ) -> LivenessResult { - let locals = map.num_variables(); + let num_live_vars = map.num_variables(); let def_use: IndexVec<_, DefsUses> = mir .basic_blocks() .iter() - .map(|b| block(mode, map, b, locals)) + .map(|b| block(mode, map, b, num_live_vars)) .collect(); let mut outs: IndexVec<_, LocalSet> = mir .basic_blocks() .indices() - .map(|_| LocalSet::new_empty(locals)) + .map(|_| LocalSet::new_empty(num_live_vars)) .collect(); - let mut bits = LocalSet::new_empty(locals); + let mut bits = LocalSet::new_empty(num_live_vars); // queue of things that need to be re-processed, and a set containing // the things currently in the queue @@ -239,13 +239,13 @@ impl LivenessResult { block, statement_index, }; - let locals = mir.local_decls.len(); + let num_live_vars = map.num_variables(); let mut visitor = DefsUsesVisitor { mode: self.mode, map, defs_uses: DefsUses { - defs: LocalSet::new_empty(locals), - uses: LocalSet::new_empty(locals), + defs: LocalSet::new_empty(num_live_vars), + uses: LocalSet::new_empty(num_live_vars), }, }; // Visit the various parts of the basic block in reverse. If we go From 4e3339efda68a699d72aee33f8c31cbff8ebdff6 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Fri, 20 Jul 2018 17:30:03 +0530 Subject: [PATCH 12/16] move NllLivenessMap and LocalWithRegion to liveness_map --- src/librustc/mir/mod.rs | 2 +- .../borrow_check/nll/liveness_map.rs | 58 +++++++++++++++ src/librustc_mir/borrow_check/nll/mod.rs | 10 ++- .../borrow_check/nll/type_check/liveness.rs | 4 +- .../borrow_check/nll/type_check/mod.rs | 1 + src/librustc_mir/transform/generator.rs | 16 ++-- src/librustc_mir/util/liveness.rs | 73 +++++-------------- 7 files changed, 93 insertions(+), 71 deletions(-) create mode 100644 src/librustc_mir/borrow_check/nll/liveness_map.rs diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index bfac03debab46..fb80a00f3f650 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2933,4 +2933,4 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { } } -newtype_index!(LocalWithRegion); + diff --git a/src/librustc_mir/borrow_check/nll/liveness_map.rs b/src/librustc_mir/borrow_check/nll/liveness_map.rs new file mode 100644 index 0000000000000..22abea8eaf097 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/liveness_map.rs @@ -0,0 +1,58 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc_data_structures::indexed_vec::IndexVec; +use rustc::mir::{Mir, Local}; +use util::liveness::LiveVariableMap; +use rustc_data_structures::indexed_vec::Idx; +use rustc::ty::TypeFoldable; + +crate struct NllLivenessMap { + pub from_local: IndexVec>, + pub to_local: IndexVec, + +} + +impl LiveVariableMap for NllLivenessMap { + type LiveVar = LocalWithRegion; + + fn from_local(&self, local: Local) -> Option { + self.from_local[local] + } + + fn from_live_var(&self, local: Self::LiveVar) -> Local { + self.to_local[local] + } + + fn num_variables(&self) -> usize { + self.to_local.len() + } +} + +impl NllLivenessMap { + pub fn compute(mir: &Mir) -> Self { + let mut to_local = IndexVec::default(); + let from_local: IndexVec> = mir + .local_decls + .iter_enumerated() + .map(|(local, local_decl)| { + if local_decl.ty.has_free_regions() { + Some(to_local.push(local)) + } + else { + None + } + }).collect(); + + Self { from_local, to_local } + } +} + +newtype_index!(LocalWithRegion); \ No newline at end of file diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index f2f8ffa6a8b89..76f8fa206be5d 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -13,13 +13,14 @@ use borrow_check::location::{LocationIndex, LocationTable}; use borrow_check::nll::facts::AllFactsExt; use borrow_check::nll::type_check::MirTypeckRegionConstraints; use borrow_check::nll::region_infer::values::RegionValueElements; +use borrow_check::nll::liveness_map::{NllLivenessMap, LocalWithRegion}; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir, LocalWithRegion}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; use std::collections::BTreeSet; @@ -30,7 +31,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::str::FromStr; use transform::MirSource; -use util::liveness::{LivenessResults, LocalSet, NllLivenessMap}; +use util::liveness::{LivenessResults, LiveVarSet}; use self::mir_util::PassWhere; use polonius_engine::{Algorithm, Output}; @@ -45,6 +46,7 @@ crate mod region_infer; mod renumber; crate mod type_check; mod universal_regions; +crate mod liveness_map; mod constraints; @@ -409,8 +411,8 @@ impl ToRegionVid for RegionVid { } fn live_variable_set( - regular: &LocalSet, - drops: &LocalSet + regular: &LiveVarSet, + drops: &LiveVarSet ) -> String { // sort and deduplicate: let all_locals: BTreeSet<_> = regular.iter().chain(drops.iter()).collect(); diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 6fa1ce44fab8f..2b9307db59af9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -8,12 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use borrow_check::nll::{NllLivenessMap, LocalWithRegion}; use borrow_check::nll::type_check::AtLocation; use dataflow::move_paths::{HasMoveData, MoveData}; use dataflow::MaybeInitializedPlaces; use dataflow::{FlowAtLocation, FlowsAtLocation}; use rustc::infer::canonical::QueryRegionConstraint; -use rustc::mir::LocalWithRegion; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::traits::query::dropck_outlives::DropckOutlivesResult; use rustc::traits::query::type_op::outlives::DropckOutlives; @@ -21,7 +21,7 @@ use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use std::rc::Rc; -use util::liveness::{NllLivenessMap, LivenessResults, LiveVariableMap }; +use util::liveness::{LivenessResults, LiveVariableMap }; use super::TypeChecker; diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index ebfad6d37dc22..e23f9b20a10f8 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -19,6 +19,7 @@ use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; use borrow_check::nll::region_infer::values::{RegionValues, RegionValueElements}; use borrow_check::nll::universal_regions::UniversalRegions; use borrow_check::nll::ToRegionVid; +use borrow_check::nll::LocalWithRegion; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 7d4d561072e7a..a43f17e40dfb6 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -130,7 +130,7 @@ struct SuspensionPoint { state: u32, resume: BasicBlock, drop: Option, - storage_liveness: liveness::LocalSet, + storage_liveness: liveness::LiveVarSet, } struct TransformVisitor<'a, 'tcx: 'a> { @@ -145,7 +145,7 @@ struct TransformVisitor<'a, 'tcx: 'a> { remap: HashMap, usize)>, // A map from a suspension point in a block to the locals which have live storage at that point - storage_liveness: HashMap>, + storage_liveness: HashMap>, // A list of suspension points, generated during the transform suspension_points: Vec, @@ -317,7 +317,7 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>, new_ret_local } -struct StorageIgnored(liveness::LocalSet); +struct StorageIgnored(liveness::LiveVarSet); impl<'tcx> Visitor<'tcx> for StorageIgnored { fn visit_statement(&mut self, @@ -332,7 +332,7 @@ impl<'tcx> Visitor<'tcx> for StorageIgnored { } } -struct BorrowedLocals(liveness::LocalSet); +struct BorrowedLocals(liveness::LiveVarSet); fn mark_as_borrowed<'tcx>(place: &Place<'tcx>, locals: &mut BorrowedLocals) { match *place { @@ -365,8 +365,8 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, source: MirSource, movable: bool) -> - (liveness::LocalSet, - HashMap>) { + (liveness::LiveVarSet, + HashMap>) { let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap(); @@ -396,7 +396,7 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; // Calculate the liveness of MIR locals ignoring borrows. - let mut set = liveness::LocalSet::new_empty(mir.local_decls.len()); + let mut set = liveness::LiveVarSet::new_empty(mir.local_decls.len()); let mut liveness = liveness::liveness_of_locals( mir, LivenessMode { @@ -479,7 +479,7 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<'tcx>) -> (HashMap, usize)>, GeneratorLayout<'tcx>, - HashMap>) + HashMap>) { // Use a liveness analysis to compute locals which are live across a suspension point let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 5ef4a9e235788..cbfd7306bb627 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -37,7 +37,7 @@ use rustc::mir::visit::MirVisitable; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::mir::Local; use rustc::mir::*; -use rustc::ty::{item_path, TyCtxt, TypeFoldable}; +use rustc::ty::{item_path, TyCtxt}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; @@ -47,7 +47,7 @@ use std::path::{Path, PathBuf}; use transform::MirSource; use util::pretty::{dump_enabled, write_basic_block, write_mir_intro}; -pub type LocalSet = IdxSetBuf; +pub type LiveVarSet = IdxSetBuf; /// This gives the result of the liveness analysis at the boundary of /// basic blocks. You can use `simulate_block` to obtain the @@ -63,7 +63,7 @@ pub struct LivenessResult { /// Live variables on exit to each basic block. This is equal to /// the union of the `ins` for each successor. - pub outs: IndexVec>, + pub outs: IndexVec>, } /// Defines the mapping to/from the MIR local variables (`Local`) to @@ -176,13 +176,13 @@ pub fn liveness_of_locals<'tcx, V: Idx>( .map(|b| block(mode, map, b, num_live_vars)) .collect(); - let mut outs: IndexVec<_, LocalSet> = mir + let mut outs: IndexVec<_, LiveVarSet> = mir .basic_blocks() .indices() - .map(|_| LocalSet::new_empty(num_live_vars)) + .map(|_| LiveVarSet::new_empty(num_live_vars)) .collect(); - let mut bits = LocalSet::new_empty(num_live_vars); + let mut bits = LiveVarSet::new_empty(num_live_vars); // queue of things that need to be re-processed, and a set containing // the things currently in the queue @@ -223,7 +223,7 @@ impl LivenessResult { map: &impl LiveVariableMap, mut callback: OP, ) where - OP: FnMut(Location, &LocalSet), + OP: FnMut(Location, &LiveVarSet), { let data = &mir[block]; @@ -244,8 +244,8 @@ impl LivenessResult { mode: self.mode, map, defs_uses: DefsUses { - defs: LocalSet::new_empty(num_live_vars), - uses: LocalSet::new_empty(num_live_vars), + defs: LiveVarSet::new_empty(num_live_vars), + uses: LiveVarSet::new_empty(num_live_vars), }, }; // Visit the various parts of the basic block in reverse. If we go @@ -362,8 +362,8 @@ where #[derive(Eq, PartialEq, Clone)] struct DefsUses { - defs: LocalSet, - uses: LocalSet, + defs: LiveVarSet, + uses: LiveVarSet, } impl DefsUses { @@ -372,7 +372,7 @@ impl DefsUses { self.defs.clear(); } - fn apply(&self, bits: &mut LocalSet) -> bool { + fn apply(&self, bits: &mut LiveVarSet) -> bool { bits.subtract(&self.defs) | bits.union(&self.uses) } @@ -418,10 +418,10 @@ where &mut self, location: Location, value: &impl MirVisitable<'tcx>, - bits: &mut LocalSet, + bits: &mut LiveVarSet, callback: &mut OP, ) where - OP: FnMut(Location, &LocalSet), + OP: FnMut(Location, &LiveVarSet), { value.apply(location, self); self.defs_uses.apply(bits); @@ -455,8 +455,8 @@ fn block<'tcx, V: Idx>( mode, map, defs_uses: DefsUses { - defs: LocalSet::new_empty(locals), - uses: LocalSet::new_empty(locals), + defs: LiveVarSet::new_empty(locals), + uses: LiveVarSet::new_empty(locals), }, }; @@ -527,7 +527,7 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>( ) -> io::Result<()> { write_mir_intro(tcx, src, mir, w)?; for block in mir.basic_blocks().indices() { - let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { + let print = |w: &mut dyn Write, prefix, result: &IndexVec>| { let live: Vec = result[block].iter() .map(|v| map.from_live_var(v)) .map(|local| format!("{:?}", local)) @@ -545,43 +545,4 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>( Ok(()) } -crate struct NllLivenessMap { - pub from_local: IndexVec>, - pub to_local: IndexVec, -} - -impl LiveVariableMap for NllLivenessMap { - type LiveVar = LocalWithRegion; - - fn from_local(&self, local: Local) -> Option { - self.from_local[local] - } - - fn from_live_var(&self, local: Self::LiveVar) -> Local { - self.to_local[local] - } - - fn num_variables(&self) -> usize { - self.to_local.len() - } -} - -impl NllLivenessMap { - pub fn compute(mir: &Mir) -> Self { - let mut to_local = IndexVec::default(); - let from_local: IndexVec> = mir - .local_decls - .iter_enumerated() - .map(|(local, local_decl)| { - if local_decl.ty.has_free_regions() { - Some(to_local.push(local)) - } - else { - None - } - }).collect(); - - Self { from_local, to_local } - } -} From dbb756ded7d72fe83a77219fee1181a5ca15dca3 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Fri, 20 Jul 2018 18:40:52 +0530 Subject: [PATCH 13/16] tidy up --- src/librustc/mir/mod.rs | 2 -- src/librustc_mir/borrow_check/nll/liveness_map.rs | 2 +- src/librustc_mir/util/liveness.rs | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index fb80a00f3f650..f6076896385a6 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2932,5 +2932,3 @@ impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> { } } } - - diff --git a/src/librustc_mir/borrow_check/nll/liveness_map.rs b/src/librustc_mir/borrow_check/nll/liveness_map.rs index 22abea8eaf097..de3b759b9ce1c 100644 --- a/src/librustc_mir/borrow_check/nll/liveness_map.rs +++ b/src/librustc_mir/borrow_check/nll/liveness_map.rs @@ -55,4 +55,4 @@ impl NllLivenessMap { } } -newtype_index!(LocalWithRegion); \ No newline at end of file +newtype_index!(LocalWithRegion); diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index cbfd7306bb627..3383a3b8368c1 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -544,5 +544,3 @@ pub fn write_mir_fn<'a, 'tcx, V: Idx>( writeln!(w, "}}")?; Ok(()) } - - From 7db332434005b823ca151804193837eaf904d2a3 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Sat, 21 Jul 2018 11:42:44 +0530 Subject: [PATCH 14/16] remove unwanted tests and a reference to it in comments --- src/librustc_mir/util/liveness.rs | 8 ++-- .../mir-opt/nll/liveness-call-subtlety.rs | 45 ----------------- .../mir-opt/nll/liveness-drop-intra-block.rs | 41 ---------------- src/test/mir-opt/nll/liveness-interblock.rs | 48 ------------------- 4 files changed, 3 insertions(+), 139 deletions(-) delete mode 100644 src/test/mir-opt/nll/liveness-call-subtlety.rs delete mode 100644 src/test/mir-opt/nll/liveness-drop-intra-block.rs delete mode 100644 src/test/mir-opt/nll/liveness-interblock.rs diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 3383a3b8368c1..6c5b38a806e57 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -294,11 +294,9 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti // We let Call define the result in both the success and // unwind cases. This is not really correct, however it // does not seem to be observable due to the way that we - // generate MIR. See the test case - // `mir-opt/nll/liveness-call-subtlety.rs`. To do things - // properly, we would apply the def in call only to the - // input from the success path and not the unwind - // path. -nmatsakis + // generate MIR. To do things properly, we would apply + // the def in call only to the input from the success + // path and not the unwind path. -nmatsakis PlaceContext::Call | // Storage live and storage dead aren't proper defines, but we can ignore diff --git a/src/test/mir-opt/nll/liveness-call-subtlety.rs b/src/test/mir-opt/nll/liveness-call-subtlety.rs deleted file mode 100644 index 5fdea4208df99..0000000000000 --- a/src/test/mir-opt/nll/liveness-call-subtlety.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-Zborrowck=mir - -fn can_panic() -> Box { - Box::new(44) -} - -fn main() { - let mut x = Box::new(22); - x = can_panic(); -} - -// Check that: -// - `_1` is the variable corresponding to `x` -// and -// - `_1` is live when `can_panic` is called (because it may be dropped) -// -// END RUST SOURCE -// START rustc.main.nll.0.mir -// bb0: { -// | Live variables on entry to bb0[0]: [] -// StorageLive(_1); -// | Live variables on entry to bb0[1]: [] -// _1 = const >::new(const 22usize) -> [return: bb2, unwind: bb1]; -// | Live variables on exit from bb0: [_1 (drop)] -// } -// END rustc.main.nll.0.mir -// START rustc.main.nll.0.mir -// bb2: { -// | Live variables on entry to bb2[0]: [_1 (drop)] -// StorageLive(_2); -// | Live variables on entry to bb2[1]: [_1 (drop)] -// _2 = const can_panic() -> [return: bb3, unwind: bb4]; -// | Live variables on exit from bb2: [_1 (drop), _2] -// } -// END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/liveness-drop-intra-block.rs b/src/test/mir-opt/nll/liveness-drop-intra-block.rs deleted file mode 100644 index 001499b657de9..0000000000000 --- a/src/test/mir-opt/nll/liveness-drop-intra-block.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-Zborrowck=mir - -#![allow(warnings)] - -fn use_x(_: usize) -> bool { true } - -fn main() { - let mut x = 22; - loop { - // Key point: `x` not live on entry to this basic block. - x = 55; - if use_x(x) { break; } - } -} - -// END RUST SOURCE -// START rustc.main.nll.0.mir -// bb3: { -// | Live variables on entry to bb3[0]: [] -// _1 = const 55usize; -// | Live variables on entry to bb3[1]: [_1] -// StorageLive(_3); -// | Live variables on entry to bb3[2]: [_1] -// StorageLive(_4); -// | Live variables on entry to bb3[3]: [_1] -// _4 = _1; -// | Live variables on entry to bb3[4]: [_4] -// _3 = const use_x(move _4) -> [return: bb4, unwind: bb1]; -// | Live variables on exit from bb3: [_3] -// } -// END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/liveness-interblock.rs b/src/test/mir-opt/nll/liveness-interblock.rs deleted file mode 100644 index fbe20d76ea721..0000000000000 --- a/src/test/mir-opt/nll/liveness-interblock.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags:-Zborrowck=mir - -fn cond() -> bool { false } - -fn make_live(_: usize) { } - -fn make_dead() { } - -fn main() { - let x = 5; - - if cond() { - make_live(x); - } else { - // x should be dead on entry to this block - make_dead(); - } -} - -// END RUST SOURCE -// START rustc.main.nll.0.mir -// bb3: { -// | Live variables on entry to bb3[0]: [_1] -// StorageLive(_4); -// | Live variables on entry to bb3[1]: [_1] -// _4 = _1; -// | Live variables on entry to bb3[2]: [_4] -// _3 = const make_live(move _4) -> [return: bb5, unwind: bb1]; -// | Live variables on exit from bb3: [] -// } -// END rustc.main.nll.0.mir -// START rustc.main.nll.0.mir -// bb4: { -// | Live variables on entry to bb4[0]: [] -// _5 = const make_dead() -> [return: bb6, unwind: bb1]; -// | Live variables on exit from bb4: [] -// } -// END rustc.main.nll.0.mir From a4c0d369b63ddb33e62abfacf190cb3fab1b5de6 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Sat, 21 Jul 2018 17:21:04 +0530 Subject: [PATCH 15/16] add docs --- .../borrow_check/nll/liveness_map.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/liveness_map.rs b/src/librustc_mir/borrow_check/nll/liveness_map.rs index de3b759b9ce1c..cbd9c9a4e1a85 100644 --- a/src/librustc_mir/borrow_check/nll/liveness_map.rs +++ b/src/librustc_mir/borrow_check/nll/liveness_map.rs @@ -8,25 +8,41 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//! For the NLL computation, we need to compute liveness, but only for those +//! local variables whose types contain regions. The others are not of interest +//! to us. This file defines a new index type (LocalWithRegion) that indexes into +//! a list of "variables whose type contain regions". It also defines a map from +//! Local to LocalWithRegion and vice versa -- this map can be given to the +//! liveness code so that it only operates over variables with regions in their +//! types, instead of all variables. + +use rustc::ty::TypeFoldable; use rustc_data_structures::indexed_vec::IndexVec; use rustc::mir::{Mir, Local}; use util::liveness::LiveVariableMap; + use rustc_data_structures::indexed_vec::Idx; -use rustc::ty::TypeFoldable; +/// Map between Local and LocalWithRegion indices: this map is supplied to the +/// liveness code so that it will only analyze those variables whose types +/// contain regions. crate struct NllLivenessMap { + /// For each local variable, contains either None (if the type has no regions) + /// or Some(i) with a suitable index. pub from_local: IndexVec>, + /// For each LocalWithRegion, maps back to the original Local index. pub to_local: IndexVec, } impl LiveVariableMap for NllLivenessMap { - type LiveVar = LocalWithRegion; fn from_local(&self, local: Local) -> Option { self.from_local[local] } + type LiveVar = LocalWithRegion; + fn from_live_var(&self, local: Self::LiveVar) -> Local { self.to_local[local] } @@ -37,6 +53,8 @@ impl LiveVariableMap for NllLivenessMap { } impl NllLivenessMap { + /// Iterates over the variables in Mir and assigns each Local whose type contains + /// regions a LocalWithRegion index. Returns a map for converting back and forth. pub fn compute(mir: &Mir) -> Self { let mut to_local = IndexVec::default(); let from_local: IndexVec> = mir @@ -55,4 +73,5 @@ impl NllLivenessMap { } } +/// Index given to each local variable whose type contains a region. newtype_index!(LocalWithRegion); From 0770ff0500e25be2931217d7d6e095b0b0ec975d Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Sat, 21 Jul 2018 19:46:41 +0530 Subject: [PATCH 16/16] delete tests --- src/test/mir-opt/nll/region-liveness-basic.rs | 58 ------------------- .../nll/region-liveness-two-disjoint-uses.rs | 52 ----------------- 2 files changed, 110 deletions(-) delete mode 100644 src/test/mir-opt/nll/region-liveness-basic.rs delete mode 100644 src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs diff --git a/src/test/mir-opt/nll/region-liveness-basic.rs b/src/test/mir-opt/nll/region-liveness-basic.rs deleted file mode 100644 index 187d9e6ca8993..0000000000000 --- a/src/test/mir-opt/nll/region-liveness-basic.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Basic test for liveness constraints: the region (`R1`) that appears -// in the type of `p` includes the points after `&v[0]` up to (but not -// including) the call to `use_x`. The `else` branch is not included. - -// compile-flags:-Zborrowck=mir -Zverbose -// ^^^^^^^^^ force compiler to dump more region information - -#![allow(warnings)] - -fn use_x(_: usize) -> bool { true } - -fn main() { - let mut v = [1, 2, 3]; - let p = &v[0]; - if true { - use_x(*p); - } else { - use_x(22); - } -} - -// END RUST SOURCE -// START rustc.main.nll.0.mir -// | '_#2r | {bb2[0..=1], bb3[0..=1]} -// | '_#3r | {bb2[1], bb3[0..=1]} -// ... -// let _2: &'_#3r usize; -// END rustc.main.nll.0.mir -// START rustc.main.nll.0.mir -// bb2: { -// | Live variables on entry to bb2[0]: [_1, _3] -// _2 = &'_#2r _1[_3]; -// | Live variables on entry to bb2[1]: [_2] -// switchInt(const true) -> [false: bb4, otherwise: bb3]; -// | Live variables on exit from bb2: [_2] -// } -// END rustc.main.nll.0.mir -// START rustc.main.nll.0.mir -// bb3: { -// | Live variables on entry to bb3[0]: [_2] -// StorageLive(_7); -// | Live variables on entry to bb3[1]: [_2] -// _7 = (*_2); -// | Live variables on entry to bb3[2]: [_7] -// _6 = const use_x(move _7) -> [return: bb5, unwind: bb1]; -// | Live variables on exit from bb3: [] -// } -// END rustc.main.nll.0.mir diff --git a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs deleted file mode 100644 index 62064fa94f2fe..0000000000000 --- a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test for the subregion constraints. In this case, the region R3 on -// `p` includes two disjoint regions of the control-flow graph. The -// borrows in `&v[0]` and `&v[1]` each (in theory) have to outlive R3, -// but only at a particular point, and hence they wind up including -// distinct regions. -// -// FIXME(#43234) -- Well, this used to be true, but we modified NLL -// for the time being to not take location into account. - -// compile-flags:-Zborrowck=mir -Zverbose -// ^^^^^^^^^ force compiler to dump more region information - -#![allow(warnings)] - -fn use_x(_: usize) -> bool { true } - -fn main() { - let mut v = [1, 2, 3]; - let mut p = &v[0]; - if true { - use_x(*p); - } else { - use_x(22); - } - - p = &v[1]; - use_x(*p); -} - -// END RUST SOURCE -// START rustc.main.nll.0.mir -// | '_#2r | {bb2[0..=1], bb3[0..=1], bb8[2..=4]} -// ... -// | '_#4r | {bb2[1], bb3[0..=1], bb8[1..=4]} -// | '_#5r | {bb2[1], bb3[0..=1], bb8[2..=4]} -// ... -// let mut _2: &'_#5r usize; -// ... -// _2 = &'_#2r _1[_3]; -// ... -// _2 = &'_#4r (*_10); -// END rustc.main.nll.0.mir