From 585c71fd3efeb2ec1ae3f01e7feb29f0ec5e4245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 12:29:37 +0000 Subject: [PATCH] refactor access fact generation - use consistent names - inline single use functions - dedupe and simplify some paths - fix fact generation timer activity: it was missing the walk and extraction process --- .../src/type_check/liveness/mod.rs | 2 +- .../src/type_check/liveness/polonius.rs | 143 ++++++++---------- .../src/type_check/liveness/trace.rs | 2 +- 3 files changed, 67 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 20d19a53752..05e4a176a6d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -45,7 +45,7 @@ pub(super) fn generate<'a, 'tcx>( let (relevant_live_locals, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body); - polonius::populate_access_facts(typeck, body, move_data); + polonius::emit_access_facts(typeck, body, move_data); trace::trace( typeck, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index e8d8ae0850b..5ffba94ee68 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -11,88 +11,19 @@ use crate::location::{LocationIndex, LocationTable}; type VarPointRelation = Vec<(Local, LocationIndex)>; type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; -struct UseFactsExtractor<'a, 'tcx> { - var_defined_at: &'a mut VarPointRelation, - var_used_at: &'a mut VarPointRelation, - location_table: &'a LocationTable, - var_dropped_at: &'a mut VarPointRelation, - move_data: &'a MoveData<'tcx>, - path_accessed_at_base: &'a mut PathPointRelation, -} - -// A Visitor to walk through the MIR and extract point-wise facts -impl<'tcx> UseFactsExtractor<'_, 'tcx> { - fn location_to_index(&self, location: Location) -> LocationIndex { - self.location_table.mid_index(location) - } - - fn insert_def(&mut self, local: Local, location: Location) { - debug!("UseFactsExtractor::insert_def()"); - self.var_defined_at.push((local, self.location_to_index(location))); - } - - fn insert_use(&mut self, local: Local, location: Location) { - debug!("UseFactsExtractor::insert_use()"); - self.var_used_at.push((local, self.location_to_index(location))); - } - - fn insert_drop_use(&mut self, local: Local, location: Location) { - debug!("UseFactsExtractor::insert_drop_use()"); - self.var_dropped_at.push((local, self.location_to_index(location))); - } - - fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { - debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location); - self.path_accessed_at_base.push((path, self.location_to_index(location))); - } - - fn place_to_mpi(&self, place: &Place<'tcx>) -> Option { - match self.move_data.rev_lookup.find(place.as_ref()) { - LookupResult::Exact(mpi) => Some(mpi), - LookupResult::Parent(mmpi) => mmpi, - } - } -} - -impl<'a, 'tcx> Visitor<'tcx> for UseFactsExtractor<'a, 'tcx> { - fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { - match def_use::categorize(context) { - Some(DefUse::Def) => self.insert_def(local, location), - Some(DefUse::Use) => self.insert_use(local, location), - Some(DefUse::Drop) => self.insert_drop_use(local, location), - _ => (), - } - } - - 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); - } - } - _ => (), - } - } -} - -pub(super) fn populate_access_facts<'a, 'tcx>( +/// Emit polonius facts for variable defs, uses, drops, and path accesses. +pub(super) fn emit_access_facts<'a, 'tcx>( typeck: &mut TypeChecker<'a, 'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, ) { if let Some(facts) = typeck.all_facts.as_mut() { - debug!("populate_access_facts()"); + debug!("emit_access_facts()"); + + let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let location_table = typeck.location_table; - let mut extractor = UseFactsExtractor { + let mut extractor = AccessFactsExtractor { var_defined_at: &mut facts.var_defined_at, var_used_at: &mut facts.var_used_at, var_dropped_at: &mut facts.var_dropped_at, @@ -107,7 +38,6 @@ pub(super) fn populate_access_facts<'a, 'tcx>( "add use_of_var_derefs_origin facts - local={:?}, type={:?}", local, local_decl.ty ); - let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let universal_regions = &typeck.universal_regions; typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| { let region_vid = universal_regions.to_region_vid(region); @@ -119,12 +49,12 @@ pub(super) fn populate_access_facts<'a, 'tcx>( /// For every potentially drop()-touched region `region` in `local`'s type /// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. -pub(super) fn add_drop_of_var_derefs_origin<'tcx>( +pub(super) fn emit_drop_facts<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, kind: &GenericArg<'tcx>, ) { - debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind); + debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind); if let Some(facts) = typeck.all_facts.as_mut() { let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let universal_regions = &typeck.universal_regions; @@ -134,3 +64,60 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>( }); } } + +/// MIR visitor extracting point-wise facts about accesses. +struct AccessFactsExtractor<'a, 'tcx> { + var_defined_at: &'a mut VarPointRelation, + var_used_at: &'a mut VarPointRelation, + location_table: &'a LocationTable, + var_dropped_at: &'a mut VarPointRelation, + move_data: &'a MoveData<'tcx>, + path_accessed_at_base: &'a mut PathPointRelation, +} + +impl<'tcx> AccessFactsExtractor<'_, 'tcx> { + fn location_to_index(&self, location: Location) -> LocationIndex { + self.location_table.mid_index(location) + } +} + +impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> { + fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { + match def_use::categorize(context) { + Some(DefUse::Def) => { + debug!("AccessFactsExtractor - emit def"); + self.var_defined_at.push((local, self.location_to_index(location))); + } + Some(DefUse::Use) => { + debug!("AccessFactsExtractor - emit use"); + self.var_used_at.push((local, self.location_to_index(location))); + } + Some(DefUse::Drop) => { + debug!("AccessFactsExtractor - emit drop"); + self.var_dropped_at.push((local, self.location_to_index(location))); + } + _ => (), + } + } + + fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) { + self.super_place(place, context, location); + + match context { + PlaceContext::NonMutatingUse(_) + | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => { + let path = match self.move_data.rev_lookup.find(place.as_ref()) { + LookupResult::Exact(path) | LookupResult::Parent(Some(path)) => path, + _ => { + // There's no path access to emit. + return; + } + }; + debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})"); + self.path_accessed_at_base.push((path, self.location_to_index(location))); + } + + _ => {} + } + } +} diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 3ec36c16cbf..539d3f97a63 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -590,7 +590,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { // the destructor and must be live at this point. for &kind in &drop_data.dropck_result.kinds { Self::make_all_regions_live(self.elements, self.typeck, kind, live_at); - polonius::add_drop_of_var_derefs_origin(self.typeck, dropped_local, &kind); + polonius::emit_drop_facts(self.typeck, dropped_local, &kind); } }