rustc_borrowck/consumers.rs
1//! This file provides API for compiler consumers.
2
3use rustc_hir::def_id::LocalDefId;
4use rustc_index::{IndexSlice, IndexVec};
5use rustc_middle::mir::{Body, Promoted};
6use rustc_middle::ty::TyCtxt;
7
8pub use super::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
9pub use super::constraints::OutlivesConstraint;
10pub use super::dataflow::{BorrowIndex, Borrows, calculate_borrows_out_of_scope_at_location};
11pub use super::place_ext::PlaceExt;
12pub use super::places_conflict::{PlaceConflictBias, places_conflict};
13pub use super::polonius::legacy::{
14 PoloniusFacts as PoloniusInput, PoloniusLocationTable, PoloniusOutput, PoloniusRegionVid,
15 RichLocation, RustcFacts,
16};
17pub use super::region_infer::RegionInferenceContext;
18
19/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
20///
21/// If executing under `-Z polonius` the choice here has no effect, and everything as if
22/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
23/// will be retrieved.
24#[derive(Debug, Copy, Clone)]
25pub enum ConsumerOptions {
26 /// Retrieve the [`Body`] along with the [`BorrowSet`]
27 /// and [`RegionInferenceContext`]. If you would like the body only, use
28 /// [`TyCtxt::mir_promoted`].
29 ///
30 /// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`].
31 RegionInferenceContext,
32 /// The recommended option. Retrieves the maximal amount of information
33 /// without significant slowdowns.
34 ///
35 /// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
36 /// and additionally retrieve the [`PoloniusLocationTable`] and [`PoloniusInput`] that
37 /// would be given to Polonius. Critically, this does not run Polonius, which
38 /// one may want to avoid due to performance issues on large bodies.
39 PoloniusInputFacts,
40 /// Implies [`PoloniusInputFacts`](ConsumerOptions::PoloniusInputFacts),
41 /// and additionally runs Polonius to calculate the [`PoloniusOutput`].
42 PoloniusOutputFacts,
43}
44
45impl ConsumerOptions {
46 /// Should the Polonius input facts be computed?
47 pub(crate) fn polonius_input(&self) -> bool {
48 matches!(self, Self::PoloniusInputFacts | Self::PoloniusOutputFacts)
49 }
50 /// Should we run Polonius and collect the output facts?
51 pub(crate) fn polonius_output(&self) -> bool {
52 matches!(self, Self::PoloniusOutputFacts)
53 }
54}
55
56/// A `Body` with information computed by the borrow checker. This struct is
57/// intended to be consumed by compiler consumers.
58///
59/// We need to include the MIR body here because the region identifiers must
60/// match the ones in the Polonius facts.
61pub struct BodyWithBorrowckFacts<'tcx> {
62 /// A mir body that contains region identifiers.
63 pub body: Body<'tcx>,
64 /// The mir bodies of promoteds.
65 pub promoted: IndexVec<Promoted, Body<'tcx>>,
66 /// The set of borrows occurring in `body` with data about them.
67 pub borrow_set: BorrowSet<'tcx>,
68 /// Context generated during borrowck, intended to be passed to
69 /// [`calculate_borrows_out_of_scope_at_location`].
70 pub region_inference_context: RegionInferenceContext<'tcx>,
71 /// The table that maps Polonius points to locations in the table.
72 /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
73 /// or [`ConsumerOptions::PoloniusOutputFacts`].
74 pub location_table: Option<PoloniusLocationTable>,
75 /// Polonius input facts.
76 /// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
77 /// or [`ConsumerOptions::PoloniusOutputFacts`].
78 pub input_facts: Option<Box<PoloniusInput>>,
79 /// Polonius output facts. Populated when using
80 /// [`ConsumerOptions::PoloniusOutputFacts`].
81 pub output_facts: Option<Box<PoloniusOutput>>,
82}
83
84/// This function computes borrowck facts for the given body. The [`ConsumerOptions`]
85/// determine which facts are returned. This function makes a copy of the body because
86/// it needs to regenerate the region identifiers. It should never be invoked during a
87/// typical compilation session due to the unnecessary overhead of returning
88/// [`BodyWithBorrowckFacts`].
89///
90/// Note:
91/// * This function will panic if the required body was already stolen. This
92/// can, for example, happen when requesting a body of a `const` function
93/// because they are evaluated during typechecking. The panic can be avoided
94/// by overriding the `mir_borrowck` query. You can find a complete example
95/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
96///
97/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
98pub fn get_body_with_borrowck_facts(
99 tcx: TyCtxt<'_>,
100 def: LocalDefId,
101 options: ConsumerOptions,
102) -> BodyWithBorrowckFacts<'_> {
103 let (input_body, promoted) = tcx.mir_promoted(def);
104 let input_body: &Body<'_> = &input_body.borrow();
105 let promoted: &IndexSlice<_, _> = &promoted.borrow();
106 *super::do_mir_borrowck(tcx, input_body, promoted, Some(options)).1.unwrap()
107}