1
1
//! This file provides API for compiler consumers.
2
2
3
+ use rustc_data_structures:: fx:: FxHashMap ;
3
4
use rustc_hir:: def_id:: LocalDefId ;
4
5
use rustc_index:: IndexVec ;
6
+ use rustc_middle:: bug;
5
7
use rustc_middle:: mir:: { Body , Promoted } ;
6
8
use rustc_middle:: ty:: TyCtxt ;
7
9
@@ -17,7 +19,39 @@ pub use super::polonius::legacy::{
17
19
pub use super :: region_infer:: RegionInferenceContext ;
18
20
use crate :: { BorrowCheckRootCtxt , do_mir_borrowck} ;
19
21
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`].
21
55
///
22
56
/// If executing under `-Z polonius` the choice here has no effect, and everything as if
23
57
/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
@@ -43,17 +77,6 @@ pub enum ConsumerOptions {
43
77
PoloniusOutputFacts ,
44
78
}
45
79
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
-
57
80
/// A `Body` with information computed by the borrow checker. This struct is
58
81
/// intended to be consumed by compiler consumers.
59
82
///
@@ -82,25 +105,35 @@ pub struct BodyWithBorrowckFacts<'tcx> {
82
105
pub output_facts : Option < Box < PoloniusOutput > > ,
83
106
}
84
107
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`].
90
114
///
91
115
/// 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
93
117
/// can, for example, happen when requesting a body of a `const` function
94
118
/// because they are evaluated during typechecking. The panic can be avoided
95
119
/// 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 `.
97
121
///
98
122
/// * 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 (
100
124
tcx : TyCtxt < ' _ > ,
101
- def_id : LocalDefId ,
125
+ root_def_id : LocalDefId ,
102
126
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
106
139
}
0 commit comments