diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs index b11e5e7a85d0..f0beb4d3ae32 100644 --- a/src/librustc_mir/borrow_check/nll/facts.rs +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -68,6 +68,7 @@ impl AllFactsExt for AllFacts { path_belongs_to_var, initialized_at, moved_out_at, + path_accessed_at, ]) } Ok(()) diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs index 25d7985653c0..3f2ec1ba9701 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/mod.rs @@ -60,7 +60,7 @@ pub(super) fn generate<'tcx>( if !live_locals.is_empty() { trace::trace(typeck, body, elements, flow_inits, move_data, live_locals); - polonius::populate_var_liveness_facts(typeck, body, location_table); + polonius::populate_access_facts(typeck, body, location_table, move_data); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs index dcdacbbe5be0..d61464b3f387 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/polonius.rs @@ -1,23 +1,28 @@ use crate::borrow_check::location::{LocationIndex, LocationTable}; +use crate::dataflow::indexes::MovePathIndex; +use crate::dataflow::move_paths::{LookupResult, MoveData}; use crate::util::liveness::{categorize, DefUse}; -use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::mir::{Body, Local, Location}; +use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc::mir::{Body, Local, Location, Place}; use rustc::ty::subst::Kind; use rustc::ty::Ty; use super::TypeChecker; type VarPointRelations = Vec<(Local, LocationIndex)>; +type MovePathPointRelations = Vec<(MovePathIndex, LocationIndex)>; -struct LivenessPointFactsExtractor<'me> { +struct UseFactsExtractor<'me> { var_defined: &'me mut VarPointRelations, var_used: &'me mut VarPointRelations, location_table: &'me LocationTable, var_drop_used: &'me mut VarPointRelations, + move_data: &'me MoveData<'me>, + path_accessed_at: &'me mut MovePathPointRelations, } // A Visitor to walk through the MIR and extract point-wise facts -impl LivenessPointFactsExtractor<'_> { +impl UseFactsExtractor<'_> { fn location_to_index(&self, location: Location) -> LocationIndex { self.location_table.mid_index(location) } @@ -36,9 +41,21 @@ impl LivenessPointFactsExtractor<'_> { debug!("LivenessFactsExtractor::insert_drop_use()"); self.var_drop_used.push((local, self.location_to_index(location))); } + + fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { + debug!("LivenessFactsExtractor::insert_path_access({:?}, {:?})", path, location); + self.path_accessed_at.push((path, self.location_to_index(location))); + } + + fn place_to_mpi(&self, place: &Place<'_>) -> Option { + match self.move_data.rev_lookup.find(place.as_ref()) { + LookupResult::Exact(mpi) => Some(mpi), + LookupResult::Parent(mmpi) => mmpi, + } + } } -impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { +impl Visitor<'tcx> for UseFactsExtractor<'_> { fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) { match categorize(context) { Some(DefUse::Def) => self.insert_def(local, location), @@ -47,6 +64,24 @@ impl Visitor<'tcx> for LivenessPointFactsExtractor<'_> { _ => (), } } + + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + self.super_place(place, context, location); + match context { + PlaceContext::NonMutatingUse(_) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + + PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + if let Some(mpi) = self.place_to_mpi(place) { + self.insert_path_access(mpi, location); + } + } + _ => (), + } + } } fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty<'tcx>) { @@ -60,24 +95,27 @@ fn add_var_uses_regions(typeck: &mut TypeChecker<'_, 'tcx>, local: Local, ty: Ty }); } -pub(super) fn populate_var_liveness_facts( +pub(super) fn populate_access_facts( typeck: &mut TypeChecker<'_, 'tcx>, - mir: &Body<'tcx>, + body: &Body<'tcx>, location_table: &LocationTable, + move_data: &MoveData<'_>, ) { debug!("populate_var_liveness_facts()"); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { - LivenessPointFactsExtractor { + UseFactsExtractor { var_defined: &mut facts.var_defined, var_used: &mut facts.var_used, var_drop_used: &mut facts.var_drop_used, + path_accessed_at: &mut facts.path_accessed_at, location_table, + move_data, } - .visit_body(mir); + .visit_body(body); } - for (local, local_decl) in mir.local_decls.iter_enumerated() { + for (local, local_decl) in body.local_decls.iter_enumerated() { add_var_uses_regions(typeck, local, local_decl.ty); } }