1
1
#![ deny( rustc:: untranslatable_diagnostic) ]
2
2
#![ deny( rustc:: diagnostic_outside_of_impl) ]
3
- use rustc_infer:: infer:: InferCtxt ;
4
3
use rustc_middle:: mir:: visit:: Visitor ;
5
4
use rustc_middle:: mir:: {
6
5
Body , Local , Location , Place , PlaceRef , ProjectionElem , Rvalue , Statement , StatementKind ,
7
6
Terminator , TerminatorKind , UserTypeProjection ,
8
7
} ;
9
- use rustc_middle:: ty:: { self } ;
8
+ use rustc_middle:: ty:: { TyCtxt , Variance } ;
10
9
11
10
use crate :: { borrow_set:: BorrowSet , facts:: AllFacts , location:: LocationTable , places_conflict} ;
12
11
13
12
pub ( super ) fn generate_constraints < ' tcx > (
14
- infcx : & InferCtxt < ' tcx > ,
15
- all_facts : & mut Option < AllFacts > ,
13
+ tcx : TyCtxt < ' tcx > ,
14
+ all_facts : & mut AllFacts ,
16
15
location_table : & LocationTable ,
17
16
body : & Body < ' tcx > ,
18
17
borrow_set : & BorrowSet < ' tcx > ,
19
18
) {
20
- let mut cg = ConstraintGeneration { borrow_set, infcx, location_table, all_facts, body } ;
19
+ let _prof_timer = tcx. prof . generic_activity ( "polonius_fact_generation" ) ;
20
+ let mut cg = ConstraintGeneration { borrow_set, tcx, location_table, all_facts, body } ;
21
21
for ( bb, data) in body. basic_blocks . iter_enumerated ( ) {
22
22
cg. visit_basic_block_data ( bb, data) ;
23
23
}
24
24
}
25
25
26
26
/// 'cg = the duration of the constraint generation process itself.
27
27
struct ConstraintGeneration < ' cg , ' tcx > {
28
- infcx : & ' cg InferCtxt < ' tcx > ,
29
- all_facts : & ' cg mut Option < AllFacts > ,
28
+ tcx : TyCtxt < ' tcx > ,
29
+ all_facts : & ' cg mut AllFacts ,
30
30
location_table : & ' cg LocationTable ,
31
31
borrow_set : & ' cg BorrowSet < ' tcx > ,
32
32
body : & ' cg Body < ' tcx > ,
33
33
}
34
34
35
35
impl < ' cg , ' tcx > Visitor < ' tcx > for ConstraintGeneration < ' cg , ' tcx > {
36
36
fn visit_statement ( & mut self , statement : & Statement < ' tcx > , location : Location ) {
37
- if let Some ( all_facts) = self . all_facts {
38
- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
39
- all_facts. cfg_edge . push ( (
40
- self . location_table . start_index ( location) ,
41
- self . location_table . mid_index ( location) ,
42
- ) ) ;
43
-
44
- all_facts. cfg_edge . push ( (
45
- self . location_table . mid_index ( location) ,
46
- self . location_table . start_index ( location. successor_within_block ( ) ) ,
47
- ) ) ;
48
-
49
- // If there are borrows on this now dead local, we need to record them as `killed`.
50
- if let StatementKind :: StorageDead ( local) = statement. kind {
51
- record_killed_borrows_for_local (
52
- all_facts,
53
- self . borrow_set ,
54
- self . location_table ,
55
- local,
56
- location,
57
- ) ;
58
- }
37
+ self . all_facts . cfg_edge . push ( (
38
+ self . location_table . start_index ( location) ,
39
+ self . location_table . mid_index ( location) ,
40
+ ) ) ;
41
+
42
+ self . all_facts . cfg_edge . push ( (
43
+ self . location_table . mid_index ( location) ,
44
+ self . location_table . start_index ( location. successor_within_block ( ) ) ,
45
+ ) ) ;
46
+
47
+ // If there are borrows on this now dead local, we need to record them as `killed`.
48
+ if let StatementKind :: StorageDead ( local) = statement. kind {
49
+ self . record_killed_borrows_for_local ( local, location) ;
59
50
}
60
51
61
52
self . super_statement ( statement, location) ;
@@ -70,21 +61,18 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
70
61
}
71
62
72
63
fn visit_terminator ( & mut self , terminator : & Terminator < ' tcx > , location : Location ) {
73
- if let Some ( all_facts) = self . all_facts {
74
- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
75
- all_facts. cfg_edge . push ( (
76
- self . location_table . start_index ( location) ,
64
+ self . all_facts . cfg_edge . push ( (
65
+ self . location_table . start_index ( location) ,
66
+ self . location_table . mid_index ( location) ,
67
+ ) ) ;
68
+
69
+ let successor_blocks = terminator. successors ( ) ;
70
+ self . all_facts . cfg_edge . reserve ( successor_blocks. size_hint ( ) . 0 ) ;
71
+ for successor_block in successor_blocks {
72
+ self . all_facts . cfg_edge . push ( (
77
73
self . location_table . mid_index ( location) ,
74
+ self . location_table . start_index ( successor_block. start_location ( ) ) ,
78
75
) ) ;
79
-
80
- let successor_blocks = terminator. successors ( ) ;
81
- all_facts. cfg_edge . reserve ( successor_blocks. size_hint ( ) . 0 ) ;
82
- for successor_block in successor_blocks {
83
- all_facts. cfg_edge . push ( (
84
- self . location_table . mid_index ( location) ,
85
- self . location_table . start_index ( successor_block. start_location ( ) ) ,
86
- ) ) ;
87
- }
88
76
}
89
77
90
78
// A `Call` terminator's return value can be a local which has borrows,
@@ -99,7 +87,7 @@ impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
99
87
fn visit_ascribe_user_ty (
100
88
& mut self ,
101
89
_place : & Place < ' tcx > ,
102
- _variance : ty :: Variance ,
90
+ _variance : Variance ,
103
91
_user_ty : & UserTypeProjection ,
104
92
_location : Location ,
105
93
) {
@@ -110,75 +98,59 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
110
98
/// When recording facts for Polonius, records the borrows on the specified place
111
99
/// as `killed`. For example, when assigning to a local, or on a call's return destination.
112
100
fn record_killed_borrows_for_place ( & mut self , place : Place < ' tcx > , location : Location ) {
113
- if let Some ( all_facts) = self . all_facts {
114
- let _prof_timer = self . infcx . tcx . prof . generic_activity ( "polonius_fact_generation" ) ;
115
-
116
- // Depending on the `Place` we're killing:
117
- // - if it's a local, or a single deref of a local,
118
- // we kill all the borrows on the local.
119
- // - if it's a deeper projection, we have to filter which
120
- // of the borrows are killed: the ones whose `borrowed_place`
121
- // conflicts with the `place`.
122
- match place. as_ref ( ) {
123
- PlaceRef { local, projection : & [ ] }
124
- | PlaceRef { local, projection : & [ ProjectionElem :: Deref ] } => {
125
- debug ! (
126
- "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
127
- local, location
128
- ) ;
129
-
130
- record_killed_borrows_for_local (
131
- all_facts,
132
- self . borrow_set ,
133
- self . location_table ,
134
- local,
135
- location,
136
- ) ;
137
- }
101
+ // Depending on the `Place` we're killing:
102
+ // - if it's a local, or a single deref of a local,
103
+ // we kill all the borrows on the local.
104
+ // - if it's a deeper projection, we have to filter which
105
+ // of the borrows are killed: the ones whose `borrowed_place`
106
+ // conflicts with the `place`.
107
+ match place. as_ref ( ) {
108
+ PlaceRef { local, projection : & [ ] }
109
+ | PlaceRef { local, projection : & [ ProjectionElem :: Deref ] } => {
110
+ debug ! (
111
+ "Recording `killed` facts for borrows of local={:?} at location={:?}" ,
112
+ local, location
113
+ ) ;
114
+
115
+ self . record_killed_borrows_for_local ( local, location) ;
116
+ }
138
117
139
- PlaceRef { local, projection : & [ .., _] } => {
140
- // Kill conflicting borrows of the innermost local.
141
- debug ! (
142
- "Recording `killed` facts for borrows of \
118
+ PlaceRef { local, projection : & [ .., _] } => {
119
+ // Kill conflicting borrows of the innermost local.
120
+ debug ! (
121
+ "Recording `killed` facts for borrows of \
143
122
innermost projected local={:?} at location={:?}",
144
- local, location
145
- ) ;
146
-
147
- if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
148
- for & borrow_index in borrow_indices {
149
- let places_conflict = places_conflict:: places_conflict (
150
- self . infcx . tcx ,
151
- self . body ,
152
- self . borrow_set [ borrow_index] . borrowed_place ,
153
- place,
154
- places_conflict:: PlaceConflictBias :: NoOverlap ,
155
- ) ;
156
-
157
- if places_conflict {
158
- let location_index = self . location_table . mid_index ( location) ;
159
- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
160
- }
123
+ local, location
124
+ ) ;
125
+
126
+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
127
+ for & borrow_index in borrow_indices {
128
+ let places_conflict = places_conflict:: places_conflict (
129
+ self . tcx ,
130
+ self . body ,
131
+ self . borrow_set [ borrow_index] . borrowed_place ,
132
+ place,
133
+ places_conflict:: PlaceConflictBias :: NoOverlap ,
134
+ ) ;
135
+
136
+ if places_conflict {
137
+ let location_index = self . location_table . mid_index ( location) ;
138
+ self . all_facts . loan_killed_at . push ( ( borrow_index, location_index) ) ;
161
139
}
162
140
}
163
141
}
164
142
}
165
143
}
166
144
}
167
- }
168
145
169
- /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
170
- fn record_killed_borrows_for_local (
171
- all_facts : & mut AllFacts ,
172
- borrow_set : & BorrowSet < ' _ > ,
173
- location_table : & LocationTable ,
174
- local : Local ,
175
- location : Location ,
176
- ) {
177
- if let Some ( borrow_indices) = borrow_set. local_map . get ( & local) {
178
- all_facts. loan_killed_at . reserve ( borrow_indices. len ( ) ) ;
179
- for & borrow_index in borrow_indices {
180
- let location_index = location_table. mid_index ( location) ;
181
- all_facts. loan_killed_at . push ( ( borrow_index, location_index) ) ;
146
+ /// When recording facts for Polonius, records the borrows on the specified local as `killed`.
147
+ fn record_killed_borrows_for_local ( & mut self , local : Local , location : Location ) {
148
+ if let Some ( borrow_indices) = self . borrow_set . local_map . get ( & local) {
149
+ let location_index = self . location_table . mid_index ( location) ;
150
+ self . all_facts . loan_killed_at . reserve ( borrow_indices. len ( ) ) ;
151
+ for & borrow_index in borrow_indices {
152
+ self . all_facts . loan_killed_at . push ( ( borrow_index, location_index) ) ;
153
+ }
182
154
}
183
155
}
184
156
}
0 commit comments