From 0d847ec1ab70e94deece40bd3b1c51787cca0126 Mon Sep 17 00:00:00 2001 From: dylan_DPC Date: Wed, 18 Jul 2018 22:31:04 +0530 Subject: [PATCH] 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 f6076896385a..18b3cf991d8b 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 758d887cd7b3..ced185d132a7 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 e7f00b577b39..ae539f43957c 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 15ebb7a7a29f..2fcf2d80d2a9 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 0eb88b7bcbfd..17cc99c55226 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 e188c9d7559c..6cf5ea576e2d 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 c7513ac88163..9cfddb5b3204 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 ea8a180e3b61..2d36e6105fe7 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 } + } +} +