1010
1111use borrow_check:: place_ext:: PlaceExt ;
1212use dataflow:: indexes:: BorrowIndex ;
13+ use dataflow:: move_paths:: MoveData ;
1314use rustc:: mir:: traversal;
1415use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
15- use rustc:: mir:: { self , Location , Mir , Place } ;
16+ use rustc:: mir:: { self , Location , Mir , Place , Local } ;
1617use rustc:: ty:: { Region , TyCtxt } ;
1718use rustc:: util:: nodemap:: { FxHashMap , FxHashSet } ;
1819use rustc_data_structures:: indexed_vec:: IndexVec ;
20+ use rustc_data_structures:: bitvec:: BitArray ;
1921use std:: fmt;
2022use std:: hash:: Hash ;
2123use std:: ops:: Index ;
@@ -43,6 +45,8 @@ crate struct BorrowSet<'tcx> {
4345
4446 /// Map from local to all the borrows on that local
4547 crate local_map : FxHashMap < mir:: Local , FxHashSet < BorrowIndex > > ,
48+
49+ crate locals_state_at_exit : LocalsStateAtExit ,
4650}
4751
4852impl < ' tcx > Index < BorrowIndex > for BorrowSet < ' tcx > {
@@ -96,8 +100,52 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
96100 }
97101}
98102
103+ crate enum LocalsStateAtExit {
104+ AllAreInvalidated ,
105+ SomeAreInvalidated { has_storage_dead_or_moved : BitArray < Local > }
106+ }
107+
108+ impl LocalsStateAtExit {
109+ fn build (
110+ locals_are_invalidated_at_exit : bool ,
111+ mir : & Mir < ' tcx > ,
112+ move_data : & MoveData < ' tcx >
113+ ) -> Self {
114+ struct HasStorageDead ( BitArray < Local > ) ;
115+
116+ impl < ' tcx > Visitor < ' tcx > for HasStorageDead {
117+ fn visit_local ( & mut self , local : & Local , ctx : PlaceContext < ' tcx > , _: Location ) {
118+ if ctx == PlaceContext :: StorageDead {
119+ self . 0 . insert ( * local) ;
120+ }
121+ }
122+ }
123+
124+ if locals_are_invalidated_at_exit {
125+ LocalsStateAtExit :: AllAreInvalidated
126+ } else {
127+ let mut has_storage_dead = HasStorageDead ( BitArray :: new ( mir. local_decls . len ( ) ) ) ;
128+ has_storage_dead. visit_mir ( mir) ;
129+ let mut has_storage_dead_or_moved = has_storage_dead. 0 ;
130+ for move_out in & move_data. moves {
131+ if let Some ( index) = move_data. base_local ( move_out. path ) {
132+ has_storage_dead_or_moved. insert ( index) ;
133+
134+ }
135+ }
136+ LocalsStateAtExit :: SomeAreInvalidated { has_storage_dead_or_moved }
137+ }
138+ }
139+ }
140+
99141impl < ' tcx > BorrowSet < ' tcx > {
100- pub fn build ( tcx : TyCtxt < ' _ , ' _ , ' tcx > , mir : & Mir < ' tcx > ) -> Self {
142+ pub fn build (
143+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
144+ mir : & Mir < ' tcx > ,
145+ locals_are_invalidated_at_exit : bool ,
146+ move_data : & MoveData < ' tcx >
147+ ) -> Self {
148+
101149 let mut visitor = GatherBorrows {
102150 tcx,
103151 mir,
@@ -107,6 +155,8 @@ impl<'tcx> BorrowSet<'tcx> {
107155 region_map : FxHashMap ( ) ,
108156 local_map : FxHashMap ( ) ,
109157 pending_activations : FxHashMap ( ) ,
158+ locals_state_at_exit :
159+ LocalsStateAtExit :: build ( locals_are_invalidated_at_exit, mir, move_data) ,
110160 } ;
111161
112162 for ( block, block_data) in traversal:: preorder ( mir) {
@@ -119,6 +169,7 @@ impl<'tcx> BorrowSet<'tcx> {
119169 activation_map : visitor. activation_map ,
120170 region_map : visitor. region_map ,
121171 local_map : visitor. local_map ,
172+ locals_state_at_exit : visitor. locals_state_at_exit ,
122173 }
123174 }
124175
@@ -148,6 +199,8 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
148199 /// the borrow. When we find a later use of this activation, we
149200 /// remove from the map (and add to the "tombstone" set below).
150201 pending_activations : FxHashMap < mir:: Local , BorrowIndex > ,
202+
203+ locals_state_at_exit : LocalsStateAtExit ,
151204}
152205
153206impl < ' a , ' gcx , ' tcx > Visitor < ' tcx > for GatherBorrows < ' a , ' gcx , ' tcx > {
@@ -159,7 +212,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
159212 location : mir:: Location ,
160213 ) {
161214 if let mir:: Rvalue :: Ref ( region, kind, ref borrowed_place) = * rvalue {
162- if borrowed_place. ignore_borrow ( self . tcx , self . mir ) {
215+ if borrowed_place. ignore_borrow (
216+ self . tcx , self . mir , & self . locals_state_at_exit ) {
163217 return ;
164218 }
165219
0 commit comments