From 388071a2cb694dfad0920d302190e207842ff768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Fiala?= Date: Sat, 29 Apr 2023 16:57:50 +0200 Subject: [PATCH 1/6] Allow consumers to retrieve borrowck output --- compiler/rustc_borrowck/src/borrow_set.rs | 4 +- compiler/rustc_borrowck/src/consumers.rs | 56 +++++++++++++++++-- compiler/rustc_borrowck/src/dataflow.rs | 35 +++++++----- compiler/rustc_borrowck/src/lib.rs | 45 +++++++++------ compiler/rustc_borrowck/src/nll.rs | 13 +++-- compiler/rustc_borrowck/src/place_ext.rs | 2 +- .../rustc_borrowck/src/places_conflict.rs | 4 +- 7 files changed, 111 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs index 4824f6346d4c8..6be20b0974ddb 100644 --- a/compiler/rustc_borrowck/src/borrow_set.rs +++ b/compiler/rustc_borrowck/src/borrow_set.rs @@ -30,7 +30,7 @@ pub struct BorrowSet<'tcx> { /// Map from local to all the borrows on that local. pub local_map: FxIndexMap>, - pub(crate) locals_state_at_exit: LocalsStateAtExit, + pub locals_state_at_exit: LocalsStateAtExit, } impl<'tcx> Index for BorrowSet<'tcx> { @@ -153,7 +153,7 @@ impl<'tcx> BorrowSet<'tcx> { self.activation_map.get(&location).map_or(&[], |activations| &activations[..]) } - pub(crate) fn len(&self) -> usize { + pub fn len(&self) -> usize { self.location_map.len() } diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 3451b7db8caae..ef2358301f205 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -9,16 +9,56 @@ use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; pub use super::{ + dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows}, facts::{AllFacts as PoloniusInput, RustcFacts}, location::{LocationTable, RichLocation}, nll::PoloniusOutput, + region_infer::RegionInferenceContext, BodyWithBorrowckFacts, }; -/// This function computes Polonius facts for the given body. It makes a copy of -/// the body because it needs to regenerate the region identifiers. This function -/// should never be invoked during a typical compilation session due to performance -/// issues with Polonius. +/// Options determining the output behavior of [`get_body_with_borrowck_facts`]. +/// +/// If executing under `-Z polonius` the choice here has no effect, and everything as if +/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected +/// will be retrieved. +#[derive(Debug, Copy, Clone)] +pub enum ConsumerOptions { + /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet) + /// and [`RegionInferenceContext`]. If you would like the body only, use + /// [`TyCtxt::mir_promoted`]. + /// + /// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`]. + RegionInferenceContext, + /// The recommended option. Retrieves the maximal amount of information + /// without significant slowdowns. + /// + /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext), + /// and additionally retrieve the [`LocationTable`] and [`PoloniusInput`] that + /// would be given to Polonius. Critically, this does not run Polonius, which + /// one may want to avoid due to performance issues on large bodies. + PoloniusInputFacts, + /// Implies [`PoloniusInputFacts`](ConsumerOptions::PoloniusInputFacts), + /// and additionally runs Polonius to calculate the [`PoloniusOutput`]. + PoloniusOutputFacts, +} + +impl ConsumerOptions { + /// Should the Polonius input facts be computed? + pub(crate) fn polonius_input(&self) -> bool { + matches!(self, Self::PoloniusInputFacts | Self::PoloniusOutputFacts) + } + /// Should we run Polonius and collect the output facts? + pub(crate) fn polonius_output(&self) -> bool { + matches!(self, Self::PoloniusOutputFacts) + } +} + +/// This function computes borrowck facts for the given body. The [`ConsumerOptions`] +/// determine which facts are returned. This function makes a copy of the body because +/// it needs to regenerate the region identifiers. It should never be invoked during a +/// typical compilation session due to the unnecessary overhead of returning +/// [`BodyWithBorrowckFacts`]. /// /// Note: /// * This function will panic if the required body was already stolen. This @@ -28,10 +68,14 @@ pub use super::{ /// that shows how to do this at `tests/run-make/obtain-borrowck/`. /// /// * Polonius is highly unstable, so expect regular changes in its signature or other details. -pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> { +pub fn get_body_with_borrowck_facts( + tcx: TyCtxt<'_>, + def: LocalDefId, + options: ConsumerOptions, +) -> BodyWithBorrowckFacts<'_> { let (input_body, promoted) = tcx.mir_promoted(def); let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); - *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap() + *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap() } diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 167f245361a22..4fe4d7085d78a 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -231,27 +231,32 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> { } } +pub fn calculate_borrows_out_of_scope_at_location<'tcx>( + body: &Body<'tcx>, + regioncx: &RegionInferenceContext<'tcx>, + borrow_set: &BorrowSet<'tcx>, +) -> FxIndexMap> { + let mut prec = OutOfScopePrecomputer::new(body, regioncx); + for (borrow_index, borrow_data) in borrow_set.iter_enumerated() { + let borrow_region = borrow_data.region; + let location = borrow_data.reserve_location; + + prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location); + } + + prec.borrows_out_of_scope_at_location +} + impl<'a, 'tcx> Borrows<'a, 'tcx> { - pub(crate) fn new( + pub fn new( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, nonlexical_regioncx: &'a RegionInferenceContext<'tcx>, borrow_set: &'a BorrowSet<'tcx>, ) -> Self { - let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx); - for (borrow_index, borrow_data) in borrow_set.iter_enumerated() { - let borrow_region = borrow_data.region; - let location = borrow_data.reserve_location; - - prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location); - } - - Borrows { - tcx, - body, - borrow_set, - borrows_out_of_scope_at_location: prec.borrows_out_of_scope_at_location, - } + let borrows_out_of_scope_at_location = + calculate_borrows_out_of_scope_at_location(body, nonlexical_regioncx, borrow_set); + Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location } } pub fn location(&self, idx: BorrowIndex) -> &Location { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index eb25d454339b5..dfab36dc0ed71 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -62,6 +62,7 @@ use crate::session_diagnostics::VarNeedNotMut; use self::diagnostics::{AccessKind, RegionName}; use self::location::LocationTable; use self::prefixes::PrefixSet; +use consumers::ConsumerOptions; use facts::AllFacts; use self::path_utils::*; @@ -144,7 +145,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build(); let input_body: &Body<'_> = &input_body.borrow(); let promoted: &IndexSlice<_, _> = &promoted.borrow(); - let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0; + let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0; debug!("mir_borrowck done"); tcx.arena.alloc(opt_closure_req) @@ -152,15 +153,15 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> { /// Perform the actual borrow checking. /// -/// If `return_body_with_facts` is true, then return the body with non-erased -/// region ids on which the borrow checking was performed together with Polonius -/// facts. +/// Use `consumer_options: None` for the default behavior of returning +/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according +/// to the given [`ConsumerOptions`]. #[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")] fn do_mir_borrowck<'tcx>( infcx: &InferCtxt<'tcx>, input_body: &Body<'tcx>, input_promoted: &IndexSlice>, - return_body_with_facts: bool, + consumer_options: Option, ) -> (BorrowCheckResult<'tcx>, Option>>) { let def = input_body.source.def_id().expect_local(); debug!(?def); @@ -241,8 +242,6 @@ fn do_mir_borrowck<'tcx>( let borrow_set = Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); - let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.unstable_opts.polonius; - // Compute non-lexical lifetimes. let nll::NllOutput { regioncx, @@ -262,7 +261,7 @@ fn do_mir_borrowck<'tcx>( &mdpe.move_data, &borrow_set, &upvars, - use_polonius, + consumer_options, ); // Dump MIR results into a file, if that is enabled. This let us @@ -444,13 +443,15 @@ fn do_mir_borrowck<'tcx>( tainted_by_errors, }; - let body_with_facts = if return_body_with_facts { - let output_facts = mbcx.polonius_output.expect("Polonius output was not computed"); + let body_with_facts = if consumer_options.is_some() { + let output_facts = mbcx.polonius_output; Some(Box::new(BodyWithBorrowckFacts { body: body_owned, - input_facts: *polonius_input.expect("Polonius input facts were not generated"), + borrow_set, + region_inference_context: regioncx, + location_table: polonius_input.as_ref().map(|_| location_table_owned), + input_facts: polonius_input, output_facts, - location_table: location_table_owned, })) } else { None @@ -469,12 +470,20 @@ fn do_mir_borrowck<'tcx>( pub struct BodyWithBorrowckFacts<'tcx> { /// A mir body that contains region identifiers. pub body: Body<'tcx>, - /// Polonius input facts. - pub input_facts: AllFacts, - /// Polonius output facts. - pub output_facts: Rc, - /// The table that maps Polonius points to locations in the table. - pub location_table: LocationTable, + /// The set of borrows occurring in `body` with data about them. + pub borrow_set: Rc>, + /// Context generated during borrowck, intended to be passed to + /// [`OutOfScopePrecomputer`](dataflow::OutOfScopePrecomputer). + pub region_inference_context: Rc>, + /// The table that maps Polonius points to locations in the table. Populated + /// when using [`ConsumerOptions::PoloniusInputFacts`] or above. + pub location_table: Option, + /// Polonius input facts. Populated when using + /// [`ConsumerOptions::PoloniusInputFacts`] or above. + pub input_facts: Option>, + /// Polonius output facts. Populated when using + /// [`ConsumerOptions::PoloniusOutputFacts`] or above. + pub output_facts: Option>, } pub struct BorrowckInferCtxt<'cx, 'tcx> { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index b6ccf924a5c88..889acb3acbed7 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -27,6 +27,7 @@ use rustc_mir_dataflow::ResultsCursor; use crate::{ borrow_set::BorrowSet, constraint_generation, + consumers::ConsumerOptions, diagnostics::RegionErrors, facts::{AllFacts, AllFactsExt, RustcFacts}, invalidation, @@ -165,10 +166,14 @@ pub(crate) fn compute_regions<'cx, 'tcx>( move_data: &MoveData<'tcx>, borrow_set: &BorrowSet<'tcx>, upvars: &[Upvar<'tcx>], - use_polonius: bool, + consumer_options: Option, ) -> NllOutput<'tcx> { + let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default() + || infcx.tcx.sess.opts.unstable_opts.polonius; + let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default() + || infcx.tcx.sess.opts.unstable_opts.polonius; let mut all_facts = - (use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default()); + (polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default()); let universal_regions = Rc::new(universal_regions); @@ -189,7 +194,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( move_data, elements, upvars, - use_polonius, + polonius_input, ); if let Some(all_facts) = &mut all_facts { @@ -284,7 +289,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>( all_facts.write_to_dir(dir_path, location_table).unwrap(); } - if use_polonius { + if polonius_output { let algorithm = env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid")); let algorithm = Algorithm::from_str(&algorithm).unwrap(); diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index 85d207b2fc9a7..d521d0db21323 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::{Body, Mutability, Place}; use rustc_middle::ty::{self, TyCtxt}; /// Extension methods for the `Place` type. -pub(crate) trait PlaceExt<'tcx> { +pub trait PlaceExt<'tcx> { /// Returns `true` if we can safely ignore borrows of this place. /// This is true whenever there is no action that the user can do /// to the place `self` that would invalidate the borrow. This is true diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 918fb2d69237e..25c485b814f4a 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -16,7 +16,7 @@ use std::iter; /// being run in the calling context, the conservative choice is to assume the compared indices /// are disjoint (and therefore, do not overlap). #[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub(crate) enum PlaceConflictBias { +pub enum PlaceConflictBias { Overlap, NoOverlap, } @@ -24,7 +24,7 @@ pub(crate) enum PlaceConflictBias { /// Helper function for checking if places conflict with a mutable borrow and deep access depth. /// This is used to check for places conflicting outside of the borrow checking code (such as in /// dataflow). -pub(crate) fn places_conflict<'tcx>( +pub fn places_conflict<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, borrow_place: Place<'tcx>, From 0e44a38892353409e4a05ccbe22a42524a407dba Mon Sep 17 00:00:00 2001 From: Dominik Stolz Date: Wed, 17 May 2023 16:07:01 +0200 Subject: [PATCH 2/6] Return promoteds in BodyWithBorrowckFacts --- compiler/rustc_borrowck/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index dfab36dc0ed71..4f1e12c364e4c 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -447,6 +447,7 @@ fn do_mir_borrowck<'tcx>( let output_facts = mbcx.polonius_output; Some(Box::new(BodyWithBorrowckFacts { body: body_owned, + promoted, borrow_set, region_inference_context: regioncx, location_table: polonius_input.as_ref().map(|_| location_table_owned), @@ -470,6 +471,8 @@ fn do_mir_borrowck<'tcx>( pub struct BodyWithBorrowckFacts<'tcx> { /// A mir body that contains region identifiers. pub body: Body<'tcx>, + /// The mir bodies of promoteds. + pub promoted: IndexVec>, /// The set of borrows occurring in `body` with data about them. pub borrow_set: Rc>, /// Context generated during borrowck, intended to be passed to From ab9e7037d1c1702010092d9134e02b88d54fe237 Mon Sep 17 00:00:00 2001 From: Dominik Stolz Date: Wed, 17 May 2023 16:07:50 +0200 Subject: [PATCH 3/6] Make place helpers accessible --- compiler/rustc_borrowck/src/consumers.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index ef2358301f205..810f199157956 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -13,6 +13,8 @@ pub use super::{ facts::{AllFacts as PoloniusInput, RustcFacts}, location::{LocationTable, RichLocation}, nll::PoloniusOutput, + place_ext::PlaceExt, + places_conflict::{places_conflict, PlaceConflictBias}, region_infer::RegionInferenceContext, BodyWithBorrowckFacts, }; From 75e172e71073d771db8e410bbe16c9827db7cada Mon Sep 17 00:00:00 2001 From: Dominik Stolz Date: Wed, 17 May 2023 16:30:12 +0200 Subject: [PATCH 4/6] Update obtain-borrowck test --- tests/run-make-fulldeps/obtain-borrowck/driver.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs index d342b2ff6d91b..c8990e535b078 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs @@ -102,7 +102,7 @@ impl rustc_driver::Callbacks for CompilerCalls { println!("Bodies retrieved for:"); for (def_id, body) in bodies { println!("{}", def_id); - assert!(body.input_facts.cfg_edge.len() > 0); + assert!(body.input_facts.unwrap().cfg_edge.len() > 0); } }); @@ -127,7 +127,8 @@ thread_local! { } fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> { - let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id); + let opts = ConsumerOptions::PoloniusInputFacts; + let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id, opts); // SAFETY: The reader casts the 'static lifetime to 'tcx before using it. let body_with_facts: BodyWithBorrowckFacts<'static> = unsafe { std::mem::transmute(body_with_facts) }; From c6e3f27864080730298dd7260f94af8784fbdc42 Mon Sep 17 00:00:00 2001 From: Dominik Stolz Date: Tue, 23 May 2023 11:16:59 +0200 Subject: [PATCH 5/6] Move BodyWithBorrowckFacts to consumers --- compiler/rustc_borrowck/src/consumers.rs | 36 +++++++++++++++++-- compiler/rustc_borrowck/src/lib.rs | 29 +-------------- .../obtain-borrowck/driver.rs | 4 +-- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 810f199157956..3b749a3a38e73 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -3,10 +3,13 @@ //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; -use rustc_index::IndexSlice; +use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt}; -use rustc_middle::mir::Body; +use rustc_middle::mir::{Body, Promoted}; use rustc_middle::ty::TyCtxt; +use std::rc::Rc; + +use crate::borrow_set::BorrowSet; pub use super::{ dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows}, @@ -16,7 +19,6 @@ pub use super::{ place_ext::PlaceExt, places_conflict::{places_conflict, PlaceConflictBias}, region_infer::RegionInferenceContext, - BodyWithBorrowckFacts, }; /// Options determining the output behavior of [`get_body_with_borrowck_facts`]. @@ -56,6 +58,34 @@ impl ConsumerOptions { } } +/// A `Body` with information computed by the borrow checker. This struct is +/// intended to be consumed by compiler consumers. +/// +/// We need to include the MIR body here because the region identifiers must +/// match the ones in the Polonius facts. +pub struct BodyWithBorrowckFacts<'tcx> { + /// A mir body that contains region identifiers. + pub body: Body<'tcx>, + /// The mir bodies of promoteds. + pub promoted: IndexVec>, + /// The set of borrows occurring in `body` with data about them. + pub borrow_set: Rc>, + /// Context generated during borrowck, intended to be passed to + /// [`calculate_borrows_out_of_scope_at_location`]. + pub region_inference_context: Rc>, + /// The table that maps Polonius points to locations in the table. + /// Populated when using [`ConsumerOptions::PoloniusInputFacts`] + /// or [`ConsumerOptions::PoloniusOutputFacts`]. + pub location_table: Option, + /// Polonius input facts. + /// Populated when using [`ConsumerOptions::PoloniusInputFacts`] + /// or [`ConsumerOptions::PoloniusOutputFacts`]. + pub input_facts: Option>, + /// Polonius output facts. Populated when using + /// [`ConsumerOptions::PoloniusOutputFacts`]. + pub output_facts: Option>, +} + /// This function computes borrowck facts for the given body. The [`ConsumerOptions`] /// determine which facts are returned. This function makes a copy of the body because /// it needs to regenerate the region identifiers. It should never be invoked during a diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 4f1e12c364e4c..28e5f3e2a16a7 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -62,8 +62,7 @@ use crate::session_diagnostics::VarNeedNotMut; use self::diagnostics::{AccessKind, RegionName}; use self::location::LocationTable; use self::prefixes::PrefixSet; -use consumers::ConsumerOptions; -use facts::AllFacts; +use consumers::{BodyWithBorrowckFacts, ConsumerOptions}; use self::path_utils::*; @@ -463,32 +462,6 @@ fn do_mir_borrowck<'tcx>( (result, body_with_facts) } -/// A `Body` with information computed by the borrow checker. This struct is -/// intended to be consumed by compiler consumers. -/// -/// We need to include the MIR body here because the region identifiers must -/// match the ones in the Polonius facts. -pub struct BodyWithBorrowckFacts<'tcx> { - /// A mir body that contains region identifiers. - pub body: Body<'tcx>, - /// The mir bodies of promoteds. - pub promoted: IndexVec>, - /// The set of borrows occurring in `body` with data about them. - pub borrow_set: Rc>, - /// Context generated during borrowck, intended to be passed to - /// [`OutOfScopePrecomputer`](dataflow::OutOfScopePrecomputer). - pub region_inference_context: Rc>, - /// The table that maps Polonius points to locations in the table. Populated - /// when using [`ConsumerOptions::PoloniusInputFacts`] or above. - pub location_table: Option, - /// Polonius input facts. Populated when using - /// [`ConsumerOptions::PoloniusInputFacts`] or above. - pub input_facts: Option>, - /// Polonius output facts. Populated when using - /// [`ConsumerOptions::PoloniusOutputFacts`] or above. - pub output_facts: Option>, -} - pub struct BorrowckInferCtxt<'cx, 'tcx> { pub(crate) infcx: &'cx InferCtxt<'tcx>, pub(crate) reg_var_to_origin: RefCell>, diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/run-make-fulldeps/obtain-borrowck/driver.rs index c8990e535b078..b59a65a713f95 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/tests/run-make-fulldeps/obtain-borrowck/driver.rs @@ -18,7 +18,7 @@ extern crate rustc_interface; extern crate rustc_middle; extern crate rustc_session; -use rustc_borrowck::consumers::BodyWithBorrowckFacts; +use rustc_borrowck::consumers::{self, BodyWithBorrowckFacts, ConsumerOptions}; use rustc_driver::Compilation; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -128,7 +128,7 @@ thread_local! { fn mir_borrowck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ProvidedValue<'tcx> { let opts = ConsumerOptions::PoloniusInputFacts; - let body_with_facts = rustc_borrowck::consumers::get_body_with_borrowck_facts(tcx, def_id, opts); + let body_with_facts = consumers::get_body_with_borrowck_facts(tcx, def_id, opts); // SAFETY: The reader casts the 'static lifetime to 'tcx before using it. let body_with_facts: BodyWithBorrowckFacts<'static> = unsafe { std::mem::transmute(body_with_facts) }; From 8dac074087afc9f02a794027bede787bb9367ad3 Mon Sep 17 00:00:00 2001 From: Dominik Stolz Date: Tue, 23 May 2023 17:33:55 +0200 Subject: [PATCH 6/6] Add RegionInferenceContext::outlives_constraints --- compiler/rustc_borrowck/src/consumers.rs | 1 + compiler/rustc_borrowck/src/region_infer/mod.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 3b749a3a38e73..dc20b371d92e0 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -12,6 +12,7 @@ use std::rc::Rc; use crate::borrow_set::BorrowSet; pub use super::{ + constraints::OutlivesConstraint, dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows}, facts::{AllFacts as PoloniusInput, RustcFacts}, location::{LocationTable, RichLocation}, diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8fbe814c85607..9bb46a50d3cf4 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -585,6 +585,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.universal_regions.to_region_vid(r) } + /// Returns an iterator over all the outlives constraints. + pub fn outlives_constraints(&self) -> impl Iterator> + '_ { + self.constraints.outlives().iter().copied() + } + /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) { self.universal_regions.annotate(tcx, err) @@ -698,7 +703,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { #[instrument(skip(self, _body), level = "debug")] fn propagate_constraints(&mut self, _body: &Body<'tcx>) { debug!("constraints={:#?}", { - let mut constraints: Vec<_> = self.constraints.outlives().iter().collect(); + let mut constraints: Vec<_> = self.outlives_constraints().collect(); constraints.sort_by_key(|c| (c.sup, c.sub)); constraints .into_iter()