11//! This file provides API for compiler consumers.
22
3+ use rustc_data_structures:: fx:: FxHashMap ;
34use rustc_hir:: def_id:: LocalDefId ;
45use rustc_index:: IndexVec ;
6+ use rustc_middle:: bug;
57use rustc_middle:: mir:: { Body , Promoted } ;
68use rustc_middle:: ty:: TyCtxt ;
79
@@ -17,7 +19,39 @@ pub use super::polonius::legacy::{
1719pub use super :: region_infer:: RegionInferenceContext ;
1820use crate :: { BorrowCheckRootCtxt , do_mir_borrowck} ;
1921
20- /// Options determining the output behavior of [`get_body_with_borrowck_facts`].
22+ /// Struct used during mir borrowck to collect bodies with facts for a typeck root and all
23+ /// its nested bodies.
24+ pub ( crate ) struct BorrowckConsumer < ' tcx > {
25+ options : ConsumerOptions ,
26+ bodies : FxHashMap < LocalDefId , BodyWithBorrowckFacts < ' tcx > > ,
27+ }
28+
29+ impl < ' tcx > BorrowckConsumer < ' tcx > {
30+ pub ( crate ) fn new ( options : ConsumerOptions ) -> Self {
31+ Self { options, bodies : Default :: default ( ) }
32+ }
33+
34+ pub ( crate ) fn insert_body ( & mut self , def_id : LocalDefId , body : BodyWithBorrowckFacts < ' tcx > ) {
35+ if self . bodies . insert ( def_id, body) . is_some ( ) {
36+ bug ! ( "unexpected previous body for {def_id:?}" ) ;
37+ }
38+ }
39+
40+ /// Should the Polonius input facts be computed?
41+ pub ( crate ) fn polonius_input ( & self ) -> bool {
42+ matches ! (
43+ self . options,
44+ ConsumerOptions :: PoloniusInputFacts | ConsumerOptions :: PoloniusOutputFacts
45+ )
46+ }
47+
48+ /// Should we run Polonius and collect the output facts?
49+ pub ( crate ) fn polonius_output ( & self ) -> bool {
50+ matches ! ( self . options, ConsumerOptions :: PoloniusOutputFacts )
51+ }
52+ }
53+
54+ /// Options determining the output behavior of [`get_bodies_with_borrowck_facts`].
2155///
2256/// If executing under `-Z polonius` the choice here has no effect, and everything as if
2357/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
@@ -43,17 +77,6 @@ pub enum ConsumerOptions {
4377 PoloniusOutputFacts ,
4478}
4579
46- impl 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-
5780/// A `Body` with information computed by the borrow checker. This struct is
5881/// intended to be consumed by compiler consumers.
5982///
@@ -82,25 +105,35 @@ pub struct BodyWithBorrowckFacts<'tcx> {
82105 pub output_facts : Option < Box < PoloniusOutput > > ,
83106}
84107
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`].
108+ /// 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`].
90114///
91115/// Note:
92- /// * This function will panic if the required body was already stolen. This
116+ /// * This function will panic if the required bodies were already stolen. This
93117/// can, for example, happen when requesting a body of a `const` function
94118/// because they are evaluated during typechecking. The panic can be avoided
95119/// 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/ `.
120+ /// that shows how to do this at `tests/ui-fulldeps /obtain-borrowck.rs `.
97121///
98122/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
99- pub fn get_body_with_borrowck_facts (
123+ pub fn get_bodies_with_borrowck_facts (
100124 tcx : TyCtxt < ' _ > ,
101- def_id : LocalDefId ,
125+ root_def_id : LocalDefId ,
102126 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 ( )
127+ ) -> FxHashMap < LocalDefId , BodyWithBorrowckFacts < ' _ > > {
128+ let mut root_cx =
129+ BorrowCheckRootCtxt :: new ( tcx, root_def_id, Some ( BorrowckConsumer :: new ( options) ) ) ;
130+
131+ // See comment in `rustc_borrowck::mir_borrowck`
132+ let nested_bodies = tcx. nested_bodies_within ( root_def_id) ;
133+ for def_id in nested_bodies {
134+ root_cx. get_or_insert_nested ( def_id) ;
135+ }
136+
137+ do_mir_borrowck ( & mut root_cx, root_def_id) ;
138+ root_cx. consumer . unwrap ( ) . bodies
106139}
0 commit comments