1//! This file provides API for compiler consumers.
23use rustc_data_structures::fx::FxHashMap;
4use rustc_hir::def_id::LocalDefId;
5use rustc_index::IndexVec;
6use rustc_middle::bug;
7use rustc_middle::mir::{Body, Promoted};
8use rustc_middle::ty::TyCtxt;
910pub use super::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
11pub use super::constraints::OutlivesConstraint;
12pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_at_location};
13pub use super::place_ext::PlaceExt;
14pub use super::places_conflict::{PlaceConflictBias, places_conflict};
15pub use super::polonius::legacy::{
16PoloniusFactsas PoloniusInput, PoloniusLocationTable, PoloniusOutput, PoloniusRegionVid,
17RichLocation, RustcFacts,
18};
19pub use super::region_infer::RegionInferenceContext;
20use crate::BorrowCheckRootCtxt;
2122/// Struct used during mir borrowck to collect bodies with facts for a typeck root and all
23/// its nested bodies.
24pub(crate) struct BorrowckConsumer<'tcx> {
25 options: ConsumerOptions,
26 bodies: FxHashMap<LocalDefId, BodyWithBorrowckFacts<'tcx>>,
27}
2829impl<'tcx> BorrowckConsumer<'tcx> {
30pub(crate) fn new(options: ConsumerOptions) -> Self {
31Self { options, bodies: Default::default() }
32 }
3334pub(crate) fn insert_body(&mut self, def_id: LocalDefId, body: BodyWithBorrowckFacts<'tcx>) {
35if self.bodies.insert(def_id, body).is_some() {
36::rustc_middle::util::bug::bug_fmt(format_args!("unexpected previous body for {0:?}",
def_id));bug!("unexpected previous body for {def_id:?}");
37 }
38 }
3940/// Should the Polonius input facts be computed?
41pub(crate) fn polonius_input(&self) -> bool {
42#[allow(non_exhaustive_omitted_patterns)] match self.options {
ConsumerOptions::PoloniusInputFacts | ConsumerOptions::PoloniusOutputFacts
=> true,
_ => false,
}matches!(
43self.options,
44 ConsumerOptions::PoloniusInputFacts | ConsumerOptions::PoloniusOutputFacts
45 )46 }
4748/// Should we run Polonius and collect the output facts?
49pub(crate) fn polonius_output(&self) -> bool {
50#[allow(non_exhaustive_omitted_patterns)] match self.options {
ConsumerOptions::PoloniusOutputFacts => true,
_ => false,
}matches!(self.options, ConsumerOptions::PoloniusOutputFacts)51 }
52}
5354/// Options determining the output behavior of [`get_bodies_with_borrowck_facts`].
55///
56/// If executing under `-Z polonius` the choice here has no effect, and everything as if
57/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
58/// will be retrieved.
59#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ConsumerOptions {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
ConsumerOptions::RegionInferenceContext =>
"RegionInferenceContext",
ConsumerOptions::PoloniusInputFacts => "PoloniusInputFacts",
ConsumerOptions::PoloniusOutputFacts => "PoloniusOutputFacts",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::Copy for ConsumerOptions { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ConsumerOptions {
#[inline]
fn clone(&self) -> ConsumerOptions { *self }
}Clone)]
60pub enum ConsumerOptions {
61/// Retrieve the [`Body`] along with the [`BorrowSet`]
62 /// and [`RegionInferenceContext`]. If you would like the body only, use
63 /// [`TyCtxt::mir_promoted`].
64 ///
65 /// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`].
66RegionInferenceContext,
67/// The recommended option. Retrieves the maximal amount of information
68 /// without significant slowdowns.
69 ///
70 /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
71 /// and additionally retrieve the [`PoloniusLocationTable`] and [`PoloniusInput`] that
72 /// would be given to Polonius. Critically, this does not run Polonius, which
73 /// one may want to avoid due to performance issues on large bodies.
74PoloniusInputFacts,
75/// Implies [`PoloniusInputFacts`](ConsumerOptions::PoloniusInputFacts),
76 /// and additionally runs Polonius to calculate the [`PoloniusOutput`].
77PoloniusOutputFacts,
78}
7980/// A `Body` with information computed by the borrow checker. This struct is
81/// intended to be consumed by compiler consumers.
82///
83/// We need to include the MIR body here because the region identifiers must
84/// match the ones in the Polonius facts.
85pub struct BodyWithBorrowckFacts<'tcx> {
86/// A mir body that contains region identifiers.
87pub body: Body<'tcx>,
88/// The mir bodies of promoteds.
89pub promoted: IndexVec<Promoted, Body<'tcx>>,
90/// The set of borrows occurring in `body` with data about them.
91pub borrow_set: BorrowSet<'tcx>,
92/// Context generated during borrowck, intended to be passed to
93 /// [`calculate_borrows_out_of_scope_at_location`].
94pub region_inference_context: RegionInferenceContext<'tcx>,
95/// The table that maps Polonius points to locations in the table.
96 /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
97 /// or [`ConsumerOptions::PoloniusOutputFacts`].
98pub location_table: Option<PoloniusLocationTable>,
99/// Polonius input facts.
100 /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
101 /// or [`ConsumerOptions::PoloniusOutputFacts`].
102pub input_facts: Option<Box<PoloniusInput>>,
103/// Polonius output facts. Populated when using
104 /// [`ConsumerOptions::PoloniusOutputFacts`].
105pub output_facts: Option<Box<PoloniusOutput>>,
106}
107108/// This function computes borrowck facts for the given def id and all its nested bodies.
109/// It must be called with a typeck root which will then borrowck all nested bodies as well.
110/// The [`ConsumerOptions`] determine which facts are returned. This function makes a copy
111/// of the bodies because it needs to regenerate the region identifiers. It should never be
112/// invoked during a typical compilation session due to the unnecessary overhead of
113/// returning [`BodyWithBorrowckFacts`].
114///
115/// Note:
116/// * This function will panic if the required bodies were already stolen. This
117/// can, for example, happen when requesting a body of a `const` function
118/// because they are evaluated during typechecking. The panic can be avoided
119/// by overriding the `mir_borrowck` query. You can find a complete example
120/// that shows how to do this at `tests/ui-fulldeps/obtain-borrowck.rs`.
121///
122/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
123pub fn get_bodies_with_borrowck_facts(
124 tcx: TyCtxt<'_>,
125 root_def_id: LocalDefId,
126 options: ConsumerOptions,
127) -> FxHashMap<LocalDefId, BodyWithBorrowckFacts<'_>> {
128let mut root_cx =
129BorrowCheckRootCtxt::new(tcx, root_def_id, Some(BorrowckConsumer::new(options)));
130root_cx.do_mir_borrowck();
131root_cx.consumer.unwrap().bodies
132}