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