@@ -21,6 +21,7 @@ use std::cell::RefCell;
21
21
use std:: marker:: PhantomData ;
22
22
use std:: ops:: { ControlFlow , Deref } ;
23
23
24
+ use borrow_set:: LocalsStateAtExit ;
24
25
use root_cx:: BorrowCheckRootCtxt ;
25
26
use rustc_abi:: FieldIdx ;
26
27
use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
@@ -303,33 +304,13 @@ fn do_mir_borrowck<'tcx>(
303
304
root_cx. set_tainted_by_errors ( e) ;
304
305
}
305
306
306
- let mut local_names = IndexVec :: from_elem ( None , & input_body. local_decls ) ;
307
- for var_debug_info in & input_body. var_debug_info {
308
- if let VarDebugInfoContents :: Place ( place) = var_debug_info. value {
309
- if let Some ( local) = place. as_local ( ) {
310
- if let Some ( prev_name) = local_names[ local]
311
- && var_debug_info. name != prev_name
312
- {
313
- span_bug ! (
314
- var_debug_info. source_info. span,
315
- "local {:?} has many names (`{}` vs `{}`)" ,
316
- local,
317
- prev_name,
318
- var_debug_info. name
319
- ) ;
320
- }
321
- local_names[ local] = Some ( var_debug_info. name ) ;
322
- }
323
- }
324
- }
325
-
326
307
// Replace all regions with fresh inference variables. This
327
308
// requires first making our own copy of the MIR. This copy will
328
309
// be modified (in place) to contain non-lexical lifetimes. It
329
310
// will have a lifetime tied to the inference context.
330
311
let mut body_owned = input_body. clone ( ) ;
331
312
let mut promoted = input_promoted. to_owned ( ) ;
332
- let free_regions = nll:: replace_regions_in_mir ( & infcx, & mut body_owned, & mut promoted) ;
313
+ let universal_regions = nll:: replace_regions_in_mir ( & infcx, & mut body_owned, & mut promoted) ;
333
314
let body = & body_owned; // no further changes
334
315
335
316
let location_table = PoloniusLocationTable :: new ( body) ;
@@ -354,7 +335,7 @@ fn do_mir_borrowck<'tcx>(
354
335
} = nll:: compute_regions (
355
336
root_cx,
356
337
& infcx,
357
- free_regions ,
338
+ universal_regions ,
358
339
body,
359
340
& promoted,
360
341
& location_table,
@@ -367,24 +348,23 @@ fn do_mir_borrowck<'tcx>(
367
348
// Dump MIR results into a file, if that is enabled. This lets us
368
349
// write unit-tests, as well as helping with debugging.
369
350
nll:: dump_nll_mir ( & infcx, body, & regioncx, & opt_closure_req, & borrow_set) ;
351
+ polonius:: dump_polonius_mir (
352
+ & infcx,
353
+ body,
354
+ & regioncx,
355
+ & opt_closure_req,
356
+ & borrow_set,
357
+ polonius_diagnostics. as_ref ( ) ,
358
+ ) ;
370
359
371
360
// We also have a `#[rustc_regions]` annotation that causes us to dump
372
361
// information.
373
- let diags_buffer = & mut BorrowckDiagnosticsBuffer :: default ( ) ;
374
- nll:: dump_annotation ( & infcx, body, & regioncx, & opt_closure_req, diags_buffer) ;
375
-
376
- let movable_coroutine =
377
- // The first argument is the coroutine type passed by value
378
- if let Some ( local) = body. local_decls . raw . get ( 1 )
379
- // Get the interior types and args which typeck computed
380
- && let ty:: Coroutine ( def_id, _) = * local. ty . kind ( )
381
- && tcx. coroutine_movability ( def_id) == hir:: Movability :: Movable
382
- {
383
- true
384
- } else {
385
- false
386
- } ;
362
+ nll:: dump_annotation ( & infcx, body, & regioncx, & opt_closure_req) ;
387
363
364
+ let movable_coroutine = body. coroutine . is_some ( )
365
+ && tcx. coroutine_movability ( def. to_def_id ( ) ) == hir:: Movability :: Movable ;
366
+
367
+ let diags_buffer = & mut BorrowckDiagnosticsBuffer :: default ( ) ;
388
368
// While promoteds should mostly be correct by construction, we need to check them for
389
369
// invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
390
370
for promoted_body in & promoted {
@@ -402,7 +382,6 @@ fn do_mir_borrowck<'tcx>(
402
382
location_table : & location_table,
403
383
movable_coroutine,
404
384
fn_self_span_reported : Default :: default ( ) ,
405
- locals_are_invalidated_at_exit,
406
385
access_place_error_reported : Default :: default ( ) ,
407
386
reservation_error_reported : Default :: default ( ) ,
408
387
uninitialized_error_reported : Default :: default ( ) ,
@@ -434,14 +413,33 @@ fn do_mir_borrowck<'tcx>(
434
413
promoted_mbcx. report_move_errors ( ) ;
435
414
}
436
415
416
+ let mut local_names = IndexVec :: from_elem ( None , & body. local_decls ) ;
417
+ for var_debug_info in & body. var_debug_info {
418
+ if let VarDebugInfoContents :: Place ( place) = var_debug_info. value {
419
+ if let Some ( local) = place. as_local ( ) {
420
+ if let Some ( prev_name) = local_names[ local]
421
+ && var_debug_info. name != prev_name
422
+ {
423
+ span_bug ! (
424
+ var_debug_info. source_info. span,
425
+ "local {:?} has many names (`{}` vs `{}`)" ,
426
+ local,
427
+ prev_name,
428
+ var_debug_info. name
429
+ ) ;
430
+ }
431
+ local_names[ local] = Some ( var_debug_info. name ) ;
432
+ }
433
+ }
434
+ }
435
+
437
436
let mut mbcx = MirBorrowckCtxt {
438
437
root_cx,
439
438
infcx : & infcx,
440
439
body,
441
440
move_data : & move_data,
442
441
location_table : & location_table,
443
442
movable_coroutine,
444
- locals_are_invalidated_at_exit,
445
443
fn_self_span_reported : Default :: default ( ) ,
446
444
access_place_error_reported : Default :: default ( ) ,
447
445
reservation_error_reported : Default :: default ( ) ,
@@ -454,9 +452,9 @@ fn do_mir_borrowck<'tcx>(
454
452
local_names,
455
453
region_names : RefCell :: default ( ) ,
456
454
next_region_name : RefCell :: new ( 1 ) ,
457
- polonius_output,
458
455
move_errors : Vec :: new ( ) ,
459
456
diags_buffer,
457
+ polonius_output : polonius_output. as_deref ( ) ,
460
458
polonius_diagnostics : polonius_diagnostics. as_ref ( ) ,
461
459
} ;
462
460
@@ -473,16 +471,6 @@ fn do_mir_borrowck<'tcx>(
473
471
474
472
mbcx. report_move_errors ( ) ;
475
473
476
- // If requested, dump polonius MIR.
477
- polonius:: dump_polonius_mir (
478
- & infcx,
479
- body,
480
- & regioncx,
481
- & borrow_set,
482
- polonius_diagnostics. as_ref ( ) ,
483
- & opt_closure_req,
484
- ) ;
485
-
486
474
// For each non-user used mutable variable, check if it's been assigned from
487
475
// a user-declared local. If so, then put that local into the used_mut set.
488
476
// Note that this set is expected to be small - only upvars from closures
@@ -513,15 +501,14 @@ fn do_mir_borrowck<'tcx>(
513
501
} ;
514
502
515
503
let body_with_facts = if consumer_options. is_some ( ) {
516
- let output_facts = mbcx. polonius_output ;
517
504
Some ( Box :: new ( BodyWithBorrowckFacts {
518
505
body : body_owned,
519
506
promoted,
520
507
borrow_set,
521
508
region_inference_context : regioncx,
522
509
location_table : polonius_input. as_ref ( ) . map ( |_| location_table) ,
523
510
input_facts : polonius_input,
524
- output_facts,
511
+ output_facts : polonius_output ,
525
512
} ) )
526
513
} else {
527
514
None
@@ -654,13 +641,6 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
654
641
location_table : & ' a PoloniusLocationTable ,
655
642
656
643
movable_coroutine : bool ,
657
- /// This keeps track of whether local variables are free-ed when the function
658
- /// exits even without a `StorageDead`, which appears to be the case for
659
- /// constants.
660
- ///
661
- /// I'm not sure this is the right approach - @eddyb could you try and
662
- /// figure this out?
663
- locals_are_invalidated_at_exit : bool ,
664
644
/// This field keeps track of when borrow errors are reported in the access_place function
665
645
/// so that there is no duplicate reporting. This field cannot also be used for the conflicting
666
646
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
@@ -708,12 +688,11 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
708
688
/// The counter for generating new region names.
709
689
next_region_name : RefCell < usize > ,
710
690
711
- /// Results of Polonius analysis.
712
- polonius_output : Option < Box < PoloniusOutput > > ,
713
-
714
691
diags_buffer : & ' a mut BorrowckDiagnosticsBuffer < ' infcx , ' tcx > ,
715
692
move_errors : Vec < MoveError < ' tcx > > ,
716
693
694
+ /// Results of Polonius analysis.
695
+ polonius_output : Option < & ' a PoloniusOutput > ,
717
696
/// When using `-Zpolonius=next`: the data used to compute errors and diagnostics.
718
697
polonius_diagnostics : Option < & ' a PoloniusDiagnosticsContext > ,
719
698
}
@@ -937,13 +916,20 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
937
916
| TerminatorKind :: Return
938
917
| TerminatorKind :: TailCall { .. }
939
918
| TerminatorKind :: CoroutineDrop => {
940
- // Returning from the function implicitly kills storage for all locals and statics.
941
- // Often, the storage will already have been killed by an explicit
942
- // StorageDead, but we don't always emit those (notably on unwind paths),
943
- // so this "extra check" serves as a kind of backup.
944
- for i in state. borrows . iter ( ) {
945
- let borrow = & self . borrow_set [ i] ;
946
- self . check_for_invalidation_at_exit ( loc, borrow, span) ;
919
+ match self . borrow_set . locals_state_at_exit ( ) {
920
+ LocalsStateAtExit :: AllAreInvalidated => {
921
+ // Returning from the function implicitly kills storage for all locals and statics.
922
+ // Often, the storage will already have been killed by an explicit
923
+ // StorageDead, but we don't always emit those (notably on unwind paths),
924
+ // so this "extra check" serves as a kind of backup.
925
+ for i in state. borrows . iter ( ) {
926
+ let borrow = & self . borrow_set [ i] ;
927
+ self . check_for_invalidation_at_exit ( loc, borrow, span) ;
928
+ }
929
+ }
930
+ // If we do not implicitly invalidate all locals on exit,
931
+ // we check for conflicts when dropping or moving this local.
932
+ LocalsStateAtExit :: SomeAreInvalidated { has_storage_dead_or_moved : _ } => { }
947
933
}
948
934
}
949
935
@@ -1715,22 +1701,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
1715
1701
// we'll have a memory leak) and assume that all statics have a destructor.
1716
1702
//
1717
1703
// FIXME: allow thread-locals to borrow other thread locals?
1718
-
1719
- let ( might_be_alive, will_be_dropped) =
1720
- if self . body . local_decls [ root_place. local ] . is_ref_to_thread_local ( ) {
1721
- // Thread-locals might be dropped after the function exits
1722
- // We have to dereference the outer reference because
1723
- // borrows don't conflict behind shared references.
1724
- root_place. projection = TyCtxtConsts :: DEREF_PROJECTION ;
1725
- ( true , true )
1726
- } else {
1727
- ( false , self . locals_are_invalidated_at_exit )
1728
- } ;
1729
-
1730
- if !will_be_dropped {
1731
- debug ! ( "place_is_invalidated_at_exit({:?}) - won't be dropped" , place) ;
1732
- return ;
1733
- }
1704
+ let might_be_alive = if self . body . local_decls [ root_place. local ] . is_ref_to_thread_local ( ) {
1705
+ // Thread-locals might be dropped after the function exits
1706
+ // We have to dereference the outer reference because
1707
+ // borrows don't conflict behind shared references.
1708
+ root_place. projection = TyCtxtConsts :: DEREF_PROJECTION ;
1709
+ true
1710
+ } else {
1711
+ false
1712
+ } ;
1734
1713
1735
1714
let sd = if might_be_alive { Deep } else { Shallow ( None ) } ;
1736
1715
0 commit comments