@@ -125,15 +125,9 @@ pub struct Borrows<'a, 'tcx> {
125
125
borrows_out_of_scope_at_location : FxIndexMap < Location , Vec < BorrowIndex > > ,
126
126
}
127
127
128
- struct StackEntry {
129
- bb : mir:: BasicBlock ,
130
- lo : usize ,
131
- hi : usize ,
132
- }
133
-
134
128
struct OutOfScopePrecomputer < ' a , ' tcx > {
135
129
visited : BitSet < mir:: BasicBlock > ,
136
- visit_stack : Vec < StackEntry > ,
130
+ visit_stack : Vec < mir :: BasicBlock > ,
137
131
body : & ' a Body < ' tcx > ,
138
132
regioncx : & ' a RegionInferenceContext < ' tcx > ,
139
133
borrows_out_of_scope_at_location : FxIndexMap < Location , Vec < BorrowIndex > > ,
@@ -156,73 +150,68 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
156
150
& mut self ,
157
151
borrow_index : BorrowIndex ,
158
152
borrow_region : RegionVid ,
159
- location : Location ,
153
+ first_location : Location ,
160
154
) {
161
- // We visit one BB at a time. The complication is that we may start in the
162
- // middle of the first BB visited (the one containing `location`), in which
163
- // case we may have to later on process the first part of that BB if there
164
- // is a path back to its start.
165
-
166
- // For visited BBs, we record the index of the first statement processed.
167
- // (In fully processed BBs this index is 0.) Note also that we add BBs to
168
- // `visited` once they are added to `stack`, before they are actually
169
- // processed, because this avoids the need to look them up again on
170
- // completion.
171
- self . visited . insert ( location. block ) ;
172
-
173
- let mut first_lo = location. statement_index ;
174
- let first_hi = self . body [ location. block ] . statements . len ( ) ;
175
-
176
- self . visit_stack . push ( StackEntry { bb : location. block , lo : first_lo, hi : first_hi } ) ;
177
-
178
- while let Some ( StackEntry { bb, lo, hi } ) = self . visit_stack . pop ( ) {
179
- // If we process the first part of the first basic block (i.e. we encounter that block
180
- // for the second time), we no longer have to visit its successors again.
181
- let mut finished_early = bb == location. block && hi != first_hi;
182
- for i in lo..=hi {
183
- let location = Location { block : bb, statement_index : i } ;
155
+ let first_block = first_location. block ;
156
+ let first_bb_data = & self . body . basic_blocks [ first_block] ;
157
+
158
+ // This is the first block, we only want to visit it from the creation of the borrow at
159
+ // `first_location`.
160
+ let first_lo = first_location. statement_index ;
161
+ let first_hi = first_bb_data. statements . len ( ) ;
162
+
163
+ if let Some ( kill_stmt) = self . regioncx . first_non_contained_inclusive (
164
+ borrow_region,
165
+ first_block,
166
+ first_lo,
167
+ first_hi,
168
+ ) {
169
+ let kill_location = Location { block : first_block, statement_index : kill_stmt } ;
170
+ // If region does not contain a point at the location, then add to list and skip
171
+ // successor locations.
172
+ debug ! ( "borrow {:?} gets killed at {:?}" , borrow_index, kill_location) ;
173
+ self . borrows_out_of_scope_at_location
174
+ . entry ( kill_location)
175
+ . or_default ( )
176
+ . push ( borrow_index) ;
177
+
178
+ // The borrow is already dead, there is no need to visit other blocks.
179
+ return ;
180
+ }
181
+
182
+ // The borrow is not dead. Add successor BBs to the work list, if necessary.
183
+ for succ_bb in first_bb_data. terminator ( ) . successors ( ) {
184
+ if self . visited . insert ( succ_bb) {
185
+ self . visit_stack . push ( succ_bb) ;
186
+ }
187
+ }
188
+
189
+ // We may end up visiting `first_block` again. This is not an issue: we know at this point
190
+ // that it does not kill the borrow in the `first_lo..=first_hi` range, so checking the
191
+ // `0..first_lo` range and the `0..first_hi` range give the same result.
192
+ while let Some ( block) = self . visit_stack . pop ( ) {
193
+ let bb_data = & self . body [ block] ;
194
+ let num_stmts = bb_data. statements . len ( ) ;
195
+ if let Some ( kill_stmt) =
196
+ self . regioncx . first_non_contained_inclusive ( borrow_region, block, 0 , num_stmts)
197
+ {
198
+ let kill_location = Location { block, statement_index : kill_stmt } ;
184
199
// If region does not contain a point at the location, then add to list and skip
185
200
// successor locations.
186
- if !self . regioncx . region_contains ( borrow_region, location) {
187
- debug ! ( "borrow {:?} gets killed at {:?}" , borrow_index, location) ;
188
- self . borrows_out_of_scope_at_location
189
- . entry ( location)
190
- . or_default ( )
191
- . push ( borrow_index) ;
192
- finished_early = true ;
193
- break ;
194
- }
201
+ debug ! ( "borrow {:?} gets killed at {:?}" , borrow_index, kill_location) ;
202
+ self . borrows_out_of_scope_at_location
203
+ . entry ( kill_location)
204
+ . or_default ( )
205
+ . push ( borrow_index) ;
206
+
207
+ // We killed the borrow, so we do not visit this block's successors.
208
+ continue ;
195
209
}
196
210
197
- if !finished_early {
198
- // Add successor BBs to the work list, if necessary.
199
- let bb_data = & self . body [ bb] ;
200
- debug_assert ! ( hi == bb_data. statements. len( ) ) ;
201
- for succ_bb in bb_data. terminator ( ) . successors ( ) {
202
- if !self . visited . insert ( succ_bb) {
203
- if succ_bb == location. block && first_lo > 0 {
204
- // `succ_bb` has been seen before. If it wasn't
205
- // fully processed, add its first part to `stack`
206
- // for processing.
207
- self . visit_stack . push ( StackEntry {
208
- bb : succ_bb,
209
- lo : 0 ,
210
- hi : first_lo - 1 ,
211
- } ) ;
212
-
213
- // And update this entry with 0, to represent the
214
- // whole BB being processed.
215
- first_lo = 0 ;
216
- }
217
- } else {
218
- // succ_bb hasn't been seen before. Add it to
219
- // `stack` for processing.
220
- self . visit_stack . push ( StackEntry {
221
- bb : succ_bb,
222
- lo : 0 ,
223
- hi : self . body [ succ_bb] . statements . len ( ) ,
224
- } ) ;
225
- }
211
+ // Add successor BBs to the work list, if necessary.
212
+ for succ_bb in bb_data. terminator ( ) . successors ( ) {
213
+ if self . visited . insert ( succ_bb) {
214
+ self . visit_stack . push ( succ_bb) ;
226
215
}
227
216
}
228
217
}
0 commit comments