@@ -21,6 +21,7 @@ use std::cell::RefCell;
2121use std:: marker:: PhantomData ;
2222use std:: ops:: { ControlFlow , Deref } ;
2323
24+ use borrow_set:: LocalsStateAtExit ;
2425use root_cx:: BorrowCheckRootCtxt ;
2526use rustc_abi:: FieldIdx ;
2627use rustc_data_structures:: fx:: { FxIndexMap , FxIndexSet } ;
@@ -303,33 +304,13 @@ fn do_mir_borrowck<'tcx>(
303304 root_cx. set_tainted_by_errors ( e) ;
304305 }
305306
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-
326307 // Replace all regions with fresh inference variables. This
327308 // requires first making our own copy of the MIR. This copy will
328309 // be modified (in place) to contain non-lexical lifetimes. It
329310 // will have a lifetime tied to the inference context.
330311 let mut body_owned = input_body. clone ( ) ;
331312 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) ;
333314 let body = & body_owned; // no further changes
334315
335316 let location_table = PoloniusLocationTable :: new ( body) ;
@@ -354,7 +335,7 @@ fn do_mir_borrowck<'tcx>(
354335 } = nll:: compute_regions (
355336 root_cx,
356337 & infcx,
357- free_regions ,
338+ universal_regions ,
358339 body,
359340 & promoted,
360341 & location_table,
@@ -367,24 +348,23 @@ fn do_mir_borrowck<'tcx>(
367348 // Dump MIR results into a file, if that is enabled. This lets us
368349 // write unit-tests, as well as helping with debugging.
369350 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+ ) ;
370359
371360 // We also have a `#[rustc_regions]` annotation that causes us to dump
372361 // 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) ;
387363
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 ( ) ;
388368 // While promoteds should mostly be correct by construction, we need to check them for
389369 // invalid moves to detect moving out of arrays:`struct S; fn main() { &([S][0]); }`.
390370 for promoted_body in & promoted {
@@ -402,7 +382,6 @@ fn do_mir_borrowck<'tcx>(
402382 location_table : & location_table,
403383 movable_coroutine,
404384 fn_self_span_reported : Default :: default ( ) ,
405- locals_are_invalidated_at_exit,
406385 access_place_error_reported : Default :: default ( ) ,
407386 reservation_error_reported : Default :: default ( ) ,
408387 uninitialized_error_reported : Default :: default ( ) ,
@@ -434,14 +413,33 @@ fn do_mir_borrowck<'tcx>(
434413 promoted_mbcx. report_move_errors ( ) ;
435414 }
436415
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+
437436 let mut mbcx = MirBorrowckCtxt {
438437 root_cx,
439438 infcx : & infcx,
440439 body,
441440 move_data : & move_data,
442441 location_table : & location_table,
443442 movable_coroutine,
444- locals_are_invalidated_at_exit,
445443 fn_self_span_reported : Default :: default ( ) ,
446444 access_place_error_reported : Default :: default ( ) ,
447445 reservation_error_reported : Default :: default ( ) ,
@@ -454,9 +452,9 @@ fn do_mir_borrowck<'tcx>(
454452 local_names,
455453 region_names : RefCell :: default ( ) ,
456454 next_region_name : RefCell :: new ( 1 ) ,
457- polonius_output,
458455 move_errors : Vec :: new ( ) ,
459456 diags_buffer,
457+ polonius_output : polonius_output. as_deref ( ) ,
460458 polonius_diagnostics : polonius_diagnostics. as_ref ( ) ,
461459 } ;
462460
@@ -473,16 +471,6 @@ fn do_mir_borrowck<'tcx>(
473471
474472 mbcx. report_move_errors ( ) ;
475473
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-
486474 // For each non-user used mutable variable, check if it's been assigned from
487475 // a user-declared local. If so, then put that local into the used_mut set.
488476 // Note that this set is expected to be small - only upvars from closures
@@ -513,15 +501,14 @@ fn do_mir_borrowck<'tcx>(
513501 } ;
514502
515503 let body_with_facts = if consumer_options. is_some ( ) {
516- let output_facts = mbcx. polonius_output ;
517504 Some ( Box :: new ( BodyWithBorrowckFacts {
518505 body : body_owned,
519506 promoted,
520507 borrow_set,
521508 region_inference_context : regioncx,
522509 location_table : polonius_input. as_ref ( ) . map ( |_| location_table) ,
523510 input_facts : polonius_input,
524- output_facts,
511+ output_facts : polonius_output ,
525512 } ) )
526513 } else {
527514 None
@@ -654,13 +641,6 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
654641 location_table : & ' a PoloniusLocationTable ,
655642
656643 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 ,
664644 /// This field keeps track of when borrow errors are reported in the access_place function
665645 /// so that there is no duplicate reporting. This field cannot also be used for the conflicting
666646 /// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
@@ -708,12 +688,11 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
708688 /// The counter for generating new region names.
709689 next_region_name : RefCell < usize > ,
710690
711- /// Results of Polonius analysis.
712- polonius_output : Option < Box < PoloniusOutput > > ,
713-
714691 diags_buffer : & ' a mut BorrowckDiagnosticsBuffer < ' infcx , ' tcx > ,
715692 move_errors : Vec < MoveError < ' tcx > > ,
716693
694+ /// Results of Polonius analysis.
695+ polonius_output : Option < & ' a PoloniusOutput > ,
717696 /// When using `-Zpolonius=next`: the data used to compute errors and diagnostics.
718697 polonius_diagnostics : Option < & ' a PoloniusDiagnosticsContext > ,
719698}
@@ -937,13 +916,20 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
937916 | TerminatorKind :: Return
938917 | TerminatorKind :: TailCall { .. }
939918 | 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 : _ } => { }
947933 }
948934 }
949935
@@ -1715,22 +1701,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
17151701 // we'll have a memory leak) and assume that all statics have a destructor.
17161702 //
17171703 // 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+ } ;
17341713
17351714 let sd = if might_be_alive { Deep } else { Shallow ( None ) } ;
17361715
0 commit comments