@@ -187,19 +187,28 @@ struct OutOfScopePrecomputer<'a, 'tcx> {
187
187
borrows_out_of_scope_at_location : FxIndexMap < Location , Vec < BorrowIndex > > ,
188
188
}
189
189
190
- impl < ' a , ' tcx > OutOfScopePrecomputer < ' a , ' tcx > {
191
- fn new ( body : & ' a Body < ' tcx > , regioncx : & ' a RegionInferenceContext < ' tcx > ) -> Self {
192
- OutOfScopePrecomputer {
190
+ impl < ' tcx > OutOfScopePrecomputer < ' _ , ' tcx > {
191
+ fn compute (
192
+ body : & Body < ' tcx > ,
193
+ regioncx : & RegionInferenceContext < ' tcx > ,
194
+ borrow_set : & BorrowSet < ' tcx > ,
195
+ ) -> FxIndexMap < Location , Vec < BorrowIndex > > {
196
+ let mut prec = OutOfScopePrecomputer {
193
197
visited : DenseBitSet :: new_empty ( body. basic_blocks . len ( ) ) ,
194
198
visit_stack : vec ! [ ] ,
195
199
body,
196
200
regioncx,
197
201
borrows_out_of_scope_at_location : FxIndexMap :: default ( ) ,
202
+ } ;
203
+ for ( borrow_index, borrow_data) in borrow_set. iter_enumerated ( ) {
204
+ let borrow_region = borrow_data. region ;
205
+ let location = borrow_data. reserve_location ;
206
+ prec. precompute_borrows_out_of_scope ( borrow_index, borrow_region, location) ;
198
207
}
208
+
209
+ prec. borrows_out_of_scope_at_location
199
210
}
200
- }
201
211
202
- impl < ' tcx > OutOfScopePrecomputer < ' _ , ' tcx > {
203
212
fn precompute_borrows_out_of_scope (
204
213
& mut self ,
205
214
borrow_index : BorrowIndex ,
@@ -280,15 +289,7 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
280
289
regioncx : & RegionInferenceContext < ' tcx > ,
281
290
borrow_set : & BorrowSet < ' tcx > ,
282
291
) -> FxIndexMap < Location , Vec < BorrowIndex > > {
283
- let mut prec = OutOfScopePrecomputer :: new ( body, regioncx) ;
284
- for ( borrow_index, borrow_data) in borrow_set. iter_enumerated ( ) {
285
- let borrow_region = borrow_data. region ;
286
- let location = borrow_data. reserve_location ;
287
-
288
- prec. precompute_borrows_out_of_scope ( borrow_index, borrow_region, location) ;
289
- }
290
-
291
- prec. borrows_out_of_scope_at_location
292
+ OutOfScopePrecomputer :: compute ( body, regioncx, borrow_set)
292
293
}
293
294
294
295
struct PoloniusOutOfScopePrecomputer < ' a , ' tcx > {
@@ -300,19 +301,30 @@ struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
300
301
loans_out_of_scope_at_location : FxIndexMap < Location , Vec < BorrowIndex > > ,
301
302
}
302
303
303
- impl < ' a , ' tcx > PoloniusOutOfScopePrecomputer < ' a , ' tcx > {
304
- fn new ( body : & ' a Body < ' tcx > , regioncx : & ' a RegionInferenceContext < ' tcx > ) -> Self {
305
- Self {
304
+ impl < ' tcx > PoloniusOutOfScopePrecomputer < ' _ , ' tcx > {
305
+ fn compute (
306
+ body : & Body < ' tcx > ,
307
+ regioncx : & RegionInferenceContext < ' tcx > ,
308
+ borrow_set : & BorrowSet < ' tcx > ,
309
+ ) -> FxIndexMap < Location , Vec < BorrowIndex > > {
310
+ // The in-tree polonius analysis computes loans going out of scope using the
311
+ // set-of-loans model.
312
+ let mut prec = PoloniusOutOfScopePrecomputer {
306
313
visited : DenseBitSet :: new_empty ( body. basic_blocks . len ( ) ) ,
307
314
visit_stack : vec ! [ ] ,
308
315
body,
309
316
regioncx,
310
317
loans_out_of_scope_at_location : FxIndexMap :: default ( ) ,
318
+ } ;
319
+ for ( loan_idx, loan_data) in borrow_set. iter_enumerated ( ) {
320
+ let issuing_region = loan_data. region ;
321
+ let loan_issued_at = loan_data. reserve_location ;
322
+ prec. precompute_loans_out_of_scope ( loan_idx, issuing_region, loan_issued_at) ;
311
323
}
324
+
325
+ prec. loans_out_of_scope_at_location
312
326
}
313
- }
314
327
315
- impl < ' tcx > PoloniusOutOfScopePrecomputer < ' _ , ' tcx > {
316
328
/// Loans are in scope while they are live: whether they are contained within any live region.
317
329
/// In the location-insensitive analysis, a loan will be contained in a region if the issuing
318
330
/// region can reach it in the subset graph. So this is a reachability problem.
@@ -325,10 +337,17 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
325
337
let sccs = self . regioncx . constraint_sccs ( ) ;
326
338
let universal_regions = self . regioncx . universal_regions ( ) ;
327
339
340
+ // The loop below was useful for the location-insensitive analysis but shouldn't be
341
+ // impactful in the location-sensitive case. It seems that it does, however, as without it a
342
+ // handful of tests fail. That likely means some liveness or outlives data related to choice
343
+ // regions is missing
344
+ // FIXME: investigate the impact of loans traversing applied member constraints and why some
345
+ // tests fail otherwise.
346
+ //
328
347
// We first handle the cases where the loan doesn't go out of scope, depending on the
329
348
// issuing region's successors.
330
349
for successor in graph:: depth_first_search ( & self . regioncx . region_graph ( ) , issuing_region) {
331
- // 1. Via applied member constraints
350
+ // Via applied member constraints
332
351
//
333
352
// The issuing region can flow into the choice regions, and they are either:
334
353
// - placeholders or free regions themselves,
@@ -346,14 +365,6 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
346
365
return ;
347
366
}
348
367
}
349
-
350
- // 2. Via regions that are live at all points: placeholders and free regions.
351
- //
352
- // If the issuing region outlives such a region, its loan escapes the function and
353
- // cannot go out of scope. We can early return.
354
- if self . regioncx . is_region_live_at_all_points ( successor) {
355
- return ;
356
- }
357
368
}
358
369
359
370
let first_block = loan_issued_at. block ;
@@ -461,34 +472,12 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> {
461
472
regioncx : & RegionInferenceContext < ' tcx > ,
462
473
borrow_set : & ' a BorrowSet < ' tcx > ,
463
474
) -> Self {
464
- let mut borrows_out_of_scope_at_location =
465
- calculate_borrows_out_of_scope_at_location ( body, regioncx, borrow_set) ;
466
-
467
- // The in-tree polonius analysis computes loans going out of scope using the set-of-loans
468
- // model, and makes sure they're identical to the existing computation of the set-of-points
469
- // model.
470
- if tcx. sess . opts . unstable_opts . polonius . is_next_enabled ( ) {
471
- let mut polonius_prec = PoloniusOutOfScopePrecomputer :: new ( body, regioncx) ;
472
- for ( loan_idx, loan_data) in borrow_set. iter_enumerated ( ) {
473
- let issuing_region = loan_data. region ;
474
- let loan_issued_at = loan_data. reserve_location ;
475
-
476
- polonius_prec. precompute_loans_out_of_scope (
477
- loan_idx,
478
- issuing_region,
479
- loan_issued_at,
480
- ) ;
481
- }
482
-
483
- assert_eq ! (
484
- borrows_out_of_scope_at_location, polonius_prec. loans_out_of_scope_at_location,
485
- "polonius loan scopes differ from NLL borrow scopes, for body {:?}" ,
486
- body. span,
487
- ) ;
488
-
489
- borrows_out_of_scope_at_location = polonius_prec. loans_out_of_scope_at_location ;
490
- }
491
-
475
+ let borrows_out_of_scope_at_location =
476
+ if !tcx. sess . opts . unstable_opts . polonius . is_next_enabled ( ) {
477
+ calculate_borrows_out_of_scope_at_location ( body, regioncx, borrow_set)
478
+ } else {
479
+ PoloniusOutOfScopePrecomputer :: compute ( body, regioncx, borrow_set)
480
+ } ;
492
481
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
493
482
}
494
483
0 commit comments