@@ -233,7 +233,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
233233 hir:: BodyOwnerKind :: Static ( _) => false ,
234234 hir:: BodyOwnerKind :: Fn => true ,
235235 } ,
236- storage_dead_or_drop_error_reported : FxHashSet ( ) ,
236+ storage_dead_or_drop_error_reported_l : FxHashSet ( ) ,
237+ storage_dead_or_drop_error_reported_s : FxHashSet ( ) ,
237238 } ;
238239
239240 mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
@@ -258,7 +259,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
258259 /// This field keeps track of when storage dead or drop errors are reported
259260 /// in order to stop duplicate error reporting and identify the conditions required
260261 /// for a "temporary value dropped here while still borrowed" error. See #45360.
261- storage_dead_or_drop_error_reported : FxHashSet < Local > ,
262+ storage_dead_or_drop_error_reported_l : FxHashSet < Local > ,
263+ /// Same as the above, but for statics (thread-locals)
264+ storage_dead_or_drop_error_reported_s : FxHashSet < DefId > ,
262265}
263266
264267// Check that:
@@ -502,19 +505,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
502505 flow_state. borrows . with_elems_outgoing ( |borrows| {
503506 for i in borrows {
504507 let borrow = & data[ i] ;
508+ let context = ContextKind :: StorageDead . new ( loc) ;
505509
506- if self . place_is_invalidated_at_exit ( & borrow. place ) {
507- debug ! ( "borrow conflicts at exit {:?}" , borrow) ;
508- // FIXME: should be talking about the region lifetime instead
509- // of just a span here.
510- let end_span = domain. opt_region_end_span ( & borrow. region ) ;
511-
512- self . report_borrowed_value_does_not_live_long_enough (
513- ContextKind :: StorageDead . new ( loc) ,
514- ( & borrow. place , end_span. unwrap_or ( span) ) ,
515- end_span,
516- )
517- }
510+ self . check_for_invalidation_at_exit ( context, borrow, span, flow_state) ;
518511 }
519512 } ) ;
520513 }
@@ -663,34 +656,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
663656 ) -> AccessErrorsReported {
664657 let ( sd, rw) = kind;
665658
666- let storage_dead_or_drop_local = match ( place_span. 0 , rw) {
667- ( & Place :: Local ( local) , Write ( WriteKind :: StorageDeadOrDrop ) ) => Some ( local) ,
668- _ => None ,
669- } ;
670-
671- // Check if error has already been reported to stop duplicate reporting.
672- if let Some ( local) = storage_dead_or_drop_local {
673- if self . storage_dead_or_drop_error_reported . contains ( & local) {
674- return AccessErrorsReported {
675- mutability_error : false ,
676- conflict_error : true
677- } ;
678- }
679- }
680-
681659 let mutability_error =
682660 self . check_access_permissions ( place_span, rw, is_local_mutation_allowed) ;
683661 let conflict_error =
684662 self . check_access_for_conflict ( context, place_span, sd, rw, flow_state) ;
685663
686- // A conflict with a storagedead/drop is a "borrow does not live long enough"
687- // error. Avoid reporting such an error multiple times for the same local.
688- if conflict_error {
689- if let Some ( local) = storage_dead_or_drop_local {
690- self . storage_dead_or_drop_error_reported . insert ( local) ;
691- }
692- }
693-
694664 AccessErrorsReported { mutability_error, conflict_error }
695665 }
696666
@@ -749,16 +719,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
749719 )
750720 }
751721 WriteKind :: StorageDeadOrDrop => {
752- let end_span = flow_state
753- . borrows
754- . operator ( )
755- . opt_region_end_span ( & borrow. region ) ;
756722 error_reported = true ;
757723 this. report_borrowed_value_does_not_live_long_enough (
758- context,
759- place_span,
760- end_span,
761- )
724+ context, borrow, place_span. 1 , flow_state. borrows . operator ( ) ) ;
762725 }
763726 WriteKind :: Mutate => {
764727 error_reported = true ;
@@ -947,16 +910,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
947910
948911 /// Returns whether a borrow of this place is invalidated when the function
949912 /// exits
950- fn place_is_invalidated_at_exit ( & mut self , place : & Place < ' tcx > ) -> bool {
951- debug ! ( "place_is_invalidated_at_exit({:?})" , place) ;
913+ fn check_for_invalidation_at_exit ( & mut self ,
914+ context : Context ,
915+ borrow : & BorrowData < ' tcx > ,
916+ span : Span ,
917+ flow_state : & Flows < ' cx , ' gcx , ' tcx > )
918+ {
919+ debug ! ( "check_for_invalidation_at_exit({:?})" , borrow) ;
920+ let place = & borrow. place ;
952921 let root_place = self . prefixes ( place, PrefixSet :: All ) . last ( ) . unwrap ( ) ;
953922
954923 // FIXME(nll-rfc#40): do more precise destructor tracking here. For now
955924 // we just know that all locals are dropped at function exit (otherwise
956925 // we'll have a memory leak) and assume that all statics have a destructor.
957926 //
958927 // FIXME: allow thread-locals to borrow other thread locals?
959- let ( might_be_alive, will_be_dropped, local ) = match root_place {
928+ let ( might_be_alive, will_be_dropped) = match root_place {
960929 Place :: Static ( statik) => {
961930 // Thread-locals might be dropped after the function exits, but
962931 // "true" statics will never be.
@@ -965,12 +934,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
965934 . iter ( )
966935 . any ( |attr| attr. check_name ( "thread_local" ) ) ;
967936
968- ( true , is_thread_local, None )
937+ ( true , is_thread_local)
969938 }
970- Place :: Local ( local ) => {
939+ Place :: Local ( _ ) => {
971940 // Locals are always dropped at function exit, and if they
972941 // have a destructor it would've been called already.
973- ( false , self . locals_are_invalidated_at_exit , Some ( * local ) )
942+ ( false , self . locals_are_invalidated_at_exit )
974943 }
975944 Place :: Projection ( ..) => {
976945 bug ! ( "root of {:?} is a projection ({:?})?" , place, root_place)
@@ -982,30 +951,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
982951 "place_is_invalidated_at_exit({:?}) - won't be dropped" ,
983952 place
984953 ) ;
985- return false ;
954+ return ;
986955 }
987956
988957 // FIXME: replace this with a proper borrow_conflicts_with_place when
989958 // that is merged.
990- let prefix_set = if might_be_alive {
991- PrefixSet :: Supporting
959+ let sd = if might_be_alive {
960+ Deep
992961 } else {
993- PrefixSet :: Shallow
962+ Shallow ( None )
994963 } ;
995964
996- let result =
997- self . prefixes ( place , prefix_set ) . any ( |prefix| prefix == root_place ) ;
998-
999- if result {
1000- if let Some ( local ) = local {
1001- if let Some ( _ ) = self . storage_dead_or_drop_error_reported . replace ( local ) {
1002- debug ! ( "place_is_invalidated_at_exit({:?}) - suppressed" , place ) ;
1003- return false ;
1004- }
1005- }
965+ if self . places_conflict ( place , root_place , sd ) {
966+ debug ! ( "check_for_invalidation_at_exit({:?}): INVALID" , place ) ;
967+ // FIXME: should be talking about the region lifetime instead
968+ // of just a span here.
969+ self . report_borrowed_value_does_not_live_long_enough (
970+ context ,
971+ borrow ,
972+ span . end_point ( ) ,
973+ flow_state . borrows . operator ( )
974+ )
1006975 }
1007-
1008- result
1009976 }
1010977}
1011978
@@ -1358,7 +1325,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
13581325 // Mutably borrowed data is mutable, but only if we have a
13591326 // unique path to the `&mut`
13601327 hir:: MutMutable => {
1361- let mode = match self . is_upvar_field_projection ( & proj. base ) {
1328+ let mode = match
1329+ self . is_upvar_field_projection ( & proj. base )
1330+ {
13621331 Some ( field) if {
13631332 self . mir . upvar_decls [ field. index ( ) ] . by_ref
13641333 } => is_local_mutation_allowed,
@@ -1485,10 +1454,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
14851454 Overlap :: Disjoint
14861455 }
14871456 }
1488- ( Place :: Static ( ..) , Place :: Static ( ..) ) => {
1489- // Borrows of statics do not have to be tracked here.
1490- debug ! ( "place_element_conflict: IGNORED-STATIC" ) ;
1491- Overlap :: Disjoint
1457+ ( Place :: Static ( static1) , Place :: Static ( static2) ) => {
1458+ if static1. def_id != static2. def_id {
1459+ debug ! ( "place_element_conflict: DISJOINT-STATIC" ) ;
1460+ Overlap :: Disjoint
1461+ } else if self . tcx . is_static_mut ( static1. def_id ) {
1462+ // We ignore mutable statics - they can only be unsafe code.
1463+ debug ! ( "place_element_conflict: IGNORE-STATIC-MUT" ) ;
1464+ Overlap :: Disjoint
1465+ } else {
1466+ debug ! ( "place_element_conflict: DISJOINT-OR-EQ-STATIC" ) ;
1467+ Overlap :: EqualOrDisjoint
1468+ }
14921469 }
14931470 ( Place :: Local ( _) , Place :: Static ( _) ) |
14941471 ( Place :: Static ( _) , Place :: Local ( _) ) => {
0 commit comments