rustc_borrowck/
consumers.rs

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