From 2fd443888e3157786c5602ceb80adfce43061353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 12:58:49 +0000 Subject: [PATCH 1/8] clean up `emit_access_facts` - remove dependency on `TypeChecker` - move to legacy fact generation module --- .../src/polonius/legacy/accesses.rs | 106 ++++++++++++++++++ .../rustc_borrowck/src/polonius/legacy/mod.rs | 3 + .../src/type_check/liveness/mod.rs | 9 +- .../src/type_check/liveness/polonius.rs | 106 +----------------- 4 files changed, 120 insertions(+), 104 deletions(-) create mode 100644 compiler/rustc_borrowck/src/polonius/legacy/accesses.rs diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs new file mode 100644 index 0000000000000..406fdba0f83df --- /dev/null +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -0,0 +1,106 @@ +use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; +use rustc_middle::mir::{Body, Local, Location, Place}; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use tracing::debug; + +use crate::def_use::{self, DefUse}; +use crate::facts::AllFacts; +use crate::location::{LocationIndex, LocationTable}; +use crate::universal_regions::UniversalRegions; + +type VarPointRelation = Vec<(Local, LocationIndex)>; +type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; + +/// Emit polonius facts for variable defs, uses, drops, and path accesses. +pub(crate) fn emit_access_facts<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + move_data: &MoveData<'tcx>, + universal_regions: &UniversalRegions<'tcx>, + location_table: &LocationTable, + all_facts: &mut Option, +) { + if let Some(facts) = all_facts.as_mut() { + debug!("emit_access_facts()"); + + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + 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, + path_accessed_at_base: &mut facts.path_accessed_at_base, + location_table, + move_data, + }; + extractor.visit_body(body); + + for (local, local_decl) in body.local_decls.iter_enumerated() { + debug!( + "add use_of_var_derefs_origin facts - local={:?}, type={:?}", + local, local_decl.ty + ); + tcx.for_each_free_region(&local_decl.ty, |region| { + let region_vid = universal_regions.to_region_vid(region); + facts.use_of_var_derefs_origin.push((local, region_vid.into())); + }); + } + } +} + +/// 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/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 9fccc00bdaf0e..593b7c5da9091 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -13,9 +13,12 @@ use crate::facts::{AllFacts, PoloniusRegionVid}; use crate::location::LocationTable; use crate::type_check::free_region_relations::UniversalRegionRelations; +mod accesses; mod loan_invalidations; mod loan_kills; +pub(crate) use accesses::emit_access_facts; + /// When requested, emit most of the facts needed by polonius: /// - moves and assignments /// - universal regions and their relations diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 05e4a176a6d19..4e1dfc6a8be04 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -45,7 +45,14 @@ pub(super) fn generate<'a, 'tcx>( let (relevant_live_locals, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body); - polonius::emit_access_facts(typeck, body, move_data); + crate::polonius::legacy::emit_access_facts( + typeck.tcx(), + body, + move_data, + typeck.universal_regions, + typeck.location_table, + typeck.all_facts, + ); 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 5ffba94ee6821..4c8a8d3e4ec2e 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -1,54 +1,11 @@ -use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; -use rustc_middle::mir::{Body, Local, Location, Place}; +use rustc_middle::mir::Local; use rustc_middle::ty::GenericArg; -use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use tracing::debug; -use super::TypeChecker; -use crate::def_use::{self, DefUse}; -use crate::location::{LocationIndex, LocationTable}; - -type VarPointRelation = Vec<(Local, LocationIndex)>; -type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; - -/// 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!("emit_access_facts()"); - - let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - let location_table = typeck.location_table; - - 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, - path_accessed_at_base: &mut facts.path_accessed_at_base, - location_table, - move_data, - }; - extractor.visit_body(body); - - for (local, local_decl) in body.local_decls.iter_enumerated() { - debug!( - "add use_of_var_derefs_origin facts - local={:?}, type={:?}", - local, local_decl.ty - ); - 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); - facts.use_of_var_derefs_origin.push((local, region_vid.into())); - }); - } - } -} +use crate::type_check::TypeChecker; /// For every potentially drop()-touched region `region` in `local`'s type -/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. +/// (`kind`), emit a Polonius `drop_of_var_derefs_origin(local, origin)` fact. pub(super) fn emit_drop_facts<'tcx>( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, @@ -64,60 +21,3 @@ pub(super) fn emit_drop_facts<'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))); - } - - _ => {} - } - } -} From 9d8f58adb27536fdd87a941fb5c770d8bcef6cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 13:12:43 +0000 Subject: [PATCH 2/8] clean up `emit_drop_facts` - remove dependency on `TypeChecker` - move to legacy fact generation module - remove polonius module from liveness --- .../rustc_borrowck/src/polonius/legacy/mod.rs | 24 +++++++++++++++++-- .../src/type_check/liveness/mod.rs | 4 ++-- .../src/type_check/liveness/polonius.rs | 23 ------------------ .../src/type_check/liveness/trace.rs | 10 ++++++-- 4 files changed, 32 insertions(+), 29 deletions(-) delete mode 100644 compiler/rustc_borrowck/src/type_check/liveness/polonius.rs diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 593b7c5da9091..154b679ac3db9 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -3,8 +3,8 @@ //! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature //! parity. -use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK}; -use rustc_middle::ty::TyCtxt; +use rustc_middle::mir::{Body, Local, LocalKind, Location, START_BLOCK}; +use rustc_middle::ty::{GenericArg, TyCtxt}; use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; use tracing::debug; @@ -12,6 +12,7 @@ use crate::borrow_set::BorrowSet; use crate::facts::{AllFacts, PoloniusRegionVid}; use crate::location::LocationTable; use crate::type_check::free_region_relations::UniversalRegionRelations; +use crate::universal_regions::UniversalRegions; mod accesses; mod loan_invalidations; @@ -185,3 +186,22 @@ fn emit_cfg_and_loan_kills_facts<'tcx>( ) { loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set); } + +/// For every potentially drop()-touched region `region` in `local`'s type +/// (`kind`), emit a `drop_of_var_derefs_origin(local, origin)` fact. +pub(crate) fn emit_drop_facts<'tcx>( + tcx: TyCtxt<'tcx>, + local: Local, + kind: &GenericArg<'tcx>, + universal_regions: &UniversalRegions<'tcx>, + all_facts: &mut Option, +) { + debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind); + if let Some(facts) = all_facts.as_mut() { + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + tcx.for_each_free_region(kind, |drop_live_region| { + let region_vid = universal_regions.to_region_vid(drop_live_region); + facts.drop_of_var_derefs_origin.push((local, region_vid.into())); + }); + } +} diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 4e1dfc6a8be04..26b738599fdef 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -13,11 +13,11 @@ use tracing::debug; use super::TypeChecker; use crate::constraints::OutlivesConstraintSet; +use crate::polonius; use crate::region_infer::values::LivenessValues; use crate::universal_regions::UniversalRegions; mod local_use_map; -mod polonius; mod trace; /// Combines liveness analysis with initialization analysis to @@ -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); - crate::polonius::legacy::emit_access_facts( + polonius::legacy::emit_access_facts( typeck.tcx(), body, move_data, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs deleted file mode 100644 index 4c8a8d3e4ec2e..0000000000000 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ /dev/null @@ -1,23 +0,0 @@ -use rustc_middle::mir::Local; -use rustc_middle::ty::GenericArg; -use tracing::debug; - -use crate::type_check::TypeChecker; - -/// For every potentially drop()-touched region `region` in `local`'s type -/// (`kind`), emit a Polonius `drop_of_var_derefs_origin(local, origin)` fact. -pub(super) fn emit_drop_facts<'tcx>( - typeck: &mut TypeChecker<'_, 'tcx>, - local: Local, - kind: &GenericArg<'tcx>, -) { - 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; - typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| { - let region_vid = universal_regions.to_region_vid(drop_live_region); - facts.drop_of_var_derefs_origin.push((local, region_vid.into())); - }); - } -} diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 539d3f97a6387..f510d193dd9f1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -15,9 +15,9 @@ use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOp, Type use tracing::debug; use crate::location::RichLocation; +use crate::polonius; use crate::region_infer::values::{self, LiveLoans}; use crate::type_check::liveness::local_use_map::LocalUseMap; -use crate::type_check::liveness::polonius; use crate::type_check::{NormalizeLocation, TypeChecker}; /// This is the heart of the liveness computation. For each variable X @@ -590,7 +590,13 @@ 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::emit_drop_facts(self.typeck, dropped_local, &kind); + polonius::legacy::emit_drop_facts( + self.typeck.tcx(), + dropped_local, + &kind, + self.typeck.universal_regions, + self.typeck.all_facts, + ); } } From afbe101f0ea0811a541dd15cba993644a1d9af1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 13:33:58 +0000 Subject: [PATCH 3/8] clean up `translate_outlives_facts` - remove dependency on `TypeChecker` - move to legacy fact generation module - group facts emitted during typeck together --- .../rustc_borrowck/src/polonius/legacy/mod.rs | 33 +++++++++++++++ .../src/type_check/liveness/mod.rs | 10 ----- compiler/rustc_borrowck/src/type_check/mod.rs | 42 +++++++------------ 3 files changed, 48 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 154b679ac3db9..4c98dfa7e3e37 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -3,14 +3,19 @@ //! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature //! parity. +use std::iter; + +use either::Either; use rustc_middle::mir::{Body, Local, LocalKind, Location, START_BLOCK}; use rustc_middle::ty::{GenericArg, TyCtxt}; use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; use tracing::debug; use crate::borrow_set::BorrowSet; +use crate::constraints::OutlivesConstraint; use crate::facts::{AllFacts, PoloniusRegionVid}; use crate::location::LocationTable; +use crate::type_check::MirTypeckRegionConstraints; use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::universal_regions::UniversalRegions; @@ -205,3 +210,31 @@ pub(crate) fn emit_drop_facts<'tcx>( }); } } + +/// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive +/// closure. +pub(crate) fn emit_outlives_facts<'tcx>( + tcx: TyCtxt<'tcx>, + constraints: &MirTypeckRegionConstraints<'tcx>, + location_table: &LocationTable, + all_facts: &mut Option, +) { + if let Some(facts) = all_facts { + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map( + |constraint: &OutlivesConstraint<'_>| { + if let Some(from_location) = constraint.locations.from_location() { + Either::Left(iter::once(( + constraint.sup.into(), + constraint.sub.into(), + location_table.mid_index(from_location), + ))) + } else { + Either::Right(location_table.all_points().map(move |location| { + (constraint.sup.into(), constraint.sub.into(), location) + })) + } + }, + )); + } +} diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 26b738599fdef..683293bf82863 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -13,7 +13,6 @@ use tracing::debug; use super::TypeChecker; use crate::constraints::OutlivesConstraintSet; -use crate::polonius; use crate::region_infer::values::LivenessValues; use crate::universal_regions::UniversalRegions; @@ -45,15 +44,6 @@ pub(super) fn generate<'a, 'tcx>( let (relevant_live_locals, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body); - polonius::legacy::emit_access_facts( - typeck.tcx(), - body, - move_data, - typeck.universal_regions, - typeck.location_table, - typeck.all_facts, - ); - trace::trace( typeck, body, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 90d327b0ad20d..2820d1d230468 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -3,7 +3,6 @@ use std::rc::Rc; use std::{fmt, iter, mem}; -use either::Either; use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -60,7 +59,7 @@ use crate::renumber::RegionCtxt; use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; use crate::universal_regions::{DefiningTy, UniversalRegions}; -use crate::{BorrowckInferCtxt, path_utils}; +use crate::{BorrowckInferCtxt, path_utils, polonius}; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -182,7 +181,20 @@ pub(crate) fn type_check<'a, 'tcx>( liveness::generate(&mut checker, body, &elements, flow_inits, move_data); - translate_outlives_facts(&mut checker); + polonius::legacy::emit_access_facts( + infcx.tcx, + body, + move_data, + &universal_region_relations.universal_regions, + location_table, + checker.all_facts, + ); + polonius::legacy::emit_outlives_facts( + infcx.tcx, + checker.constraints, + location_table, + checker.all_facts, + ); let opaque_type_values = infcx.take_opaque_types(); let opaque_type_values = opaque_type_values @@ -234,30 +246,6 @@ pub(crate) fn type_check<'a, 'tcx>( MirTypeckResults { constraints, universal_region_relations, opaque_type_values } } -fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { - if let Some(facts) = typeck.all_facts { - let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - let location_table = typeck.location_table; - facts.subset_base.extend( - typeck.constraints.outlives_constraints.outlives().iter().flat_map( - |constraint: &OutlivesConstraint<'_>| { - if let Some(from_location) = constraint.locations.from_location() { - Either::Left(iter::once(( - constraint.sup.into(), - constraint.sub.into(), - location_table.mid_index(from_location), - ))) - } else { - Either::Right(location_table.all_points().map(move |location| { - (constraint.sup.into(), constraint.sub.into(), location) - })) - } - }, - ), - ); - } -} - #[track_caller] fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) { // We sometimes see MIR failures (notably predicate failures) due to From 5486857448ad37a90ed1d75c87fac8adb9884894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 13:57:34 +0000 Subject: [PATCH 4/8] use let else more consistently in fact generation also remove a useless trace --- .../src/polonius/legacy/accesses.rs | 40 ++++++-------- .../rustc_borrowck/src/polonius/legacy/mod.rs | 52 +++++++++---------- 2 files changed, 43 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs index 406fdba0f83df..4266aba9cc551 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -21,30 +21,24 @@ pub(crate) fn emit_access_facts<'tcx>( location_table: &LocationTable, all_facts: &mut Option, ) { - if let Some(facts) = all_facts.as_mut() { - debug!("emit_access_facts()"); + let Some(facts) = all_facts.as_mut() else { return }; + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + 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, + path_accessed_at_base: &mut facts.path_accessed_at_base, + location_table, + move_data, + }; + extractor.visit_body(body); - let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - 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, - path_accessed_at_base: &mut facts.path_accessed_at_base, - location_table, - move_data, - }; - extractor.visit_body(body); - - for (local, local_decl) in body.local_decls.iter_enumerated() { - debug!( - "add use_of_var_derefs_origin facts - local={:?}, type={:?}", - local, local_decl.ty - ); - tcx.for_each_free_region(&local_decl.ty, |region| { - let region_vid = universal_regions.to_region_vid(region); - facts.use_of_var_derefs_origin.push((local, region_vid.into())); - }); - } + for (local, local_decl) in body.local_decls.iter_enumerated() { + debug!("add use_of_var_derefs_origin facts - local={:?}, type={:?}", local, local_decl.ty); + tcx.for_each_free_region(&local_decl.ty, |region| { + let region_vid = universal_regions.to_region_vid(region); + facts.use_of_var_derefs_origin.push((local, region_vid.into())); + }); } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 4c98dfa7e3e37..15988fad57f6d 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -39,8 +39,8 @@ pub(crate) fn emit_facts<'tcx>( location_table: &LocationTable, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, - move_data: &MoveData<'_>, - universal_region_relations: &UniversalRegionRelations<'_>, + move_data: &MoveData<'tcx>, + universal_region_relations: &UniversalRegionRelations<'tcx>, ) { let Some(all_facts) = all_facts else { // We don't do anything if there are no facts to fill. @@ -202,13 +202,12 @@ pub(crate) fn emit_drop_facts<'tcx>( all_facts: &mut Option, ) { debug!("emit_drop_facts(local={:?}, kind={:?}", local, kind); - if let Some(facts) = all_facts.as_mut() { - let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - tcx.for_each_free_region(kind, |drop_live_region| { - let region_vid = universal_regions.to_region_vid(drop_live_region); - facts.drop_of_var_derefs_origin.push((local, region_vid.into())); - }); - } + let Some(facts) = all_facts.as_mut() else { return }; + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + tcx.for_each_free_region(kind, |drop_live_region| { + let region_vid = universal_regions.to_region_vid(drop_live_region); + facts.drop_of_var_derefs_origin.push((local, region_vid.into())); + }); } /// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive @@ -219,22 +218,23 @@ pub(crate) fn emit_outlives_facts<'tcx>( location_table: &LocationTable, all_facts: &mut Option, ) { - if let Some(facts) = all_facts { - let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map( - |constraint: &OutlivesConstraint<'_>| { - if let Some(from_location) = constraint.locations.from_location() { - Either::Left(iter::once(( - constraint.sup.into(), - constraint.sub.into(), - location_table.mid_index(from_location), - ))) - } else { - Either::Right(location_table.all_points().map(move |location| { + let Some(facts) = all_facts else { return }; + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map( + |constraint: &OutlivesConstraint<'_>| { + if let Some(from_location) = constraint.locations.from_location() { + Either::Left(iter::once(( + constraint.sup.into(), + constraint.sub.into(), + location_table.mid_index(from_location), + ))) + } else { + Either::Right( + location_table.all_points().map(move |location| { (constraint.sup.into(), constraint.sub.into(), location) - })) - } - }, - )); - } + }), + ) + } + }, + )); } From 1740a5f84a19da866915e53f1dc05a9f929b4b37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 14:09:08 +0000 Subject: [PATCH 5/8] simplify `emit_access_facts` and fact generation - integrate it within existing fact generation instead of being called in typeck - simplify access fact extraction - also remove single use fact emit functions in root fact generation --- .../src/polonius/legacy/accesses.rs | 33 +++++----------- .../rustc_borrowck/src/polonius/legacy/mod.rs | 38 ++++++------------- compiler/rustc_borrowck/src/type_check/mod.rs | 8 ---- 3 files changed, 21 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs index 4266aba9cc551..b4c39567da1b9 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -1,7 +1,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, Place}; use rustc_middle::ty::TyCtxt; -use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use rustc_mir_dataflow::move_paths::{LookupResult, MoveData}; use tracing::debug; use crate::def_use::{self, DefUse}; @@ -9,28 +9,16 @@ use crate::facts::AllFacts; use crate::location::{LocationIndex, LocationTable}; use crate::universal_regions::UniversalRegions; -type VarPointRelation = Vec<(Local, LocationIndex)>; -type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; - /// Emit polonius facts for variable defs, uses, drops, and path accesses. pub(crate) fn emit_access_facts<'tcx>( + facts: &mut AllFacts, tcx: TyCtxt<'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, universal_regions: &UniversalRegions<'tcx>, location_table: &LocationTable, - all_facts: &mut Option, ) { - let Some(facts) = all_facts.as_mut() else { return }; - let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - 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, - path_accessed_at_base: &mut facts.path_accessed_at_base, - location_table, - move_data, - }; + let mut extractor = AccessFactsExtractor { facts, move_data, location_table }; extractor.visit_body(body); for (local, local_decl) in body.local_decls.iter_enumerated() { @@ -44,12 +32,9 @@ pub(crate) fn emit_access_facts<'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, + facts: &'a mut AllFacts, move_data: &'a MoveData<'tcx>, - path_accessed_at_base: &'a mut PathPointRelation, + location_table: &'a LocationTable, } impl<'tcx> AccessFactsExtractor<'_, 'tcx> { @@ -63,15 +48,15 @@ impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> { match def_use::categorize(context) { Some(DefUse::Def) => { debug!("AccessFactsExtractor - emit def"); - self.var_defined_at.push((local, self.location_to_index(location))); + self.facts.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))); + self.facts.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))); + self.facts.var_dropped_at.push((local, self.location_to_index(location))); } _ => (), } @@ -91,7 +76,7 @@ impl<'a, 'tcx> Visitor<'tcx> for AccessFactsExtractor<'a, 'tcx> { } }; debug!("AccessFactsExtractor - emit path access ({path:?}, {location:?})"); - self.path_accessed_at_base.push((path, self.location_to_index(location))); + self.facts.path_accessed_at_base.push((path, self.location_to_index(location))); } _ => {} diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 15988fad57f6d..d1363d98c88b3 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -23,14 +23,14 @@ mod accesses; mod loan_invalidations; mod loan_kills; -pub(crate) use accesses::emit_access_facts; - /// When requested, emit most of the facts needed by polonius: /// - moves and assignments /// - universal regions and their relations /// - CFG points and edges /// - loan kills /// - loan invalidations +/// - access facts such as variable definitions, uses, drops, and path accesses +/// - outlives constraints /// /// The rest of the facts are emitted during typeck and liveness. pub(crate) fn emit_facts<'tcx>( @@ -49,8 +49,16 @@ pub(crate) fn emit_facts<'tcx>( let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); emit_move_facts(all_facts, move_data, location_table, body); emit_universal_region_facts(all_facts, borrow_set, universal_region_relations); - emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set); - emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set); + loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set); + loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set); + accesses::emit_access_facts( + all_facts, + tcx, + body, + move_data, + &universal_region_relations.universal_regions, + location_table, + ); } /// Emit facts needed for move/init analysis: moves and assignments. @@ -170,28 +178,6 @@ fn emit_universal_region_facts( } } -/// Emit facts about loan invalidations. -fn emit_loan_invalidations_facts<'tcx>( - all_facts: &mut AllFacts, - tcx: TyCtxt<'tcx>, - location_table: &LocationTable, - body: &Body<'tcx>, - borrow_set: &BorrowSet<'tcx>, -) { - loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set); -} - -/// Emit facts about CFG points and edges, as well as locations where loans are killed. -fn emit_cfg_and_loan_kills_facts<'tcx>( - all_facts: &mut AllFacts, - tcx: TyCtxt<'tcx>, - location_table: &LocationTable, - body: &Body<'tcx>, - borrow_set: &BorrowSet<'tcx>, -) { - loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set); -} - /// For every potentially drop()-touched region `region` in `local`'s type /// (`kind`), emit a `drop_of_var_derefs_origin(local, origin)` fact. pub(crate) fn emit_drop_facts<'tcx>( diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 2820d1d230468..94ef491814dfe 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -181,14 +181,6 @@ pub(crate) fn type_check<'a, 'tcx>( liveness::generate(&mut checker, body, &elements, flow_inits, move_data); - polonius::legacy::emit_access_facts( - infcx.tcx, - body, - move_data, - &universal_region_relations.universal_regions, - location_table, - checker.all_facts, - ); polonius::legacy::emit_outlives_facts( infcx.tcx, checker.constraints, From 2024c5d8697d68c735e253986a5fe29aab8e2b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 14:22:59 +0000 Subject: [PATCH 6/8] simplify `emit_outlives_facts` - integrate into `emit_facts` and remove from typeck --- compiler/rustc_borrowck/src/nll.rs | 1 + compiler/rustc_borrowck/src/polonius/legacy/mod.rs | 11 +++++------ compiler/rustc_borrowck/src/type_check/mod.rs | 8 +------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index d7ea8e1bcc2cc..2bd067d416142 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -124,6 +124,7 @@ pub(crate) fn compute_regions<'a, 'tcx>( borrow_set, move_data, &universal_region_relations, + &constraints, ); let mut regioncx = RegionInferenceContext::new( diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index d1363d98c88b3..9cf88704e3a5c 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -41,6 +41,7 @@ pub(crate) fn emit_facts<'tcx>( borrow_set: &BorrowSet<'tcx>, move_data: &MoveData<'tcx>, universal_region_relations: &UniversalRegionRelations<'tcx>, + constraints: &MirTypeckRegionConstraints<'tcx>, ) { let Some(all_facts) = all_facts else { // We don't do anything if there are no facts to fill. @@ -59,6 +60,7 @@ pub(crate) fn emit_facts<'tcx>( &universal_region_relations.universal_regions, location_table, ); + emit_outlives_facts(all_facts, location_table, constraints); } /// Emit facts needed for move/init analysis: moves and assignments. @@ -198,14 +200,11 @@ pub(crate) fn emit_drop_facts<'tcx>( /// Emit facts about the outlives constraints: the `subset` base relation, i.e. not a transitive /// closure. -pub(crate) fn emit_outlives_facts<'tcx>( - tcx: TyCtxt<'tcx>, - constraints: &MirTypeckRegionConstraints<'tcx>, +fn emit_outlives_facts<'tcx>( + facts: &mut AllFacts, location_table: &LocationTable, - all_facts: &mut Option, + constraints: &MirTypeckRegionConstraints<'tcx>, ) { - let Some(facts) = all_facts else { return }; - let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); facts.subset_base.extend(constraints.outlives_constraints.outlives().iter().flat_map( |constraint: &OutlivesConstraint<'_>| { if let Some(from_location) = constraint.locations.from_location() { diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 94ef491814dfe..20668fc3397ef 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -59,7 +59,7 @@ use crate::renumber::RegionCtxt; use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; use crate::universal_regions::{DefiningTy, UniversalRegions}; -use crate::{BorrowckInferCtxt, path_utils, polonius}; +use crate::{BorrowckInferCtxt, path_utils}; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -181,12 +181,6 @@ pub(crate) fn type_check<'a, 'tcx>( liveness::generate(&mut checker, body, &elements, flow_inits, move_data); - polonius::legacy::emit_outlives_facts( - infcx.tcx, - checker.constraints, - location_table, - checker.all_facts, - ); let opaque_type_values = infcx.take_opaque_types(); let opaque_type_values = opaque_type_values From 7ad1f5bec596a8c23bf03e83eae6958f85951761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 14:40:49 +0000 Subject: [PATCH 7/8] refactor `type_check` module slightly - use a consistent name for `TypeChecker`, which is usually referred to as `typeck` - remove an incorrect doc comment - remove a single-use local --- compiler/rustc_borrowck/src/type_check/mod.rs | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 20668fc3397ef..de0804b01895a 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -106,7 +106,6 @@ mod relate_tys; /// # Parameters /// /// - `infcx` -- inference context to use -/// - `param_env` -- parameter environment to use for trait solving /// - `body` -- MIR body to type-check /// - `promoted` -- map of promoted constants within `body` /// - `universal_regions` -- the universal regions from `body`s function signature @@ -154,7 +153,7 @@ pub(crate) fn type_check<'a, 'tcx>( debug!(?normalized_inputs_and_output); - let mut checker = TypeChecker { + let mut typeck = TypeChecker { infcx, last_span: body.span, body, @@ -170,23 +169,22 @@ pub(crate) fn type_check<'a, 'tcx>( constraints: &mut constraints, }; - checker.check_user_type_annotations(); + typeck.check_user_type_annotations(); - let mut verifier = TypeVerifier { cx: &mut checker, promoted, last_span: body.span }; + let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span }; verifier.visit_body(body); - checker.typeck_mir(body); - checker.equate_inputs_and_outputs(body, &normalized_inputs_and_output); - checker.check_signature_annotation(body); + typeck.typeck_mir(body); + typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output); + typeck.check_signature_annotation(body); - liveness::generate(&mut checker, body, &elements, flow_inits, move_data); + liveness::generate(&mut typeck, body, &elements, flow_inits, move_data); - let opaque_type_values = infcx.take_opaque_types(); - - let opaque_type_values = opaque_type_values + let opaque_type_values = infcx + .take_opaque_types() .into_iter() .map(|(opaque_type_key, decl)| { - let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op( + let _: Result<_, ErrorGuaranteed> = typeck.fully_perform_op( Locations::All(body.span), ConstraintCategory::OpaqueType, CustomTypeOp::new( @@ -216,11 +214,11 @@ pub(crate) fn type_check<'a, 'tcx>( match region.kind() { ty::ReVar(_) => region, ty::RePlaceholder(placeholder) => { - checker.constraints.placeholder_region(infcx, placeholder) + typeck.constraints.placeholder_region(infcx, placeholder) } _ => ty::Region::new_var( infcx.tcx, - checker.universal_regions.to_region_vid(region), + typeck.universal_regions.to_region_vid(region), ), } }); @@ -250,7 +248,7 @@ enum FieldAccessError { /// type, calling `span_mirbug` and returning an error type if there /// is a problem. struct TypeVerifier<'a, 'b, 'tcx> { - cx: &'a mut TypeChecker<'b, 'tcx>, + typeck: &'a mut TypeChecker<'b, 'tcx>, promoted: &'b IndexSlice>, last_span: Span, } @@ -272,9 +270,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { self.super_const_operand(constant, location); let ty = self.sanitize_type(constant, constant.const_.ty()); - self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| { - let live_region_vid = self.cx.universal_regions.to_region_vid(live_region); - self.cx.constraints.liveness_constraints.add_location(live_region_vid, location); + self.typeck.infcx.tcx.for_each_free_region(&ty, |live_region| { + let live_region_vid = self.typeck.universal_regions.to_region_vid(live_region); + self.typeck.constraints.liveness_constraints.add_location(live_region_vid, location); }); // HACK(compiler-errors): Constants that are gathered into Body.required_consts @@ -286,14 +284,14 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { }; if let Some(annotation_index) = constant.user_ty { - if let Err(terr) = self.cx.relate_type_and_user_type( + if let Err(terr) = self.typeck.relate_type_and_user_type( constant.const_.ty(), ty::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![] }, locations, ConstraintCategory::Boring, ) { - let annotation = &self.cx.user_type_annotations[annotation_index]; + let annotation = &self.typeck.user_type_annotations[annotation_index]; span_mirbug!( self, constant, @@ -322,9 +320,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { promoted: &Body<'tcx>, ty, san_ty| { - if let Err(terr) = - verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring) - { + if let Err(terr) = verifier.typeck.eq_types( + ty, + san_ty, + locations, + ConstraintCategory::Boring, + ) { span_mirbug!( verifier, promoted, @@ -342,21 +343,21 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let promoted_ty = promoted_body.return_ty(); check_err(self, promoted_body, ty, promoted_ty); } else { - self.cx.ascribe_user_type( + self.typeck.ascribe_user_type( constant.const_.ty(), ty::UserType::new(ty::UserTypeKind::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None, })), - locations.span(self.cx.body), + locations.span(self.typeck.body), ); } } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity(); - let normalized_ty = self.cx.normalize(unnormalized_ty, locations); + let normalized_ty = self.typeck.normalize(unnormalized_ty, locations); let literal_ty = constant.const_.ty().builtin_deref(true).unwrap(); - if let Err(terr) = self.cx.eq_types( + if let Err(terr) = self.typeck.eq_types( literal_ty, normalized_ty, locations, @@ -368,7 +369,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args); - self.cx.normalize_and_prove_instantiated_predicates( + self.typeck.normalize_and_prove_instantiated_predicates( def_id, instantiated_predicates, locations, @@ -378,7 +379,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)), Some(DefKind::Impl { of_trait: true }) )); - self.cx.prove_predicates( + self.typeck.prove_predicates( args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())), locations, ConstraintCategory::Boring, @@ -412,7 +413,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { local_decl.ty }; - if let Err(terr) = self.cx.relate_type_and_user_type( + if let Err(terr) = self.typeck.relate_type_and_user_type( ty, ty::Invariant, user_ty, @@ -442,11 +443,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { fn body(&self) -> &Body<'tcx> { - self.cx.body + self.typeck.body } fn tcx(&self) -> TyCtxt<'tcx> { - self.cx.infcx.tcx + self.typeck.infcx.tcx } fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> { @@ -496,7 +497,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // whether the bounds fully apply: in effect, the rule is // that if a value of some type could implement `Copy`, then // it must. - self.cx.prove_trait_ref( + self.typeck.prove_trait_ref( trait_ref, location.to_locations(), ConstraintCategory::CopyBound, @@ -511,7 +512,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // checker on the promoted MIR, then transfer the constraints back to // the main MIR, changing the locations to the provided location. - let parent_body = mem::replace(&mut self.cx.body, promoted_body); + let parent_body = mem::replace(&mut self.typeck.body, promoted_body); // Use new sets of constraints and closure bounds so that we can // modify their locations. @@ -522,18 +523,18 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // Don't try to add borrow_region facts for the promoted MIR let mut swap_constraints = |this: &mut Self| { - mem::swap(this.cx.all_facts, all_facts); - mem::swap(&mut this.cx.constraints.outlives_constraints, &mut constraints); - mem::swap(&mut this.cx.constraints.liveness_constraints, &mut liveness_constraints); + mem::swap(this.typeck.all_facts, all_facts); + mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints); + mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints); }; swap_constraints(self); self.visit_body(promoted_body); - self.cx.typeck_mir(promoted_body); + self.typeck.typeck_mir(promoted_body); - self.cx.body = parent_body; + self.typeck.body = parent_body; // Merge the outlives constraints back in, at the given location. swap_constraints(self); @@ -549,7 +550,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // temporary from the user's point of view. constraint.category = ConstraintCategory::Boring; } - self.cx.constraints.outlives_constraints.push(constraint) + self.typeck.constraints.outlives_constraints.push(constraint) } // If the region is live at least one location in the promoted MIR, // then add a liveness constraint to the main MIR for this region @@ -559,7 +560,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { // unordered. #[allow(rustc::potential_query_instability)] for region in liveness_constraints.live_regions_unordered() { - self.cx.constraints.liveness_constraints.add_location(region, location); + self.typeck.constraints.liveness_constraints.add_location(region, location); } } @@ -643,13 +644,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }, ProjectionElem::Field(field, fty) => { let fty = self.sanitize_type(place, fty); - let fty = self.cx.normalize(fty, location); + let fty = self.typeck.normalize(fty, location); match self.field_ty(place, base, field, location) { Ok(ty) => { - let ty = self.cx.normalize(ty, location); + let ty = self.typeck.normalize(ty, location); debug!(?fty, ?ty); - if let Err(terr) = self.cx.relate_types( + if let Err(terr) = self.typeck.relate_types( ty, self.get_ambient_variance(context), fty, @@ -681,8 +682,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } ProjectionElem::OpaqueCast(ty) => { let ty = self.sanitize_type(place, ty); - let ty = self.cx.normalize(ty, location); - self.cx + let ty = self.typeck.normalize(ty, location); + self.typeck .relate_types( ty, self.get_ambient_variance(context), @@ -791,7 +792,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }; if let Some(field) = variant.fields.get(field) { - Ok(self.cx.normalize(field.ty(tcx, args), location)) + Ok(self.typeck.normalize(field.ty(tcx, args), location)) } else { Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() }) } From 8562497d0a42c5ab8a9b91ce45f38c4eb9ff5687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 11 Dec 2024 15:23:32 +0000 Subject: [PATCH 8/8] improve consistency within fact gen - fix names - fix ordering of arguments --- .../src/polonius/legacy/accesses.rs | 4 +- .../src/polonius/legacy/loan_invalidations.rs | 16 +++---- .../src/polonius/legacy/loan_kills.rs | 24 +++++----- .../rustc_borrowck/src/polonius/legacy/mod.rs | 46 +++++++++---------- 4 files changed, 44 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs index b4c39567da1b9..9c4aa8ea1edb7 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/accesses.rs @@ -11,12 +11,12 @@ use crate::universal_regions::UniversalRegions; /// Emit polonius facts for variable defs, uses, drops, and path accesses. pub(crate) fn emit_access_facts<'tcx>( - facts: &mut AllFacts, tcx: TyCtxt<'tcx>, + facts: &mut AllFacts, body: &Body<'tcx>, + location_table: &LocationTable, move_data: &MoveData<'tcx>, universal_regions: &UniversalRegions<'tcx>, - location_table: &LocationTable, ) { let mut extractor = AccessFactsExtractor { facts, move_data, location_table }; extractor.visit_body(body); diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs index f646beeecf7b3..0d5b6f3a2c8c2 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs @@ -21,22 +21,22 @@ use crate::{ /// Emit `loan_invalidated_at` facts. pub(super) fn emit_loan_invalidations<'tcx>( tcx: TyCtxt<'tcx>, - all_facts: &mut AllFacts, - location_table: &LocationTable, + facts: &mut AllFacts, body: &Body<'tcx>, + location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, ) { let dominators = body.basic_blocks.dominators(); let mut visitor = - LoanInvalidationsGenerator { all_facts, borrow_set, tcx, location_table, body, dominators }; + LoanInvalidationsGenerator { facts, borrow_set, tcx, location_table, body, dominators }; visitor.visit_body(body); } struct LoanInvalidationsGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, - all_facts: &'a mut AllFacts, - location_table: &'a LocationTable, + facts: &'a mut AllFacts, body: &'a Body<'tcx>, + location_table: &'a LocationTable, dominators: &'a Dominators, borrow_set: &'a BorrowSet<'tcx>, } @@ -151,7 +151,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { let resume = self.location_table.start_index(resume.start_location()); for (i, data) in borrow_set.iter_enumerated() { if borrow_of_local_data(data.borrowed_place) { - self.all_facts.loan_invalidated_at.push((resume, i)); + self.facts.loan_invalidated_at.push((resume, i)); } } @@ -165,7 +165,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> { let start = self.location_table.start_index(location); for (i, data) in borrow_set.iter_enumerated() { if borrow_of_local_data(data.borrowed_place) { - self.all_facts.loan_invalidated_at.push((start, i)); + self.facts.loan_invalidated_at.push((start, i)); } } } @@ -409,7 +409,7 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> { /// Generates a new `loan_invalidated_at(L, B)` fact. fn emit_loan_invalidated_at(&mut self, b: BorrowIndex, l: Location) { let lidx = self.location_table.start_index(l); - self.all_facts.loan_invalidated_at.push((lidx, b)); + self.facts.loan_invalidated_at.push((lidx, b)); } fn check_activations(&mut self, location: Location) { diff --git a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs index 68e0865ab82c9..fdde9fa047621 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/loan_kills.rs @@ -14,12 +14,12 @@ use crate::places_conflict; /// Emit `loan_killed_at` and `cfg_edge` facts at the same time. pub(super) fn emit_loan_kills<'tcx>( tcx: TyCtxt<'tcx>, - all_facts: &mut AllFacts, - location_table: &LocationTable, + facts: &mut AllFacts, body: &Body<'tcx>, + location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, ) { - let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, all_facts, body }; + let mut visitor = LoanKillsGenerator { borrow_set, tcx, location_table, facts, body }; for (bb, data) in body.basic_blocks.iter_enumerated() { visitor.visit_basic_block_data(bb, data); } @@ -27,7 +27,7 @@ pub(super) fn emit_loan_kills<'tcx>( struct LoanKillsGenerator<'a, 'tcx> { tcx: TyCtxt<'tcx>, - all_facts: &'a mut AllFacts, + facts: &'a mut AllFacts, location_table: &'a LocationTable, borrow_set: &'a BorrowSet<'tcx>, body: &'a Body<'tcx>, @@ -36,12 +36,12 @@ struct LoanKillsGenerator<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { // Also record CFG facts here. - self.all_facts.cfg_edge.push(( + self.facts.cfg_edge.push(( self.location_table.start_index(location), self.location_table.mid_index(location), )); - self.all_facts.cfg_edge.push(( + self.facts.cfg_edge.push(( self.location_table.mid_index(location), self.location_table.start_index(location.successor_within_block()), )); @@ -63,15 +63,15 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanKillsGenerator<'a, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { // Also record CFG facts here. - self.all_facts.cfg_edge.push(( + self.facts.cfg_edge.push(( self.location_table.start_index(location), self.location_table.mid_index(location), )); let successor_blocks = terminator.successors(); - self.all_facts.cfg_edge.reserve(successor_blocks.size_hint().0); + self.facts.cfg_edge.reserve(successor_blocks.size_hint().0); for successor_block in successor_blocks { - self.all_facts.cfg_edge.push(( + self.facts.cfg_edge.push(( self.location_table.mid_index(location), self.location_table.start_index(successor_block.start_location()), )); @@ -128,7 +128,7 @@ impl<'tcx> LoanKillsGenerator<'_, 'tcx> { if places_conflict { let location_index = self.location_table.mid_index(location); - self.all_facts.loan_killed_at.push((borrow_index, location_index)); + self.facts.loan_killed_at.push((borrow_index, location_index)); } } } @@ -140,9 +140,9 @@ impl<'tcx> LoanKillsGenerator<'_, 'tcx> { fn record_killed_borrows_for_local(&mut self, local: Local, location: Location) { if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { let location_index = self.location_table.mid_index(location); - self.all_facts.loan_killed_at.reserve(borrow_indices.len()); + self.facts.loan_killed_at.reserve(borrow_indices.len()); for &borrow_index in borrow_indices { - self.all_facts.loan_killed_at.push((borrow_index, location_index)); + self.facts.loan_killed_at.push((borrow_index, location_index)); } } } diff --git a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs index 9cf88704e3a5c..60fd2afe63e1c 100644 --- a/compiler/rustc_borrowck/src/polonius/legacy/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/legacy/mod.rs @@ -43,40 +43,38 @@ pub(crate) fn emit_facts<'tcx>( universal_region_relations: &UniversalRegionRelations<'tcx>, constraints: &MirTypeckRegionConstraints<'tcx>, ) { - let Some(all_facts) = all_facts else { + let Some(facts) = all_facts else { // We don't do anything if there are no facts to fill. return; }; let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); - emit_move_facts(all_facts, move_data, location_table, body); - emit_universal_region_facts(all_facts, borrow_set, universal_region_relations); - loan_kills::emit_loan_kills(tcx, all_facts, location_table, body, borrow_set); - loan_invalidations::emit_loan_invalidations(tcx, all_facts, location_table, body, borrow_set); + emit_move_facts(facts, body, location_table, move_data); + emit_universal_region_facts(facts, borrow_set, universal_region_relations); + loan_kills::emit_loan_kills(tcx, facts, body, location_table, borrow_set); + loan_invalidations::emit_loan_invalidations(tcx, facts, body, location_table, borrow_set); accesses::emit_access_facts( - all_facts, tcx, + facts, body, + location_table, move_data, &universal_region_relations.universal_regions, - location_table, ); - emit_outlives_facts(all_facts, location_table, constraints); + emit_outlives_facts(facts, location_table, constraints); } /// Emit facts needed for move/init analysis: moves and assignments. fn emit_move_facts( - all_facts: &mut AllFacts, - move_data: &MoveData<'_>, - location_table: &LocationTable, + facts: &mut AllFacts, body: &Body<'_>, + location_table: &LocationTable, + move_data: &MoveData<'_>, ) { - all_facts - .path_is_var - .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l))); + facts.path_is_var.extend(move_data.rev_lookup.iter_locals_enumerated().map(|(l, r)| (r, l))); for (child, move_path) in move_data.move_paths.iter_enumerated() { if let Some(parent) = move_path.parent { - all_facts.child_path.push((child, parent)); + facts.child_path.push((child, parent)); } } @@ -102,14 +100,14 @@ fn emit_move_facts( // The initialization happened in (or rather, when arriving at) // the successors, but not in the unwind block. let first_statement = Location { block: successor, statement_index: 0 }; - all_facts + facts .path_assigned_at_base .push((init.path, location_table.start_index(first_statement))); } } else { // In all other cases, the initialization just happens at the // midpoint, like any other effect. - all_facts + facts .path_assigned_at_base .push((init.path, location_table.mid_index(location))); } @@ -117,7 +115,7 @@ fn emit_move_facts( // Arguments are initialized on function entry InitLocation::Argument(local) => { assert!(body.local_kind(local) == LocalKind::Arg); - all_facts.path_assigned_at_base.push((init.path, fn_entry_start)); + facts.path_assigned_at_base.push((init.path, fn_entry_start)); } } } @@ -126,20 +124,20 @@ fn emit_move_facts( if body.local_kind(local) != LocalKind::Arg { // Non-arguments start out deinitialised; we simulate this with an // initial move: - all_facts.path_moved_at_base.push((path, fn_entry_start)); + facts.path_moved_at_base.push((path, fn_entry_start)); } } // moved_out_at // deinitialisation is assumed to always happen! - all_facts + facts .path_moved_at_base .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); } /// Emit universal regions facts, and their relations. fn emit_universal_region_facts( - all_facts: &mut AllFacts, + facts: &mut AllFacts, borrow_set: &BorrowSet<'_>, universal_region_relations: &UniversalRegionRelations<'_>, ) { @@ -150,7 +148,7 @@ fn emit_universal_region_facts( // added to the existing number of loans, as if they succeeded them in the set. // let universal_regions = &universal_region_relations.universal_regions; - all_facts + facts .universal_region .extend(universal_regions.universal_regions_iter().map(PoloniusRegionVid::from)); let borrow_count = borrow_set.len(); @@ -163,7 +161,7 @@ fn emit_universal_region_facts( for universal_region in universal_regions.universal_regions_iter() { let universal_region_idx = universal_region.index(); let placeholder_loan_idx = borrow_count + universal_region_idx; - all_facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into())); + facts.placeholder.push((universal_region.into(), placeholder_loan_idx.into())); } // 2: the universal region relations `outlives` constraints are emitted as @@ -175,7 +173,7 @@ fn emit_universal_region_facts( fr1={:?}, fr2={:?}", fr1, fr2 ); - all_facts.known_placeholder_subset.push((fr1.into(), fr2.into())); + facts.known_placeholder_subset.push((fr1.into(), fr2.into())); } } }