@@ -233,7 +233,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
233
233
hir:: BodyOwnerKind :: Static ( _) => false ,
234
234
hir:: BodyOwnerKind :: Fn => true ,
235
235
} ,
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 ( ) ,
237
238
} ;
238
239
239
240
mbcx. analyze_results ( & mut state) ; // entry point for DataflowResultsConsumer
@@ -258,7 +259,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
258
259
/// This field keeps track of when storage dead or drop errors are reported
259
260
/// in order to stop duplicate error reporting and identify the conditions required
260
261
/// 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 > ,
262
265
}
263
266
264
267
// Check that:
@@ -502,19 +505,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
502
505
flow_state. borrows . with_elems_outgoing ( |borrows| {
503
506
for i in borrows {
504
507
let borrow = & data[ i] ;
508
+ let context = ContextKind :: StorageDead . new ( loc) ;
505
509
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) ;
518
511
}
519
512
} ) ;
520
513
}
@@ -663,34 +656,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
663
656
) -> AccessErrorsReported {
664
657
let ( sd, rw) = kind;
665
658
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
-
681
659
let mutability_error =
682
660
self . check_access_permissions ( place_span, rw, is_local_mutation_allowed) ;
683
661
let conflict_error =
684
662
self . check_access_for_conflict ( context, place_span, sd, rw, flow_state) ;
685
663
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
-
694
664
AccessErrorsReported { mutability_error, conflict_error }
695
665
}
696
666
@@ -749,16 +719,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
749
719
)
750
720
}
751
721
WriteKind :: StorageDeadOrDrop => {
752
- let end_span = flow_state
753
- . borrows
754
- . operator ( )
755
- . opt_region_end_span ( & borrow. region ) ;
756
722
error_reported = true ;
757
723
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 ( ) ) ;
762
725
}
763
726
WriteKind :: Mutate => {
764
727
error_reported = true ;
@@ -947,16 +910,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
947
910
948
911
/// Returns whether a borrow of this place is invalidated when the function
949
912
/// 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 ;
952
921
let root_place = self . prefixes ( place, PrefixSet :: All ) . last ( ) . unwrap ( ) ;
953
922
954
923
// FIXME(nll-rfc#40): do more precise destructor tracking here. For now
955
924
// we just know that all locals are dropped at function exit (otherwise
956
925
// we'll have a memory leak) and assume that all statics have a destructor.
957
926
//
958
927
// 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 {
960
929
Place :: Static ( statik) => {
961
930
// Thread-locals might be dropped after the function exits, but
962
931
// "true" statics will never be.
@@ -965,12 +934,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
965
934
. iter ( )
966
935
. any ( |attr| attr. check_name ( "thread_local" ) ) ;
967
936
968
- ( true , is_thread_local, None )
937
+ ( true , is_thread_local)
969
938
}
970
- Place :: Local ( local ) => {
939
+ Place :: Local ( _ ) => {
971
940
// Locals are always dropped at function exit, and if they
972
941
// 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 )
974
943
}
975
944
Place :: Projection ( ..) => {
976
945
bug ! ( "root of {:?} is a projection ({:?})?" , place, root_place)
@@ -982,30 +951,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
982
951
"place_is_invalidated_at_exit({:?}) - won't be dropped" ,
983
952
place
984
953
) ;
985
- return false ;
954
+ return ;
986
955
}
987
956
988
957
// FIXME: replace this with a proper borrow_conflicts_with_place when
989
958
// that is merged.
990
- let prefix_set = if might_be_alive {
991
- PrefixSet :: Supporting
959
+ let sd = if might_be_alive {
960
+ Deep
992
961
} else {
993
- PrefixSet :: Shallow
962
+ Shallow ( None )
994
963
} ;
995
964
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
+ )
1006
975
}
1007
-
1008
- result
1009
976
}
1010
977
}
1011
978
@@ -1358,7 +1325,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1358
1325
// Mutably borrowed data is mutable, but only if we have a
1359
1326
// unique path to the `&mut`
1360
1327
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
+ {
1362
1331
Some ( field) if {
1363
1332
self . mir . upvar_decls [ field. index ( ) ] . by_ref
1364
1333
} => is_local_mutation_allowed,
@@ -1485,10 +1454,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1485
1454
Overlap :: Disjoint
1486
1455
}
1487
1456
}
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
+ }
1492
1469
}
1493
1470
( Place :: Local ( _) , Place :: Static ( _) ) |
1494
1471
( Place :: Static ( _) , Place :: Local ( _) ) => {
0 commit comments