diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 1b4c92e3ee2..0c88f5cf363 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -158,7 +158,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( borrow_set, ); polonius::emit_cfg_and_loan_kills_facts( - infcx, + infcx.tcx, &mut all_facts, location_table, body, diff --git a/compiler/rustc_borrowck/src/polonius/constraint_generation.rs b/compiler/rustc_borrowck/src/polonius/constraint_generation.rs index ac9401924fb..27efc3c4108 100644 --- a/compiler/rustc_borrowck/src/polonius/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/polonius/constraint_generation.rs @@ -1,23 +1,23 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use rustc_infer::infer::InferCtxt; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection, }; -use rustc_middle::ty::{self}; +use rustc_middle::ty::{TyCtxt, Variance}; use crate::{borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict}; pub(super) fn generate_constraints<'tcx>( - infcx: &InferCtxt<'tcx>, - all_facts: &mut Option, + tcx: TyCtxt<'tcx>, + all_facts: &mut AllFacts, location_table: &LocationTable, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, ) { - let mut cg = ConstraintGeneration { borrow_set, infcx, location_table, all_facts, body }; + let _prof_timer = tcx.prof.generic_activity("polonius_fact_generation"); + let mut cg = ConstraintGeneration { borrow_set, tcx, location_table, all_facts, body }; for (bb, data) in body.basic_blocks.iter_enumerated() { cg.visit_basic_block_data(bb, data); } @@ -25,8 +25,8 @@ pub(super) fn generate_constraints<'tcx>( /// 'cg = the duration of the constraint generation process itself. struct ConstraintGeneration<'cg, 'tcx> { - infcx: &'cg InferCtxt<'tcx>, - all_facts: &'cg mut Option, + tcx: TyCtxt<'tcx>, + all_facts: &'cg mut AllFacts, location_table: &'cg LocationTable, borrow_set: &'cg BorrowSet<'tcx>, body: &'cg Body<'tcx>, @@ -34,28 +34,19 @@ struct ConstraintGeneration<'cg, 'tcx> { impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) { - if let Some(all_facts) = self.all_facts { - let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - all_facts.cfg_edge.push(( - self.location_table.start_index(location), - self.location_table.mid_index(location), - )); + self.all_facts.cfg_edge.push(( + self.location_table.start_index(location), + self.location_table.mid_index(location), + )); - all_facts.cfg_edge.push(( - self.location_table.mid_index(location), - self.location_table.start_index(location.successor_within_block()), - )); + self.all_facts.cfg_edge.push(( + self.location_table.mid_index(location), + self.location_table.start_index(location.successor_within_block()), + )); - // If there are borrows on this now dead local, we need to record them as `killed`. - if let StatementKind::StorageDead(local) = statement.kind { - record_killed_borrows_for_local( - all_facts, - self.borrow_set, - self.location_table, - local, - location, - ); - } + // If there are borrows on this now dead local, we need to record them as `killed`. + if let StatementKind::StorageDead(local) = statement.kind { + self.record_killed_borrows_for_local(local, location); } self.super_statement(statement, location); @@ -70,21 +61,18 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> { } fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { - if let Some(all_facts) = self.all_facts { - let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); - all_facts.cfg_edge.push(( - self.location_table.start_index(location), - self.location_table.mid_index(location), - )); + self.all_facts.cfg_edge.push(( + self.location_table.start_index(location), + self.location_table.mid_index(location), + )); - let successor_blocks = terminator.successors(); - all_facts.cfg_edge.reserve(successor_blocks.size_hint().0); - for successor_block in successor_blocks { - all_facts.cfg_edge.push(( - self.location_table.mid_index(location), - self.location_table.start_index(successor_block.start_location()), - )); - } + let successor_blocks = terminator.successors(); + self.all_facts.cfg_edge.reserve(successor_blocks.size_hint().0); + for successor_block in successor_blocks { + self.all_facts.cfg_edge.push(( + self.location_table.mid_index(location), + self.location_table.start_index(successor_block.start_location()), + )); } // A `Call` terminator's return value can be a local which has borrows, @@ -99,7 +87,7 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> { fn visit_ascribe_user_ty( &mut self, _place: &Place<'tcx>, - _variance: ty::Variance, + _variance: Variance, _user_ty: &UserTypeProjection, _location: Location, ) { @@ -110,75 +98,59 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> { /// When recording facts for Polonius, records the borrows on the specified place /// as `killed`. For example, when assigning to a local, or on a call's return destination. fn record_killed_borrows_for_place(&mut self, place: Place<'tcx>, location: Location) { - if let Some(all_facts) = self.all_facts { - let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation"); + // Depending on the `Place` we're killing: + // - if it's a local, or a single deref of a local, + // we kill all the borrows on the local. + // - if it's a deeper projection, we have to filter which + // of the borrows are killed: the ones whose `borrowed_place` + // conflicts with the `place`. + match place.as_ref() { + PlaceRef { local, projection: &[] } + | PlaceRef { local, projection: &[ProjectionElem::Deref] } => { + debug!( + "Recording `killed` facts for borrows of local={:?} at location={:?}", + local, location + ); - // Depending on the `Place` we're killing: - // - if it's a local, or a single deref of a local, - // we kill all the borrows on the local. - // - if it's a deeper projection, we have to filter which - // of the borrows are killed: the ones whose `borrowed_place` - // conflicts with the `place`. - match place.as_ref() { - PlaceRef { local, projection: &[] } - | PlaceRef { local, projection: &[ProjectionElem::Deref] } => { - debug!( - "Recording `killed` facts for borrows of local={:?} at location={:?}", - local, location - ); + self.record_killed_borrows_for_local(local, location); + } - record_killed_borrows_for_local( - all_facts, - self.borrow_set, - self.location_table, - local, - location, - ); - } - - PlaceRef { local, projection: &[.., _] } => { - // Kill conflicting borrows of the innermost local. - debug!( - "Recording `killed` facts for borrows of \ + PlaceRef { local, projection: &[.., _] } => { + // Kill conflicting borrows of the innermost local. + debug!( + "Recording `killed` facts for borrows of \ innermost projected local={:?} at location={:?}", - local, location - ); + local, location + ); - if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { - for &borrow_index in borrow_indices { - let places_conflict = places_conflict::places_conflict( - self.infcx.tcx, - self.body, - self.borrow_set[borrow_index].borrowed_place, - place, - places_conflict::PlaceConflictBias::NoOverlap, - ); + if let Some(borrow_indices) = self.borrow_set.local_map.get(&local) { + for &borrow_index in borrow_indices { + let places_conflict = places_conflict::places_conflict( + self.tcx, + self.body, + self.borrow_set[borrow_index].borrowed_place, + place, + places_conflict::PlaceConflictBias::NoOverlap, + ); - if places_conflict { - let location_index = self.location_table.mid_index(location); - all_facts.loan_killed_at.push((borrow_index, location_index)); - } + if places_conflict { + let location_index = self.location_table.mid_index(location); + self.all_facts.loan_killed_at.push((borrow_index, location_index)); } } } } } } -} -/// When recording facts for Polonius, records the borrows on the specified local as `killed`. -fn record_killed_borrows_for_local( - all_facts: &mut AllFacts, - borrow_set: &BorrowSet<'_>, - location_table: &LocationTable, - local: Local, - location: Location, -) { - if let Some(borrow_indices) = borrow_set.local_map.get(&local) { - all_facts.loan_killed_at.reserve(borrow_indices.len()); - for &borrow_index in borrow_indices { - let location_index = location_table.mid_index(location); - all_facts.loan_killed_at.push((borrow_index, location_index)); + /// When recording facts for Polonius, records the borrows on the specified local as `killed`. + 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()); + for &borrow_index in borrow_indices { + self.all_facts.loan_killed_at.push((borrow_index, location_index)); + } } } } diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index c41afc8078a..0fbe221ad10 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -3,7 +3,6 @@ //! Will be removed in the future, once the in-tree `-Zpolonius=next` implementation reaches feature //! parity. -use rustc_infer::infer::InferCtxt; use rustc_middle::mir::{Body, LocalKind, Location, START_BLOCK}; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::move_paths::{InitKind, InitLocation, MoveData}; @@ -150,11 +149,16 @@ pub(crate) fn emit_loan_invalidations_facts<'tcx>( /// Emit facts about CFG points and edges, as well as locations where loans are killed. pub(crate) fn emit_cfg_and_loan_kills_facts<'tcx>( - infcx: &InferCtxt<'tcx>, + tcx: TyCtxt<'tcx>, all_facts: &mut Option, location_table: &LocationTable, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, ) { - constraint_generation::generate_constraints(infcx, all_facts, location_table, body, borrow_set); + let Some(all_facts) = all_facts else { + // Nothing to do if we don't have any facts to fill + return; + }; + + constraint_generation::generate_constraints(tcx, all_facts, location_table, body, borrow_set); }