#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] //! This file provides API for compiler consumers. use rustc_hir::def_id::LocalDefId; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::{Body, Promoted}; use rustc_middle::traits::DefiningAnchor; use rustc_middle::ty::TyCtxt; 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}, nll::PoloniusOutput, place_ext::PlaceExt, places_conflict::{places_conflict, PlaceConflictBias}, region_infer::RegionInferenceContext, }; /// 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`] /// 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) } } /// 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 /// typical compilation session due to the unnecessary overhead of returning /// [`BodyWithBorrowckFacts`]. /// /// Note: /// * This function will panic if the required body was already stolen. This /// can, for example, happen when requesting a body of a `const` function /// because they are evaluated during typechecking. The panic can be avoided /// by overriding the `mir_borrowck` query. You can find a complete example /// 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, 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, Some(options)).1.unwrap() }